checkers.cxx
来自「SRI international 发布的OAA框架软件」· CXX 代码 · 共 1,360 行 · 第 1/3 页
CXX
1,360 行
}
#define ISIZE black_1_width
void draw_piece(int which, int x, int y) {
if (!fl_not_clipped(x,y,ISIZE,ISIZE)) return;
switch (which) {
case BLACK: which = 0; break;
case WHITE: which = 1; break;
case BLACKKING: which = 2; break;
case WHITEKING: which = 3; break;
default: return;
}
fl_color(FL_BLACK); bm[which][0]->draw(x, y);
fl_color(FL_INACTIVE_COLOR); bm[which][1]->draw(x, y);
fl_color(FL_SELECTION_COLOR); bm[which][2]->draw(x, y);
fl_color(FL_WHITE); bm[which][3]->draw(x, y);
}
//----------------------------------------------------------------
class Board : public Fl_Double_Window {
void draw();
int handle(int);
public:
void drag_piece(int, int, int);
void drop_piece(int);
void animate(node* move, int backwards);
void computer_move(int);
Board(int w, int h) : Fl_Double_Window(w,h) {color(15);}
};
#define BOXSIZE 52
#define BORDER 4
#define BOARDSIZE (8*BOXSIZE+BORDER)
#define BMOFFSET 5
static int erase_this; // real location of dragging piece, don't draw it
static int dragging; // piece being dragged
static int dragx; // where it is
static int dragy;
static int showlegal; // show legal moves
int squarex(int i) {return (usermoves(i,1)-'A')*BOXSIZE+BMOFFSET;}
int squarey(int i) {return (usermoves(i,2)-'1')*BOXSIZE+BMOFFSET;}
void Board::draw() {
make_bitmaps();
fl_draw_box(box(),0,0,w(),h(),color());
fl_color((Fl_Color)10 /*107*/);
int x; for (x=0; x<8; x++) for (int y=0; y<8; y++) {
if (!((x^y)&1)) fl_rectf(BORDER+x*BOXSIZE, BORDER+y*BOXSIZE,
BOXSIZE-BORDER, BOXSIZE-BORDER);
}
fl_color(FL_DARK3 /*FL_GRAY_RAMP+4*/);
for (x=0; x<9; x++) {
fl_rectf(x*BOXSIZE,0,BORDER,h());
fl_rectf(0,x*BOXSIZE,w(),BORDER);
}
for (int j = 5; j < 40; j++) if (j != erase_this) {
draw_piece(b[j], squarex(j), squarey(j));
}
if (showlegal) {
fl_color(FL_WHITE);
node* n;
for (n = root->son; n; n = showlegal==2 ? n->son : n->brother) {
int x1 = squarex(n->from)+BOXSIZE/2-5;
int y1 = squarey(n->from)+BOXSIZE/2-5;
int x2 = squarex(n->to)+BOXSIZE/2-5;
int y2 = squarey(n->to)+BOXSIZE/2-5;
fl_line(x1,y1,x2,y2);
fl_push_matrix();
fl_mult_matrix(x2-x1,y2-y1,y1-y2,x2-x1,x2,y2);
fl_begin_polygon();
fl_vertex(0,0);
fl_vertex(-.3, .1);
fl_vertex(-.3, -.1);
fl_end_polygon();
fl_pop_matrix();
}
int num = 1;
fl_color(FL_BLACK);
fl_font(FL_BOLD,10);
for (n = root->son; n; n = showlegal==2 ? n->son : n->brother) {
int x1 = squarex(n->from)+BOXSIZE/2-5;
int y1 = squarey(n->from)+BOXSIZE/2-5;
int x2 = squarex(n->to)+BOXSIZE/2-5;
int y2 = squarey(n->to)+BOXSIZE/2-5;
char buf[20]; sprintf(buf,"%d",num);
fl_draw(buf, x1+int((x2-x1)*.85)-3, y1+int((y2-y1)*.85)+5);
num++;
}
}
if (dragging) draw_piece(dragging, dragx, dragy);
}
// drag the piece on square i to dx dy, or undo drag if i is zero:
void Board::drag_piece(int j, int dx, int dy) {
dy = (dy&-2) | dx&1; // make halftone shadows line up
if (j != erase_this) drop_piece(erase_this); // should not happen
if (!erase_this) { // pick up old piece
dragx = squarex(j); dragy = squarey(j);
erase_this = j;
dragging = b[j];
}
if (dx != dragx || dy != dragy) {
damage(FL_DAMAGE_ALL, dragx, dragy, ISIZE, ISIZE);
damage(FL_DAMAGE_ALL, dx, dy, ISIZE, ISIZE);
}
dragx = dx;
dragy = dy;
}
// drop currently dragged piece on square i
void Board::drop_piece(int j) {
if (!erase_this) return; // should not happen!
erase_this = 0;
dragging = 0;
int x = squarex(j);
int y = squarey(j);
if (x != dragx || y != dragy) {
damage(4, dragx, dragy, ISIZE, ISIZE);
damage(4, x, y, ISIZE, ISIZE);
}
}
// show move (call this *before* the move, *after* undo):
void Board::animate(node* move, int backwards) {
if (showlegal) {showlegal = 0; redraw();}
if (!move) return;
int f = move->from;
int t = move->to;
if (backwards) {int x = f; f = t; t = x;}
int x1 = squarex(f);
int y1 = squarey(f);
int x2 = squarex(t);
int y2 = squarey(t);
const int STEPS=35;
for (int j=0; j<STEPS; j++) {
int x = x1+(x2-x1)*j/STEPS;
int y = y1+(y2-y1)*j/STEPS;
drag_piece(move->from,x,y);
Fl::flush();
}
drop_piece(t);
if (move->jump) redraw();
}
int busy; // causes pop-up abort menu
void Board::computer_move(int help) {
if (!playing) return;
cursor(FL_CURSOR_WAIT);
Fl::flush();
busy = 1; abortflag = 0;
node* move = calcmove(root);
busy = 0;
if (move) {
if (!help && move->value <= -30000) {
fl_message("%s resigns", move->who ? "White" : "Black");
playing = autoplay = 0;
cursor(FL_CURSOR_DEFAULT);
return;
}
animate(move,0);
domove(move);
}
expandnode(root);
if (!root->son) {
fl_message("%s has no move", root->who ? "Black" : "White");
playing = autoplay = 0;
}
if (!autoplay) cursor(FL_CURSOR_DEFAULT);
}
extern Fl_Menu_Item menu[];
extern Fl_Menu_Item busymenu[];
int Board::handle(int e) {
if (busy) {
const Fl_Menu_Item* m;
switch(e) {
case FL_PUSH:
m = busymenu->popup(Fl::event_x(), Fl::event_y(), 0, 0, 0);
if (m) m->do_callback(this, (void*)m);
return 1;
case FL_SHORTCUT:
m = busymenu->test_shortcut();
if (m) {m->do_callback(this, (void*)m); return 1;}
return 0;
default:
return 0;
}
}
node *t, *n;
static int deltax, deltay;
int dist;
const Fl_Menu_Item* m;
switch (e) {
case FL_PUSH:
if (Fl::event_button() > 1) {
m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, 0);
if (m) m->do_callback(this, (void*)m);
return 1;
}
if (playing) {
expandnode(root);
for (t = root->son; t; t = t->brother) {
int x = squarex(t->from);
int y = squarey(t->from);
if (Fl::event_inside(x,y,BOXSIZE,BOXSIZE)) {
deltax = Fl::event_x()-x;
deltay = Fl::event_y()-y;
drag_piece(t->from,x,y);
return 1;
}
}
}
return 0;
case FL_SHORTCUT:
m = menu->test_shortcut();
if (m) {m->do_callback(this, (void*)m); return 1;}
return 0;
case FL_DRAG:
drag_piece(erase_this, Fl::event_x()-deltax, Fl::event_y()-deltay);
return 1;
case FL_RELEASE:
// find the closest legal move he dropped it on:
dist = 50*50; n = 0;
for (t = root->son; t; t = t->brother) if (t->from==erase_this) {
int d1 = Fl::event_x()-deltax-squarex(t->to);
int d = d1*d1;
d1 = Fl::event_y()-deltay-squarey(t->to);
d += d1*d1;
if (d < dist) {dist = d; n = t;}
}
if (!n) {drop_piece(erase_this); return 1;} // none found
drop_piece(n->to);
domove(n);
if (showlegal) {showlegal = 0; redraw();}
if (n->jump) redraw();
computer_move(0);
return 1;
default:
return 0;
}
}
void quit_cb(Fl_Widget*, void*) {exit(0);}
int FLTKmain(int argc, char** argv) {
Fl::visual(FL_DOUBLE|FL_INDEX);
Board b(BOARDSIZE,BOARDSIZE);
b.callback(quit_cb);
b.show(argc,argv);
return Fl::run();
}
void autoplay_cb(Fl_Widget*bp, void*) {
if (autoplay) {autoplay = 0; return;}
if (!playing) return;
Board* b = (Board*)bp;
autoplay = 1;
while (autoplay) {b->computer_move(0); b->computer_move(0);}
}
#include <FL/Fl_Box.H>
Fl_Window *copyright_window;
void copyright_cb(Fl_Widget*, void*) {
if (!copyright_window) {
copyright_window = new Fl_Window(400,270,"Copyright");
copyright_window->color(FL_WHITE);
Fl_Box *b = new Fl_Box(20,0,380,270,copyright);
b->labelsize(10);
b->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
copyright_window->end();
}
copyright_window->hotspot(copyright_window);
copyright_window->set_non_modal();
copyright_window->show();
}
void debug_cb(Fl_Widget*, void*v) {
debug = !debug;
((Fl_Menu_Item*)v)->flags =
debug ? FL_MENU_TOGGLE|FL_MENU_VALUE : FL_MENU_TOGGLE;
}
void forced_cb(Fl_Widget*b, void*v) {
forcejumps = !forcejumps;
((Fl_Menu_Item*)v)->flags =
forcejumps ? FL_MENU_TOGGLE|FL_MENU_VALUE : FL_MENU_TOGGLE;
killnode(root->son); root->son = 0;
if (showlegal) {expandnode(root); b->redraw();}
}
void move_cb(Fl_Widget*pb, void*) {
Board* b = (Board*)pb;
if (playing) b->computer_move(1);
if (playing) b->computer_move(0);
}
void newgame_cb(Fl_Widget*b, void*) {
showlegal = 0;
newgame();
b->redraw();
}
void legal_cb(Fl_Widget*pb, void*) {
if (showlegal == 1) {showlegal = 0; ((Board*)pb)->redraw(); return;}
if (!playing) return;
expandnode(root);
showlegal = 1; ((Board*)pb)->redraw();
}
void predict_cb(Fl_Widget*pb, void*) {
if (showlegal == 2) {showlegal = 0; ((Board*)pb)->redraw(); return;}
if (playing) expandnode(root);
showlegal = 2; ((Board*)pb)->redraw();
}
void switch_cb(Fl_Widget*pb, void*) {
user = !user;
((Board*)pb)->computer_move(0);
}
void undo_cb(Fl_Widget*pb, void*) {
Board* b = (Board*)pb;
b->animate(undomove(),1);
b->animate(undomove(),1);
}
//--------------------------
#include <FL/Fl_Slider.H>
#include <FL/Fl_Value_Output.H>
Fl_Window *intel_window;
Fl_Value_Output *intel_output;
void intel_slider_cb(Fl_Widget*w, void*) {
double v = ((Fl_Slider*)w)->value();
int n = int(v*v);
intel_output->value(n);
maxevaluate = maxnodes = n;
}
void intel_cb(Fl_Widget*, void*) {
if (!intel_window) {
intel_window = new Fl_Window(200,25,"Checkers Intelligence");
Fl_Slider* s = new Fl_Slider(60,0,140,25);
s->type(FL_HOR_NICE_SLIDER);
s->minimum(1); s->maximum(500); s->value(50);
s->callback(intel_slider_cb);
intel_output = new Fl_Value_Output(0,0,60,25);
intel_output->value(maxevaluate);
intel_window->resizable(s);
}
intel_window->hotspot(intel_window);
intel_window->set_non_modal();
intel_window->show();
}
//---------------------------
void stop_cb(Fl_Widget*, void*) {abortflag = 1;}
void continue_cb(Fl_Widget*, void*) {}
Fl_Menu_Item menu[] = {
{"Autoplay", 'a', autoplay_cb},
{"Legal moves", 'l', legal_cb},
{"Move for me", 'm', move_cb},
{"New game", 'n', newgame_cb},
{"Predict", 'p', predict_cb},
{"Switch sides", 's', switch_cb},
{"Undo", 'u', undo_cb, 0, FL_MENU_DIVIDER},
{"Forced jumps rule", 'f', forced_cb, 0, FL_MENU_TOGGLE|FL_MENU_VALUE},
{"Debug", 'd', debug_cb, (void *)"d", FL_MENU_TOGGLE},
{"Intelligence...", 'i', intel_cb, 0, FL_MENU_DIVIDER},
{"Copyright", 'c', copyright_cb},
{"Quit", 'q', quit_cb},
{0}};
Fl_Menu_Item busymenu[] = {
{"Stop", '.', stop_cb},
{"Autoplay", 'a', autoplay_cb},
{"Continue", 0, continue_cb},
{"Debug", 'd', debug_cb, (void *)"d", FL_MENU_TOGGLE},
{"Intelligence...", 'i', intel_cb},
{"Copyright", 'c', copyright_cb},
{"Quit", 'q', quit_cb},
{0}};
#endif
////////////////////////////////////////////////////////////////
// parts shared by both interface:
#ifdef FLTK
#ifdef VT100
#define BOTH
#endif
#endif
#ifdef BOTH
int terminal;
int arg(int, char **argv, int &i) {
if (argv[i][1] == 't') {terminal = 1; i++; return 1;}
return 0;
}
#endif
int didabort(void) {
#ifdef FLTK
#ifdef BOTH
if (!terminal)
#endif
Fl::check();
#endif
if (abortflag) {
autoplay = 0;
abortflag = 0;
return 1;
}
return(0);
}
int main(int argc, char **argv) {
seed = time(0);
newgame();
#ifdef BOTH
int i = 1;
if (Fl::args(argc, argv, i, arg) < argc) {
fprintf(stderr," -t : use VT100 display\n", Fl::help);
exit(1);
}
if (!getenv("DISPLAY")) terminal = 1;
if (!terminal)
#endif
#ifdef FLTK
return FLTKmain(argc,argv);
#endif
#ifdef VT100
return VT100main();
#endif
}
//
// End of "$Id: checkers.cxx,v 1.1.1.1 2003/06/03 22:25:47 agno Exp $".
//
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?