Code:
#include <stdio.h>
#include <stdlib.h>
#include "KillerMoves.h"
int board[49];
int height[7];
int ply;
int lastMove;
int getColumnByIndex[] = {0,0,0,0,0,0,-1,1,1,1,1,1,1,-1,2,2,2,2,2,2,-1,3,3,3,3,3,3,-1,4,4,4,4,4,4,-1,5,5,5,5,5,5,-1,6,6,6,6,6,6,-1};
//int columns[] = {3,2,4,1,5,0,6};
int rootNegamax(int depth,int alpha,int beta,int color);
void reset();
int checkFullBoard();
int checkWin();
void makeMove(int *n,int *color);
int main()
{
int turn = 1; // set to 1 for engine as first player ,0 for engine as second
int m;
int engineNumber = 1;
int opponentNumber = -1;
const int DEPTH = 10;
const int INFINITY = 1001;
reset();
if(turn){
while(1 < 2){
initKillersTable();
printf("Thinking..\n");
m = rootNegamax(DEPTH,-INFINITY,INFINITY,engineNumber);
makeMove(&m,&engineNumber);
printf("Engine played in column %d\n",m);
if(checkWin()){
printf("Engine Wins!");
break;
}
else if(checkFullBoard()){
printf("Draw");
break;
}
printf("Enter column\n");
scanf("%d",&m);
makeMove(&m,&opponentNumber);
if(checkWin()){
printf("You won!");
break;
}
else if(checkFullBoard()){
printf("Draw");
break;
}
}
}
else{
while(1 < 2){
printf("Enter column\n");
scanf("%d",&m);
makeMove(&m,&opponentNumber);
if(checkWin()){
printf("You won!");
break;
}
else if(checkFullBoard()){
printf("Draw");
break;
}
initKillersTable();
printf("Thinking..\n");
m = rootNegamax(DEPTH,-INFINITY,INFINITY,engineNumber);
makeMove(&m,&engineNumber);
printf("Engine played in column %d\n",m);
if(checkWin()){
printf("Engine Wins!");
break;
}
else if(checkFullBoard()){
printf("Draw");
break;
}
}
}
return 0;
}
void reset(){
for(int i = 0; i < 49; i++){
board[i] = 0;
}
for(int i = 0; i < 7; i++){
height[i] = i*7;
}
ply = 0;
}
void makeMove(int *n,int *color){
board[height[*n]] = *color;
lastMove = height[*n];
height[*n]++;
ply++;
}
void unmakeMove(int *n){
height[*n]--;
board[height[*n]] = 0;
ply--;
}
int checkFullColumn(int *n){
return board[(*n)*7+5] != 0;
}
int checkFullBoard(){
return ply == 42;
}
int checkValidSquare(int *square){
return *square >= 0 && *square <= 48;
}
int checkWin(){
int color = board[lastMove];
int counter;
int startPoint;
int endPoint;
//check horizontal
startPoint = lastMove-21;
endPoint = lastMove+21;
counter = 0;
while(startPoint <= endPoint){
if(checkValidSquare(&startPoint)){
if(board[startPoint] == color){
counter++;
}
else{
counter = 0;
}
}
if(counter == 4){
return 1;
}
startPoint+=7;
}
//check diagonal down right
startPoint = lastMove-18;
endPoint = lastMove+18;
counter = 0;
while(startPoint <= endPoint){
if(checkValidSquare(&startPoint)){
if(board[startPoint] == color){
counter++;
}
else{
counter = 0;
}
}
if(counter == 4){
return 1;
}
startPoint+=6;
}
//check diagonal up right
startPoint = lastMove-24;
endPoint = lastMove+24;
counter = 0;
while(startPoint <= endPoint){
if(checkValidSquare(&startPoint)){
if(board[startPoint] == color){
counter++;
}
else{
counter = 0;
}
}
if(counter == 4){
return 1;
}
startPoint+=8;
}
//check vertical
startPoint = lastMove-3;
endPoint = lastMove+3;
counter = 0;
while(startPoint <= endPoint){
if(checkValidSquare(&startPoint)){
if(board[startPoint] == color){
counter++;
}
else{
counter = 0;
}
}
if(counter == 4){
return 1;
}
startPoint++;
}
return 0;
}
int evaluate(){
int i;
int j;
int k;
int enThree = 0;
int enTwo = 0;
int enOne = 0;
int opThree = 0;
int opTwo = 0;
int opOne = 0;
int enCount;
int opCount;
//horizontal
for(i = 0; i <= 5; i++){
for(j = i; j <= i+21; j+=7){
enCount = 0;
opCount = 0;
for(k = j; k <= j+21; k+=7){
if(board[k] == 1){
enCount++;
}
else if(board[k] == -1){
opCount++;
}
}
if(enCount > 0 && opCount == 0){
switch(enCount){
case 1:
enOne++;
break;
case 2:
enTwo++;
break;
case 3:
enThree++;
break;
}
}
else if(enCount == 0 && opCount > 0){
switch(opCount){
case 1:
opOne++;
break;
case 2:
opTwo++;
break;
case 3:
opThree++;
break;
}
}
}
}
//diagonals
for(i = 5; i <= 17; i+=6){
enCount = 0;
opCount = 0;
for(j = i; j <= i+18; j+=6){
if(board[j] == 1){
enCount++;
}
else if(board[j] == -1){
opCount++;
}
}
if(enCount > 0 && opCount == 0){
switch(enCount){
case 1:
enOne++;
break;
case 2:
enTwo++;
break;
case 3:
enThree++;
break;
}
}
else if(enCount == 0 && opCount > 0){
switch(opCount){
case 1:
opOne++;
break;
case 2:
opTwo++;
break;
case 3:
opThree++;
break;
}
}
}
for(i = 4; i <= 10; i+=6){
enCount = 0;
opCount = 0;
for(j = i; j <= i+18; j+=6){
if(board[j] == 1){
enCount++;
}
else if(board[j] == -1){
opCount++;
}
}
if(enCount > 0 && opCount == 0){
switch(enCount){
case 1:
enOne++;
break;
case 2:
enTwo++;
break;
case 3:
enThree++;
break;
}
}
else if(enCount == 0 && opCount > 0){
switch(opCount){
case 1:
opOne++;
break;
case 2:
opTwo++;
break;
case 3:
opThree++;
break;
}
}
}
enCount = 0;
opCount = 0;
for(j = 3; j <= 21; j+=6){
if(board[j] == 1){
enCount++;
}
else if(board[j] == -1){
opCount++;
}
}
if(enCount > 0 && opCount == 0){
switch(enCount){
case 1:
enOne++;
break;
case 2:
enTwo++;
break;
case 3:
enThree++;
break;
}
}
else if(enCount == 0 && opCount > 0){
switch(opCount){
case 1:
opOne++;
break;
case 2:
opTwo++;
break;
case 3:
opThree++;
break;
}
}
for(i = 12; i <= 24; i+=6){
enCount = 0;
opCount = 0;
for(j = i; j <= i+18; j+=6){
if(board[j] == 1){
enCount++;
}
else if(board[j] == -1){
opCount++;
}
}
if(enCount > 0 && opCount == 0){
switch(enCount){
case 1:
enOne++;
break;
case 2:
enTwo++;
break;
case 3:
enThree++;
break;
}
}
else if(enCount == 0 && opCount > 0){
switch(opCount){
case 1:
opOne++;
break;
case 2:
opTwo++;
break;
case 3:
opThree++;
break;
}
}
}
for(i = 19; i <= 25; i+=6){
enCount = 0;
opCount = 0;
for(j = i; j <= i+18; j+=6){
if(board[j] == 1){
enCount++;
}
else if(board[j] == -1){
opCount++;
}
}
if(enCount > 0 && opCount == 0){
switch(enCount){
case 1:
enOne++;
break;
case 2:
enTwo++;
break;
case 3:
enThree++;
break;
}
}
else if(enCount == 0 && opCount > 0){
switch(opCount){
case 1:
opOne++;
break;
case 2:
opTwo++;
break;
case 3:
opThree++;
break;
}
}
}
enCount = 0;
opCount = 0;
for(j = 26; j <= 44; j+=6){
if(board[j] == 1){
enCount++;
}
else if(board[j] == -1){
opCount++;
}
}
if(enCount > 0 && opCount == 0){
switch(enCount){
case 1:
enOne++;
break;
case 2:
enTwo++;
break;
case 3:
enThree++;
break;
}
}
else if(enCount == 0 && opCount > 0){
switch(opCount){
case 1:
opOne++;
break;
case 2:
opTwo++;
break;
case 3:
opThree++;
break;
}
}
for(i = 7; i <= 23; i+=8){
enCount = 0;
opCount = 0;
for(j = i; j <= i+24; j+=8){
if(board[j] == 1){
enCount++;
}
else if(board[j] == -1){
opCount++;
}
}
if(enCount > 0 && opCount == 0){
switch(enCount){
case 1:
enOne++;
break;
case 2:
enTwo++;
break;
case 3:
enThree++;
break;
}
}
else if(enCount == 0 && opCount > 0){
switch(opCount){
case 1:
opOne++;
break;
case 2:
opTwo++;
break;
case 3:
opThree++;
break;
}
}
}
for(i = 14; i <= 22; i+=8){
enCount = 0;
opCount = 0;
for(j = i; j <= i+24; j+=8){
if(board[j] == 1){
enCount++;
}
else if(board[j] == -1){
opCount++;
}
}
if(enCount > 0 && opCount == 0){
switch(enCount){
case 1:
enOne++;
break;
case 2:
enTwo++;
break;
case 3:
enThree++;
break;
}
}
else if(enCount == 0 && opCount > 0){
switch(opCount){
case 1:
opOne++;
break;
case 2:
opTwo++;
break;
case 3:
opThree++;
break;
}
}
}
enCount = 0;
opCount = 0;
for(j = 21; j <= 45; j+=8){
if(board[j] == 1){
enCount++;
}
else if(board[j] == -1){
opCount++;
}
}
if(enCount > 0 && opCount == 0){
switch(enCount){
case 1:
enOne++;
break;
case 2:
enTwo++;
break;
case 3:
enThree++;
break;
}
}
else if(enCount == 0 && opCount > 0){
switch(opCount){
case 1:
opOne++;
break;
case 2:
opTwo++;
break;
case 3:
opThree++;
break;
}
}
for(i = 0; i <= 16; i+=8){
enCount = 0;
opCount = 0;
for(j = i; j <= i+24; j+=8){
if(board[j] == 1){
enCount++;
}
else if(board[j] == -1){
opCount++;
}
}
if(enCount > 0 && opCount == 0){
switch(enCount){
case 1:
enOne++;
break;
case 2:
enTwo++;
break;
case 3:
enThree++;
break;
}
}
else if(enCount == 0 && opCount > 0){
switch(opCount){
case 1:
opOne++;
break;
case 2:
opTwo++;
break;
case 3:
opThree++;
break;
}
}
}
for(i = 1; i <= 9; i+=8){
enCount = 0;
opCount = 0;
for(j = i; j <= i+24; j+=8){
if(board[j] == 1){
enCount++;
}
else if(board[j] == -1){
opCount++;
}
}
if(enCount > 0 && opCount == 0){
switch(enCount){
case 1:
enOne++;
break;
case 2:
enTwo++;
break;
case 3:
enThree++;
break;
}
}
else if(enCount == 0 && opCount > 0){
switch(opCount){
case 1:
opOne++;
break;
case 2:
opTwo++;
break;
case 3:
opThree++;
break;
}
}
}
enCount = 0;
opCount = 0;
for(j = 2; j <= 26; j+=8){
if(board[j] == 1){
enCount++;
}
else if(board[j] == -1){
opCount++;
}
}
if(enCount > 0 && opCount == 0){
switch(enCount){
case 1:
enOne++;
break;
case 2:
enTwo++;
break;
case 3:
enThree++;
break;
}
}
else if(enCount == 0 && opCount > 0){
switch(opCount){
case 1:
opOne++;
break;
case 2:
opTwo++;
break;
case 3:
opThree++;
break;
}
}
return ((enThree*32) + (enTwo*4) + enOne) - ((opThree*32) + (opTwo*4) + opOne);
}
int negamax(int depth,int alpha,int beta,int color){
if(checkWin()){
return -1000;
}
else if(depth == 0 || checkFullBoard()){
return color*evaluate();
}
else{
int val;
int killerAdded = 0;
int killer = getKiller(depth);
if(killer != -1 && height[getColumnByIndex[killer]] == killer){
killerAdded = 1;
makeMove(getColumnByIndex[killer],&color);
val = -negamax(depth-1,-beta,-alpha,-color);
unmakeMove(getColumnByIndex[killer]);
if(val >= beta){
return val;
}
if(val > alpha){
alpha = val;
}
}
for(int i = 0; i < 7; i++){
if(killerAdded && i == getColumnByIndex[killer]){
continue;
}
if(checkFullColumn(&i)){
continue;
}
makeMove(&i,&color);
val = -negamax(depth-1,-beta,-alpha,-color);
unmakeMove(&i);
if(val >= beta){
addKiller(height[i],depth);
return val;
}
if(val > alpha){
alpha = val;
}
}
return alpha;
}
}
int rootNegamax(int depth,int alpha,int beta,int color){
int bestMove = -1;
int val;
for(int i = 0; i < 7; i++){
if(checkFullColumn(&i)){
continue;
}
makeMove(&i,&color);
val = -negamax(depth-1,-beta,-alpha,-color);
unmakeMove(&i);
if(val > alpha){
alpha = val;
bestMove = i;
}
}
return bestMove;
}