1 /* a 3D chess display for KnightCap
2
3 Andrew.Tridgell@anu.edu.au January 1997 */
4
5 #include "includes.h"
6 #include "knightcap.h"
7
8 extern struct state *state;
9 int need_redraw=1;
10
11 #if RENDERED_DISPLAY
12 #include <GL/glut.h>
13 #include "trackball.h"
14
15 static int window_size = 500;
16
17 #define SLEEP_TIME 100000 /* microseconds */
18
19
20 static int do_scaling;
21 static int do_motion;
22 static int mouse_moved;
23 extern int demo_mode;
24 static int downx, downy;
25
26 /* the pieces don't sit quite on the board - there is a
27 small gap */
28 #define BOARDGAP 0.05
29
30 #define BOARD1(p) (state->position.board[p])
31 #define BOARD(x,y) BOARD1(POSN(x,y))
32
33 static float a_color[4] = {0.75, 0.75, 0.55};
34 static float b_color[4] = {0.4, 0.4, 0.6};
35
36 /* traditional white and black squares */
37 static float square_color_1[4] = {0.7, 0.7, 0.7};
38 /* static float square_color_2[4] = {0, 0, 0}; */
39
40 enum {MENU_RESET, MENU_QUIT, MENU_FLIP, MENU_RESET_VIEW, MENU_DEMO,
41 MENU_COMPUTER_WHITE, MENU_COMPUTER_BLACK, MENU_SAVE, MENU_RESTORE,
42 MENU_EVAL};
43
44
45 enum {EDIT_NONE, EDIT_RECREATE, EDIT_CLEAR, EDIT_WHITES_MOVE,
46 EDIT_BLACKS_MOVE,
47 EDIT_BPAWN, EDIT_BKNIGHT, EDIT_BBISHOP,
48 EDIT_BROOK, EDIT_BQUEEN, EDIT_BKING,
49 EDIT_WPAWN, EDIT_WKNIGHT, EDIT_WBISHOP,
50 EDIT_WROOK, EDIT_WQUEEN, EDIT_WKING};
51
52
53
54 #define NUM_SLICES 10
55 #define NUM_STACKS 8
56
57 static int menu_ics_robot, menu_always_think, menu_demo_mode;
58
redraw(void)59 void redraw(void)
60 {
61 need_redraw = 1;
62 }
63
set_cursor(int c)64 static void set_cursor(int c)
65 {
66 static int last_c;
67 if (last_c == c) return;
68 glutSetCursor(c);
69 last_c = c;
70 }
71
72 /* this is taken from the glut library */
drawBox(GLfloat x0,GLfloat x1,GLfloat y0,GLfloat y1,GLfloat z0,GLfloat z1)73 static void drawBox(GLfloat x0, GLfloat x1, GLfloat y0, GLfloat y1,
74 GLfloat z0, GLfloat z1)
75 {
76 static GLfloat n[6][3] =
77 {
78 {-1.0, 0.0, 0.0},
79 {0.0, 1.0, 0.0},
80 {1.0, 0.0, 0.0},
81 {0.0, -1.0, 0.0},
82 {0.0, 0.0, 1.0},
83 {0.0, 0.0, -1.0}
84 };
85 static GLint faces[6][4] =
86 {
87 {0, 1, 2, 3},
88 {3, 2, 6, 7},
89 {7, 6, 5, 4},
90 {4, 5, 1, 0},
91 {5, 6, 2, 1},
92 {7, 4, 0, 3}
93 };
94 GLfloat v[8][3];
95 GLint i;
96
97 v[0][0] = v[1][0] = v[2][0] = v[3][0] = x0;
98 v[4][0] = v[5][0] = v[6][0] = v[7][0] = x1;
99 v[0][1] = v[1][1] = v[4][1] = v[5][1] = y0;
100 v[2][1] = v[3][1] = v[6][1] = v[7][1] = y1;
101 v[0][2] = v[3][2] = v[4][2] = v[7][2] = z0;
102 v[1][2] = v[2][2] = v[5][2] = v[6][2] = z1;
103
104 for (i = 0; i < 6; i++) {
105 glBegin(GL_QUADS);
106 glNormal3fv(&n[i][0]);
107 glVertex3fv(&v[faces[i][0]][0]);
108 glVertex3fv(&v[faces[i][1]][0]);
109 glVertex3fv(&v[faces[i][2]][0]);
110 glVertex3fv(&v[faces[i][3]][0]);
111 glEnd();
112 }
113 }
114
draw_pawn(void)115 static void draw_pawn(void)
116 {
117 GLUquadricObj *q;
118 q = gluNewQuadric();
119 gluCylinder(q, 0.22, 0.1, 0.65, NUM_SLICES, NUM_STACKS);
120 glTranslatef(0,0,0.6);
121 glutSolidSphere(0.14,NUM_SLICES,NUM_STACKS);
122 }
123
draw_rook(void)124 static void draw_rook(void)
125 {
126 GLUquadricObj *q;
127
128 /* the base */
129 drawBox(-0.25, 0.25, -0.25, 0.25, 0, 0.1);
130 glTranslatef(0,0,0.1);
131
132 /* the torso */
133 q = gluNewQuadric();
134 gluCylinder(q, 0.22, 0.16, 0.5, NUM_SLICES, NUM_STACKS);
135 glTranslatef(0, 0, 0.5);
136
137 /* the top */
138 drawBox(-0.2, 0.2, -0.2, 0.2, 0, 0.1);
139 glTranslatef(0,0,0.1);
140
141 glTranslatef(-0.15, -0.15, 0.05);
142 glutSolidCube(0.1);
143 glTranslatef(0.3, 0, 0);
144 glutSolidCube(0.1);
145 glTranslatef(0, 0.3, 0);
146 glutSolidCube(0.1);
147 glTranslatef(-0.3, 0, 0);
148 glutSolidCube(0.1);
149 }
150
draw_bishop(void)151 static void draw_bishop(void)
152 {
153 GLUquadricObj *q;
154
155 glScalef(1.2, 1.2, 1);
156
157 /* the torso */
158 q = gluNewQuadric();
159 gluCylinder(q, 0.22, 0.12, 0.9, NUM_SLICES, NUM_STACKS);
160 glTranslatef(0, 0, 0.85);
161
162 /* the sash */
163 glPushMatrix();
164 glRotatef(-45, 1, 0, 0);
165 glScalef(1, 1.5, 1);
166 glutSolidTorus(0.05, 0.12, NUM_SLICES, NUM_STACKS);
167 glPopMatrix();
168
169 /* the shoulders? */
170 glTranslatef(0, 0, 0.2);
171 glScalef(1,1,1.5);
172 glutSolidSphere(0.1, NUM_SLICES, NUM_STACKS);
173 }
174
draw_queen(void)175 static void draw_queen(void)
176 {
177 GLUquadricObj *q;
178 glScalef(1,1,1.15);
179
180 /* the base */
181 glTranslatef(0, 0, 0.07);
182 glutSolidTorus(0.06, 0.23, NUM_SLICES, NUM_STACKS);
183
184 /* the torso */
185 q = gluNewQuadric();
186 gluCylinder(q, 0.25, 0.15, 1.0, NUM_SLICES, NUM_STACKS);
187 glTranslatef(0,0, 0.9);
188
189 /* the ruff */
190 glutSolidTorus(0.08, 0.16, NUM_SLICES, NUM_STACKS);
191 glTranslatef(0,0, 0.15);
192
193 /* the head */
194 glutSolidSphere(0.15, NUM_SLICES, NUM_STACKS);
195
196 /* the crown */
197 glTranslatef(0,0,0.08);
198 glutSolidTorus(0.03, 0.13, NUM_SLICES, NUM_SLICES);
199
200 /* and a knob on top */
201 glTranslatef(0,0, 0.07);
202 glutSolidSphere(0.07, NUM_SLICES/2, NUM_STACKS/2);
203 }
204
draw_king(void)205 static void draw_king(void)
206 {
207 GLUquadricObj *q;
208 q = gluNewQuadric();
209
210 /* the base */
211 drawBox(-0.27, 0.27, -0.27, 0.27, 0, 0.1);
212 glTranslatef(0,0,0.1);
213
214 /* torso and shoulders */
215 gluCylinder(q, 0.25, 0.15, 1.0, NUM_SLICES, NUM_STACKS);
216 glTranslatef(0,0,1);
217 glutSolidTorus(0.07, 0.14, NUM_SLICES, NUM_STACKS);
218
219 /* the cross */
220 drawBox(-0.075, 0.075, -0.075, 0.075, 0, 0.4);
221 glTranslatef(0,0,0.2);
222
223 drawBox(-0.2, 0.2, -0.075, 0.075, -0.07, 0.07);
224 }
225
226
draw_knight(void)227 static void draw_knight(void)
228 {
229 GLUquadricObj *q;
230 q = gluNewQuadric();
231
232
233 glRotatef(-90,0,0,1);
234
235 /* base */
236 glTranslatef(0,0,0.05);
237 glutSolidTorus(0.1,0.2,NUM_SLICES,NUM_STACKS);
238 glTranslatef(0,0,0.1);
239 glutSolidTorus(0.1,0.2,NUM_SLICES,NUM_STACKS);
240 glTranslatef(0,0,0.05);
241
242 /* torso */
243 glRotatef(10, 0, 1, 0);
244 gluCylinder(q, 0.2, 0.15, 0.7, NUM_SLICES, NUM_STACKS);
245 glTranslatef(0,0, 0.65);
246
247 /* head */
248 glutSolidSphere(0.16, NUM_SLICES, NUM_STACKS);
249
250 /* ears */
251 glPushMatrix();
252 glRotatef(10, 0, 1, 0);
253 glRotatef(25, 1, 0, 0);
254 glTranslatef(0.05,0,0.13);
255 gluCylinder(q, 0.08, 0.0, 0.15, NUM_SLICES/2, NUM_STACKS/2);
256 glPopMatrix();
257
258 glPushMatrix();
259 glRotatef(10, 0, 1, 0);
260 glRotatef(-25, 1, 0, 0);
261 glTranslatef(0.05,0,0.13);
262 gluCylinder(q, 0.08, 0, 0.15, NUM_SLICES/2, NUM_STACKS/2);
263 glPopMatrix();
264
265 /* nose */
266 glRotatef(-110, 0, 1, 0);
267 gluCylinder(q, 0.17, 0.1, 0.3, NUM_SLICES, NUM_STACKS);
268 glTranslatef(0,0, 0.3);
269 glutSolidSphere(0.1, NUM_SLICES, NUM_STACKS);
270 }
271
272
273 /* its cute to make the bishops and knights face the opponents king */
face_king(int p,int x,int y)274 static void face_king(int p, int x, int y)
275 {
276 Square kpos = PIECES(&state->position, -p)[IKING].pos;
277 double dx, dy, theta;
278
279 dx = XPOS(kpos) - x;
280 dy = YPOS(kpos) - y;
281
282 theta = 360*atan(dx/(dy+0.01))/(2*M_PI);
283
284 if (dy < 0) theta += 180;
285
286 glRotatef(-theta,0,0,1);
287 }
288
draw_piece(int p,int x,int y)289 static void draw_piece(int p, int x, int y)
290 {
291 glPushMatrix();
292 glTranslatef(0.5, 0.5, BOARDGAP);
293 if (p > 0) {
294 glColor3fv(a_color);
295 } else {
296 glColor3fv(b_color);
297 }
298
299 switch (abs(p)) {
300 case PAWN:
301 draw_pawn();
302 break;
303 case KNIGHT:
304 face_king(p, x, y);
305 draw_knight();
306 break;
307 case BISHOP:
308 face_king(p, x, y);
309 draw_bishop();
310 break;
311 case ROOK:
312 draw_rook();
313 break;
314 case QUEEN:
315 draw_queen();
316 break;
317 case KING:
318 draw_king();
319 break;
320 }
321
322 glPopMatrix();
323 }
324
325
draw_pieces(void)326 static void draw_pieces(void)
327 {
328 int i,j;
329 int p;
330
331 for (i=0;i<8;i++)
332 for (j=0;j<8;j++) {
333 if (!(p=BOARD(i,j))) continue;
334 glPushMatrix();
335 glTranslatef(i,j,0);
336 draw_piece(p, i, j);
337 glPopMatrix();
338 }
339 }
340
341 /* this draws the board itself - must be called with lighting
342 off (otherwise we'd need to give the squares some depth) */
draw_board(void)343 static void draw_board(void)
344 {
345 int i, j;
346
347 glPushAttrib(GL_ENABLE_BIT);
348 glDisable(GL_LIGHTING);
349 glDisable(GL_DITHER);
350 for (i=0;i<8;i++)
351 for (j=0;j<8;j++) {
352 if (!((i+j)&1)) continue;
353
354 glPushMatrix();
355 glTranslatef(i, j, 0);
356 glColor3fv(square_color_1);
357 glRectf(0,0,1,1);
358 glPopMatrix();
359 }
360 glEnable(GL_DITHER);
361 glPopAttrib();
362 }
363
setup_lighting(void)364 static void setup_lighting(void)
365 {
366 GLfloat light_position[] = {2, -1, 20.0, 0.0};
367
368 glLightfv(GL_LIGHT0, GL_POSITION, light_position);
369 glEnable(GL_LIGHTING);
370 glEnable(GL_LIGHT0);
371
372 glEnable(GL_COLOR_MATERIAL);
373 glShadeModel(GL_SMOOTH);
374 }
375
position_board(void)376 static void position_board(void)
377 {
378 GLfloat m[4][4];
379
380 glScalef(state->scale, state->scale, state->scale);
381
382 setup_lighting();
383
384 gluPerspective(26, 1, 10, 100);
385
386 glMatrixMode(GL_MODELVIEW);
387
388 glTranslatef(0, 0, -20);
389
390 build_rotmatrix(m, state->curquat);
391 glMultMatrixf(&m[0][0]);
392
393 if (state->flip_view) {
394 /* its easier to flip the view than to use the trackball */
395 glRotatef(180, 0, 0, 1);
396 }
397
398 glTranslatef(-4, -4, 0);
399 }
400
401 /* this starts us at a reasonable viewing angle */
reset_view(void)402 static void reset_view(void)
403 {
404 state->scale = 1;
405 state->curquat[0] = 0.28;
406 state->curquat[1] = 0;
407 state->curquat[2] = 0;
408 state->curquat[3] = 0.90;
409 }
410
411
draw_all(void)412 void draw_all(void)
413 {
414 need_redraw = 0;
415 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
416
417 glPushMatrix();
418 glMatrixMode(GL_PROJECTION);
419 glLoadIdentity();
420 position_board();
421 draw_pieces();
422 draw_board();
423 glPopMatrix();
424
425 glutSwapBuffers();
426 }
427
428
429 /* check if mouse click at (px,py) is in a square, returning the
430 square in (*rx,*ry) if it is */
in_square(int px,int py,Square * p)431 static int in_square(int px,int py, Square *p)
432 {
433 int x, y;
434 int ret;
435 GLint vp[4];
436 int squares_only=1;
437
438 glGetIntegerv(GL_VIEWPORT, vp);
439
440 glPushMatrix();
441
442 again:
443
444 for (x=0;x<8;x++)
445 for (y=0;y<8;y++) {
446 glFeedbackBuffer(0, GL_2D, NULL);
447 glRenderMode(GL_FEEDBACK);
448 glInitNames();
449 glPushName(~0);
450 glPushMatrix();
451 glMatrixMode(GL_PROJECTION);
452 glLoadIdentity();
453 gluPickMatrix(px, vp[3] - py, 1, 1, vp);
454 position_board();
455 glTranslatef(x, y, 0);
456 if (!squares_only && BOARD(x,y)) {
457 draw_piece(BOARD(x,y), x, y);
458 } else {
459 glRectf(0, 0, 1, 1);
460 }
461 glPopMatrix();
462
463 ret = glRenderMode(GL_RENDER);
464
465 if (ret != 0) {
466 (*p) = POSN(x,y);
467 glPopMatrix();
468 return 1;
469 }
470 }
471
472 if (!squares_only) {
473 squares_only = 1;
474 goto again;
475 }
476
477 glPopMatrix();
478
479 return 0;
480 }
481
482
mouse_func(int button,int bstate,int x,int y)483 static void mouse_func(int button, int bstate, int x, int y)
484 {
485 static Square from, to;
486 static int do_movement;
487
488 if (bstate == GLUT_DOWN && button == GLUT_MIDDLE_BUTTON) {
489 downx = x;
490 downy = y;
491 }
492
493 if (bstate == GLUT_DOWN && button == GLUT_LEFT_BUTTON) {
494 mouse_moved = 0;
495 downx = x;
496 downy = y;
497 if(glutGetModifiers() & GLUT_ACTIVE_SHIFT) {
498 do_scaling = 1;
499 } else if (in_square(x,y,&from) && BOARD1(from)) {
500 do_movement = 1;
501 } else {
502 do_motion = 1;
503 }
504 }
505
506 if (bstate == GLUT_UP && button == GLUT_LEFT_BUTTON) {
507 do_motion = 0;
508 do_scaling = 0;
509 if (do_movement && in_square(x,y,&to) && to != from &&
510 next_to_play(&state->position) != state->computer) {
511 Move move;
512 move.from = from;
513 move.to = to;
514 prog_tell_move(&state->position,&move);
515 player_moved(from, to);
516 }
517 do_movement = 0;
518 }
519 }
520
motion_func(int x,int y)521 static void motion_func(int x, int y)
522 {
523 float lastquat[4];
524 GLint vp[4];
525
526 if (x == downx && y == downy) return;
527
528 mouse_moved = 1;
529
530 if (!do_motion && !do_scaling) return;
531
532 glGetIntegerv(GL_VIEWPORT, vp);
533
534 if (do_motion) {
535 trackball(lastquat,
536 (2.0*downx - vp[2]) / vp[2],
537 (vp[3] - 2.0*downy) / vp[3],
538 (2.0*x - vp[2]) / vp[2],
539 (vp[3] - 2.0*y) / vp[3]
540 );
541
542 add_quats(lastquat, state->curquat, state->curquat);
543 }
544
545 if (do_scaling) {
546 state->scale *= (1.0 + (((float) (downy - y)) / vp[3]));
547 }
548
549 downx = x;
550 downy = y;
551 redraw();
552 }
553
554
edit_menu(int v)555 static void edit_menu(int v)
556 {
557 Square sq;
558
559 if (!in_square(downx, downy, &sq))
560 return;
561
562 switch (v) {
563 case EDIT_NONE:
564 lprintf(0,"remove at %d %d\n", downx, downy);
565 state->position.board[sq] = 0;
566 break;
567 case EDIT_RECREATE:
568 lprintf(0,"recreate\n");
569 create_pboard(&state->position);
570 break;
571
572 case EDIT_CLEAR:
573 memset(state->position.board, 0,
574 sizeof(state->position.board));
575 break;
576
577 case EDIT_WHITES_MOVE:
578 state->position.move_num &= ~1;
579 break;
580
581 case EDIT_BLACKS_MOVE:
582 state->position.move_num |= 1;
583 break;
584
585 case EDIT_BPAWN:
586 case EDIT_BKNIGHT:
587 case EDIT_BBISHOP:
588 case EDIT_BROOK:
589 case EDIT_BQUEEN:
590 case EDIT_BKING:
591 lprintf(0,"set black %d at %d %d\n",
592 v - EDIT_BPAWN, downx, downy);
593
594 state->position.board[sq] = -(PAWN + (v - EDIT_BPAWN));
595 break;
596
597 case EDIT_WPAWN:
598 case EDIT_WKNIGHT:
599 case EDIT_WBISHOP:
600 case EDIT_WROOK:
601 case EDIT_WQUEEN:
602 case EDIT_WKING:
603 lprintf(0,"set black %d at %d %d\n",
604 v - EDIT_WPAWN, downx, downy);
605
606 state->position.board[sq] = PAWN + (v - EDIT_WPAWN);
607 break;
608 }
609
610 redraw();
611 }
612
613
main_menu(int v)614 static void main_menu(int v)
615 {
616 switch (v) {
617 case MENU_EVAL:
618 eval_debug(&state->position);
619 break;
620
621 case MENU_SAVE:
622 save_game("knightcap.save");
623 break;
624
625 case MENU_RESTORE:
626 restore_game("knightcap.save");
627 break;
628
629 case MENU_DEMO:
630 demo_mode = !demo_mode;
631 if (!demo_mode)
632 state->stop_search = 1;
633 if (demo_mode) {
634 glutChangeToMenuEntry(menu_demo_mode,
635 "disable demo mode", MENU_DEMO);
636 } else {
637 glutChangeToMenuEntry(menu_demo_mode,
638 "demo mode", MENU_DEMO);
639 }
640 break;
641
642 case MENU_QUIT:
643 state->stop_search = 1;
644 state->quit = 1;
645 prog_exit();
646 exit(0);
647 break;
648
649 case MENU_RESET:
650 reset_board();
651 break;
652
653 case MENU_RESET_VIEW:
654 reset_view();
655 break;
656
657 case MENU_FLIP:
658 state->flip_view = !state->flip_view;
659 break;
660 }
661
662 redraw();
663 }
664
665
computer_menu(int v)666 static void computer_menu(int v)
667 {
668 if (v == 2) {
669 state->always_think = !state->always_think;
670 if (state->always_think) {
671 glutChangeToMenuEntry(menu_always_think,
672 "disable always think",v);
673 } else {
674 glutChangeToMenuEntry(menu_always_think,
675 "always think", v);
676 }
677 return;
678 }
679 if (v == 3) {
680 state->ics_robot = !state->ics_robot;
681 if (state->ics_robot) {
682 glutChangeToMenuEntry(menu_ics_robot,
683 "disable ICS robot",v);
684 } else {
685 glutChangeToMenuEntry(menu_ics_robot,
686 "enable ICS robot", v);
687 }
688 return;
689 }
690 state->stop_search = 1;
691 state->computer = v;
692 }
693
move_time_menu(int v)694 static void move_time_menu(int v)
695 {
696 state->move_time = v;
697 }
698
create_menus(void)699 static void create_menus(void)
700 {
701 int comp, undo, redo, move;
702
703 comp = glutCreateMenu(computer_menu);
704 glutAddMenuEntry("computer plays white", PIECE_WHITE);
705 glutAddMenuEntry("computer plays black", PIECE_BLACK);
706 glutAddMenuEntry("disable computer", 0);
707 menu_always_think = 4;
708 glutAddMenuEntry("always think", 2);
709 menu_ics_robot = 5;
710 glutAddMenuEntry("enable ICS robot", 3);
711
712 undo = glutCreateMenu(undo_menu);
713 glutAddMenuEntry("1 move", 1);
714 glutAddMenuEntry("2 moves", 2);
715 glutAddMenuEntry("4 moves", 4);
716 glutAddMenuEntry("8 moves", 8);
717
718 redo = glutCreateMenu(undo_menu);
719 glutAddMenuEntry("1 move", -1);
720 glutAddMenuEntry("2 moves",-2);
721 glutAddMenuEntry("4 moves",-4);
722 glutAddMenuEntry("8 moves",-8);
723
724 move = glutCreateMenu(move_time_menu);
725 glutAddMenuEntry("2 seconds", 2);
726 glutAddMenuEntry("5 seconds", 5);
727 glutAddMenuEntry("9 seconds", 9);
728 glutAddMenuEntry("10 seconds", 10);
729 glutAddMenuEntry("30 seconds", 30);
730 glutAddMenuEntry("60 seconds", 60);
731 glutAddMenuEntry("5 minutes", 300);
732
733 glutCreateMenu(main_menu);
734 glutAddMenuEntry("reset game", MENU_RESET);
735 glutAddMenuEntry("reset view", MENU_RESET_VIEW);
736 glutAddMenuEntry("flip view", MENU_FLIP);
737 menu_demo_mode = 4;
738 glutAddMenuEntry("demo mode", MENU_DEMO);
739 glutAddMenuEntry("eval debug", MENU_EVAL);
740 glutAddSubMenu("computer",comp);
741 glutAddSubMenu("undo",undo);
742 glutAddSubMenu("redo",redo);
743 glutAddSubMenu("move time",move);
744 glutAddMenuEntry("save game", MENU_SAVE);
745 glutAddMenuEntry("restore game", MENU_RESTORE);
746 glutAddMenuEntry("quit", MENU_QUIT);
747 glutAttachMenu(GLUT_RIGHT_BUTTON);
748
749 glutCreateMenu(edit_menu);
750 glutAddMenuEntry("delete", EDIT_NONE);
751 glutAddMenuEntry("recreate", EDIT_RECREATE);
752 glutAddMenuEntry("clear board", EDIT_CLEAR);
753 glutAddMenuEntry("whites move", EDIT_WHITES_MOVE);
754 glutAddMenuEntry("blacks move", EDIT_BLACKS_MOVE);
755 glutAddMenuEntry("black pawn", EDIT_BPAWN);
756 glutAddMenuEntry("black knight", EDIT_BKNIGHT);
757 glutAddMenuEntry("black bishop", EDIT_BBISHOP);
758 glutAddMenuEntry("black rook", EDIT_BROOK);
759 glutAddMenuEntry("black queen", EDIT_BQUEEN);
760 glutAddMenuEntry("black king", EDIT_BKING);
761 glutAddMenuEntry("white pawn", EDIT_WPAWN);
762 glutAddMenuEntry("white knight", EDIT_WKNIGHT);
763 glutAddMenuEntry("white bishop", EDIT_WBISHOP);
764 glutAddMenuEntry("white rook", EDIT_WROOK);
765 glutAddMenuEntry("white queen", EDIT_WQUEEN);
766 glutAddMenuEntry("white king", EDIT_WKING);
767 glutAttachMenu(GLUT_MIDDLE_BUTTON);
768 }
769
start_display(int argc,char * argv[])770 void start_display(int argc,char *argv[])
771 {
772 glutInit(&argc, argv);
773 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
774
775 reset_view();
776
777 glutCreateWindow("KnightCap");
778 glutReshapeWindow(window_size, window_size);
779 glutDisplayFunc(draw_all);
780 glutMouseFunc(mouse_func);
781 glutMotionFunc(motion_func);
782 glutIdleFunc(idle_func);
783
784 /* set other relevant state information */
785 glEnable(GL_DEPTH_TEST);
786 glEnable(GL_LINE_SMOOTH);
787
788 set_cursor(GLUT_CURSOR_CROSSHAIR);
789 create_menus();
790
791 glutMainLoop();
792 }
793
794 #else
795
redraw(void)796 void redraw(void)
797 {
798
799 }
800
draw_all(void)801 void draw_all(void)
802 {
803 need_redraw = 0;
804 print_board(state->position.board);
805 }
806 #endif
807