/* alpha-beta.c - Discussion at http://www.cis.temple.edu/~ingargio/cis587/readings/alpha-beta.html */ #include #include enum kind {Min, Max}; /* A node can have any number of successors. We represent the tree using a binary tree. The link child goes to one of the successors, and from there the link sibling will take to all other successors. */ struct node { char * name; /* used only for convenience in displaying information */ enum kind knd; /* if the node is a Max node or a Min node */ int value; /* relevant only for leaves */ int alpha; int beta; struct node *child; struct node *sibling; }; /* preorder traversal of the tree */ void printNode(const struct node * const p) { const struct node * r; for (r = p; r != NULL; r = r->sibling) { printf ("name = %s\t kind = %d\t value = %d\t alpha = %d\t beta = %d\n", r->name, (int)(r->knd), r->value, r->alpha, r->beta); printNode(r->child); } } #define min(x,y) ((x)<(y))?x:y #define max(x,y) ((x)>(y))?x:y /* The Minimax algorithm with Alpha-Beta cutoff */ int minimaxAB (struct node * n, int a, int b) /* Here A is always less than B */ { if (n->child == NULL) return n->value; n->alpha = INT_MIN; n->beta = INT_MAX; if (n->knd == Min) { struct node *r; for (r = n->child; r != NULL; r = r->sibling) { int newb = min(b, n->beta); int val = minimaxAB(r, a, newb); printf("minimax at %s, with a = %d, b = %d is %d\n", r->name, a, newb, val); n->beta = min(n->beta, val); if (a >= n->beta) break; } return n->beta; } else { struct node *r; for (r = n->child; r != NULL; r = r->sibling) { int newa = max(a, n->alpha); int val = minimaxAB(r, newa, b); printf("minimax at %s, with a = %d, b = %d is %d\n", r->name, newa, b, val); n->alpha = max(n->alpha, val); if (n->alpha >= b) break; } return n->alpha; } } /* Just an example of a game */ struct node game[31] = { /* 0 */ {"A", Max, 0, INT_MIN, INT_MAX, (struct node *)(game+1), (struct node *)NULL}, /* 1 */ {"B", Min, 0, INT_MIN, INT_MAX, (struct node *)(game+3), (struct node *)(game+2)}, /* 2 */ {"Q", Min, 0, INT_MIN, INT_MAX, (struct node *)(game+5), (struct node *)NULL}, /* 3 */ {"C", Max, 0, INT_MIN, INT_MAX, (struct node *)(game+7), (struct node *)(game+4)}, /* 4 */ {"J", Max, 0, INT_MIN, INT_MAX, (struct node *)(game+9), (struct node *)NULL}, /* 5 */ {"R", Max, 0, INT_MIN, INT_MAX, (struct node *)(game+11), (struct node *)(game+6)}, /* 6 */ {"Y", Max, 0, INT_MIN, INT_MAX, (struct node *)(game+13), (struct node *)NULL}, /* 7 */ {"D", Min, 0, INT_MIN, INT_MAX, (struct node *)(game+15), (struct node *)(game+8)}, /* 8 */ {"G", Min, 0, INT_MIN, INT_MAX, (struct node *)(game+17), (struct node *)NULL}, /* 9 */ {"K", Min, 0, INT_MIN, INT_MAX, (struct node *)(game+19), (struct node *)(game+10)}, /*10 */ {"N", Min, 0, INT_MIN, INT_MAX, (struct node *)(game+21), (struct node *)NULL}, /*11 */ {"S", Min, 0, INT_MIN, INT_MAX, (struct node *)(game+23), (struct node *)(game+12)}, /*12 */ {"V", Min, 0, INT_MIN, INT_MAX, (struct node *)(game+25), (struct node *)NULL}, /*13 */ {"Z", Min, 0, INT_MIN, INT_MAX, (struct node *)(game+27), (struct node *)(game+14)}, /*14 */ {"Z3", Min, 0, INT_MIN, INT_MAX, (struct node *)(game+29), (struct node *)NULL}, /*15 */ {"E", Max, 10, INT_MIN, INT_MAX, (struct node *)NULL, (struct node *)(game+16)}, /*16 */ {"F", Max, 11, INT_MIN, INT_MAX, (struct node *)NULL, (struct node *)NULL}, /*17 */ {"H", Max, 9, INT_MIN, INT_MAX, (struct node *)NULL, (struct node *)(game+18)}, /*18 */ {"I", Max, 12, INT_MIN, INT_MAX, (struct node *)NULL, (struct node *)NULL}, /*19 */ {"L", Max, 14, INT_MIN, INT_MAX, (struct node *)NULL, (struct node *)(game+20)}, /*20 */ {"M", Max, 15, INT_MIN, INT_MAX, (struct node *)NULL, (struct node *)NULL}, /*21 */ {"O", Max, 13, INT_MIN, INT_MAX, (struct node *)NULL, (struct node *)(game+22)}, /*22 */ {"P", Max, 14, INT_MIN, INT_MAX, (struct node *)NULL, (struct node *)NULL}, /*23 */ {"T", Max, 15, INT_MIN, INT_MAX, (struct node *)NULL, (struct node *)(game+24)}, /*24 */ {"U", Max, 2, INT_MIN, INT_MAX, NULL, NULL}, /*25 */ {"W", Max, 4, INT_MIN, INT_MAX, NULL, game+26}, /*26 */ {"X", Max, 1, INT_MIN, INT_MAX, NULL, NULL}, /*27 */ {"Z1", Max, 3, INT_MIN, INT_MAX, NULL, game+28}, /*28 */ {"Z2", Max, 22, INT_MIN, INT_MAX, NULL, NULL}, /*29 */ {"Z4", Max, 24, INT_MIN, INT_MAX, NULL, game+30}, /*30 */ {"Z5", Max, 25, INT_MIN, INT_MAX, NULL, NULL} }; /* Game in Nillson, 1980 pg 124 */ struct node game1[99] = { {"0", Max, 0, INT_MIN, INT_MAX, game1+1, NULL}, {"1", Min, 0, INT_MIN, INT_MAX, game1+4, game1+2}, {"2", Min, 0, INT_MIN, INT_MAX, game1+6, game1+3}, {"3", Min, 0, INT_MIN, INT_MAX, game1+8, NULL}, {"4", Max, 0, INT_MIN, INT_MAX, game1+11, game1+5}, {"5", Max, 0, INT_MIN, INT_MAX, game1+12, NULL}, {"6", Max, 0, INT_MIN, INT_MAX, game1+14, game1+7}, {"7", Max, 0, INT_MIN, INT_MAX, game1+16, NULL}, {"8", Max, 0, INT_MIN, INT_MAX, game1+17, game1+9}, {"9", Max, 0, INT_MIN, INT_MAX, game1+19, game1+10}, {"10", Max, 0, INT_MIN, INT_MAX, game1+21, NULL}, {"11", Min, 0, INT_MIN, INT_MAX, game1+22, NULL}, {"12", Min, 0, INT_MIN, INT_MAX, game1+24, game1+13}, {"13", Min, 0, INT_MIN, INT_MAX, game1+25, NULL}, {"14", Min, 0, INT_MIN, INT_MAX, game1+26, game1+15}, {"15", Min, 0, INT_MIN, INT_MAX, game1+27, NULL}, {"16", Min, 0, INT_MIN, INT_MAX, game1+29, NULL}, {"17", Min, 0, INT_MIN, INT_MAX, game1+30, game1+18}, {"18", Min, 0, INT_MIN, INT_MAX, game1+31, NULL}, {"19", Min, 0, INT_MIN, INT_MAX, game1+32, game1+20}, {"20", Min, 0, INT_MIN, INT_MAX, game1+33, NULL}, {"21", Min, 0, INT_MIN, INT_MAX, game1+34, NULL}, {"22", Max, 0, INT_MIN, INT_MAX, game1+36, game1+23}, {"23", Max, 0, INT_MIN, INT_MAX, game1+38, NULL}, {"24", Max, 0, INT_MIN, INT_MAX, game1+41, NULL}, {"25", Max, 0, INT_MIN, INT_MAX, game1+43, NULL}, {"26", Max, 0, INT_MIN, INT_MAX, game1+44, NULL}, {"27", Max, 0, INT_MIN, INT_MAX, game1+46, game1+28}, {"28", Max, 0, INT_MIN, INT_MAX, game1+47, NULL}, {"29", Max, 0, INT_MIN, INT_MAX, game1+48, NULL}, {"30", Max, 0, INT_MIN, INT_MAX, game1+49, NULL}, {"31", Max, 0, INT_MIN, INT_MAX, game1+51, NULL}, {"32", Max, 0, INT_MIN, INT_MAX, game1+53, NULL}, {"33", Max, 0, INT_MIN, INT_MAX, game1+54, NULL}, {"34", Max, 0, INT_MIN, INT_MAX, game1+55, game1+35}, {"35", Max, 0, INT_MIN, INT_MAX, game1+56, NULL}, {"36", Min, 0, INT_MIN, INT_MAX, game1+58, game1+37}, {"37", Min, 0, INT_MIN, INT_MAX, game1+60, NULL}, {"38", Min, 0, INT_MIN, INT_MAX, game1+62, game1+39}, {"39", Min, 0, INT_MIN, INT_MAX, game1+63, game1+40}, {"40", Min, 0, INT_MIN, INT_MAX, game1+66, NULL}, {"41", Min, 0, INT_MIN, INT_MAX, game1+68, game1+42}, {"42", Min, 0, INT_MIN, INT_MAX, game1+70, NULL}, {"43", Min, 0, INT_MIN, INT_MAX, game1+72, NULL}, {"44", Min, 0, INT_MIN, INT_MAX, game1+74, game1+45}, {"45", Min, 0, INT_MIN, INT_MAX, game1+76, NULL}, {"46", Min, 0, INT_MIN, INT_MAX, game1+78, NULL}, {"47", Min, 0, INT_MIN, INT_MAX, game1+80, NULL}, {"48", Min, 0, INT_MIN, INT_MAX, game1+82, NULL}, {"49", Min, 0, INT_MIN, INT_MAX, game1+83, game1+50}, {"50", Min, 0, INT_MIN, INT_MAX, game1+84, NULL}, {"51", Min, 0, INT_MIN, INT_MAX, game1+86, game1+52}, {"52", Min, 0, INT_MIN, INT_MAX, game1+88, NULL}, {"53", Min, 0, INT_MIN, INT_MAX, game1+90, NULL}, {"54", Min, 0, INT_MIN, INT_MAX, game1+92, NULL}, {"55", Min, 0, INT_MIN, INT_MAX, game1+94, NULL}, {"56", Min, 0, INT_MIN, INT_MAX, game1+96, game1+57}, {"57", Min, 0, INT_MIN, INT_MAX, game1+98, NULL}, {"58", Max, 0, INT_MIN, INT_MAX, NULL, game1+59}, {"59", Max, 5, INT_MIN, INT_MAX, NULL, NULL}, {"60", Max, -3, INT_MIN, INT_MAX, NULL, game1+61}, {"61", Max, 3, INT_MIN, INT_MAX, NULL, NULL}, {"62", Max, 3, INT_MIN, INT_MAX, NULL, NULL}, {"63", Max, -3, INT_MIN, INT_MAX, NULL, game1+64}, {"64", Max, 0, INT_MIN, INT_MAX, NULL, game1+65}, {"65", Max, 2, INT_MIN, INT_MAX, NULL, NULL}, {"66", Max, -2, INT_MIN, INT_MAX, NULL, game1+67}, {"67", Max, 3, INT_MIN, INT_MAX, NULL, NULL}, {"68", Max, 5, INT_MIN, INT_MAX, NULL, game1+69}, {"69", Max, 2, INT_MIN, INT_MAX, NULL, NULL}, {"70", Max, 5, INT_MIN, INT_MAX, NULL, game1+71}, {"71", Max, -5, INT_MIN, INT_MAX, NULL, NULL}, {"72", Max, 0, INT_MIN, INT_MAX, NULL, game1+73}, {"73", Max, 1, INT_MIN, INT_MAX, NULL, NULL}, {"74", Max, 5, INT_MIN, INT_MAX, NULL, game1+75}, {"75", Max, 1, INT_MIN, INT_MAX, NULL, NULL}, {"76", Max, -3, INT_MIN, INT_MAX, NULL, game1+77}, {"77", Max, 0, INT_MIN, INT_MAX, NULL, NULL}, {"78", Max, -5, INT_MIN, INT_MAX, NULL, game1+79}, {"79", Max, 5, INT_MIN, INT_MAX, NULL, NULL}, {"80", Max, -3, INT_MIN, INT_MAX, NULL, game1+81}, {"81", Max, 3, INT_MIN, INT_MAX, NULL, NULL}, {"82", Max, 2, INT_MIN, INT_MAX, NULL, NULL}, {"83", Max, 3, INT_MIN, INT_MAX, NULL, NULL}, {"84", Max, -3, INT_MIN, INT_MAX, NULL, game1+85}, {"85", Max, 0, INT_MIN, INT_MAX, NULL, NULL}, {"86", Max, -1, INT_MIN, INT_MAX, NULL, game1+87}, {"87", Max, -2, INT_MIN, INT_MAX, NULL, NULL}, {"88", Max, 0, INT_MIN, INT_MAX, NULL, game1+89}, {"89", Max, 1, INT_MIN, INT_MAX, NULL, NULL}, {"90", Max, 4, INT_MIN, INT_MAX, NULL, game1+91}, {"91", Max, 5, INT_MIN, INT_MAX, NULL, NULL}, {"92", Max, 1, INT_MIN, INT_MAX, NULL, game1+93}, {"93", Max, -1, INT_MIN, INT_MAX, NULL, NULL}, {"94", Max, -1, INT_MIN, INT_MAX, NULL, game1+95}, {"95", Max, 3, INT_MIN, INT_MAX, NULL, NULL}, {"96", Max, -3, INT_MIN, INT_MAX, NULL, game1+97}, {"97", Max, 2, INT_MIN, INT_MAX, NULL, NULL}, {"98", Max, -2, INT_MIN, INT_MAX, NULL, NULL} }; int main() { int val; /* Example from http://www.cis.temple.edu/~ingargio/cis587/readings/alpha-beta-example.html printNode(game); val = minimaxAB(game, INT_MIN, INT_MAX); printf("\nValue is: %d\n", val); */ /* Example from Nillson: Principles of AI, 1980, page 124 */ printNode(game1); val = minimaxAB(game1, INT_MIN, INT_MAX); printf("\nValue is: %d\n", val); return 0; }