3 * plays through a chess game ending. enjoy.
5 * version 1.0 - June 6, 2002
7 * Copyright (C) 2002 Blair Tennessy (tennessb@unbc.ca)
9 * Permission to use, copy, modify, distribute, and sell this software and its
10 * documentation for any purpose is hereby granted without fee, provided that
11 * the above copyright notice appear in all copies and that both that
12 * copyright notice and this permission notice appear in supporting
13 * documentation. No representations are made about the suitability of this
14 * software for any purpose. It is provided "as is" without express or
18 #include <X11/Intrinsic.h>
21 # define PROGCLASS "Endgame"
22 # define HACK_INIT init_chess
23 # define HACK_DRAW draw_chess
24 # define HACK_RESHAPE reshape_chess
25 # define HACK_HANDLE_EVENT chess_handle_event
26 # define EVENT_MASK PointerMotionMask
27 # define chess_opts xlockmore_opts
29 #define DEFAULTS "*delay: 20000 \n" \
30 "*showFPS: False \n" \
31 "*wireframe: False \n" \
33 # include "xlockmore.h"
42 #include "gltrackball.h"
43 #include "chessmodels.h"
46 #define countof(x) (sizeof((x))/sizeof((*x)))
48 static XrmOptionDescRec opts[] = {
49 {"+rotate", ".chess.rotate", XrmoptionNoArg, (caddr_t) "false" },
50 {"-rotate", ".chess.rotate", XrmoptionNoArg, (caddr_t) "true" },
55 static argtype vars[] = {
56 {(caddr_t *) &rotate, "rotate", "Rotate", "True", t_Bool},
59 ModeSpecOpt chess_opts = {countof(opts), opts, countof(vars), vars, NULL};
62 ModStruct chess_description =
63 {"chess", "init_chess", "draw_chess", "release_chess",
64 "draw_chess", "init_chess", NULL, &chess_opts,
65 1000, 1, 2, 1, 4, 1.0, "",
71 GLXContext *glx_context;
73 trackball_state *trackball;
77 static Chesscreen *qs = NULL;
85 #define M_PI 3.14159265
90 /** definition of white/black (orange/gray) colors */
91 GLfloat colors[2][3] =
97 GLfloat whites[3][3] =
104 /* int board[BOARDSIZE][BOARDSIZE]; */
106 #include "chessgames.h"
110 /* void buildBoard(void) { */
111 /* board[0][5] = BKING; */
112 /* board[1][4] = BPAWN; */
113 /* board[1][2] = BPAWN; */
114 /* board[1][0] = BPAWN; */
115 /* board[2][2] = BPAWN; */
116 /* board[2][4] = BPAWN; */
117 /* board[2][7] = KNIGHT; */
118 /* board[3][0] = PAWN; */
119 /* board[3][2] = ROOK; */
120 /* board[4][0] = PAWN; */
121 /* board[4][4] = KING; */
122 /* board[4][5] = PAWN; */
123 /* board[6][0] = BPAWN; */
124 /* board[6][7] = PAWN; */
125 /* board[7][0] = BBISHOP; */
128 void build_colors(void) {
129 int white = random()%3;
130 colors[0][0] = whites[white][0];
131 colors[0][1] = whites[white][1];
132 colors[0][2] = whites[white][2];
135 /* int moves[MOVES][4] = */
136 /* { {3, 2, 6, 2}, */
147 /* {3, 2, 4, 2}, /\* pawn to bishop 5 *\/ */
148 /* {1, 5, 0, 3}, /\* check *\/ */
150 /* {0, 3, 2, 4}, /\* takes pawn *\/ */
154 /* {6, 3, 6, 1}, /\* rook takes bishop *\/ */
163 int mpiece = 0, tpiece, steps = 0, done = 1;
164 double from[2], to[2];
166 int moving = 0, take = 0, mc = 0, count = 99, wire = 0;
168 /** handle X event (trackball) */
169 Bool chess_handle_event (ModeInfo *mi, XEvent *event) {
170 Chesscreen *c = &qs[MI_SCREEN(mi)];
172 if(event->xany.type == ButtonPress && event->xbutton.button & Button1) {
173 c->button_down_p = True;
174 gltrackball_start (c->trackball,
175 event->xbutton.x, event->xbutton.y,
176 MI_WIDTH (mi), MI_HEIGHT (mi));
179 else if(event->xany.type == ButtonRelease
180 && event->xbutton.button & Button1) {
181 c->button_down_p = False;
184 else if(event->xany.type == MotionNotify && c->button_down_p) {
185 gltrackball_track (c->trackball,
186 event->xmotion.x, event->xmotion.y,
187 MI_WIDTH (mi), MI_HEIGHT (mi));
194 GLfloat position[] = { 3.0, 8.0, 3.0, 1.0 };
196 /* configure lighting */
197 void setup_lights(void) {
198 glEnable(GL_LIGHTING);
199 glLightfv(GL_LIGHT0, GL_POSITION, position);
204 void drawPieces(void) {
207 for(i = 0; i < BOARDSIZE; ++i) {
208 for(j = 0; j < BOARDSIZE; ++j) {
209 if(game.board[i][j]) {
210 int c = game.board[i][j]/PIECES;
211 glColor3fv(colors[c]);
212 glCallList(game.board[i][j]%PIECES);
215 glTranslatef(1.0, 0.0, 0.0);
218 glTranslatef(-1.0*BOARDSIZE, 0.0, 1.0);
221 glTranslatef(0.0, 0.0, -1.0*BOARDSIZE);
224 /** draw a moving piece */
225 void drawMovingPiece(void) {
226 int piece = mpiece % PIECES;
229 glColor3fv(colors[mpiece/PIECES]);
231 /** assume a queening. should be more general */
232 if((mpiece == PAWN && fabs(to[0]) < 0.01) ||
233 (mpiece == BPAWN && fabs(to[0]-7.0) < 0.01)) {
234 glTranslatef(from[1]+steps*dx, 0.0, from[0]+steps*dz);
235 glColor4f(colors[mpiece/7][0], colors[mpiece/7][1], colors[mpiece/7][2],
236 (fabs(50.0-steps))/50.0);
237 piece = steps < 50 ? PAWN : QUEEN;
241 mpiece = mpiece == PAWN ? QUEEN : BQUEEN;
243 else if(mpiece % PIECES == KNIGHT) {
244 glTranslatef(steps < 50 ? from[1] : to[1], 0.0,
245 steps < 50 ? from[0] : to[0]);
247 glColor4f(colors[mpiece/7][0], colors[mpiece/7][1], colors[mpiece/7][2],
248 fabs(49-steps)/49.0);
249 glScalef(fabs(49-steps)/49.0, fabs(49-steps)/49.0, fabs(49-steps)/49.0);
252 glTranslatef(from[1]+steps*dx, 0.0, from[0]+steps*dz);
264 /** code to squish a taken piece */
265 void drawTakePiece(void) {
269 glColor4f(colors[tpiece/7][0], colors[tpiece/7][1], colors[tpiece/7][2],
270 (100-1.6*steps)/100.0);
272 glTranslatef(to[1], 0.0, to[0]);
274 if(mpiece % PIECES == KNIGHT)
275 glScalef(1.0+steps/100.0, 1.0, 1.0+steps/100.0);
277 glScalef(1.0, 1 - steps/50.0 > 0.01 ? 1 - steps/50.0 : 0.01, 1.0);
278 glCallList(tpiece % 7);
285 void drawBoard(void) {
290 for(i = 0; i < BOARDSIZE; ++i)
291 for(j = 0; j < BOARDSIZE; ++j) {
292 /*glColor3fv(colors[(i+j)%2]);*/
293 glColor4f(colors[(i+j)%2][0], colors[(i+j)%2][1],
294 colors[(i+j)%2][2], 0.8);
295 glNormal3f(0.0, 1.0, 0.0);
296 glVertex3f(i, 0.0, j + 1.0);
297 glVertex3f(i + 1.0, 0.0, j + 1.0);
298 glVertex3f(i + 1.0, 0.0, j);
299 glVertex3f(i, 0.0, j);
302 /* chop underneath board */
303 /* glColor3f(0, 0, 0); */
304 /* glNormal3f(0, -1, 0); */
305 /* glVertex3f(0, 0, BOARDSIZE); */
306 /* glVertex3f(0, 0, 0); */
307 /* glVertex3f(BOARDSIZE, 0, 0); */
308 /* glVertex3f(BOARDSIZE, 0, BOARDSIZE); */
314 void draw_pieces(void) {
316 if(moving) drawMovingPiece();
317 if(take) drawTakePiece();
320 /** reflectionboard */
321 void draw_reflections(void) {
322 glEnable(GL_STENCIL_TEST);
323 glStencilFunc(GL_ALWAYS, 1, 1);
324 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
325 glColorMask(0,0,0,0);
326 glDisable(GL_CULL_FACE);
328 glDisable(GL_DEPTH_TEST);
330 glVertex3f(0, 0, BOARDSIZE);
332 glVertex3f(BOARDSIZE, 0, 0);
333 glVertex3f(BOARDSIZE, 0, BOARDSIZE);
335 glEnable(GL_DEPTH_TEST);
337 glColorMask(1, 1, 1, 1);
338 glStencilFunc(GL_EQUAL, 1, 1);
339 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
342 glScalef(1.0, -1.0, 1.0);
343 glTranslatef(0.5, 0.0, 0.5);
345 glLightfv(GL_LIGHT0, GL_POSITION, position);
349 glDisable(GL_STENCIL_TEST);
350 glLightfv(GL_LIGHT0, GL_POSITION, position);
352 glEnable(GL_CULL_FACE);
354 glColorMask(1,1,1,1);
357 /** draws the scene */
358 void display(Chesscreen *c) {
359 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
361 glMatrixMode(GL_MODELVIEW);
364 /** setup perspectif */
365 glTranslatef(0.0, 0.0, -1.5*BOARDSIZE);
366 glRotatef(30.0, 1.0, 0.0, 0.0);
367 gltrackball_rotate (c->trackball);
368 glRotatef(theta*100, 0.0, 1.0, 0.0);
369 glTranslatef(-0.5*BOARDSIZE, 0.0, -0.5*BOARDSIZE);
371 /** draw board, pieces */
373 glEnable(GL_LIGHTING);
374 glEnable(GL_COLOR_MATERIAL);
383 glTranslatef(0.5, .01, 0.5);
387 glDisable(GL_COLOR_MATERIAL);
388 glDisable(GL_LIGHTING);
391 if (!c->button_down_p)
395 /** reshape handler */
396 void reshape_chess(ModeInfo *mi, int width, int height) {
397 GLfloat h = (GLfloat) height / (GLfloat) width;
398 glViewport(0,0, width, height);
399 glMatrixMode(GL_PROJECTION);
401 gluPerspective(45, 1/h, 2.0, 30.0);
402 glMatrixMode(GL_MODELVIEW);
405 /** initialization handler */
406 void init_chess(ModeInfo *mi) {
408 int screen = MI_SCREEN(mi);
409 wire = MI_IS_WIREFRAME(mi);
412 !(qs = (Chesscreen *) calloc(MI_NUM_SCREENS(mi), sizeof(Chesscreen))))
416 c->window = MI_WINDOW(mi);
417 c->trackball = gltrackball_init ();
419 if((c->glx_context = init_GL(mi)))
420 reshape_chess(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
424 glClearColor(0.0, 0.0, 0.0, 0.0);
426 glDepthFunc(GL_LEQUAL);
428 glEnable(GL_CULL_FACE);
435 glColorMaterial(GL_FRONT, GL_DIFFUSE);
436 glShadeModel(GL_SMOOTH);
437 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
438 glEnable(GL_DEPTH_TEST);
441 glPolygonMode(GL_FRONT, GL_LINE);
446 /** does dirty work drawing scene, moving pieces */
447 void draw_chess(ModeInfo *mi) {
448 Chesscreen *c = &qs[MI_SCREEN(mi)];
449 Window w = MI_WINDOW(mi);
450 Display *disp = MI_DISPLAY(mi);
455 glXMakeCurrent(disp, w, *(c->glx_context));
457 /** code for moving a piece */
458 if(moving && ++steps == 100) {
459 moving = count = steps = take = 0;
460 game.board[game.moves[mc][2]][game.moves[mc][3]] = mpiece;
463 if(mc == game.movecount) {
470 glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION,
471 done == 1 ? 1.0+0.1*count : 99.0/count);
475 mpiece = game.board[game.moves[mc][0]][game.moves[mc][1]];
476 game.board[game.moves[mc][0]][game.moves[mc][1]] = NONE;
478 if((tpiece = game.board[game.moves[mc][2]][game.moves[mc][3]])) {
479 game.board[game.moves[mc][2]][game.moves[mc][3]] = NONE;
483 from[0] = game.moves[mc][0];
484 from[1] = game.moves[mc][1];
485 to[0] = game.moves[mc][2];
486 to[1] = game.moves[mc][3];
488 dz = (to[0] - from[0]) / 100;
489 dx = (to[1] - from[1]) / 100;
494 /* copy over new game */
495 game = games[random()%GAMES];
508 if(mi->fps_p) do_fps(mi);
510 glXSwapBuffers(disp, w);
514 void release_chess(ModeInfo *mi) {