From http://www.jwz.org/xscreensaver/xscreensaver-5.37.tar.gz
[xscreensaver] / hacks / glx / endgame.c
index d0ae2f39befef30e165cca41f48800619ee7d6a1..e69a21c0ec3bbcfad70570ee2ebb1c9e55f55a0f 100644 (file)
@@ -21,6 +21,7 @@
                       "*wireframe: False \n" \
 
 # define refresh_chess 0
+# define release_chess 0
 # include "xlockmore.h"
 
 #else
@@ -73,7 +74,7 @@ ENTRYPOINT ModeSpecOpt chess_opts = {countof(opts), opts, countof(vars), vars, N
 
 #ifdef USE_MODULES
 ModStruct   chess_description =
-{"chess", "init_chess", "draw_chess", "release_chess",
+{"chess", "init_chess", "draw_chess", NULL,
  "draw_chess", "init_chess", NULL, &chess_opts,
  1000, 1, 2, 1, 4, 1.0, "",
  "Chess", 0, NULL};
@@ -204,35 +205,16 @@ ENTRYPOINT Bool chess_handle_event (ModeInfo *mi, XEvent *event)
 {
   Chesscreen *cs = &qs[MI_SCREEN(mi)];
 
-  if(event->xany.type == ButtonPress && event->xbutton.button == Button1) {
-    cs->button_down_p = True;
-    gltrackball_start (cs->trackball,
-                      event->xbutton.x, event->xbutton.y,
-                      MI_WIDTH (mi), MI_HEIGHT (mi));
+  if (gltrackball_event_handler (event, cs->trackball,
+                                 MI_WIDTH (mi), MI_HEIGHT (mi),
+                                 &cs->button_down_p))
     return True;
-  }
-  else if(event->xany.type == ButtonRelease 
-         && event->xbutton.button == Button1) {
-    cs->button_down_p = False;
-    return True;
-  }
-  else if (event->xany.type == ButtonPress &&
-           (event->xbutton.button == Button4 ||
-            event->xbutton.button == Button5 ||
-            event->xbutton.button == Button6 ||
-            event->xbutton.button == Button7))
+  else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
     {
-      gltrackball_mousewheel (cs->trackball, event->xbutton.button, 5,
-                              !event->xbutton.state);
+      cs->done = 1;
       return True;
     }
-  else if(event->xany.type == MotionNotify && cs->button_down_p) {
-    gltrackball_track (cs->trackball,
-                      event->xmotion.x, event->xmotion.y,
-                      MI_WIDTH (mi), MI_HEIGHT (mi));
-    return True;
-  }
-  
   return False;
 }
 
@@ -309,6 +291,8 @@ static void drawMovingPiece(ModeInfo *mi, Chesscreen *cs, int shadow)
 {
   int piece = cs->mpiece % PIECES;
 
+  if (piece == NONE) return;
+
   glPushMatrix();
 
   if(shadow) glColor4fv(MaterialShadow);
@@ -331,33 +315,42 @@ static void drawMovingPiece(ModeInfo *mi, Chesscreen *cs, int shadow)
       cs->mpiece = cs->mpiece == PAWN ? QUEEN : BQUEEN;
   }
   else if(cs->mpiece % PIECES == KNIGHT) {
-    GLfloat shine[1];
-    GLfloat spec[4];
-    GLfloat mult;
-    glTranslatef(cs->steps < 50 ? cs->from[1] : cs->to[1], 0.0, 
-                cs->steps < 50 ? cs->from[0] : cs->to[0]);
-
-    mult = cs->steps < 10 
-      ? (1.0 - cs->steps / 10.0) : 100 - cs->steps < 10 
-      ? (1.0 - (100 - cs->steps) / 10.0) : 0.0;
-
-    shine[0] = mult*shininess[0];
-    spec[0] = mult*specular[0];
-    spec[1] = mult*specular[1];
-    spec[2] = mult*specular[2];
-    spec[3] = 1.0;
-    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shine);
-    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
+    /* If there is nothing in the path of a knight, move it by sliding,
+       just like the other pieces.  But if there are any pieces on the
+       middle two squares in its path, the knight would intersect them,
+       so in that case, move it in an airborne arc. */
+    GLfloat y;
+    int i, j;
+    Bool blocked_p = False;
+    int fromx = MIN(cs->from[1], cs->to[1]);
+    int fromy = MIN(cs->from[0], cs->to[0]);
+    int tox   = MAX(cs->from[1], cs->to[1]);
+    int toy   = MAX(cs->from[0], cs->to[0]);
+    if (fromx == tox-2) fromx = tox = fromx+1;
+    if (fromy == toy-2) fromy = toy = fromy+1;
+    for (i = fromy; i <= toy; i++) {
+      for (j = fromx; j <= tox; j++) {
+        if (cs->game.board[i][j]) {
+          blocked_p = True;
+          break;
+        }
+      }
+    }
 
-    glColor4f(shadow ? MaterialShadow[0] : cs->colors[cs->mpiece/7][0], 
-             shadow ? MaterialShadow[1] : cs->colors[cs->mpiece/7][1], 
-             shadow ? MaterialShadow[2] : cs->colors[cs->mpiece/7][2],
-             fabs(49-cs->steps)/49.0);
+    if (!blocked_p)
+      goto SLIDE;
 
-    glScalef(fabs(49-cs->steps)/49.0, fabs(49-cs->steps)/49.0, fabs(49-cs->steps)/49.0);
-  }
-  else
+    /* Move by hopping. */
+    y = 1.5 * sin (M_PI * cs->steps / 100.0);
+    glTranslatef(cs->from[1]+cs->steps*cs->dx, y,
+                 cs->from[0]+cs->steps*cs->dz);
+
+  } else {
+  SLIDE:
+    /* Move by sliding. */
     glTranslatef(cs->from[1]+cs->steps*cs->dx, 0.0, cs->from[0]+cs->steps*cs->dz);
+  }
+
 
   if(!cs->wire)
     glEnable(GL_BLEND);
@@ -432,15 +425,87 @@ static void drawBoard(ModeInfo *mi, Chesscreen *cs)
 
       mi->polygon_count++;
     }
-
-  /* chop underneath board */
-/*   glColor3f(0, 0, 0); */
-/*   glNormal3f(0, -1, 0); */
-/*   glVertex3f(0,         0,  BOARDSIZE); */
-/*   glVertex3f(0,         0,  0); */
-/*   glVertex3f(BOARDSIZE, 0,  0); */
-/*   glVertex3f(BOARDSIZE, 0,  BOARDSIZE); */
   glEnd();
+
+  {
+    GLfloat off = 0.01;
+    GLfloat w = BOARDSIZE;
+    GLfloat h = 0.1;
+
+    /* Give the board a slight lip. */
+    /* #### oops, normals are wrong here, but you can't tell */
+
+    glColor3f(0.3, 0.3, 0.3);
+    glBegin (GL_QUADS);
+    glVertex3f (0,  0, 0);
+    glVertex3f (0, -h, 0);
+    glVertex3f (0, -h, w);
+    glVertex3f (0,  0, w);
+
+    glVertex3f (0,  0, w);
+    glVertex3f (0, -h, w);
+    glVertex3f (w, -h, w);
+    glVertex3f (w,  0, w);
+
+    glVertex3f (w,  0, w);
+    glVertex3f (w, -h, w);
+    glVertex3f (w, -h, 0);
+    glVertex3f (w,  0, 0);
+
+    glVertex3f (w,  0, 0);
+    glVertex3f (w, -h, 0);
+    glVertex3f (0, -h, 0);
+    glVertex3f (0,  0, 0);
+
+    glVertex3f (0, -h, 0);
+    glVertex3f (w, -h, 0);
+    glVertex3f (w, -h, w);
+    glVertex3f (0, -h, w);
+    glEnd();
+    mi->polygon_count += 4;
+
+    /* Fill in the underside of the board with an invisible black box
+       to hide the reflections that are not on tiles.  Probably there's
+       a way to do this with stencils instead.
+     */
+    w -= off*2;
+    h = 5;
+
+    glPushMatrix();
+    glTranslatef (off, 0, off);
+    glDisable(GL_LIGHTING);
+    glColor3f(0,0,0);
+    glBegin (GL_QUADS);
+    glVertex3f (0,  0, 0);
+    glVertex3f (0, -h, 0);
+    glVertex3f (0, -h, w);
+    glVertex3f (0,  0, w);
+
+    glVertex3f (0,  0, w);
+    glVertex3f (0, -h, w);
+    glVertex3f (w, -h, w);
+    glVertex3f (w,  0, w);
+
+    glVertex3f (w,  0, w);
+    glVertex3f (w, -h, w);
+    glVertex3f (w, -h, 0);
+    glVertex3f (w,  0, 0);
+
+    glVertex3f (w,  0, 0);
+    glVertex3f (w, -h, 0);
+    glVertex3f (0, -h, 0);
+    glVertex3f (0,  0, 0);
+
+    glVertex3f (0, -h, 0);
+    glVertex3f (w, -h, 0);
+    glVertex3f (w, -h, w);
+    glVertex3f (0, -h, w);
+    glEnd();
+    mi->polygon_count += 4;
+    glPopMatrix();
+    if (!cs->wire)
+      glEnable(GL_LIGHTING);
+  }
 }
 
 static void draw_pieces(ModeInfo *mi, Chesscreen *cs, int wire) 
@@ -632,12 +697,15 @@ static void display(ModeInfo *mi, Chesscreen *cs)
 
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
+  glRotatef(current_device_rotation(), 0, 0, 1);
 
   /** setup perspectiv */
   glTranslatef(0.0, 0.0, -1.5*BOARDSIZE);
   glRotatef(30.0, 1.0, 0.0, 0.0);
   gltrackball_rotate (cs->trackball);
-  glRotatef(cs->theta*100, 0.0, 1.0, 0.0);
+
+  if (rotate)
+    glRotatef(cs->theta*100, 0.0, 1.0, 0.0);
   glTranslatef(-0.5*BOARDSIZE, 0.0, -0.5*BOARDSIZE);
 
 /*   cs->position[0] = 4.0 + 1.0*-sin(cs->theta*100*M_PI/180.0); */
@@ -732,14 +800,12 @@ ENTRYPOINT void init_chess(ModeInfo *mi)
   Chesscreen *cs;
   int screen = MI_SCREEN(mi);
 
-  if(!qs && 
-     !(qs = (Chesscreen *) calloc(MI_NUM_SCREENS(mi), sizeof(Chesscreen))))
-    return;
+  MI_INIT(mi, qs, NULL);
   
   cs = &qs[screen];
   cs->window = MI_WINDOW(mi);
   cs->wire = MI_IS_WIREFRAME(mi);
-  cs->trackball = gltrackball_init ();
+  cs->trackball = gltrackball_init (False);
   
   cs->oldwhite = -1;
 
@@ -793,7 +859,11 @@ ENTRYPOINT void init_chess(ModeInfo *mi)
     make_piece_texture(cs);
     make_board_texture(cs);
   }
-  gen_model_lists( classic, cs->poly_counts);
+  chessmodels_gen_lists( classic, cs->poly_counts);
+
+# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */
+    cs->wire = 0;
+# endif
 
   if(!cs->wire) {
     setup_lights(cs);
@@ -888,16 +958,6 @@ ENTRYPOINT void draw_chess(ModeInfo *mi)
   glXSwapBuffers(disp, w);
 }
 
-/** bust it */
-ENTRYPOINT void release_chess(ModeInfo *mi) 
-{
-  if(qs)
-    free((void *) qs);
-  qs = 0;
-
-  FreeAllGL(mi);
-}
-
 XSCREENSAVER_MODULE_2 ("Endgame", endgame, chess)
 
 #endif