glpuzzle.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:30k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /* glpuzzle - written by Kevin Smith (kpsmith@engr.sgi.com) */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <sys/types.h>
  6. #include <time.h>
  7. #include <math.h>
  8. #include <GL/glut.h>
  9. #include "trackball.h"
  10. #define WIDTH 4
  11. #define HEIGHT 5
  12. #define PIECES 10
  13. #define OFFSETX -2
  14. #define OFFSETY -2.5
  15. #define OFFSETZ -0.5
  16. typedef unsigned char Config[HEIGHT][WIDTH];
  17. struct puzzle {
  18.   struct puzzle *backptr;
  19.   struct puzzle *solnptr;
  20.   Config pieces;
  21.   struct puzzle *next;
  22.   unsigned hashvalue;
  23. };
  24. #define HASHSIZE 10691
  25. struct puzzlelist {
  26.   struct puzzle *puzzle;
  27.   struct puzzlelist *next;
  28. };
  29. static char convert[PIECES + 1] =
  30. {0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4};
  31. static unsigned char colors[PIECES + 1][3] =
  32. {
  33.   {0, 0, 0},
  34.   {255, 255, 127},
  35.   {255, 255, 127},
  36.   {255, 255, 127},
  37.   {255, 255, 127},
  38.   {255, 127, 255},
  39.   {255, 127, 255},
  40.   {255, 127, 255},
  41.   {255, 127, 255},
  42.   {255, 127, 127},
  43.   {255, 255, 255},
  44. };
  45. void changeState(void);
  46. static struct puzzle *hashtable[HASHSIZE];
  47. static struct puzzle *startPuzzle;
  48. static struct puzzlelist *puzzles;
  49. static struct puzzlelist *lastentry;
  50. int curX, curY, visible;
  51. #define MOVE_SPEED 0.2
  52. static unsigned char movingPiece;
  53. static float move_x, move_y;
  54. static float curquat[4];
  55. static int doubleBuffer = 1;
  56. static int depth = 1;
  57. static char xsize[PIECES + 1] =
  58. {0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2};
  59. static char ysize[PIECES + 1] =
  60. {0, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2};
  61. static float zsize[PIECES + 1] =
  62. {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.6};
  63. static Config startConfig =
  64. {
  65.   {8, 10, 10, 7},
  66.   {8, 10, 10, 7},
  67.   {6, 9, 9, 5},
  68.   {6, 4, 3, 5},
  69.   {2, 0, 0, 1}
  70. };
  71. static Config thePuzzle =
  72. {
  73.   {8, 10, 10, 7},
  74.   {8, 10, 10, 7},
  75.   {6, 9, 9, 5},
  76.   {6, 4, 3, 5},
  77.   {2, 0, 0, 1}
  78. };
  79. static int xadds[4] =
  80. {-1, 0, 1, 0};
  81. static int yadds[4] =
  82. {0, -1, 0, 1};
  83. static int W = 400, H = 300;
  84. static GLint viewport[4];
  85. #define srandom srand
  86. #define random() (rand() >> 2)
  87. unsigned
  88. hash(Config config)
  89. {
  90.   int i, j, value;
  91.   value = 0;
  92.   for (i = 0; i < HEIGHT; i++) {
  93.     for (j = 0; j < WIDTH; j++) {
  94.       value = value + convert[config[i][j]];
  95.       value *= 6;
  96.     }
  97.   }
  98.   return (value);
  99. }
  100. int
  101. solution(Config config)
  102. {
  103.   if (config[4][1] == 10 && config[4][2] == 10)
  104.     return (1);
  105.   return (0);
  106. }
  107. float boxcoords[][3] =
  108. {
  109.   {0.2, 0.2, 0.9},
  110.   {0.8, 0.2, 0.9},
  111.   {0.8, 0.8, 0.9},
  112.   {0.2, 0.8, 0.9},
  113.   {0.2, 0.1, 0.8},
  114.   {0.8, 0.1, 0.8},
  115.   {0.9, 0.2, 0.8},
  116.   {0.9, 0.8, 0.8},
  117.   {0.8, 0.9, 0.8},
  118.   {0.2, 0.9, 0.8},
  119.   {0.1, 0.8, 0.8},
  120.   {0.1, 0.2, 0.8},
  121.   {0.2, 0.1, 0.2},
  122.   {0.8, 0.1, 0.2},
  123.   {0.9, 0.2, 0.2},
  124.   {0.9, 0.8, 0.2},
  125.   {0.8, 0.9, 0.2},
  126.   {0.2, 0.9, 0.2},
  127.   {0.1, 0.8, 0.2},
  128.   {0.1, 0.2, 0.2},
  129.   {0.2, 0.2, 0.1},
  130.   {0.8, 0.2, 0.1},
  131.   {0.8, 0.8, 0.1},
  132.   {0.2, 0.8, 0.1},
  133. };
  134. float boxnormals[][3] =
  135. {
  136.   {0, 0, 1},            /* 0 */
  137.   {0, 1, 0},
  138.   {1, 0, 0},
  139.   {0, 0, -1},
  140.   {0, -1, 0},
  141.   {-1, 0, 0},
  142.   {0.7071, 0.7071, 0.0000},  /* 6 */
  143.   {0.7071, -0.7071, 0.0000},
  144.   {-0.7071, 0.7071, 0.0000},
  145.   {-0.7071, -0.7071, 0.0000},
  146.   {0.7071, 0.0000, 0.7071},  /* 10 */
  147.   {0.7071, 0.0000, -0.7071},
  148.   {-0.7071, 0.0000, 0.7071},
  149.   {-0.7071, 0.0000, -0.7071},
  150.   {0.0000, 0.7071, 0.7071},  /* 14 */
  151.   {0.0000, 0.7071, -0.7071},
  152.   {0.0000, -0.7071, 0.7071},
  153.   {0.0000, -0.7071, -0.7071},
  154.   {0.5774, 0.5774, 0.5774},  /* 18 */
  155.   {0.5774, 0.5774, -0.5774},
  156.   {0.5774, -0.5774, 0.5774},
  157.   {0.5774, -0.5774, -0.5774},
  158.   {-0.5774, 0.5774, 0.5774},
  159.   {-0.5774, 0.5774, -0.5774},
  160.   {-0.5774, -0.5774, 0.5774},
  161.   {-0.5774, -0.5774, -0.5774},
  162. };
  163. int boxfaces[][4] =
  164. {
  165.   {0, 1, 2, 3},         /* 0 */
  166.   {9, 8, 16, 17},
  167.   {6, 14, 15, 7},
  168.   {20, 23, 22, 21},
  169.   {12, 13, 5, 4},
  170.   {19, 11, 10, 18},
  171.   {7, 15, 16, 8},       /* 6 */
  172.   {13, 14, 6, 5},
  173.   {18, 10, 9, 17},
  174.   {19, 12, 4, 11},
  175.   {1, 6, 7, 2},         /* 10 */
  176.   {14, 21, 22, 15},
  177.   {11, 0, 3, 10},
  178.   {20, 19, 18, 23},
  179.   {3, 2, 8, 9},         /* 14 */
  180.   {17, 16, 22, 23},
  181.   {4, 5, 1, 0},
  182.   {20, 21, 13, 12},
  183.   {2, 7, 8, -1},        /* 18 */
  184.   {16, 15, 22, -1},
  185.   {5, 6, 1, -1},
  186.   {13, 21, 14, -1},
  187.   {10, 3, 9, -1},
  188.   {18, 17, 23, -1},
  189.   {11, 4, 0, -1},
  190.   {20, 12, 19, -1},
  191. };
  192. #define NBOXFACES (sizeof(boxfaces)/sizeof(boxfaces[0]))
  193. /* Draw a box.  Bevel as desired. */
  194. void
  195. drawBox(int piece, float xoff, float yoff)
  196. {
  197.   int xlen, ylen;
  198.   int i, k;
  199.   float x, y, z;
  200.   float zlen;
  201.   float *v;
  202.   xlen = xsize[piece];
  203.   ylen = ysize[piece];
  204.   zlen = zsize[piece];
  205.   glColor3ubv(colors[piece]);
  206.   glBegin(GL_QUADS);
  207.   for (i = 0; i < 18; i++) {
  208.     glNormal3fv(boxnormals[i]);
  209.     for (k = 0; k < 4; k++) {
  210.       if (boxfaces[i][k] == -1)
  211.         continue;
  212.       v = boxcoords[boxfaces[i][k]];
  213.       x = v[0] + OFFSETX;
  214.       if (v[0] > 0.5)
  215.         x += xlen - 1;
  216.       y = v[1] + OFFSETY;
  217.       if (v[1] > 0.5)
  218.         y += ylen - 1;
  219.       z = v[2] + OFFSETZ;
  220.       if (v[2] > 0.5)
  221.         z += zlen - 1;
  222.       glVertex3f(xoff + x, yoff + y, z);
  223.     }
  224.   }
  225.   glEnd();
  226.   glBegin(GL_TRIANGLES);
  227.   for (i = 18; i < NBOXFACES; i++) {
  228.     glNormal3fv(boxnormals[i]);
  229.     for (k = 0; k < 3; k++) {
  230.       if (boxfaces[i][k] == -1)
  231.         continue;
  232.       v = boxcoords[boxfaces[i][k]];
  233.       x = v[0] + OFFSETX;
  234.       if (v[0] > 0.5)
  235.         x += xlen - 1;
  236.       y = v[1] + OFFSETY;
  237.       if (v[1] > 0.5)
  238.         y += ylen - 1;
  239.       z = v[2] + OFFSETZ;
  240.       if (v[2] > 0.5)
  241.         z += zlen - 1;
  242.       glVertex3f(xoff + x, yoff + y, z);
  243.     }
  244.   }
  245.   glEnd();
  246. }
  247. float containercoords[][3] =
  248. {
  249.   {-0.1, -0.1, 1.0},
  250.   {-0.1, -0.1, -0.1},
  251.   {4.1, -0.1, -0.1},
  252.   {4.1, -0.1, 1.0},
  253.   {1.0, -0.1, 0.6},     /* 4 */
  254.   {3.0, -0.1, 0.6},
  255.   {1.0, -0.1, 0.0},
  256.   {3.0, -0.1, 0.0},
  257.   {1.0, 0.0, 0.0},      /* 8 */
  258.   {3.0, 0.0, 0.0},
  259.   {3.0, 0.0, 0.6},
  260.   {1.0, 0.0, 0.6},
  261.   {0.0, 0.0, 1.0},      /* 12 */
  262.   {4.0, 0.0, 1.0},
  263.   {4.0, 0.0, 0.0},
  264.   {0.0, 0.0, 0.0},
  265.   {0.0, 5.0, 0.0},      /* 16 */
  266.   {0.0, 5.0, 1.0},
  267.   {4.0, 5.0, 1.0},
  268.   {4.0, 5.0, 0.0},
  269.   {-0.1, 5.1, -0.1},    /* 20 */
  270.   {4.1, 5.1, -0.1},
  271.   {4.1, 5.1, 1.0},
  272.   {-0.1, 5.1, 1.0},
  273. };
  274. float containernormals[][3] =
  275. {
  276.   {0, -1, 0},
  277.   {0, -1, 0},
  278.   {0, -1, 0},
  279.   {0, -1, 0},
  280.   {0, -1, 0},
  281.   {0, 1, 0},
  282.   {0, 1, 0},
  283.   {0, 1, 0},
  284.   {1, 0, 0},
  285.   {1, 0, 0},
  286.   {1, 0, 0},
  287.   {-1, 0, 0},
  288.   {-1, 0, 0},
  289.   {-1, 0, 0},
  290.   {0, 1, 0},
  291.   {0, 0, -1},
  292.   {0, 0, -1},
  293.   {0, 0, 1},
  294.   {0, 0, 1},
  295.   {0, 0, 1},
  296.   {0, 0, 1},
  297.   {0, 0, 1},
  298.   {0, 0, 1},
  299.   {0, 0, 1},
  300. };
  301. int containerfaces[][4] =
  302. {
  303.   {1, 6, 4, 0},
  304.   {0, 4, 5, 3},
  305.   {1, 2, 7, 6},
  306.   {7, 2, 3, 5},
  307.   {16, 19, 18, 17},
  308.   {23, 22, 21, 20},
  309.   {12, 11, 8, 15},
  310.   {10, 13, 14, 9},
  311.   {15, 16, 17, 12},
  312.   {2, 21, 22, 3},
  313.   {6, 8, 11, 4},
  314.   {1, 0, 23, 20},
  315.   {14, 13, 18, 19},
  316.   {9, 7, 5, 10},
  317.   {12, 13, 10, 11},
  318.   {1, 20, 21, 2},
  319.   {4, 11, 10, 5},
  320.   {15, 8, 19, 16},
  321.   {19, 8, 9, 14},
  322.   {8, 6, 7, 9},
  323.   {0, 3, 13, 12},
  324.   {13, 3, 22, 18},
  325.   {18, 22, 23, 17},
  326.   {17, 23, 0, 12},
  327. };
  328. #define NCONTFACES (sizeof(containerfaces)/sizeof(containerfaces[0]))
  329. /* Draw the container */
  330. void
  331. drawContainer(void)
  332. {
  333.   int i, k;
  334.   float *v;
  335.   /* Y is reversed here because the model has it reversed */
  336.   /* Arbitrary bright wood-like color */
  337.   glColor3ub(209, 103, 23);
  338.   glBegin(GL_QUADS);
  339.   for (i = 0; i < NCONTFACES; i++) {
  340.     v = containernormals[i];
  341.     glNormal3f(v[0], -v[1], v[2]);
  342.     for (k = 3; k >= 0; k--) {
  343.       v = containercoords[containerfaces[i][k]];
  344.       glVertex3f(v[0] + OFFSETX, -(v[1] + OFFSETY), v[2] + OFFSETZ);
  345.     }
  346.   }
  347.   glEnd();
  348. }
  349. void
  350. drawAll(void)
  351. {
  352.   int i, j;
  353.   int piece;
  354.   char done[PIECES + 1];
  355.   float m[4][4];
  356.   build_rotmatrix(m, curquat);
  357.   glMatrixMode(GL_MODELVIEW);
  358.   glLoadIdentity();
  359.   glTranslatef(0, 0, -10);
  360.   glMultMatrixf(&(m[0][0]));
  361.   glRotatef(180, 0, 0, 1);
  362.   if (depth) {
  363.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  364.   } else {
  365.     glClear(GL_COLOR_BUFFER_BIT);
  366.   }
  367.   for (i = 1; i <= PIECES; i++) {
  368.     done[i] = 0;
  369.   }
  370.   glLoadName(0);
  371.   drawContainer();
  372.   for (i = 0; i < HEIGHT; i++) {
  373.     for (j = 0; j < WIDTH; j++) {
  374.       piece = thePuzzle[i][j];
  375.       if (piece == 0)
  376.         continue;
  377.       if (done[piece])
  378.         continue;
  379.       done[piece] = 1;
  380.       glLoadName(piece);
  381.       if (piece == movingPiece) {
  382.         drawBox(piece, move_x, move_y);
  383.       } else {
  384.         drawBox(piece, j, i);
  385.       }
  386.     }
  387.   }
  388. }
  389. void
  390. redraw(void)
  391. {
  392.   glMatrixMode(GL_PROJECTION);
  393.   glLoadIdentity();
  394.   gluPerspective(45, 1.0, 0.1, 100.0);
  395.   drawAll();
  396.   if (doubleBuffer)
  397.     glutSwapBuffers();
  398.   else
  399.     glFinish();
  400. }
  401. void
  402. solidifyChain(struct puzzle *puzzle)
  403. {
  404.   int i;
  405.   char buf[256];
  406.   i = 0;
  407.   while (puzzle->backptr) {
  408.     i++;
  409.     puzzle->backptr->solnptr = puzzle;
  410.     puzzle = puzzle->backptr;
  411.   }
  412.   sprintf(buf, "%d moves to complete!", i);
  413.   glutSetWindowTitle(buf);
  414. }
  415. int
  416. addConfig(Config config, struct puzzle *back)
  417. {
  418.   unsigned hashvalue;
  419.   struct puzzle *newpiece;
  420.   struct puzzlelist *newlistentry;
  421.   hashvalue = hash(config);
  422.   newpiece = hashtable[hashvalue % HASHSIZE];
  423.   while (newpiece != NULL) {
  424.     if (newpiece->hashvalue == hashvalue) {
  425.       int i, j;
  426.       for (i = 0; i < WIDTH; i++) {
  427.         for (j = 0; j < HEIGHT; j++) {
  428.           if (convert[config[j][i]] !=
  429.             convert[newpiece->pieces[j][i]])
  430.             goto nomatch;
  431.         }
  432.       }
  433.       return 0;
  434.     }
  435.   nomatch:
  436.     newpiece = newpiece->next;
  437.   }
  438.   newpiece = (struct puzzle *) malloc(sizeof(struct puzzle));
  439.   newpiece->next = hashtable[hashvalue % HASHSIZE];
  440.   newpiece->hashvalue = hashvalue;
  441.   memcpy(newpiece->pieces, config, HEIGHT * WIDTH);
  442.   newpiece->backptr = back;
  443.   newpiece->solnptr = NULL;
  444.   hashtable[hashvalue % HASHSIZE] = newpiece;
  445.   newlistentry = (struct puzzlelist *) malloc(sizeof(struct puzzlelist));
  446.   newlistentry->puzzle = newpiece;
  447.   newlistentry->next = NULL;
  448.   if (lastentry) {
  449.     lastentry->next = newlistentry;
  450.   } else {
  451.     puzzles = newlistentry;
  452.   }
  453.   lastentry = newlistentry;
  454.   if (back == NULL) {
  455.     startPuzzle = newpiece;
  456.   }
  457.   if (solution(config)) {
  458.     solidifyChain(newpiece);
  459.     return 1;
  460.   }
  461.   return 0;
  462. }
  463. /* Checks if a space can move */
  464. int
  465. canmove0(Config pieces, int x, int y, int dir, Config newpieces)
  466. {
  467.   char piece;
  468.   int xadd, yadd;
  469.   int l, m;
  470.   xadd = xadds[dir];
  471.   yadd = yadds[dir];
  472.   if (x + xadd < 0 || x + xadd >= WIDTH ||
  473.     y + yadd < 0 || y + yadd >= HEIGHT)
  474.     return 0;
  475.   piece = pieces[y + yadd][x + xadd];
  476.   if (piece == 0)
  477.     return 0;
  478.   memcpy(newpieces, pieces, HEIGHT * WIDTH);
  479.   for (l = 0; l < WIDTH; l++) {
  480.     for (m = 0; m < HEIGHT; m++) {
  481.       if (newpieces[m][l] == piece)
  482.         newpieces[m][l] = 0;
  483.     }
  484.   }
  485.   xadd = -xadd;
  486.   yadd = -yadd;
  487.   for (l = 0; l < WIDTH; l++) {
  488.     for (m = 0; m < HEIGHT; m++) {
  489.       if (pieces[m][l] == piece) {
  490.         int newx, newy;
  491.         newx = l + xadd;
  492.         newy = m + yadd;
  493.         if (newx < 0 || newx >= WIDTH ||
  494.           newy < 0 || newy >= HEIGHT)
  495.           return 0;
  496.         if (newpieces[newy][newx] != 0)
  497.           return 0;
  498.         newpieces[newy][newx] = piece;
  499.       }
  500.     }
  501.   }
  502.   return 1;
  503. }
  504. /* Checks if a piece can move */
  505. int
  506. canmove(Config pieces, int x, int y, int dir, Config newpieces)
  507. {
  508.   int xadd, yadd;
  509.   xadd = xadds[dir];
  510.   yadd = yadds[dir];
  511.   if (x + xadd < 0 || x + xadd >= WIDTH ||
  512.     y + yadd < 0 || y + yadd >= HEIGHT)
  513.     return 0;
  514.   if (pieces[y + yadd][x + xadd] == pieces[y][x]) {
  515.     return canmove(pieces, x + xadd, y + yadd, dir, newpieces);
  516.   }
  517.   if (pieces[y + yadd][x + xadd] != 0)
  518.     return 0;
  519.   return canmove0(pieces, x + xadd, y + yadd, (dir + 2) % 4, newpieces);
  520. }
  521. int
  522. generateNewConfigs(struct puzzle *puzzle)
  523. {
  524.   int i, j, k;
  525.   Config pieces;
  526.   Config newpieces;
  527.   memcpy(pieces, puzzle->pieces, HEIGHT * WIDTH);
  528.   for (i = 0; i < WIDTH; i++) {
  529.     for (j = 0; j < HEIGHT; j++) {
  530.       if (pieces[j][i] == 0) {
  531.         for (k = 0; k < 4; k++) {
  532.           if (canmove0(pieces, i, j, k, newpieces)) {
  533.             if (addConfig(newpieces, puzzle))
  534.               return 1;
  535.           }
  536.         }
  537.       }
  538.     }
  539.   }
  540.   return 0;
  541. }
  542. void
  543. freeSolutions(void)
  544. {
  545.   struct puzzlelist *nextpuz;
  546.   struct puzzle *puzzle, *next;
  547.   int i;
  548.   while (puzzles) {
  549.     nextpuz = puzzles->next;
  550.     free((char *) puzzles);
  551.     puzzles = nextpuz;
  552.   }
  553.   lastentry = NULL;
  554.   for (i = 0; i < HASHSIZE; i++) {
  555.     puzzle = hashtable[i];
  556.     hashtable[i] = NULL;
  557.     while (puzzle) {
  558.       next = puzzle->next;
  559.       free((char *) puzzle);
  560.       puzzle = next;
  561.     }
  562.   }
  563.   startPuzzle = NULL;
  564. }
  565. int
  566. continueSolving(void)
  567. {
  568.   struct puzzle *nextpuz;
  569.   int i, j;
  570.   int movedPiece;
  571.   int movedir;
  572.   int fromx, fromy;
  573.   int tox, toy;
  574.   if (startPuzzle == NULL)
  575.     return 0;
  576.   if (startPuzzle->solnptr == NULL) {
  577.     freeSolutions();
  578.     return 0;
  579.   }
  580.   nextpuz = startPuzzle->solnptr;
  581.   movedPiece = 0;
  582.   movedir = 0;
  583.   for (i = 0; i < HEIGHT; i++) {
  584.     for (j = 0; j < WIDTH; j++) {
  585.       if (startPuzzle->pieces[i][j] != nextpuz->pieces[i][j]) {
  586.         if (startPuzzle->pieces[i][j]) {
  587.           movedPiece = startPuzzle->pieces[i][j];
  588.           fromx = j;
  589.           fromy = i;
  590.           if (i < HEIGHT - 1 && nextpuz->pieces[i + 1][j] == movedPiece) {
  591.             movedir = 3;
  592.           } else {
  593.             movedir = 2;
  594.           }
  595.           goto found_piece;
  596.         } else {
  597.           movedPiece = nextpuz->pieces[i][j];
  598.           if (i < HEIGHT - 1 &&
  599.             startPuzzle->pieces[i + 1][j] == movedPiece) {
  600.             fromx = j;
  601.             fromy = i + 1;
  602.             movedir = 1;
  603.           } else {
  604.             fromx = j + 1;
  605.             fromy = i;
  606.             movedir = 0;
  607.           }
  608.           goto found_piece;
  609.         }
  610.       }
  611.     }
  612.   }
  613.   glutSetWindowTitle("What!  No change?");
  614.   freeSolutions();
  615.   return 0;
  616. found_piece:
  617.   if (!movingPiece) {
  618.     movingPiece = movedPiece;
  619.     move_x = fromx;
  620.     move_y = fromy;
  621.   }
  622.   move_x += xadds[movedir] * MOVE_SPEED;
  623.   move_y += yadds[movedir] * MOVE_SPEED;
  624.   tox = fromx + xadds[movedir];
  625.   toy = fromy + yadds[movedir];
  626.   if (move_x > tox - MOVE_SPEED / 2 && move_x < tox + MOVE_SPEED / 2 &&
  627.     move_y > toy - MOVE_SPEED / 2 && move_y < toy + MOVE_SPEED / 2) {
  628.     startPuzzle = nextpuz;
  629.     movingPiece = 0;
  630.   }
  631.   memcpy(thePuzzle, startPuzzle->pieces, HEIGHT * WIDTH);
  632.   changeState();
  633.   return 1;
  634. }
  635. int
  636. solvePuzzle(void)
  637. {
  638.   struct puzzlelist *nextpuz;
  639.   char buf[256];
  640.   int i;
  641.   if (solution(thePuzzle)) {
  642.     glutSetWindowTitle("Puzzle already solved!");
  643.     return 0;
  644.   }
  645.   addConfig(thePuzzle, NULL);
  646.   i = 0;
  647.   while (puzzles) {
  648.     i++;
  649.     if (generateNewConfigs(puzzles->puzzle))
  650.       break;
  651.     nextpuz = puzzles->next;
  652.     free((char *) puzzles);
  653.     puzzles = nextpuz;
  654.   }
  655.   if (puzzles == NULL) {
  656.     freeSolutions();
  657.     sprintf(buf, "I can't solve it! (%d positions examined)", i);
  658.     glutSetWindowTitle(buf);
  659.     return 1;
  660.   }
  661.   return 1;
  662. }
  663. int
  664. selectPiece(int mousex, int mousey)
  665. {
  666.   long hits;
  667.   GLuint selectBuf[1024];
  668.   GLuint closest;
  669.   GLuint dist;
  670.   glSelectBuffer(1024, selectBuf);
  671.   (void) glRenderMode(GL_SELECT);
  672.   glInitNames();
  673.   /* Because LoadName() won't work with no names on the stack */
  674.   glPushName(-1);
  675.   glMatrixMode(GL_PROJECTION);
  676.   glLoadIdentity();
  677.   gluPickMatrix(mousex, H - mousey, 4, 4, viewport);
  678.   gluPerspective(45, 1.0, 0.1, 100.0);
  679.   drawAll();
  680.   hits = glRenderMode(GL_RENDER);
  681.   if (hits <= 0) {
  682.     return 0;
  683.   }
  684.   closest = 0;
  685.   dist = 4294967295U;
  686.   while (hits) {
  687.     if (selectBuf[(hits - 1) * 4 + 1] < dist) {
  688.       dist = selectBuf[(hits - 1) * 4 + 1];
  689.       closest = selectBuf[(hits - 1) * 4 + 3];
  690.     }
  691.     hits--;
  692.   }
  693.   return closest;
  694. }
  695. void
  696. nukePiece(int piece)
  697. {
  698.   int i, j;
  699.   for (i = 0; i < HEIGHT; i++) {
  700.     for (j = 0; j < WIDTH; j++) {
  701.       if (thePuzzle[i][j] == piece) {
  702.         thePuzzle[i][j] = 0;
  703.       }
  704.     }
  705.   }
  706. }
  707. void
  708. multMatrices(const GLfloat a[16], const GLfloat b[16], GLfloat r[16])
  709. {
  710.   int i, j;
  711.   for (i = 0; i < 4; i++) {
  712.     for (j = 0; j < 4; j++) {
  713.       r[i * 4 + j] =
  714.         a[i * 4 + 0] * b[0 * 4 + j] +
  715.         a[i * 4 + 1] * b[1 * 4 + j] +
  716.         a[i * 4 + 2] * b[2 * 4 + j] +
  717.         a[i * 4 + 3] * b[3 * 4 + j];
  718.     }
  719.   }
  720. }
  721. void
  722. makeIdentity(GLfloat m[16])
  723. {
  724.   m[0 + 4 * 0] = 1;
  725.   m[0 + 4 * 1] = 0;
  726.   m[0 + 4 * 2] = 0;
  727.   m[0 + 4 * 3] = 0;
  728.   m[1 + 4 * 0] = 0;
  729.   m[1 + 4 * 1] = 1;
  730.   m[1 + 4 * 2] = 0;
  731.   m[1 + 4 * 3] = 0;
  732.   m[2 + 4 * 0] = 0;
  733.   m[2 + 4 * 1] = 0;
  734.   m[2 + 4 * 2] = 1;
  735.   m[2 + 4 * 3] = 0;
  736.   m[3 + 4 * 0] = 0;
  737.   m[3 + 4 * 1] = 0;
  738.   m[3 + 4 * 2] = 0;
  739.   m[3 + 4 * 3] = 1;
  740. }
  741. /*
  742.    ** inverse = invert(src)
  743.  */
  744. int
  745. invertMatrix(const GLfloat src[16], GLfloat inverse[16])
  746. {
  747.   int i, j, k, swap;
  748.   double t;
  749.   GLfloat temp[4][4];
  750.   for (i = 0; i < 4; i++) {
  751.     for (j = 0; j < 4; j++) {
  752.       temp[i][j] = src[i * 4 + j];
  753.     }
  754.   }
  755.   makeIdentity(inverse);
  756.   for (i = 0; i < 4; i++) {
  757.     /* 
  758.        ** Look for largest element in column */
  759.     swap = i;
  760.     for (j = i + 1; j < 4; j++) {
  761.       if (fabs(temp[j][i]) > fabs(temp[i][i])) {
  762.         swap = j;
  763.       }
  764.     }
  765.     if (swap != i) {
  766.       /* 
  767.          ** Swap rows. */
  768.       for (k = 0; k < 4; k++) {
  769.         t = temp[i][k];
  770.         temp[i][k] = temp[swap][k];
  771.         temp[swap][k] = t;
  772.         t = inverse[i * 4 + k];
  773.         inverse[i * 4 + k] = inverse[swap * 4 + k];
  774.         inverse[swap * 4 + k] = t;
  775.       }
  776.     }
  777.     if (temp[i][i] == 0) {
  778.       /* 
  779.          ** No non-zero pivot.  The matrix is singular, which
  780.          shouldn't ** happen.  This means the user gave us a
  781.          bad matrix. */
  782.       return 0;
  783.     }
  784.     t = temp[i][i];
  785.     for (k = 0; k < 4; k++) {
  786.       temp[i][k] /= t;
  787.       inverse[i * 4 + k] /= t;
  788.     }
  789.     for (j = 0; j < 4; j++) {
  790.       if (j != i) {
  791.         t = temp[j][i];
  792.         for (k = 0; k < 4; k++) {
  793.           temp[j][k] -= temp[i][k] * t;
  794.           inverse[j * 4 + k] -= inverse[i * 4 + k] * t;
  795.         }
  796.       }
  797.     }
  798.   }
  799.   return 1;
  800. }
  801. /*
  802.    ** This is a screwball function.  What it does is the following:
  803.    ** Given screen x and y coordinates, compute the corresponding object space 
  804.    **   x and y coordinates given that the object space z is 0.9 + OFFSETZ.
  805.    ** Since the tops of (most) pieces are at z = 0.9 + OFFSETZ, we use that 
  806.    **   number.
  807.  */
  808. int
  809. computeCoords(int piece, int mousex, int mousey,
  810.   GLfloat * selx, GLfloat * sely)
  811. {
  812.   GLfloat modelMatrix[16];
  813.   GLfloat projMatrix[16];
  814.   GLfloat finalMatrix[16];
  815.   GLfloat in[4];
  816.   GLfloat a, b, c, d;
  817.   GLfloat top, bot;
  818.   GLfloat z;
  819.   GLfloat w;
  820.   GLfloat height;
  821.   if (piece == 0)
  822.     return 0;
  823.   height = zsize[piece] - 0.1 + OFFSETZ;
  824.   glGetFloatv(GL_PROJECTION_MATRIX, projMatrix);
  825.   glGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix);
  826.   multMatrices(modelMatrix, projMatrix, finalMatrix);
  827.   if (!invertMatrix(finalMatrix, finalMatrix))
  828.     return 0;
  829.   in[0] = (2.0 * (mousex - viewport[0]) / viewport[2]) - 1;
  830.   in[1] = (2.0 * ((H - mousey) - viewport[1]) / viewport[3]) - 1;
  831.   a = in[0] * finalMatrix[0 * 4 + 2] +
  832.     in[1] * finalMatrix[1 * 4 + 2] +
  833.     finalMatrix[3 * 4 + 2];
  834.   b = finalMatrix[2 * 4 + 2];
  835.   c = in[0] * finalMatrix[0 * 4 + 3] +
  836.     in[1] * finalMatrix[1 * 4 + 3] +
  837.     finalMatrix[3 * 4 + 3];
  838.   d = finalMatrix[2 * 4 + 3];
  839.   /* 
  840.      ** Ok, now we need to solve for z: **   (a + b z) / (c + d 
  841.      z) = height. ** ("height" is the height in object space we 
  842.      want to solve z for) ** ** ==>  a + b z = height c +
  843.      height d z **      bz - height d z = height c - a ** z =
  844.      (height c - a) / (b - height d) */
  845.   top = height * c - a;
  846.   bot = b - height * d;
  847.   if (bot == 0.0)
  848.     return 0;
  849.   z = top / bot;
  850.   /* 
  851.      ** Ok, no problem. ** Now we solve for x and y.  We know
  852.      that w = c + d z, so we compute it. */
  853.   w = c + d * z;
  854.   /* 
  855.      ** Now for x and y: */
  856.   *selx = (in[0] * finalMatrix[0 * 4 + 0] +
  857.     in[1] * finalMatrix[1 * 4 + 0] +
  858.     z * finalMatrix[2 * 4 + 0] +
  859.     finalMatrix[3 * 4 + 0]) / w - OFFSETX;
  860.   *sely = (in[0] * finalMatrix[0 * 4 + 1] +
  861.     in[1] * finalMatrix[1 * 4 + 1] +
  862.     z * finalMatrix[2 * 4 + 1] +
  863.     finalMatrix[3 * 4 + 1]) / w - OFFSETY;
  864.   return 1;
  865. }
  866. static int selected;
  867. static int selectx, selecty;
  868. static float selstartx, selstarty;
  869. void
  870. grabPiece(int piece, float selx, float sely)
  871. {
  872.   int hit;
  873.   selectx = selx;
  874.   selecty = sely;
  875.   if (selectx < 0 || selecty < 0 || selectx >= WIDTH || selecty >= HEIGHT) {
  876.     return;
  877.   }
  878.   hit = thePuzzle[selecty][selectx];
  879.   if (hit != piece)
  880.     return;
  881.   if (hit) {
  882.     movingPiece = hit;
  883.     while (selectx > 0 && thePuzzle[selecty][selectx - 1] == movingPiece) {
  884.       selectx--;
  885.     }
  886.     while (selecty > 0 && thePuzzle[selecty - 1][selectx] == movingPiece) {
  887.       selecty--;
  888.     }
  889.     move_x = selectx;
  890.     move_y = selecty;
  891.     selected = 1;
  892.     selstartx = selx;
  893.     selstarty = sely;
  894.   } else {
  895.     selected = 0;
  896.   }
  897.   changeState();
  898. }
  899. void
  900. moveSelection(float selx, float sely)
  901. {
  902.   float deltax, deltay;
  903.   int dir;
  904.   Config newpieces;
  905.   if (!selected)
  906.     return;
  907.   deltax = selx - selstartx;
  908.   deltay = sely - selstarty;
  909.   if (fabs(deltax) > fabs(deltay)) {
  910.     deltay = 0;
  911.     if (deltax > 0) {
  912.       if (deltax > 1)
  913.         deltax = 1;
  914.       dir = 2;
  915.     } else {
  916.       if (deltax < -1)
  917.         deltax = -1;
  918.       dir = 0;
  919.     }
  920.   } else {
  921.     deltax = 0;
  922.     if (deltay > 0) {
  923.       if (deltay > 1)
  924.         deltay = 1;
  925.       dir = 3;
  926.     } else {
  927.       if (deltay < -1)
  928.         deltay = -1;
  929.       dir = 1;
  930.     }
  931.   }
  932.   if (canmove(thePuzzle, selectx, selecty, dir, newpieces)) {
  933.     move_x = deltax + selectx;
  934.     move_y = deltay + selecty;
  935.     if (deltax > 0.5) {
  936.       memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
  937.       selectx++;
  938.       selstartx++;
  939.     } else if (deltax < -0.5) {
  940.       memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
  941.       selectx--;
  942.       selstartx--;
  943.     } else if (deltay > 0.5) {
  944.       memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
  945.       selecty++;
  946.       selstarty++;
  947.     } else if (deltay < -0.5) {
  948.       memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
  949.       selecty--;
  950.       selstarty--;
  951.     }
  952.   } else {
  953.     if (deltay > 0 && thePuzzle[selecty][selectx] == 10 &&
  954.       selectx == 1 && selecty == 3) {
  955.       /* Allow visual movement of solution piece outside of the 
  956.          box */
  957.       move_x = selectx;
  958.       move_y = sely - selstarty + selecty;
  959.     } else {
  960.       move_x = selectx;
  961.       move_y = selecty;
  962.     }
  963.   }
  964. }
  965. void
  966. dropSelection(void)
  967. {
  968.   if (!selected)
  969.     return;
  970.   movingPiece = 0;
  971.   selected = 0;
  972.   changeState();
  973. }
  974. static int left_mouse, middle_mouse;
  975. static int mousex, mousey;
  976. static int solving;
  977. static int spinning;
  978. static float lastquat[4];
  979. static int sel_piece;
  980. static void
  981. Reshape(int width, int height)
  982. {
  983.   W = width;
  984.   H = height;
  985.   glViewport(0, 0, W, H);
  986.   glGetIntegerv(GL_VIEWPORT, viewport);
  987. }
  988. void
  989. toggleSolve(void)
  990. {
  991.     if (solving) {
  992.       freeSolutions();
  993.       solving = 0;
  994.       glutChangeToMenuEntry(1, "Solving", 1);
  995.       glutSetWindowTitle("glpuzzle");
  996.       movingPiece = 0;
  997.     } else {
  998.       glutChangeToMenuEntry(1, "Stop solving", 1);
  999.       glutSetWindowTitle("Solving...");
  1000.       if (solvePuzzle()) {
  1001.         solving = 1;
  1002.       }
  1003.     }
  1004.     changeState();
  1005.     glutPostRedisplay();
  1006. }
  1007. void reset(void)
  1008. {
  1009.     if (solving) {
  1010.       freeSolutions();
  1011.       solving = 0;
  1012.       glutChangeToMenuEntry(1, "Solving", 1);
  1013.       movingPiece = 0;
  1014.       changeState();
  1015.     }
  1016.     glutSetWindowTitle("glpuzzle");
  1017.     memcpy(thePuzzle, startConfig, HEIGHT * WIDTH);
  1018.     glutPostRedisplay();
  1019. }
  1020. void
  1021. keyboard(unsigned char c, int x, int y)
  1022. {
  1023.   int piece;
  1024.   switch (c) {
  1025.   case 27:
  1026.     exit(0);
  1027.     break;
  1028.   case 'D':
  1029.   case 'd':
  1030.     if (solving) {
  1031.       freeSolutions();
  1032.       solving = 0;
  1033.       glutChangeToMenuEntry(1, "Solving", 1);
  1034.       glutSetWindowTitle("glpuzzle");
  1035.       movingPiece = 0;
  1036.       changeState();
  1037.     }
  1038.     piece = selectPiece(x, y);
  1039.     if (piece) {
  1040.       nukePiece(piece);
  1041.     }
  1042.     glutPostRedisplay();
  1043.     break;
  1044.   case 'R':
  1045.   case 'r':
  1046.     reset();
  1047.     break;
  1048.   case 'S':
  1049.   case 's':
  1050.     toggleSolve();
  1051.     break;
  1052.   case 'b':
  1053.   case 'B':
  1054.     depth = 1 - depth;
  1055.     if (depth) {
  1056.       glEnable(GL_DEPTH_TEST);
  1057.     } else {
  1058.       glDisable(GL_DEPTH_TEST);
  1059.     }
  1060.     glutPostRedisplay();
  1061.     break;
  1062.   default:
  1063.     break;
  1064.   }
  1065. }
  1066. void
  1067. motion(int x, int y)
  1068. {
  1069.   float selx, sely;
  1070.   if (middle_mouse && !left_mouse) {
  1071.     if (mousex != x || mousey != y) {
  1072.       trackball(lastquat,
  1073.         (2.0*mousex - W) / W,
  1074.         (H - 2.0*mousey) / H,
  1075.         (2.0*x - W) / W,
  1076.         (H - 2.0*y) / H);
  1077.       spinning = 1;
  1078.     } else {
  1079.       spinning = 0;
  1080.     }
  1081.     changeState();
  1082.   } else {
  1083.     computeCoords(sel_piece, x, y, &selx, &sely);
  1084.     moveSelection(selx, sely);
  1085.   }
  1086.   mousex = x;
  1087.   mousey = y;
  1088.   glutPostRedisplay();
  1089. }
  1090. void
  1091. mouse(int b, int s, int x, int y)
  1092. {
  1093.   float selx, sely;
  1094.   mousex = x;
  1095.   mousey = y;
  1096.   curX = x;
  1097.   curY = y;
  1098.   if (s == GLUT_DOWN) {
  1099.     switch (b) {
  1100.     case GLUT_LEFT_BUTTON:
  1101.       if (solving) {
  1102.         freeSolutions();
  1103.         solving = 0;
  1104.       glutChangeToMenuEntry(1, "Solving", 1);
  1105.         glutSetWindowTitle("glpuzzle");
  1106.         movingPiece = 0;
  1107.       }
  1108.       left_mouse = GL_TRUE;
  1109.       sel_piece = selectPiece(mousex, mousey);
  1110.       if (computeCoords(sel_piece, mousex, mousey, &selx, &sely)) {
  1111.         grabPiece(sel_piece, selx, sely);
  1112.       }
  1113.       glutPostRedisplay();
  1114.       break;
  1115.     case GLUT_MIDDLE_BUTTON:
  1116.       middle_mouse = GL_TRUE;
  1117.       glutPostRedisplay();
  1118.       break;
  1119.     }
  1120.   } else {
  1121.     switch (b) {
  1122.     case GLUT_LEFT_BUTTON:
  1123.       left_mouse = GL_FALSE;
  1124.       dropSelection();
  1125.       glutPostRedisplay();
  1126.       break;
  1127.     case GLUT_MIDDLE_BUTTON:
  1128.       middle_mouse = GL_FALSE;
  1129.       glutPostRedisplay();
  1130.       break;
  1131.     }
  1132.   }
  1133.   motion(x, y);
  1134. }
  1135. void
  1136. animate(void)
  1137. {
  1138.   if (spinning) {
  1139.     add_quats(lastquat, curquat, curquat);
  1140.   }
  1141.   glutPostRedisplay();
  1142.   if (solving) {
  1143.     if (!continueSolving()) {
  1144.       solving = 0;
  1145.       glutChangeToMenuEntry(1, "Solving", 1);
  1146.       glutSetWindowTitle("glpuzzle");
  1147.     }
  1148.   }
  1149.   if (!solving && !spinning && !visible) {
  1150.     glutIdleFunc(NULL);
  1151.   }
  1152. }
  1153. void
  1154. changeState(void)
  1155. {
  1156.   if (visible) {
  1157.     if (!solving && !spinning) {
  1158.       glutIdleFunc(NULL);
  1159.     } else {
  1160.       glutIdleFunc(animate);
  1161.     }
  1162.   } else {
  1163.     glutIdleFunc(NULL);
  1164.   }
  1165. }
  1166. void
  1167. init(void)
  1168. {
  1169.   static float lmodel_ambient[] =
  1170.   {0.0, 0.0, 0.0, 0.0};
  1171.   static float lmodel_twoside[] =
  1172.   {GL_FALSE};
  1173.   static float lmodel_local[] =
  1174.   {GL_FALSE};
  1175.   static float light0_ambient[] =
  1176.   {0.1, 0.1, 0.1, 1.0};
  1177.   static float light0_diffuse[] =
  1178.   {1.0, 1.0, 1.0, 0.0};
  1179.   static float light0_position[] =
  1180.   {0.8660254, 0.5, 1, 0};
  1181.   static float light0_specular[] =
  1182.   {0.0, 0.0, 0.0, 0.0};
  1183.   static float bevel_mat_ambient[] =
  1184.   {0.0, 0.0, 0.0, 1.0};
  1185.   static float bevel_mat_shininess[] =
  1186.   {40.0};
  1187.   static float bevel_mat_specular[] =
  1188.   {0.0, 0.0, 0.0, 0.0};
  1189.   static float bevel_mat_diffuse[] =
  1190.   {1.0, 0.0, 0.0, 0.0};
  1191.   glEnable(GL_CULL_FACE);
  1192.   glCullFace(GL_BACK);
  1193.   glEnable(GL_DEPTH_TEST);
  1194.   glClearDepth(1.0);
  1195.   glClearColor(0.5, 0.5, 0.5, 0.0);
  1196.   glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
  1197.   glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
  1198.   glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
  1199.   glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
  1200.   glEnable(GL_LIGHT0);
  1201.   glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_local);
  1202.   glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
  1203.   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
  1204.   glEnable(GL_LIGHTING);
  1205.   glMaterialfv(GL_FRONT, GL_AMBIENT, bevel_mat_ambient);
  1206.   glMaterialfv(GL_FRONT, GL_SHININESS, bevel_mat_shininess);
  1207.   glMaterialfv(GL_FRONT, GL_SPECULAR, bevel_mat_specular);
  1208.   glMaterialfv(GL_FRONT, GL_DIFFUSE, bevel_mat_diffuse);
  1209.   glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
  1210.   glEnable(GL_COLOR_MATERIAL);
  1211.   glShadeModel(GL_FLAT);
  1212.   trackball(curquat, 0.0, 0.0, 0.0, 0.0);
  1213.   srandom(time(NULL));
  1214. }
  1215. static void
  1216. Usage(void)
  1217. {
  1218.   printf("Usage: puzzle [-s]n");
  1219.   printf("   -s:  Run in single buffered moden");
  1220.   exit(-1);
  1221. }
  1222. void
  1223. visibility(int v)
  1224. {
  1225.   if (v == GLUT_VISIBLE) {
  1226.     visible = 1;
  1227.   } else {
  1228.     visible = 0;
  1229.   }
  1230.   changeState();
  1231. }
  1232. void
  1233. menu(int choice)
  1234. {
  1235.    switch(choice) {
  1236.    case 1:
  1237.       toggleSolve();
  1238.       break;
  1239.    case 2:
  1240.       reset();
  1241.       break;
  1242.    case 3:
  1243.       exit(0);
  1244.       break;
  1245.    }
  1246. }
  1247. int
  1248. main(int argc, char **argv)
  1249. {
  1250.   long i;
  1251.   glutInit(&argc, argv);
  1252.   for (i = 1; i < argc; i++) {
  1253.     if (argv[i][0] == '-') {
  1254.       switch (argv[i][1]) {
  1255.       case 's':
  1256.         doubleBuffer = 0;
  1257.         break;
  1258.       default:
  1259.         Usage();
  1260.       }
  1261.     } else {
  1262.       Usage();
  1263.     }
  1264.   }
  1265.   glutInitWindowSize(W, H);
  1266.   if (doubleBuffer) {
  1267.     glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE);
  1268.   } else {
  1269.     glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_SINGLE | GLUT_MULTISAMPLE);
  1270.   }
  1271.   glutCreateWindow("glpuzzle");
  1272.   init();
  1273.   glGetIntegerv(GL_VIEWPORT, viewport);
  1274.   printf("n");
  1275.   printf("r   Reset puzzlen");
  1276.   printf("s   Solve puzzle (may take a few seconds to compute)n");
  1277.   printf("d   Destroy a piece - makes the puzzle easiern");
  1278.   printf("b   Toggles the depth buffer on and offn");
  1279.   printf("n");
  1280.   printf("Left mouse moves piecesn");
  1281.   printf("Middle mouse spins the puzzlen");
  1282.   printf("Right mouse has menun");
  1283.   glutReshapeFunc(Reshape);
  1284.   glutDisplayFunc(redraw);
  1285.   glutKeyboardFunc(keyboard);
  1286.   glutMotionFunc(motion);
  1287.   glutMouseFunc(mouse);
  1288.   glutVisibilityFunc(visibility);
  1289.   glutCreateMenu(menu);
  1290.   glutAddMenuEntry("Solve", 1);
  1291.   glutAddMenuEntry("Reset", 2);
  1292.   glutAddMenuEntry("Quit", 3);
  1293.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  1294.   glutMainLoop();
  1295.   return 0;             /* ANSI C requires main to return int. */
  1296. }