161 lines
3.9 KiB
C
161 lines
3.9 KiB
C
#include "structure.h"
|
|
|
|
// #define AI_DEBUG
|
|
|
|
#define AI_NAIVE 1
|
|
#define AI_NOT_NAIVE 0
|
|
int AI_NAIVE_MODE = ; // switches 'naive mode'
|
|
|
|
#define AI_DEPTH_EASY 3
|
|
#define AI_DEPTH_MEDIUM 3
|
|
#define AI_DEPTH_HARD 5
|
|
#define AI_DEPTH_SUPERHARD 9
|
|
int AI_DEPTH = 3;
|
|
|
|
int miniMaxHandler(struct GAME* game, int turn, int maxDepth)
|
|
{
|
|
struct GAME game_copy = *game;
|
|
}
|
|
|
|
int miniMaxField(struct FIELD field, int turn, int maxDepth, int curDepth, int* retX, int* retY) // default curdepth = 1
|
|
{
|
|
int result = 0;
|
|
|
|
if (curDepth > maxDepth)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (field.winner != 0)
|
|
{
|
|
return field.winner;
|
|
}
|
|
|
|
#ifdef AI_DEBUG
|
|
for (int ts = 1; ts < curDepth; ts++) printf("\t");
|
|
printf("=== minimax on depth %d, Turn: %d\n\n", curDepth, turn);
|
|
#endif
|
|
|
|
int peakScore = turn * (-3);
|
|
|
|
// cord's of the best score
|
|
int peakX = 1;
|
|
int peakY = 1;
|
|
|
|
int lastX, lastY;
|
|
|
|
for (int i = 0; i < MAP_SIZE; i++)
|
|
{
|
|
for (int j = 0; j < MAP_SIZE; j++)
|
|
{
|
|
if (field.fieldCells[i][j] != 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// remember the last empty cell for ai if it is not
|
|
// enough deep for making smart turn
|
|
lastX = i; lastY = j;
|
|
|
|
#ifdef AI_DEBUG
|
|
for (int ts = 1; ts < curDepth; ts++) printf("\t");
|
|
printf("=== %d %d ===\n", i, j);
|
|
#endif
|
|
|
|
struct FIELD tmpField = field; // temporary field for calculating best move
|
|
tmpField.fieldCells[i][j] = turn; // making turn
|
|
tmpField.FUpdateFieldScore(&tmpField);
|
|
tmpField.winner = FCheckFieldWin(&tmpField);
|
|
|
|
result = miniMaxField(tmpField, turn * (-1), maxDepth, curDepth + 1, NULL, NULL);
|
|
if (result == 0)
|
|
{
|
|
printf("DRAW!\n");
|
|
}
|
|
if (curDepth == 1)
|
|
{
|
|
printf("res (%d %d): %d\n", i, j, result);
|
|
}
|
|
|
|
// find desired score
|
|
if ((turn < 0 && result < peakScore) || (turn > 0 && result > peakScore))
|
|
{
|
|
if (result == 0 || result == MAP_SIZE || result == MAP_SIZE * (-1))
|
|
{
|
|
peakScore = result;
|
|
peakX = i; peakY = j;
|
|
if (curDepth == 1)
|
|
printf("writtern peek: %d %d : %d\n", turn, result, peakScore);
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
if (curDepth == 1)
|
|
printf("nope... peek: %d %d : %d\n", turn, result, peakScore);
|
|
continue;
|
|
}
|
|
|
|
#ifdef AI_DEBUG
|
|
|
|
for (int ts = 1; ts < curDepth; ts++) printf("\t");
|
|
printf("Peak : %d\n", peakScore);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifdef AI_DEBUG
|
|
for (int ts = 1; ts < curDepth; ts++) printf("\t");
|
|
printf("Abs.Local Peak : %d\n", peakScore);
|
|
#endif
|
|
|
|
if (curDepth == 1)
|
|
{
|
|
if (field.fieldCells[peakX][peakY] != 0)
|
|
{
|
|
// #ifdef AI_DEBUG
|
|
for (int ts = 1; ts < curDepth; ts++) printf("\t");
|
|
printf("%d %d -- LAST\n", peakX, peakY);
|
|
// #endif
|
|
peakX = lastX;
|
|
peakY = lastY;
|
|
}
|
|
|
|
#ifdef AI_DEBUG
|
|
for (int ts = 1; ts < curDepth; ts++) printf("\t");
|
|
printf("MOVE: %d %d\n", peakX, peakY);
|
|
#endif
|
|
if (retX != NULL && retY != NULL)
|
|
{
|
|
*retX = peakX;
|
|
*retY = peakY;
|
|
}
|
|
}
|
|
|
|
if (!NAIVE_MODE)
|
|
{
|
|
if (FCheckFieldDraw(&field) && FCheckFieldWin(&field) == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return peakScore;
|
|
}
|
|
|
|
int AIMakeMove(struct GAME* game)
|
|
{
|
|
if (game->locked)
|
|
{
|
|
int retX, retY;
|
|
miniMaxField(game->gameMap.FMap[game->lockedX][game->lockedY],
|
|
game->turn, AI_DEPTH, &retX, &retY);
|
|
GMakeMove(game, game->lockedX, game->lockedY, retX, retY, game->turn);
|
|
}
|
|
|
|
else
|
|
{
|
|
printf("TBD!\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
} |