📄 checkers.cxx
字号:
n->jump |= jnode->jump; n->king |= jnode->king; } piece jumpedpiece = b[jumploc]; b[jumploc] = EMPTY; jumphappened = 0; movepiece(f,j,n); if (forcejumps && jumphappened) killnode(n); else {evaluateboard(n,0); insert(n);} b[i] = oldpiece; b[j] = EMPTY; b[jumploc] = jumpedpiece; jumphappened = 1; } }}void expandnode(node *f) { if (f->son || f->value > 28000) return; // already done piece turn = f->who ? CBLACK : CWHITE; for (int i=5; i<40; i++) if (b[i]&turn) movepiece(f,i,0); if (f->son) { f->value = -f->son->value; if (f->brother) f->value -= depthpenalty; } else f->value = 30000;}void makemove(node *n) { b[n->to] = b[n->from]; if (n->king) b[n->to] |= KING; b[n->from] = EMPTY; if (n->jump) for(int i=0; i<32; i++) { if (n->jump & (1<<i)) b[10+i] = EMPTY; }}int didabort(void);int fullexpand(node *f, int level) { if (didabort() || nodes > maxnodes-(maxply*10) || evaluated > maxevaluate) return(0); expandnode(f); if (!f->son) return(1); piece oldboard[45]; memmove(oldboard,b,sizeof(b)); node* n = f->son; if (!n->jump && n->brother) {if (level<1) return(1); level--;} int i; node* sons[32]; for (i=0; (sons[i++] = n); n = n->brother); int ret = 1; for (i=0; ret && (n = sons[i++]);) { makemove(n); ret = fullexpand(n,level); memmove(b,oldboard,sizeof(b)); extract(n); insert(n); } f->value = -f->son->value; return(ret);}int descend(node *f) { static int depth; if (didabort() || nodes > maxnodes || depth >= maxply) return(0); if (f->son) { node* n = f->son; makemove(n); depth++; int ret = descend(n); depth--; extract(n); insert(n); f->value = -f->son->value; return(ret); } else {expandnode(f); return(1);}}char debug;node *calcmove(node *root) { // return best move after root expandnode(root); if (!root->son) return(0); // no move due to loss if (debug) printf("calcmove() initial nodes = %d\n",nodes); evaluated = 0; if (root->son->brother) { int x; for (x = 1; abs(root->value)<28000 && fullexpand(root,x); x++); piece saveboard[45]; memmove(saveboard,b,sizeof(b)); while (abs(root->value)<28000) { x = descend(root); memmove(b,saveboard,sizeof(b)); if (!x) break; } } if (debug) printf(" evaluated %d, nodes = %d\n", evaluated, nodes); return(root->son);}// the actual game state ----------------node *root,*undoroot;piece jumpboards[24][45]; // saved boards for undoing jumpsint nextjump;char user; // 0 = black, 1 = whitechar playing;char autoplay;void newgame(void) { int n; for (n=0; n<5; n++) b[n] = CBLUE; for (n=5; n<18; n++) b[n] = CWHITE; for (n=18; n<27; n++) b[n] = EMPTY; for (n=27; n<40; n++) b[n] = CBLACK; for (n=40; n<45; n++) b[n] = CBLUE; b[13] = b[22] = b[31] = CBLUE; centralsquares[15] = centralsquares[16] = centralsquares[19] = centralsquares[20] = centralsquares[24] = centralsquares[25] = centralsquares[28] = centralsquares[29] = 1; // set up initial search tree: nextjump = 0; killnode(undoroot); undoroot = root = newnode(); // make it white's move, so first move is black: root->who = 1; user = 0; playing = 1;}void domove(node* move) { if (move->jump) memmove(jumpboards[nextjump++],b,sizeof(b)); makemove(move); extract(move); killnode(root->son); root->son = move; root = move; if (debug) evaluateboard(move,1);}node* undomove() { node *n = root; if (n == undoroot) return 0; // no more undo possible if (n->jump) memmove(b,jumpboards[--nextjump],sizeof(b)); else { b[n->from] = b[n->to]; if (n->king) b[n->from] &= (CWHITE|CBLACK); b[n->to] = EMPTY; } root = n->father; killnode(n); root->son = 0; root->value = 0; // prevent it from thinking game is over playing = 1; if (root == undoroot) user = 0; return n;}const char _usermoves[] ="B1D1F1H1A2C2E2G2??B3D3F3H3A4C4E4G4??B5D5F5H5A6C6E6G6??B7D7F7H7A8C8E8G8??";#define usermoves(x,y) _usermoves[2*((x)-5)+(y)-1]void dumpnode(node *n, int help) { int x = n->from; int y = n->to; if (help) printf("%c%c %c%c\t- ", usermoves(x,1),usermoves(x,2), usermoves(y,1),usermoves(y,2)); printf("%s %ss from %c%c to %c%c", n->who ? "White" : "Black", n->jump ? "jump" : "move", usermoves(x,1),usermoves(x,2), usermoves(y,1),usermoves(y,2)); if (n->jump) { for (int i=0; i<32; i++) if (n->jump & (1<<i)) printf(", %c%c",usermoves(10+i,1),usermoves(10+i,2)); printf(" removed"); } printf(" (%+d).\n",n->value);}int abortflag;////////////////////////////////////////////////////////////////// VT100 Interface:#ifdef VT100void positioncursor(int i) { printf("\033[%d;%dH", usermoves(i,2)-'0'+1, 2*(usermoves(i,1)-'A')+1);}void outpiecename(piece n) { printf(n&CBLACK ? "\033[1;7m" : "\033[1m"); putchar(" BW??BW??"[n]); putchar(" BW??KK??"[n]); printf("\033[0m");}void VT100board(void) { printf("\033<\033[H\033[J\033[10r"); int l = 0; puts(" A B C D E F G H"); for (int i=0; i<4; i++) { int j = 9*i+5; int k; for (k=0; k<4; k++) { printf("\033[7m \033[0m"); outpiecename(b[j+k]); } l++; printf("%d\n",l); j += 4; for (k=0; k<4; k++) { outpiecename(b[j+k]); printf("\033[7m \033[0m"); } l++; printf("%d\n",l); }}void VT100move(node *n, int) { if (!n) return; printf("\0337"); positioncursor(n->from); outpiecename(b[n->from]); positioncursor(n->to); outpiecename(b[n->to]); if (n->jump) for(int i=0; i<32; i++) { if (n->jump & (1<<i)) { positioncursor(10+i); outpiecename(b[10+i]); } } printf("\0338");}int decode(char *m) { int i; for(i=5; i<=40; i++) if (toupper(m[0])==usermoves(i,1) && m[1]==usermoves(i,2)) return(i); return(0);}#include <signal.h>static void sigint(...) { abortflag = 1; signal(SIGINT,sigint);}void fixexit(int x) { printf("\0337\033[r\0338"); exit(x);}// Returns a son, or 0 if no move specified, or root to cause "help"node *getusermove(void) { int i,j; node *t; char line[100],*m1,*m2; if (playing) printf("\033[1m%s's move?\033[0m ",root->who ? "Black" : "White"); else printf("\033[1mCommand?\033[0m "); abortflag = 0; if (!gets(line)) { putchar('\n'); if (feof(stdin)) fixexit(0); return 0; } for (m1 = line; *m1 && *m1<=' '; m1++); if (!*m1) return(0); m2 = m1+1; if (*m2) m2++; for (; *m2 && *m2<'0'; m2++); if (playing && m1[1]>='0' && m1[1]<='9') { i = decode(m1); j = decode(m2); if (i && j) for (t = root->son; t; t = t->brother) if (t->from == i && t->to == j) return(t); puts("Valid moves are:"); m1[0] = 'L'; } switch(toupper(m1[0])) { case 0: return(0); case 'A': if (playing) autoplay = 1; return(root); case 'C': puts(copyright); break; case 'D': debug = !debug; printf("Debug is now %s.", debug ? "on" : "off"); break; case 'F': forcejumps = !forcejumps; printf("Forced jumps rule is now %s.",forcejumps ? "on" : "off"); killnode(root->son); root->son = 0; return(0); case 'L': expandnode(root); if (playing) for (t = root->son; t; t = t->brother) dumpnode(t,1); break; case 'M': return(playing ? root : 0); case 'N': newgame(); VT100board(); return(0); case 'P': printf("I expect the following moves:\n"); for (t = root->son; t; t = t->son) dumpnode(t,0); break; case 'Q': fixexit(0); case 'R': VT100board(); break; case 'S': user = !user; return(root); case 'U': VT100move(undomove(),1); VT100move(undomove(),1); return(0); case '+': maxevaluate = maxnodes = 2*maxevaluate; goto J2; case '-': if (maxevaluate > 1) maxevaluate = maxnodes = maxevaluate/2; J2: printf("Moves evaluated set to %d.",maxevaluate); break; default: puts( "A(utoplay)\n" "C(opyright)\n" "D(ebug on/off)\n" "F(orce jumps rule on/off)\n" "L(ist legal moves)\n" "M(ake a move for me)\n" "N(ew game)\n" "P(redict next few moves)\n" "Q(uit)\n" "R(edraw screen)\n" "S(witch sides)\n" "U(ndo)\n" "+ - smarter\n" "- - stupider"); expandnode(root); for (t = root->son; t; t = t->brother) dumpnode(t,1); } return(0);}int VT100main() { signal(SIGINT,sigint); VT100board(); for (;;) { if (playing) { expandnode(root); if (!root->son) { printf("%s has no move. Game over.",root->who ? "Black" : "White"); playing = autoplay = 0; } } node* move; if (playing && (autoplay || root->who == user)) { move = calcmove(root); if (move->value <= -30000) { printf("%s resigns.", move->who ? "White" : "Black"); move = 0; playing = autoplay = 0; } } else { move = getusermove(); if (move == root) move = calcmove(root); } if (move) { dumpnode(move,0); domove(move); VT100move(move,0); } }}#endif////////////////////////////////////////////////////////////////// fltk interface:#ifdef FLTK#include <FL/Fl.H>#include <FL/Fl_Double_Window.H>#include <FL/Fl_Bitmap.H>#include <FL/fl_draw.H>#include <FL/Fl_Menu_Item.H>#include <FL/fl_ask.H>//----------------------------------------------------------------// old 4-level NeXT images have been seperated into bitmaps so they// can be drawn with arbitrary colors and real transparency. This is// rather tedious and perhaps fltk should provide a direct support// to do this:#include "black_1.xbm"#include "black_2.xbm"#include "black_3.xbm"#include "black_4.xbm"#include "white_1.xbm"#include "white_2.xbm"#include "white_3.xbm"#include "white_4.xbm"#include "blackking_1.xbm"#include "blackking_2.xbm"#include "blackking_3.xbm"#include "blackking_4.xbm"#include "whiteking_1.xbm"#include "whiteking_2.xbm"#include "whiteking_3.xbm"#include "whiteking_4.xbm"Fl_Bitmap *bm[4][4];void make_bitmaps() { if (bm[0][0]) return; bm[0][0] = new Fl_Bitmap(black_1_bits, black_1_width, black_1_height); bm[0][1] = new Fl_Bitmap(black_2_bits, black_1_width, black_1_height); bm[0][2] = new Fl_Bitmap(black_3_bits, black_1_width, black_1_height); bm[0][3] = new Fl_Bitmap(black_4_bits, black_1_width, black_1_height); bm[1][0] = new Fl_Bitmap(white_1_bits, black_1_width, black_1_height); bm[1][1] = new Fl_Bitmap(white_2_bits, black_1_width, black_1_height); bm[1][2] = new Fl_Bitmap(white_3_bits, black_1_width, black_1_height); bm[1][3] = new Fl_Bitmap(white_4_bits, black_1_width, black_1_height); bm[2][0] = new Fl_Bitmap(blackking_1_bits, black_1_width, black_1_height); bm[2][1] = new Fl_Bitmap(blackking_2_bits, black_1_width, black_1_height); bm[2][2] = new Fl_Bitmap(blackking_3_bits, black_1_width, black_1_height); bm[2][3] = new Fl_Bitmap(blackking_4_bits, black_1_width, black_1_height); bm[3][0] = new Fl_Bitmap(whiteking_1_bits, black_1_width, black_1_height); bm[3][1] = new Fl_Bitmap(whiteking_2_bits, black_1_width, black_1_height); bm[3][2] = new Fl_Bitmap(whiteking_3_bits, black_1_width, black_1_height); bm[3][3] = new Fl_Bitmap(whiteking_4_bits, black_1_width, black_1_height);}#define ISIZE black_1_widthvoid draw_piece(int which, int x, int y) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -