#include #include #include #include #include /*#define DEBUG*/ /*#define DEBUGALG*/ #define INFO typedef unsigned long ulong; int debug(char* fmt, ...) /* print out DEBUG information if DEBUG defined */ { #ifdef DEBUG va_list ap; int err; va_start(ap,fmt); err = vprintf(fmt,ap); va_end(ap); return err; #endif #ifndef DEBUG return 0; #endif } int info(char* fmt, ...) /* print out INFO information if INFO defined */ { #ifdef INFO va_list ap; int err; va_start(ap,fmt); err = vprintf(fmt,ap); va_end(ap); return err; #endif #ifndef INFO return 0; #endif } int Debug(char* fmt, ...) /* print out DEBUG information if DEBUG defined */ { #ifdef DEBUGALG va_list ap; int err; va_start(ap,fmt); err = vprintf(fmt,ap); va_end(ap); return err; #endif #ifndef DEBUGALG return 0; #endif } int Randomize() /* init random engine */ { time_t tm; time(&tm); srand((unsigned int)tm); return 1; } int Random(int lb) /* randomize number from 0 to lb-1 */ { return rand() % lb; } static int selected = 0; /* AKTUALNIE ZAZNACZONE POLE */ static int board[0x100]; /* board 0-empty, 1-human, 2-CPU */ static int done = 0; /*quit when done*/ static int end_cond = 0; /* CPU win or lost currently */ static int cpu_wins=0; static int hum_wins=0; static int halt=0; void stats() { printf("\n***********************\n"); printf("\n\nHUMAN/CPU: %d/%d\n\n",hum_wins,cpu_wins); printf("\n***********************\n"); if ((hum_wins-cpu_wins)>5) { printf("GRATULACJE WYGRALES(AS)\n\n\n"); exit(0); } if ((hum_wins-cpu_wins)<-5) { printf("CPU WYGRAL 6 RAZY WIECEJ NIZ TY\n\n\n"); exit(0); } printf("Nacisnij 'N' aby zagrac jeszcze raz!\n"); } void init() { int i; info("Clearing board\n"); for (i=0;i<0x100;i++) board[i] = 0; } void move_x(int arg) /* move selected +/- X */ { int tst; int tst2; debug("move_x:%d\n", arg); tst = (selected%4); /* x is last bits 0..3 */ if (arg>0) { selected++; tst2 = (selected%4); if (tst2tst) selected +=4; } } void move_y(int arg) /* move selected +/- Y */ { int tst; int tst2; debug("move_y:%d\n", arg); tst = ((selected/4)%4); /* y is 4*sel: 0,4,8,12 */ if (arg>0) { selected+=4; tst2 = ((selected/4)%4); if (tst2tst) selected +=0x10; } } void move_z(int arg) /* move selected +/- Z */ { int tst; int tst2; debug("move_z:%d\n", arg); tst = ((selected/0x10)%4); /* z is 4*sel: 0,16,32,48 */ if (arg>0) { selected+=0x10; tst2 = ((selected/0x10)%4); if (tst2tst) selected +=0x40; } } void move_v(int arg) /* move selected +/- V */ { int tst; debug("move_v:%d\n", arg); tst = selected/0x40; /* v is 64*sel: 0,64,128,192 */ if (arg>0) { selected+=0x40; if (selected>=0x100) selected-=0x100; } else { selected-=0x40; if (selected<0) selected+=0x100; } } void set_at(int x, int y, int z, int v, int value) { board[x+(y<<2)+(z<<4)+(v<<6)] = value; } int get_at(int x, int y, int z, int v) { return board[x+(y<<2)+(z<<4)+(v<<6)]; } /* The brain of the game */ void heuristic_count_moves_to_win(int player, int* rmin, int* rways) { int xc,yc,zc,vc,i; int vec[4]; int cmin; int min; int ways; debug("MOVES_TO_WIN FOR PLAYER: %d\n", player); min = 5; ways = 0; /* 1D lines through all posible directions (there are 4: X,Y,Z,V) fixing one param x,y,z or v and change all 3 remianing from 0..3 this gives: loops: 64 (p1,p2,p3) -> (0,1,2,3) wariants: 4 (all principle axes: X,Y,Z,V) cases in loop: 1, (0,1,2,3) because the inverse is the same line finally #1D: 64 x 4 x 1 = 256 lines */ /* GO BY PARALLEL LINES */ /* BY V */ for (xc=0;xc<4;xc++) for (yc=0;yc<4;yc++) for (zc=0;zc<4;zc++) { for (vc=0;vc<4;vc++) vec[vc] = get_at(xc,yc,zc,vc); cmin=4; for (i=0;i<4;i++) { if (vec[i] && vec[i]!=player) { cmin=6; ways--; break; } if (vec[i]==player) cmin--; } ways ++; if (cmin (0,1,2,3) wariants: 6 (all principle planes: XY,XZ,XV,YZ,YV,ZV) cases in loop: 2, because face (square) has 2 unique dissections (0123)(0123) and (0123)(3210) dissections in square: (2^2dimensions) - combinations / 2 (2ends) = 4/2 = 2 finally #2D: 16 x 6 x 2 = 192 lines */ /* WGLAB ZV */ for (zc=0;zc<4;zc++) for (vc=0;vc<4;vc++) { vec[0] = get_at(0,3, zc, vc); vec[1] = get_at(1,2, zc, vc); vec[2] = get_at(2,1, zc, vc); vec[3] = get_at(3,0, zc, vc); cmin=4; for (i=0;i<4;i++) { if (vec[i] && vec[i]!=player) { cmin=6; ways--; break; } if (vec[i]==player) cmin--; } ways++; if (cmin (0,1,2,3) [each param can be from this set] wariants: 4 (fixing just x,y,z or v) - choosing one of 4 3D sub-spaces, each has 4 loops and 4 dissections within cases in loop: 4, because cube has 4 unique dissections 2^3 = 8 / 2 = 4 (because each dissection has 2 ends) example dissection (0123)(0123)(3210) is identical to (3210)(3210)(0123) so 2^3/2 = 4 finally #2D: 4 x 4 x 4 = 64 */ /* WOKOL X */ for (xc=0;xc<4;xc++) { vec[0] = get_at(xc,0,0,0); vec[1] = get_at(xc,1,1,1); vec[2] = get_at(xc,2,2,2); vec[3] = get_at(xc,3,3,3); cmin=4; for (i=0;i<4;i++) { if (vec[i] && vec[i]!=player) { cmin=6; ways--; break; } if (vec[i]==player) cmin--; } ways++; if (cmin> (%d,%d,%d,%d)\n",i,i%4,(i/4)%4,(i/16)%4, i/64); printf("MSI COMPUTED RESULT\n"); free(at); free(val); free(vam); free(hx1); free(hx2); free(hx3); free(hx4); /* VICTORY HERE! */ return 1; } for (i=0;imin) val[i] = 0; Debug("min=%d\n", min); for (i=0;icmov && val[i]) cmov = hx3[i]; Debug("cmov=%d\n", cmov); for (i=0;i=10) cpu_msi_move(1); while(!done) { draw_scene(); printf("command>> "); scanf("%s", str); zn = (unsigned char)str[0]; printf("\n"); if (zn>='A' && zn <= 'Z') zn += 0x20; if (zn=='q') done=1; if (zn=='k') move_z(1); if (zn=='i') move_z(-1); if (zn=='j') move_x(-1); if (zn=='l') move_x(1); if (zn=='m') move_y(-1); if (zn=='o') move_y(1); if (zn=='u') move_v(-1); if (zn=='n') move_v(1); if (zn=='h') help(); if (zn=='z') { draw_scene(); if (!board[selected]) { board[selected] = 1; cpu_msi_move(1); } draw_scene(); if (end_cond) { clear_board(); if (Random(20)>=11) cpu_msi_move(1); end_cond=0; } } if (zn=='x') { cpu_msi_move(0); cpu_msi_move(1); if (end_cond) { clear_board(); if (Random(20)>=11) cpu_msi_move(1); end_cond=0; } } } return 0; } /* CopyLeft Morgoth DBMA, +48693582014, morgothdbma@o2.pl, heroine@o2.pl */