checkers.cxx
来自「SRI international 发布的OAA框架软件」· CXX 代码 · 共 1,360 行 · 第 1/3 页
CXX
1,360 行
if (jnode) {
n->from = jnode->from;
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 ? BLACK : WHITE;
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 jumps
int nextjump;
char user; // 0 = black, 1 = white
char playing;
char autoplay;
void newgame(void) {
int n;
for (n=0; n<5; n++) b[n] = BLUE;
for (n=5; n<18; n++) b[n] = WHITE;
for (n=18; n<27; n++) b[n] = EMPTY;
for (n=27; n<40; n++) b[n] = BLACK;
for (n=40; n<45; n++) b[n] = BLUE;
b[13] = b[22] = b[31] = BLUE;
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] &= (WHITE|BLACK);
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 VT100
void positioncursor(int i) {
printf("\033[%d;%dH",
usermoves(i,2)-'0'+1,
2*(usermoves(i,1)-'A')+1);
}
void outpiecename(piece n) {
printf(n&BLACK ? "\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);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?