#include #include #include #include "oware.h" int value3(int v) { if (v < 24) return v; if (v > 24) return 100; return 50; } /** * Weighting function of the Minimax algorithm * @param thisside * @param otherside * @return */ int value(int thisside[], int otherside[]) { return value3(thisside[houses]) - value3(otherside[houses]); } /* * Implements heuristic H2 ordering for the houses with the minimum amount of * pieces in a house. * * This heuristic is taken from: * Prof. Pier Luca Lanzi. Design of Artificial Intelligence for Mancala Games. 2015-2016 * * H2: Keep as many counters on the players own side. This heuristic is * a generalized version of H1 and is based on the same principles. */ int *sortHouses(int thisside[]) { static int sortedHouses[houses]; int a[houses]; for (int i = 0; i < houses; i++) { sortedHouses[i] = i; a[i] = thisside[i]; } for (int j = 0; j < houses; j++) { int min = 1000; int minIndex = 0; for (int i = 1; i < houses; i++) { if (a[i] < min) { min = a[i]; minIndex = i; } } a[minIndex] = 1000; sortedHouses[j] = minIndex; } return sortedHouses; } /* best move when looking ahead from the position thisside/otherside for depth levels, and finally using value(); the return value is the best move (range 0-5), the value is passed back through vp; this function implements the negamax() algorithm */ int bestmove(int depth, int thisside[], int otherside[], int *vp, int alpha, int beta) { int best = -1; *vp = alpha; int* sortedHouses = sortHouses(thisside); for (int i = 0; i < houses; i++) { int ts1[houses + 1], os1[houses + 1]; memcpy(ts1, thisside, sizeof(int) * (houses + 1)); memcpy(os1, otherside, sizeof(int) * (houses + 1)); if (plyfull(sortedHouses[i], ts1, os1)) { int v = value(ts1, os1); if (depth > 0 && -50 <= v && v <= 50) { (void) bestmove(depth - 1, os1, ts1, &v, -beta, -*vp); v = -v; } #if 0 printf("%*c%d %d%c\n",20-depth,' ',i+1,v,(v>*vp)?'*':' '); #endif if (*vp >= beta) { return best; } if (v > *vp) { *vp = v; best = sortedHouses[i]; } } } return best; } int main(int argc, char *argv[]) { int side1[houses + 1]; int side2[houses + 1]; int depth; int best, value; if (argc != 2 * houses + 4) { fprintf(stderr, "%s ... ... \n", argv[0]); exit(1); } depth = atoi(argv[1]); if (depth < 0) { fprintf(stderr, "depth must be positive\n"); exit(1); } if (cmdline2pos(argc - 2, argv + 2, side1, side2) == 0) { fprintf(stderr, "this should not happen\n"); exit(1); } printf("Position:\n"); printboard(side1, side2); printf("\n"); best = bestmove(depth, side1, side2, &value, -1000, 1000); printf("Best move (1-6): %d Value: %d\n", best + 1, value); return 0; }