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" },
53 int rotate, spidey, spideydark;
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
106 /* definition of white/black colors */
107 GLfloat colors[2][3] = { {1.0, 0.5, 0.0},
110 /* int board[8][8] = */
111 /* { {ROOK, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK}, */
112 /* {PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN}, */
113 /* {NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE}, */
114 /* {NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE}, */
115 /* {NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE}, */
116 /* {NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE}, */
117 /* {BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN}, */
118 /* {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK}}; */
122 void buildBoard(void) {
129 board[2][7] = KNIGHT;
137 board[7][0] = BBISHOP;
142 int moves[MOVES][4] =
154 {3, 2, 4, 2}, /* pawn to bishop 5 */
155 {1, 5, 0, 3}, /* check */
157 {0, 3, 2, 4}, /* takes pawn */
161 {6, 3, 6, 1}, /* rook takes bishop */
162 {6, 0, 7, 0}, /* hack this in! */
170 int mpiece = 0, tpiece, steps = 0;
172 double from[2], to[2];
174 int moving = 0, take = 0, mc = 0, count = 0;
176 Bool chess_handle_event (ModeInfo *mi, XEvent *event) {
177 Chesscreen *c = &qs[MI_SCREEN(mi)];
179 if(event->xany.type == ButtonPress && event->xbutton.button & Button1) {
180 c->button_down_p = True;
181 gltrackball_start (c->trackball,
182 event->xbutton.x, event->xbutton.y,
183 MI_WIDTH (mi), MI_HEIGHT (mi));
186 else if(event->xany.type == ButtonRelease
187 && event->xbutton.button & Button1) {
188 c->button_down_p = False;
191 else if(event->xany.type == MotionNotify && c->button_down_p) {
192 gltrackball_track (c->trackball,
193 event->xmotion.x, event->xmotion.y,
194 MI_WIDTH (mi), MI_HEIGHT (mi));
205 for(i = 0; i < BOARDSIZE; ++i)
206 for(j = 0; j < BOARDSIZE; ++j)
210 /* configure lighting */
211 void setup_lights(void) {
212 GLfloat position[] = { 0.0, 8.0, 0.0, 1.0 };
214 glEnable(GL_LIGHTING);
215 glLightfv(GL_LIGHT0, GL_POSITION, position);
220 void drawPieces(void) {
223 for(i = 0; i < BOARDSIZE; ++i) {
224 for(j = 0; j < BOARDSIZE; ++j) {
226 int c = board[i][j]/PIECES;
227 glColor3fv(colors[c]);
228 glCallList(board[i][j]%7);
231 glTranslatef(1.0, 0.0, 0.0);
234 glTranslatef(-1.0*BOARDSIZE, 0.0, 1.0);
237 glTranslatef(0.0, 0.0, -1.0*BOARDSIZE);
240 void drawMovingPiece(int wire) {
241 glTranslatef(from[1], 0.0, from[0]);
242 glColor3fv(colors[mpiece/7]);
244 /* assume a queening. should be more general */
245 if((mpiece == PAWN && fabs(to[0]) < 0.01) ||
246 (mpiece == BPAWN && fabs(to[0]-7.0) < 0.01)) {
250 glColor4f(colors[mpiece/7][0], colors[mpiece/7][1], colors[mpiece/7][2],
251 (fabs(50.0-steps))/50.0);
253 glCallList(steps < 50 ? PAWN : QUEEN);
255 /* what a kludge. yay for side effects */
257 mpiece = mpiece == PAWN ? QUEEN : BQUEEN;
263 glCallList(mpiece % 7);
266 void drawTakePiece(int wire) {
270 glColor4f(colors[tpiece/7][0], colors[tpiece/7][1], colors[tpiece/7][2],
271 (100-1.6*steps)/100.0);
273 glTranslatef(to[1] - from[1], 0.0, to[0] - from[0]);
274 glScalef(1.0, 1 - steps/50.0 > 0.01 ? 1 - steps/50.0 : 0.01, 1.0);
275 glCallList(tpiece % 7);
282 void drawBoard(void) {
285 for(i = 0; i < BOARDSIZE; ++i)
286 for(j = 0; j < BOARDSIZE; ++j) {
287 glColor3fv(colors[(i+j)%2]);
288 glNormal3f(0.0, 1.0, 0.0);
292 glVertex3f(i - 0.5, 0.0, j + 0.5);
293 glVertex3f(i + 0.5, 0.0, j + 0.5);
294 glVertex3f(i + 0.5, 0.0, j - 0.5);
295 glVertex3f(i - 0.5, 0.0, j - 0.5);
297 /* draw the bottom, too */
298 glNormal3f(0.0, -1.0, 0.0);
300 glVertex3f(i - 0.5, 0.0, j - 0.5);
301 glVertex3f(i + 0.5, 0.0, j - 0.5);
302 glVertex3f(i + 0.5, 0.0, j + 0.5);
303 glVertex3f(i - 0.5, 0.0, j + 0.5);
313 void display(Chesscreen *c, int wire) {
314 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
316 glMatrixMode(GL_MODELVIEW);
319 glTranslatef(0.0, -3.0+fabs(sin(theta)), -1.3*BOARDSIZE);
320 gltrackball_rotate (c->trackball);
321 glRotatef(theta*100, 0.0, 1.0, 0.0);
322 glTranslatef(-0.5*(BOARDSIZE-1), 0.0, -0.5*(BOARDSIZE-1));
325 glEnable(GL_LIGHTING);
326 glEnable(GL_COLOR_MATERIAL);
330 glTranslatef(0.0, .02, 0.0);
332 if(moving) drawMovingPiece(wire);
333 if(take) drawTakePiece(wire);
335 glDisable(GL_COLOR_MATERIAL);
336 glDisable(GL_LIGHTING);
341 void reshape_chess(ModeInfo *mi, int width, int height) {
342 GLfloat h = (GLfloat) height / (GLfloat) width;
343 glViewport(0,0, width, height);
344 glMatrixMode(GL_PROJECTION);
346 gluPerspective(45, 1/h, 2.0, 30.0);
347 glMatrixMode(GL_MODELVIEW);
350 void init_chess(ModeInfo *mi) {
351 GLfloat mat_shininess[] = { 90.0 };
352 GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
354 int screen = MI_SCREEN(mi);
355 int wire = MI_IS_WIREFRAME(mi);
359 !(qs = (Chesscreen *) calloc(MI_NUM_SCREENS(mi), sizeof(Chesscreen))))
363 c->window = MI_WINDOW(mi);
364 c->trackball = gltrackball_init ();
366 if((c->glx_context = init_GL(mi)))
367 reshape_chess(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
371 glClearColor(0.0, 0.0, 0.0, 0.0);
373 glEnable(GL_CULL_FACE);
376 glDepthFunc(GL_LEQUAL);
383 glColorMaterial(GL_FRONT, GL_DIFFUSE);
385 glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
386 glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
387 glShadeModel(GL_SMOOTH);
388 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
389 glEnable(GL_DEPTH_TEST);
392 glPolygonMode(GL_FRONT, GL_LINE);
397 void draw_chess(ModeInfo *mi) {
398 Chesscreen *c = &qs[MI_SCREEN(mi)];
399 Window w = MI_WINDOW(mi);
400 Display *disp = MI_DISPLAY(mi);
405 glXMakeCurrent(disp, w, *(c->glx_context));
415 moving = count = steps = take = 0;
416 board[moves[mc][2]][moves[mc][3]] = mpiece;
428 mpiece = board[moves[mc][0]][moves[mc][1]];
429 board[moves[mc][0]][moves[mc][1]] = NONE;
431 if((tpiece = board[moves[mc][2]][moves[mc][3]]) != NONE) {
432 board[moves[mc][2]][moves[mc][3]] = NONE;
437 from[0] = moves[mc][0];
438 from[1] = moves[mc][1];
439 to[0] = moves[mc][2];
440 to[1] = moves[mc][3];
442 dz = (to[0] - from[0]) / 100;
443 dx = (to[1] - from[1]) / 100;
447 display(c, MI_IS_WIREFRAME(mi));
449 if(mi->fps_p) do_fps(mi);
451 glXSwapBuffers(disp, w);
454 void release_chess(ModeInfo *mi) {