ftp://ftp.uni-heidelberg.de/pub/X11/contrib/applications/xscreensaver-2.07.tar.gz
[xscreensaver] / hacks / glx / rubik.c
1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* rubik --- Shows a self-solving Rubik's cube */
3
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)rubik.c       4.04 97/07/28 xlockmore";
6
7 #endif
8
9 #undef DEBUG_LISTS
10
11 /*-
12  * Permission to use, copy, modify, and distribute this software and its
13  * documentation for any purpose and without fee is hereby granted,
14  * provided that the above copyright notice appear in all copies and that
15  * both that copyright notice and this permission notice appear in
16  * supporting documentation.
17  *
18  * This file is provided AS IS with no warranties of any kind.  The author
19  * shall have no liability with respect to the infringement of copyrights,
20  * trade secrets or any patents by this file or any part thereof.  In no
21  * event will the author be liable for any lost revenue or profits or
22  * other special, indirect and consequential damages.
23  *
24  * This mode shows a self solving rubik's cube "puzzle". If somebody
25  * intends to make a game or something based on this code, please let me
26  * know first, my e-mail address is provided in this comment. Marcelo.
27  *
28  * Thanks goes also to Brian Paul for making it possible and inexpensive
29  * to use OpenGL at home.
30  *
31  * Since I'm not a native english speaker, my apologies for any gramatical
32  * mistake.
33  *
34  * My e-mail addresses are
35  * vianna@cat.cbpf.br 
36  *         and
37  * marcelo@venus.rdc.puc-rio.br
38  *
39  * Marcelo F. Vianna (Jul-31-1997)
40  *
41  * Revision History:
42  * 02-Aug-97: Now behaves more like puzzle.c: first show the cube being
43  *            shuffled and then being solved. A mode specific option was added:
44  *            "+/-hideshuffling" to provide the original behavior (in which
45  *            only the solution is shown).
46  *            The color labels corners are now rounded.
47  *            Optimized the cubit() routine using glLists.
48  * 01-Aug-97: Shuffling now avoids movements that undoes the previous movement
49  *            and three consecutive identical moves (which is pretty stupid).
50  *            improved the "cycles" option in replacement of David's hack,
51  *            now rp->anglestep is a GLfloat, so this option selects the
52  *            "exact" number of frames that a rotation (movement) takes to
53  *            complete.
54  * 30-Jul-97: Initial release, there is no algorithm to solve the puzzle,
55  *            instead, it randomly shuffle the cube and then make the
56  *            movements in the reverse order.
57  *            The mode was written in 1 day (I got sick and had a license
58  *            at work...) There was not much to do since I could not exit
59  *            from home... :)
60  *
61  */
62
63 /*-
64  * Color labels mapping:
65  * =====================
66  *
67  *                       +------------+
68  *                       |          22|
69  *                       |            |
70  *                       |            |
71  *                       |   TOP(0)   |
72  *                       |^           |
73  *                       ||           |
74  *                       |00-->       |
75  *           +-----------+------------+-----------+
76  *           |         22|          22|         22|
77  *           |           |            |           |
78  *           |           |            |           |
79  *           |  LEFT(1)  |  FRONT(2)  |  RIGHT(3) |
80  *           |^          |^           |^          |
81  *           ||          ||           ||          |
82  *           |00-->      |00-->       |00-->      |
83  *           +-----------+------------+-----------+
84  *                       |          22|
85  *                       |            |
86  *                       |            |
87  *                       |  BOTTOM(4) |  rp->faces[N][X][Y]=
88  *                       |^           |         F_[N][X][Y]=
89  *                       ||           | 
90  *                       |00-->       |         +---+---+---+
91  *                       +------------+         |   |   |XY |
92  *                       |          22|         |02 |12 |22 |
93  *                       |            |         |---+---+---+
94  *                       |            |         |  xxxxx(N) |
95  *                       |   BACK(5)  |         |01 |11 |21 |
96  *                       |^           |         +---+---+---+
97  *                       ||           |         |XY |   |   |
98  *                       |00-->       |         |00 |10 |20 |
99  *                       +------------+         +---+---+---+
100  *
101  *  Map to 3d
102  *  FRONT  => X, Y
103  *  BACK   => X, Y
104  *  LEFT   => Z, Y
105  *  RIGHT  => Z, Y
106  *  TOP    => X, Z
107  *  BOTTOM => X, Z
108  */
109
110 /*-
111  * PURIFY 3.0a on SunOS4 reports an unitialized memory read on each of
112  * the glCallList() functions below when using MesaGL 2.1.  This has
113  * been fixed in MesaGL 2.2 and later releases.
114  */
115
116 /*-
117  * due to a Bug/feature in VMS X11/Intrinsic.h has to be placed before xlock.
118  * otherwise caddr_t is not defined correctly
119  */
120 #include <X11/Intrinsic.h>
121 #include <string.h>
122
123 #ifdef STANDALONE
124 # define PROGCLASS      "Rubik"
125 # define HACK_INIT      init_rubik
126 # define HACK_DRAW      draw_rubik
127 # define rubik_opts     xlockmore_opts
128 # define DEFAULTS       "*delay: 50000 \n"              \
129                                         "*count: -30 \n"                \
130                                         "*cycles: 5 \n"
131 # include "xlockmore.h"                         /* from the xscreensaver distribution */
132 #else /* !STANDALONE */
133 # include "xlock.h"                                     /* from the xlockmore distribution */
134 #endif /* !STANDALONE */
135
136 #ifdef USE_GL
137
138 #define DEF_HIDESHUFFLING     "False"
139
140 static Bool hideshuffling;
141
142 static XrmOptionDescRec opts[] =
143 {
144   {"-hideshuffling", ".rubik.hideshuffling", XrmoptionNoArg, (caddr_t) "on"},
145   {"+hideshuffling", ".rubik.hideshuffling", XrmoptionNoArg, (caddr_t) "off"}
146 };
147
148 static argtype vars[] =
149 {
150         {(caddr_t *) & hideshuffling, "hideshuffling", "Hideshuffling", DEF_HIDESHUFFLING, t_Bool}
151 };
152
153 static OptionStruct desc[] =
154 {
155         {"-/+hideshuffling", "turn on/off hidden shuffle phase"}
156 };
157
158 ModeSpecOpt rubik_opts =
159 {2, opts, 1, vars, desc};
160
161 #define Scale4Window               0.3
162 #define Scale4Iconic               0.7
163
164 #define VectMul(X1,Y1,Z1,X2,Y2,Z2) (Y1)*(Z2)-(Z1)*(Y2),(Z1)*(X2)-(X1)*(Z2),(X1)*(Y2)-(Y1)*(X2)
165 #define sqr(A)                     ((A)*(A))
166
167 #ifndef Pi
168 #define Pi                         M_PI
169 #endif
170
171 #define NO_ROTATION    -1
172 #define TOP_ROTATION    0
173 #define LEFT_ROTATION   1
174 #define FRONT_ROTATION  2
175 #define RIGHT_ROTATION  3
176 #define BOTTOM_ROTATION 4
177 #define BACK_ROTATION   5
178
179 #define CLOCK_WISE      0
180 #define C_CLOCK_WISE    1
181
182 #define ACTION_SOLVE    1
183 #define ACTION_SHUFFLE  0
184
185 #define DELAY_AFTER_SHUFFLING  5
186 #define DELAY_AFTER_SOLVING   20
187
188 #define F_ rp->faces
189
190 /*************************************************************************/
191
192 /*-
193  * Ignore trivial case, since it adds needless complications.
194  * MAXSIZE must be 2 or greater.
195  */
196
197 #define MAXSIZEX 3
198 #define MAXSIZEY 3
199 #define MAXSIZEZ 3
200 #define MAXSIZE (MAX(MAX(MAXSIZEX,MAXSIZEY),MAXSIZEZ))
201 #define MAXSIZEXY (MAXSIZEX*MAXSIZEY)
202 #define MAXSIZEZY (MAXSIZEZ*MAXSIZEY)
203 #define MAXSIZEXZ (MAXSIZEX*MAXSIZEZ)
204 #define MAXSIZESQ (MAX(MAX(MAXSIZEXY,MAXSIZEZY),MAXSIZEXZ))
205 #define LAST (MAXSIZE-1)
206 #define LASTX (MAXSIZEX-1)
207 #define LASTY (MAXSIZEY-1)
208 #define LASTZ (MAXSIZEZ-1)
209
210 typedef struct {
211         GLint       WindH, WindW;
212         GLfloat     step;
213         char       *movedfaces;
214         char       *movedorient;
215         int         storedmoves;
216         int         shufflingmoves;
217         int         action;
218         int         done;
219         GLfloat     anglestep;
220         char        faces[6][MAXSIZE][MAXSIZE];
221         int         movement;
222         int         orientation;
223         GLfloat     rotatestep;
224         GLXContext  glx_context;
225         int         AreObjectsDefined[1];
226 } rubikstruct;
227
228 static float front_shininess[] =
229 {60.0};
230 static float front_specular[] =
231 {0.7, 0.7, 0.7, 1.0};
232 static float ambient[] =
233 {0.0, 0.0, 0.0, 1.0};
234 static float diffuse[] =
235 {1.0, 1.0, 1.0, 1.0};
236 static float position0[] =
237 {1.0, 1.0, 1.0, 0.0};
238 static float position1[] =
239 {-1.0, -1.0, 1.0, 0.0};
240 static float lmodel_ambient[] =
241 {0.5, 0.5, 0.5, 1.0};
242 static float lmodel_twoside[] =
243 {GL_TRUE};
244
245 static float MaterialRed[] =
246 {0.5, 0.0, 0.0, 1.0};
247 static float MaterialGreen[] =
248 {0.0, 0.5, 0.0, 1.0};
249 static float MaterialBlue[] =
250 {0.0, 0.0, 0.5, 1.0};
251 static float MaterialYellow[] =
252 {0.7, 0.7, 0.0, 1.0};
253 static float MaterialOrange[] =
254 {1.0, 0.5, 0.4, 1.0};
255
256 #if 0
257 static float MaterialMagenta[] =
258 {0.7, 0.0, 0.7, 1.0};
259 static float MaterialCyan[] =
260 {0.0, 0.7, 0.7, 1.0};
261
262 #endif
263 static float MaterialWhite[] =
264 {0.8, 0.8, 0.8, 1.0};
265 static float MaterialGray[] =
266 {0.2, 0.2, 0.2, 1.0};
267
268 static rubikstruct *rubik = NULL;
269 static GLuint objects;
270
271 #define ObjCubit        0
272
273 static void
274 pickcolor(char C)
275 {
276         switch (C) {
277                 case 'R':
278                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
279                         break;
280                 case 'G':
281                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGreen);
282                         break;
283                 case 'B':
284                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialBlue);
285                         break;
286                 case 'Y':
287                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialYellow);
288                         break;
289 #if 0
290                 case 'C':
291                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialCyan);
292                         break;
293                 case 'M':
294                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialMagenta);
295                         break;
296 #else
297                 case 'O':
298                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialOrange);
299                         break;
300                 case 'W':
301                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
302                         break;
303 #endif
304         }
305 }
306
307 static void
308 draw_cubit(ModeInfo * mi, char BACK, char FRONT, char LEFT, char RIGHT, char BOTTOM, char TOP)
309 {
310         rubikstruct *rp = &rubik[MI_SCREEN(mi)];
311
312         if (!rp->AreObjectsDefined[ObjCubit]) {
313                 glNewList(objects + ObjCubit, GL_COMPILE_AND_EXECUTE);
314                 glBegin(GL_QUADS);
315                 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
316                 glNormal3f(0.00, 0.00, 1.00);
317                 glVertex3f(-0.45, -0.45, 0.50);
318                 glVertex3f(0.45, -0.45, 0.50);
319                 glVertex3f(0.45, 0.45, 0.50);
320                 glVertex3f(-0.45, 0.45, 0.50);
321                 glNormal3f(0.00, 0.00, -1.00);
322                 glVertex3f(-0.45, 0.45, -0.50);
323                 glVertex3f(0.45, 0.45, -0.50);
324                 glVertex3f(0.45, -0.45, -0.50);
325                 glVertex3f(-0.45, -0.45, -0.50);
326                 glNormal3f(-1.00, 0.00, 0.00);
327                 glVertex3f(-0.50, -0.45, 0.45);
328                 glVertex3f(-0.50, 0.45, 0.45);
329                 glVertex3f(-0.50, 0.45, -0.45);
330                 glVertex3f(-0.50, -0.45, -0.45);
331                 glNormal3f(1.00, 0.00, 0.00);
332                 glVertex3f(0.50, -0.45, -0.45);
333                 glVertex3f(0.50, 0.45, -0.45);
334                 glVertex3f(0.50, 0.45, 0.45);
335                 glVertex3f(0.50, -0.45, 0.45);
336                 glNormal3f(0.00, -1.00, 0.00);
337                 glVertex3f(0.45, -0.50, -0.45);
338                 glVertex3f(0.45, -0.50, 0.45);
339                 glVertex3f(-0.45, -0.50, 0.45);
340                 glVertex3f(-0.45, -0.50, -0.45);
341                 glNormal3f(0.00, 1.00, 0.00);
342                 glVertex3f(-0.45, 0.50, -0.45);
343                 glVertex3f(-0.45, 0.50, 0.45);
344                 glVertex3f(0.45, 0.50, 0.45);
345                 glVertex3f(0.45, 0.50, -0.45);
346                 glNormal3f(-1.00, -1.00, 0.00);
347                 glVertex3f(-0.45, -0.50, -0.45);
348                 glVertex3f(-0.45, -0.50, 0.45);
349                 glVertex3f(-0.50, -0.45, 0.45);
350                 glVertex3f(-0.50, -0.45, -0.45);
351                 glNormal3f(1.00, 1.00, 0.00);
352                 glVertex3f(0.45, 0.50, -0.45);
353                 glVertex3f(0.45, 0.50, 0.45);
354                 glVertex3f(0.50, 0.45, 0.45);
355                 glVertex3f(0.50, 0.45, -0.45);
356                 glNormal3f(-1.00, 1.00, 0.00);
357                 glVertex3f(-0.50, 0.45, -0.45);
358                 glVertex3f(-0.50, 0.45, 0.45);
359                 glVertex3f(-0.45, 0.50, 0.45);
360                 glVertex3f(-0.45, 0.50, -0.45);
361                 glNormal3f(1.00, -1.00, 0.00);
362                 glVertex3f(0.50, -0.45, -0.45);
363                 glVertex3f(0.50, -0.45, 0.45);
364                 glVertex3f(0.45, -0.50, 0.45);
365                 glVertex3f(0.45, -0.50, -0.45);
366                 glNormal3f(0.00, -1.00, -1.00);
367                 glVertex3f(-0.45, -0.45, -0.50);
368                 glVertex3f(0.45, -0.45, -0.50);
369                 glVertex3f(0.45, -0.50, -0.45);
370                 glVertex3f(-0.45, -0.50, -0.45);
371                 glNormal3f(0.00, 1.00, 1.00);
372                 glVertex3f(-0.45, 0.45, 0.50);
373                 glVertex3f(0.45, 0.45, 0.50);
374                 glVertex3f(0.45, 0.50, 0.45);
375                 glVertex3f(-0.45, 0.50, 0.45);
376                 glNormal3f(0.00, -1.00, 1.00);
377                 glVertex3f(-0.45, -0.50, 0.45);
378                 glVertex3f(0.45, -0.50, 0.45);
379                 glVertex3f(0.45, -0.45, 0.50);
380                 glVertex3f(-0.45, -0.45, 0.50);
381                 glNormal3f(0.00, 1.00, -1.00);
382                 glVertex3f(-0.45, 0.50, -0.45);
383                 glVertex3f(0.45, 0.50, -0.45);
384                 glVertex3f(0.45, 0.45, -0.50);
385                 glVertex3f(-0.45, 0.45, -0.50);
386                 glNormal3f(-1.00, 0.00, -1.00);
387                 glVertex3f(-0.50, -0.45, -0.45);
388                 glVertex3f(-0.50, 0.45, -0.45);
389                 glVertex3f(-0.45, 0.45, -0.50);
390                 glVertex3f(-0.45, -0.45, -0.50);
391                 glNormal3f(1.00, 0.00, 1.00);
392                 glVertex3f(0.50, -0.45, 0.45);
393                 glVertex3f(0.50, 0.45, 0.45);
394                 glVertex3f(0.45, 0.45, 0.50);
395                 glVertex3f(0.45, -0.45, 0.50);
396                 glNormal3f(1.00, 0.00, -1.00);
397                 glVertex3f(0.45, -0.45, -0.50);
398                 glVertex3f(0.45, 0.45, -0.50);
399                 glVertex3f(0.50, 0.45, -0.45);
400                 glVertex3f(0.50, -0.45, -0.45);
401                 glNormal3f(-1.00, 0.00, 1.00);
402                 glVertex3f(-0.45, -0.45, 0.50);
403                 glVertex3f(-0.45, 0.45, 0.50);
404                 glVertex3f(-0.50, 0.45, 0.45);
405                 glVertex3f(-0.50, -0.45, 0.45);
406                 glEnd();
407                 glBegin(GL_TRIANGLES);
408                 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
409                 glNormal3f(1.00, 1.00, 1.00);
410                 glVertex3f(0.45, 0.45, 0.50);
411                 glVertex3f(0.50, 0.45, 0.45);
412                 glVertex3f(0.45, 0.50, 0.45);
413                 glNormal3f(-1.00, -1.00, -1.00);
414                 glVertex3f(-0.45, -0.50, -0.45);
415                 glVertex3f(-0.50, -0.45, -0.45);
416                 glVertex3f(-0.45, -0.45, -0.50);
417                 glNormal3f(-1.00, 1.00, 1.00);
418                 glVertex3f(-0.45, 0.45, 0.50);
419                 glVertex3f(-0.45, 0.50, 0.45);
420                 glVertex3f(-0.50, 0.45, 0.45);
421                 glNormal3f(1.00, -1.00, -1.00);
422                 glVertex3f(0.50, -0.45, -0.45);
423                 glVertex3f(0.45, -0.50, -0.45);
424                 glVertex3f(0.45, -0.45, -0.50);
425                 glNormal3f(1.00, -1.00, 1.00);
426                 glVertex3f(0.45, -0.45, 0.50);
427                 glVertex3f(0.45, -0.50, 0.45);
428                 glVertex3f(0.50, -0.45, 0.45);
429                 glNormal3f(-1.00, 1.00, -1.00);
430                 glVertex3f(-0.50, 0.45, -0.45);
431                 glVertex3f(-0.45, 0.50, -0.45);
432                 glVertex3f(-0.45, 0.45, -0.50);
433                 glNormal3f(-1.00, -1.00, 1.00);
434                 glVertex3f(-0.45, -0.45, 0.50);
435                 glVertex3f(-0.50, -0.45, 0.45);
436                 glVertex3f(-0.45, -0.50, 0.45);
437                 glNormal3f(1.00, 1.00, -1.00);
438                 glVertex3f(0.50, 0.45, -0.45);
439                 glVertex3f(0.45, 0.45, -0.50);
440                 glVertex3f(0.45, 0.50, -0.45);
441                 glEnd();
442                 glEndList();
443                 rp->AreObjectsDefined[ObjCubit] = 1;
444 #ifdef DEBUG_LISTS
445                 (void) printf("Cubit drawn SLOWLY\n");
446 #endif
447         } else {
448                 glCallList(objects + ObjCubit);
449 #ifdef DEBUG_LISTS
450                 (void) printf("Cubit drawn quickly\n");
451 #endif
452         }
453
454         if (BACK != ' ') {
455                 glBegin(GL_POLYGON);
456                 pickcolor(BACK);
457                 glNormal3f(0.00, 0.00, -1.00);
458                 glVertex3f(-0.35, 0.40, -0.51);
459                 glVertex3f(0.35, 0.40, -0.51);
460                 glVertex3f(0.40, 0.35, -0.51);
461                 glVertex3f(0.40, -0.35, -0.51);
462                 glVertex3f(0.35, -0.40, -0.51);
463                 glVertex3f(-0.35, -0.40, -0.51);
464                 glVertex3f(-0.40, -0.35, -0.51);
465                 glVertex3f(-0.40, 0.35, -0.51);
466                 glEnd();
467         }
468         if (FRONT != ' ') {
469                 glBegin(GL_POLYGON);
470                 pickcolor(FRONT);
471                 glNormal3f(0.00, 0.00, 1.00);
472                 glVertex3f(-0.35, -0.40, 0.51);
473                 glVertex3f(0.35, -0.40, 0.51);
474                 glVertex3f(0.40, -0.35, 0.51);
475                 glVertex3f(0.40, 0.35, 0.51);
476                 glVertex3f(0.35, 0.40, 0.51);
477                 glVertex3f(-0.35, 0.40, 0.51);
478                 glVertex3f(-0.40, 0.35, 0.51);
479                 glVertex3f(-0.40, -0.35, 0.51);
480                 glEnd();
481         }
482         if (LEFT != ' ') {
483                 glBegin(GL_POLYGON);
484                 pickcolor(LEFT);
485                 glNormal3f(-1.00, 0.00, 0.00);
486                 glVertex3f(-0.51, -0.35, 0.40);
487                 glVertex3f(-0.51, 0.35, 0.40);
488                 glVertex3f(-0.51, 0.40, 0.35);
489                 glVertex3f(-0.51, 0.40, -0.35);
490                 glVertex3f(-0.51, 0.35, -0.40);
491                 glVertex3f(-0.51, -0.35, -0.40);
492                 glVertex3f(-0.51, -0.40, -0.35);
493                 glVertex3f(-0.51, -0.40, 0.35);
494                 glEnd();
495         }
496         if (RIGHT != ' ') {
497                 glBegin(GL_POLYGON);
498                 pickcolor(RIGHT);
499                 glNormal3f(1.00, 0.00, 0.00);
500                 glVertex3f(0.51, -0.35, -0.40);
501                 glVertex3f(0.51, 0.35, -0.40);
502                 glVertex3f(0.51, 0.40, -0.35);
503                 glVertex3f(0.51, 0.40, 0.35);
504                 glVertex3f(0.51, 0.35, 0.40);
505                 glVertex3f(0.51, -0.35, 0.40);
506                 glVertex3f(0.51, -0.40, 0.35);
507                 glVertex3f(0.51, -0.40, -0.35);
508                 glEnd();
509         }
510         if (BOTTOM != ' ') {
511                 glBegin(GL_POLYGON);
512                 pickcolor(BOTTOM);
513                 glNormal3f(0.00, -1.00, 0.00);
514                 glVertex3f(0.40, -0.51, -0.35);
515                 glVertex3f(0.40, -0.51, 0.35);
516                 glVertex3f(0.35, -0.51, 0.40);
517                 glVertex3f(-0.35, -0.51, 0.40);
518                 glVertex3f(-0.40, -0.51, 0.35);
519                 glVertex3f(-0.40, -0.51, -0.35);
520                 glVertex3f(-0.35, -0.51, -0.40);
521                 glVertex3f(0.35, -0.51, -0.40);
522                 glEnd();
523         }
524         if (TOP != ' ') {
525                 glBegin(GL_POLYGON);
526                 pickcolor(TOP);
527                 glNormal3f(0.00, 1.00, 0.00);
528                 glVertex3f(-0.40, 0.51, -0.35);
529                 glVertex3f(-0.40, 0.51, 0.35);
530                 glVertex3f(-0.35, 0.51, 0.40);
531                 glVertex3f(0.35, 0.51, 0.40);
532                 glVertex3f(0.40, 0.51, 0.35);
533                 glVertex3f(0.40, 0.51, -0.35);
534                 glVertex3f(0.35, 0.51, -0.40);
535                 glVertex3f(-0.35, 0.51, -0.40);
536                 glEnd();
537         }
538         glEnd();
539 }
540
541 static void
542 draw_cube(ModeInfo * mi)
543 {
544 #define S1 1
545 #define S2 (S1*2)
546         rubikstruct *rp = &rubik[MI_SCREEN(mi)];
547
548         switch (rp->movement) {
549                 case NO_ROTATION:
550                 case BACK_ROTATION:
551                 case FRONT_ROTATION:
552                         glPushMatrix();
553                         if (rp->movement == BACK_ROTATION)
554                                 glRotatef(-rp->rotatestep, 0, 0, 1);
555                         glTranslatef(-S1, -S1, -S1);
556                         draw_cubit(mi, F_[BACK_ROTATION][0][LAST], ' ',
557                                    F_[LEFT_ROTATION][0][0], ' ',
558                                    F_[BOTTOM_ROTATION][0][0], ' ');
559                         glTranslatef(S1, 0, 0);
560                         draw_cubit(mi, F_[BACK_ROTATION][1][LAST], ' ',
561                                    ' ', ' ',
562                                    F_[BOTTOM_ROTATION][1][0], ' ');
563                         glTranslatef(S1, 0, 0);
564                         draw_cubit(mi, F_[BACK_ROTATION][LAST][LAST], ' ',
565                                    ' ', F_[RIGHT_ROTATION][LAST][0],
566                                    F_[BOTTOM_ROTATION][LAST][0], ' ');
567                         glTranslatef(-S2, S1, 0);
568                         draw_cubit(mi, F_[BACK_ROTATION][0][1], ' ',
569                                    F_[LEFT_ROTATION][0][1], ' ',
570                                    ' ', ' ');
571                         glTranslatef(S1, 0, 0);
572                         draw_cubit(mi, F_[BACK_ROTATION][1][1], ' ',
573                                    ' ', ' ',
574                                    ' ', ' ');
575                         glTranslatef(S1, 0, 0);
576                         draw_cubit(mi, F_[BACK_ROTATION][LAST][1], ' ',
577                                    ' ', F_[RIGHT_ROTATION][LAST][1],
578                                    ' ', ' ');
579                         glTranslatef(-S2, S1, 0);
580                         draw_cubit(mi, F_[BACK_ROTATION][0][0], ' ',
581                                    F_[LEFT_ROTATION][0][LAST], ' ',
582                                    ' ', F_[TOP_ROTATION][0][LAST]);
583                         glTranslatef(S1, 0, 0);
584                         draw_cubit(mi, F_[BACK_ROTATION][1][0], ' ',
585                                    ' ', ' ',
586                                    ' ', F_[TOP_ROTATION][1][LAST]);
587                         glTranslatef(S1, 0, 0);
588                         draw_cubit(mi, F_[BACK_ROTATION][LAST][0], ' ',
589                                    ' ', F_[RIGHT_ROTATION][LAST][LAST],
590                                    ' ', F_[TOP_ROTATION][LAST][LAST]);
591                         glPopMatrix();
592                         glPushMatrix();
593                         glTranslatef(-S1, -S1, 0);
594                         draw_cubit(mi, ' ', ' ',
595                                    F_[LEFT_ROTATION][1][0], ' ',
596                                    F_[BOTTOM_ROTATION][0][1], ' ');
597                         glTranslatef(S1, 0, 0);
598                         draw_cubit(mi, ' ', ' ',
599                                    ' ', ' ',
600                                    F_[BOTTOM_ROTATION][1][1], ' ');
601                         glTranslatef(S1, 0, 0);
602                         draw_cubit(mi, ' ', ' ',
603                                    ' ', F_[RIGHT_ROTATION][1][0],
604                                    F_[BOTTOM_ROTATION][LAST][1], ' ');
605                         glTranslatef(-S2, S1, 0);
606                         draw_cubit(mi, ' ', ' ',
607                                    F_[LEFT_ROTATION][1][1], ' ',
608                                    ' ', ' ');
609                         glTranslatef(2, 0, 0);
610                         draw_cubit(mi, ' ', ' ',
611                                    ' ', F_[RIGHT_ROTATION][1][1],
612                                    ' ', ' ');
613                         glTranslatef(-S2, S1, 0);
614                         draw_cubit(mi, ' ', ' ',
615                                    F_[LEFT_ROTATION][1][LAST], ' ',
616                                    ' ', F_[TOP_ROTATION][0][1]);
617                         glTranslatef(S1, 0, 0);
618                         draw_cubit(mi, ' ', ' ',
619                                    ' ', ' ',
620                                    ' ', F_[TOP_ROTATION][1][1]);
621                         glTranslatef(S1, 0, 0);
622                         draw_cubit(mi, ' ', ' ',
623                                    ' ', F_[RIGHT_ROTATION][1][LAST],
624                                    ' ', F_[TOP_ROTATION][LAST][1]);
625                         glPopMatrix();
626                         if (rp->movement == FRONT_ROTATION)
627                                 glRotatef(rp->rotatestep, 0, 0, 1);
628                         glTranslatef(-S1, -S1, S1);
629                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][0][0],
630                                    F_[LEFT_ROTATION][LAST][0], ' ',
631                                    F_[BOTTOM_ROTATION][0][LAST], ' ');
632                         glTranslatef(S1, 0, 0);
633                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][1][0],
634                                    ' ', ' ',
635                                    F_[BOTTOM_ROTATION][1][LAST], ' ');
636                         glTranslatef(S1, 0, 0);
637                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][LASTX][0],
638                                    ' ', F_[RIGHT_ROTATION][0][0],
639                                    F_[BOTTOM_ROTATION][LAST][LAST], ' ');
640                         glTranslatef(-S2, S1, 0);
641                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][0][1],
642                                    F_[LEFT_ROTATION][LAST][1], ' ',
643                                    ' ', ' ');
644                         glTranslatef(S1, 0, 0);
645                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][1][1],
646                                    ' ', ' ',
647                                    ' ', ' ');
648                         glTranslatef(S1, 0, 0);
649                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][LASTX][1],
650                                    ' ', F_[RIGHT_ROTATION][0][1],
651                                    ' ', ' ');
652                         glTranslatef(-S2, S1, 0);
653                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][0][LASTY],
654                                    F_[LEFT_ROTATION][LAST][LAST], ' ',
655                                    ' ', F_[TOP_ROTATION][0][0]);
656                         glTranslatef(S1, 0, 0);
657                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][1][LASTY],
658                                    ' ', ' ',
659                                    ' ', F_[TOP_ROTATION][1][0]);
660                         glTranslatef(S1, 0, 0);
661                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][LASTX][LASTY],
662                                    ' ', F_[RIGHT_ROTATION][0][LAST],
663                                    ' ', F_[TOP_ROTATION][LAST][0]);
664                         break;
665                 case LEFT_ROTATION:
666                 case RIGHT_ROTATION:
667                         glPushMatrix();
668                         if (rp->movement == LEFT_ROTATION)
669                                 glRotatef(-rp->rotatestep, 1, 0, 0);
670                         glTranslatef(-S1, -S1, -S1);
671                         draw_cubit(mi, F_[BACK_ROTATION][0][LAST], ' ',
672                                    F_[LEFT_ROTATION][0][0], ' ',
673                                    F_[BOTTOM_ROTATION][0][0], ' ');
674                         glTranslatef(0, S1, 0);
675                         draw_cubit(mi, F_[BACK_ROTATION][0][1], ' ',
676                                    F_[LEFT_ROTATION][0][1], ' ',
677                                    ' ', ' ');
678                         glTranslatef(0, S1, 0);
679                         draw_cubit(mi, F_[BACK_ROTATION][0][0], ' ',
680                                    F_[LEFT_ROTATION][0][LAST], ' ',
681                                    ' ', F_[TOP_ROTATION][0][LAST]);
682                         glTranslatef(0, -S2, S1);
683                         draw_cubit(mi, ' ', ' ',
684                                    F_[LEFT_ROTATION][1][0], ' ',
685                                    F_[BOTTOM_ROTATION][0][1], ' ');
686                         glTranslatef(0, S1, 0);
687                         draw_cubit(mi, ' ', ' ',
688                                    F_[LEFT_ROTATION][1][1], ' ',
689                                    ' ', ' ');
690                         glTranslatef(0, S1, 0);
691                         draw_cubit(mi, ' ', ' ',
692                                    F_[LEFT_ROTATION][1][LAST], ' ',
693                                    ' ', F_[TOP_ROTATION][0][1]);
694                         glTranslatef(0, -S2, S1);
695                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][0][0],
696                                    F_[LEFT_ROTATION][LAST][0], ' ',
697                                    F_[BOTTOM_ROTATION][0][LAST], ' ');
698                         glTranslatef(0, S1, 0);
699                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][0][1],
700                                    F_[LEFT_ROTATION][LAST][1], ' ',
701                                    ' ', ' ');
702                         glTranslatef(0, S1, 0);
703                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][0][LASTY],
704                                    F_[LEFT_ROTATION][LAST][LAST], ' ',
705                                    ' ', F_[TOP_ROTATION][0][0]);
706                         glPopMatrix();
707                         glPushMatrix();
708                         glTranslatef(0, -S1, -S1);
709                         draw_cubit(mi, F_[BACK_ROTATION][1][LAST], ' ',
710                                    ' ', ' ',
711                                    F_[BOTTOM_ROTATION][1][0], ' ');
712                         glTranslatef(0, S1, 0);
713                         draw_cubit(mi, F_[BACK_ROTATION][1][1], ' ',
714                                    ' ', ' ',
715                                    ' ', ' ');
716                         glTranslatef(0, S1, 0);
717                         draw_cubit(mi, F_[BACK_ROTATION][1][0], ' ',
718                                    ' ', ' ',
719                                    ' ', F_[TOP_ROTATION][1][LAST]);
720                         glTranslatef(0, -S2, S1);
721                         draw_cubit(mi, ' ', ' ',
722                                    ' ', ' ',
723                                    F_[BOTTOM_ROTATION][1][1], ' ');
724                         glTranslatef(0, S2, 0);
725                         draw_cubit(mi, ' ', ' ',
726                                    ' ', ' ',
727                                    ' ', F_[TOP_ROTATION][1][1]);
728                         glTranslatef(0, -S2, S1);
729                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][1][0],
730                                    ' ', ' ',
731                                    F_[BOTTOM_ROTATION][1][LAST], ' ');
732                         glTranslatef(0, S1, 0);
733                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][1][1],
734                                    ' ', ' ',
735                                    ' ', ' ');
736                         glTranslatef(0, S1, 0);
737                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][1][LASTY],
738                                    ' ', ' ',
739                                    ' ', F_[TOP_ROTATION][1][0]);
740                         glPopMatrix();
741                         if (rp->movement == RIGHT_ROTATION)
742                                 glRotatef(rp->rotatestep, 1, 0, 0);
743                         glTranslatef(S1, -S1, -S1);
744                         draw_cubit(mi, F_[BACK_ROTATION][LAST][LAST], ' ',
745                                    ' ', F_[RIGHT_ROTATION][LAST][0],
746                                    F_[BOTTOM_ROTATION][LAST][0], ' ');
747                         glTranslatef(0, S1, 0);
748                         draw_cubit(mi, F_[BACK_ROTATION][LAST][1], ' ',
749                                    ' ', F_[RIGHT_ROTATION][LAST][1],
750                                    ' ', ' ');
751                         glTranslatef(0, S1, 0);
752                         draw_cubit(mi, F_[BACK_ROTATION][LAST][0], ' ',
753                                    ' ', F_[RIGHT_ROTATION][LAST][LAST],
754                                    ' ', F_[TOP_ROTATION][LAST][LAST]);
755                         glTranslatef(0, -S2, S1);
756                         draw_cubit(mi, ' ', ' ',
757                                    ' ', F_[RIGHT_ROTATION][1][0],
758                                    F_[BOTTOM_ROTATION][LAST][1], ' ');
759                         glTranslatef(0, S1, 0);
760                         draw_cubit(mi, ' ', ' ',
761                                    ' ', F_[RIGHT_ROTATION][1][1],
762                                    ' ', ' ');
763                         glTranslatef(0, S1, 0);
764                         draw_cubit(mi, ' ', ' ',
765                                    ' ', F_[RIGHT_ROTATION][1][LAST],
766                                    ' ', F_[TOP_ROTATION][LAST][1]);
767                         glTranslatef(0, -S2, S1);
768                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][LASTX][0],
769                                    ' ', F_[RIGHT_ROTATION][0][0],
770                                    F_[BOTTOM_ROTATION][LAST][LAST], ' ');
771                         glTranslatef(0, S1, 0);
772                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][LASTX][1],
773                                    ' ', F_[RIGHT_ROTATION][0][1],
774                                    ' ', ' ');
775                         glTranslatef(0, S1, 0);
776                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][LASTX][LASTY],
777                                    ' ', F_[RIGHT_ROTATION][0][LAST],
778                                    ' ', F_[TOP_ROTATION][LAST][0]);
779                         break;
780                 case BOTTOM_ROTATION:
781                 case TOP_ROTATION:
782                         glPushMatrix();
783                         if (rp->movement == BOTTOM_ROTATION)
784                                 glRotatef(-rp->rotatestep, 0, 1, 0);
785                         glTranslatef(-S1, -S1, -S1);
786                         draw_cubit(mi, F_[BACK_ROTATION][0][LAST], ' ',
787                                    F_[LEFT_ROTATION][0][0], ' ',
788                                    F_[BOTTOM_ROTATION][0][0], ' ');
789                         glTranslatef(0, 0, S1);
790                         draw_cubit(mi, ' ', ' ',
791                                    F_[LEFT_ROTATION][1][0], ' ',
792                                    F_[BOTTOM_ROTATION][0][1], ' ');
793                         glTranslatef(0, 0, S1);
794                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][0][0],
795                                    F_[LEFT_ROTATION][LAST][0], ' ',
796                                    F_[BOTTOM_ROTATION][0][LAST], ' ');
797                         glTranslatef(S1, 0, -S2);
798                         draw_cubit(mi, F_[BACK_ROTATION][1][LAST], ' ',
799                                    ' ', ' ',
800                                    F_[BOTTOM_ROTATION][1][0], ' ');
801                         glTranslatef(0, 0, S1);
802                         draw_cubit(mi, ' ', ' ',
803                                    ' ', ' ',
804                                    F_[BOTTOM_ROTATION][1][1], ' ');
805                         glTranslatef(0, 0, S1);
806                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][1][0],
807                                    ' ', ' ',
808                                    F_[BOTTOM_ROTATION][1][LAST], ' ');
809                         glTranslatef(1, 0, -S2);
810                         draw_cubit(mi, F_[BACK_ROTATION][LAST][LAST], ' ',
811                                    ' ', F_[RIGHT_ROTATION][LAST][0],
812                                    F_[BOTTOM_ROTATION][LAST][0], ' ');
813                         glTranslatef(0, 0, S1);
814                         draw_cubit(mi, ' ', ' ',
815                                    ' ', F_[RIGHT_ROTATION][1][0],
816                                    F_[BOTTOM_ROTATION][LAST][1], ' ');
817                         glTranslatef(0, 0, S1);
818                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][LASTX][0],
819                                    ' ', F_[RIGHT_ROTATION][0][0],
820                                    F_[BOTTOM_ROTATION][LAST][LAST], ' ');
821                         glPopMatrix();
822                         glPushMatrix();
823                         glTranslatef(-S1, 0, -S1);
824                         draw_cubit(mi, F_[BACK_ROTATION][0][1], ' ',
825                                    F_[LEFT_ROTATION][0][1], ' ',
826                                    ' ', ' ');
827                         glTranslatef(0, 0, S1);
828                         draw_cubit(mi, ' ', ' ',
829                                    F_[LEFT_ROTATION][1][1], ' ',
830                                    ' ', ' ');
831                         glTranslatef(0, 0, S1);
832                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][0][1],
833                                    F_[LEFT_ROTATION][LAST][1], ' ',
834                                    ' ', ' ');
835                         glTranslatef(1, 0, -S2);
836                         draw_cubit(mi, F_[BACK_ROTATION][1][1], ' ',
837                                    ' ', ' ',
838                                    ' ', ' ');
839                         glTranslatef(0, 0, S2);
840                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][1][1],
841                                    ' ', ' ',
842                                    ' ', ' ');
843                         glTranslatef(S1, 0, -S2);
844                         draw_cubit(mi, F_[BACK_ROTATION][LAST][1], ' ',
845                                    ' ', F_[RIGHT_ROTATION][LAST][1],
846                                    ' ', ' ');
847                         glTranslatef(0, 0, S1);
848                         draw_cubit(mi, ' ', ' ',
849                                    ' ', F_[RIGHT_ROTATION][1][1],
850                                    ' ', ' ');
851                         glTranslatef(0, 0, S1);
852                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][LASTX][1],
853                                    ' ', F_[RIGHT_ROTATION][0][1],
854                                    ' ', ' ');
855                         glPopMatrix();
856                         if (rp->movement == TOP_ROTATION)
857                                 glRotatef(rp->rotatestep, 0, 1, 0);
858                         glTranslatef(-S1, S1, -S1);
859                         draw_cubit(mi, F_[BACK_ROTATION][0][0], ' ',
860                                    F_[LEFT_ROTATION][0][LAST], ' ',
861                                    ' ', F_[TOP_ROTATION][0][LAST]);
862                         glTranslatef(0, 0, S1);
863                         draw_cubit(mi, ' ', ' ',
864                                    F_[LEFT_ROTATION][1][LAST], ' ',
865                                    ' ', F_[TOP_ROTATION][0][1]);
866                         glTranslatef(0, 0, S1);
867                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][0][LASTY],
868                                    F_[LEFT_ROTATION][LAST][LAST], ' ',
869                                    ' ', F_[TOP_ROTATION][0][0]);
870                         glTranslatef(S1, 0, -S2);
871                         draw_cubit(mi, F_[BACK_ROTATION][1][0], ' ',
872                                    ' ', ' ',
873                                    ' ', F_[TOP_ROTATION][1][LAST]);
874                         glTranslatef(0, 0, S1);
875                         draw_cubit(mi, ' ', ' ',
876                                    ' ', ' ',
877                                    ' ', F_[TOP_ROTATION][1][1]);
878                         glTranslatef(0, 0, S1);
879                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][1][LASTY],
880                                    ' ', ' ',
881                                    ' ', F_[TOP_ROTATION][1][0]);
882                         glTranslatef(S1, 0, -S2);
883                         draw_cubit(mi, F_[BACK_ROTATION][LAST][0], ' ',
884                                    ' ', F_[RIGHT_ROTATION][LAST][LAST],
885                                    ' ', F_[TOP_ROTATION][LAST][LAST]);
886                         glTranslatef(0, 0, S1);
887                         draw_cubit(mi, ' ', ' ',
888                                    ' ', F_[RIGHT_ROTATION][1][LAST],
889                                    ' ', F_[TOP_ROTATION][LAST][1]);
890                         glTranslatef(0, 0, S1);
891                         draw_cubit(mi, ' ', F_[FRONT_ROTATION][LASTX][LASTY],
892                                    ' ', F_[RIGHT_ROTATION][0][LAST],
893                                    ' ', F_[TOP_ROTATION][LAST][0]);
894                         break;
895         }
896 #undef S1
897 #undef S2
898 }
899
900 static void
901 evalmovement(ModeInfo * mi, int face, char orient)
902 {
903         rubikstruct *rp = &rubik[MI_SCREEN(mi)];
904         char        T1, T2, T3;
905
906         if (face < 0 || face > 5)
907                 return;
908
909         if (orient == CLOCK_WISE) {
910                 T1 = F_[face][0][LAST];
911                 T2 = F_[face][1][LAST];
912                 F_[face][0][LAST] = F_[face][0][0];
913                 F_[face][1][LAST] = F_[face][0][1];
914                 F_[face][0][0] = F_[face][LAST][0];
915                 F_[face][0][1] = F_[face][1][0];
916                 F_[face][1][0] = F_[face][LAST][1];
917                 F_[face][LAST][0] = F_[face][LAST][LAST];
918                 F_[face][LAST][LAST] = T1;      /* F_[face][0][LAST]; */
919                 F_[face][LAST][1] = T2;         /* F_[face][1][LAST]; */
920         } else {
921                 T1 = F_[face][0][0];
922                 T2 = F_[face][0][1];
923                 F_[face][0][0] = F_[face][0][LAST];
924                 F_[face][0][1] = F_[face][1][LAST];
925                 F_[face][0][LAST] = F_[face][LAST][LAST];
926                 F_[face][1][LAST] = F_[face][LAST][1];
927                 F_[face][LAST][1] = F_[face][1][0];
928                 F_[face][LAST][LAST] = F_[face][LAST][0];
929                 F_[face][1][0] = T2;    /* F_[face][0][1]; */
930                 F_[face][LAST][0] = T1;         /* F_[face][0][0]; */
931         }
932
933         switch (face) {
934                 case BACK_ROTATION:
935                         if (orient == CLOCK_WISE) {
936                                 T1 = F_[BOTTOM_ROTATION][0][0];
937                                 T2 = F_[BOTTOM_ROTATION][1][0];
938                                 T3 = F_[BOTTOM_ROTATION][LAST][0];
939                                 F_[BOTTOM_ROTATION][0][0] = F_[LEFT_ROTATION][0][LAST];
940                                 F_[BOTTOM_ROTATION][1][0] = F_[LEFT_ROTATION][0][1];
941                                 F_[BOTTOM_ROTATION][LAST][0] = F_[LEFT_ROTATION][0][0];
942                                 F_[LEFT_ROTATION][0][0] = F_[TOP_ROTATION][0][LAST];
943                                 F_[LEFT_ROTATION][0][1] = F_[TOP_ROTATION][1][LAST];
944                                 F_[LEFT_ROTATION][0][LAST] = F_[TOP_ROTATION][LAST][LAST];
945                                 F_[TOP_ROTATION][0][LAST] = F_[RIGHT_ROTATION][LAST][LAST];
946                                 F_[TOP_ROTATION][1][LAST] = F_[RIGHT_ROTATION][LAST][1];
947                                 F_[TOP_ROTATION][LAST][LAST] = F_[RIGHT_ROTATION][LAST][0];
948                                 F_[RIGHT_ROTATION][LAST][0] = T1;       /* F_[BOTTOM_ROTATION][0][0]; */
949                                 F_[RIGHT_ROTATION][LAST][1] = T2;       /* F_[BOTTOM_ROTATION][1][0]; */
950                                 F_[RIGHT_ROTATION][LAST][LAST] = T3;    /* F_[BOTTOM_ROTATION][LAST][0]; */
951                         } else {
952                                 T1 = F_[LEFT_ROTATION][0][LAST];
953                                 T2 = F_[LEFT_ROTATION][0][1];
954                                 T3 = F_[LEFT_ROTATION][0][0];
955                                 F_[LEFT_ROTATION][0][LAST] = F_[BOTTOM_ROTATION][0][0];
956                                 F_[LEFT_ROTATION][0][1] = F_[BOTTOM_ROTATION][1][0];
957                                 F_[LEFT_ROTATION][0][0] = F_[BOTTOM_ROTATION][LAST][0];
958                                 F_[BOTTOM_ROTATION][0][0] = F_[RIGHT_ROTATION][LAST][0];
959                                 F_[BOTTOM_ROTATION][1][0] = F_[RIGHT_ROTATION][LAST][1];
960                                 F_[BOTTOM_ROTATION][LAST][0] = F_[RIGHT_ROTATION][LAST][LAST];
961                                 F_[RIGHT_ROTATION][LAST][LAST] = F_[TOP_ROTATION][0][LAST];
962                                 F_[RIGHT_ROTATION][LAST][1] = F_[TOP_ROTATION][1][LAST];
963                                 F_[RIGHT_ROTATION][LAST][0] = F_[TOP_ROTATION][LAST][LAST];
964                                 F_[TOP_ROTATION][0][LAST] = T3;         /* F_[LEFT_ROTATION][0][0]; */
965                                 F_[TOP_ROTATION][1][LAST] = T2;         /* F_[LEFT_ROTATION][0][1]; */
966                                 F_[TOP_ROTATION][LAST][LAST] = T1;      /* F_[LEFT_ROTATION][0][LAST]; */
967                         }
968                         break;
969                 case FRONT_ROTATION:
970                         if (orient == CLOCK_WISE) {
971                                 T1 = F_[RIGHT_ROTATION][0][LAST];
972                                 T2 = F_[RIGHT_ROTATION][0][1];
973                                 T3 = F_[RIGHT_ROTATION][0][0];
974                                 F_[RIGHT_ROTATION][0][LAST] = F_[TOP_ROTATION][0][0];
975                                 F_[RIGHT_ROTATION][0][1] = F_[TOP_ROTATION][1][0];
976                                 F_[RIGHT_ROTATION][0][0] = F_[TOP_ROTATION][LAST][0];
977                                 F_[TOP_ROTATION][0][0] = F_[LEFT_ROTATION][LAST][0];
978                                 F_[TOP_ROTATION][1][0] = F_[LEFT_ROTATION][LAST][1];
979                                 F_[TOP_ROTATION][LAST][0] = F_[LEFT_ROTATION][LAST][LAST];
980                                 F_[LEFT_ROTATION][LAST][LAST] = F_[BOTTOM_ROTATION][0][LAST];
981                                 F_[LEFT_ROTATION][LAST][1] = F_[BOTTOM_ROTATION][1][LAST];
982                                 F_[LEFT_ROTATION][LAST][0] = F_[BOTTOM_ROTATION][LAST][LAST];
983                                 F_[BOTTOM_ROTATION][0][LAST] = T3;      /* F_[RIGHT_ROTATION][0][0]; */
984                                 F_[BOTTOM_ROTATION][1][LAST] = T2;      /* F_[RIGHT_ROTATION][0][1]; */
985                                 F_[BOTTOM_ROTATION][LAST][LAST] = T1;   /* F_[RIGHT_ROTATION][0][LAST]; */
986                         } else {
987                                 T1 = F_[TOP_ROTATION][0][0];
988                                 T2 = F_[TOP_ROTATION][1][0];
989                                 T3 = F_[TOP_ROTATION][LAST][0];
990                                 F_[TOP_ROTATION][0][0] = F_[RIGHT_ROTATION][0][LAST];
991                                 F_[TOP_ROTATION][1][0] = F_[RIGHT_ROTATION][0][1];
992                                 F_[TOP_ROTATION][LAST][0] = F_[RIGHT_ROTATION][0][0];
993                                 F_[RIGHT_ROTATION][0][0] = F_[BOTTOM_ROTATION][0][LAST];
994                                 F_[RIGHT_ROTATION][0][1] = F_[BOTTOM_ROTATION][1][LAST];
995                                 F_[RIGHT_ROTATION][0][LAST] = F_[BOTTOM_ROTATION][LAST][LAST];
996                                 F_[BOTTOM_ROTATION][0][LAST] = F_[LEFT_ROTATION][LAST][LAST];
997                                 F_[BOTTOM_ROTATION][1][LAST] = F_[LEFT_ROTATION][LAST][1];
998                                 F_[BOTTOM_ROTATION][LAST][LAST] = F_[LEFT_ROTATION][LAST][0];
999                                 F_[LEFT_ROTATION][LAST][0] = T1;        /* F_[TOP_ROTATION][0][0]; */
1000                                 F_[LEFT_ROTATION][LAST][1] = T2;        /* F_[TOP_ROTATION][1][0]; */
1001                                 F_[LEFT_ROTATION][LAST][LAST] = T3;     /* F_[TOP_ROTATION][LAST][0]; */
1002                         }
1003                         break;
1004                 case LEFT_ROTATION:
1005                         if (orient == CLOCK_WISE) {
1006                                 T1 = F_[TOP_ROTATION][0][0];
1007                                 T2 = F_[TOP_ROTATION][0][1];
1008                                 T3 = F_[TOP_ROTATION][0][LAST];
1009                                 F_[TOP_ROTATION][0][0] = F_[BACK_ROTATION][0][0];
1010                                 F_[TOP_ROTATION][0][1] = F_[BACK_ROTATION][0][1];
1011                                 F_[TOP_ROTATION][0][LAST] = F_[BACK_ROTATION][0][LAST];
1012                                 F_[BACK_ROTATION][0][0] = F_[BOTTOM_ROTATION][0][0];
1013                                 F_[BACK_ROTATION][0][1] = F_[BOTTOM_ROTATION][0][1];
1014                                 F_[BACK_ROTATION][0][LAST] = F_[BOTTOM_ROTATION][0][LAST];
1015                                 F_[BOTTOM_ROTATION][0][0] = F_[FRONT_ROTATION][0][0];
1016                                 F_[BOTTOM_ROTATION][0][1] = F_[FRONT_ROTATION][0][1];
1017                                 F_[BOTTOM_ROTATION][0][LAST] = F_[FRONT_ROTATION][0][LASTY];
1018                                 F_[FRONT_ROTATION][0][0] = T1;  /* F_[TOP_ROTATION][0][0]; */
1019                                 F_[FRONT_ROTATION][0][1] = T2;  /* F_[TOP_ROTATION][0][1]; */
1020                                 F_[FRONT_ROTATION][0][LASTY] = T3;      /* F_[TOP_ROTATION][0][LAST]; */
1021                         } else {
1022                                 T1 = F_[BACK_ROTATION][0][0];
1023                                 T2 = F_[BACK_ROTATION][0][1];
1024                                 T3 = F_[BACK_ROTATION][0][LAST];
1025                                 F_[BACK_ROTATION][0][0] = F_[TOP_ROTATION][0][0];
1026                                 F_[BACK_ROTATION][0][1] = F_[TOP_ROTATION][0][1];
1027                                 F_[BACK_ROTATION][0][LAST] = F_[TOP_ROTATION][0][LAST];
1028                                 F_[TOP_ROTATION][0][0] = F_[FRONT_ROTATION][0][0];
1029                                 F_[TOP_ROTATION][0][1] = F_[FRONT_ROTATION][0][1];
1030                                 F_[TOP_ROTATION][0][LAST] = F_[FRONT_ROTATION][0][LASTY];
1031                                 F_[FRONT_ROTATION][0][0] = F_[BOTTOM_ROTATION][0][0];
1032                                 F_[FRONT_ROTATION][0][1] = F_[BOTTOM_ROTATION][0][1];
1033                                 F_[FRONT_ROTATION][0][LASTY] = F_[BOTTOM_ROTATION][0][LAST];
1034                                 F_[BOTTOM_ROTATION][0][0] = T1;         /* F_[BACK_ROTATION][0][0]; */
1035                                 F_[BOTTOM_ROTATION][0][1] = T2;         /* F_[BACK_ROTATION][0][1]; */
1036                                 F_[BOTTOM_ROTATION][0][LAST] = T3;      /* F_[BACK_ROTATION][0][LAST]; */
1037                         }
1038                         break;
1039                 case RIGHT_ROTATION:
1040                         if (orient == CLOCK_WISE) {
1041                                 T1 = F_[TOP_ROTATION][LAST][0];
1042                                 T2 = F_[TOP_ROTATION][LAST][1];
1043                                 T3 = F_[TOP_ROTATION][LAST][LAST];
1044                                 F_[TOP_ROTATION][LAST][0] = F_[FRONT_ROTATION][LASTX][0];
1045                                 F_[TOP_ROTATION][LAST][1] = F_[FRONT_ROTATION][LASTX][1];
1046                                 F_[TOP_ROTATION][LAST][LAST] = F_[FRONT_ROTATION][LASTX][LASTY];
1047                                 F_[FRONT_ROTATION][LASTX][0] = F_[BOTTOM_ROTATION][LAST][0];
1048                                 F_[FRONT_ROTATION][LASTX][1] = F_[BOTTOM_ROTATION][LAST][1];
1049                                 F_[FRONT_ROTATION][LASTX][LASTY] = F_[BOTTOM_ROTATION][LAST][LAST];
1050                                 F_[BOTTOM_ROTATION][LAST][0] = F_[BACK_ROTATION][LAST][0];
1051                                 F_[BOTTOM_ROTATION][LAST][1] = F_[BACK_ROTATION][LAST][1];
1052                                 F_[BOTTOM_ROTATION][LAST][LAST] = F_[BACK_ROTATION][LAST][LAST];
1053                                 F_[BACK_ROTATION][LAST][0] = T1;        /* F_[TOP_ROTATION][LAST][0]; */
1054                                 F_[BACK_ROTATION][LAST][1] = T2;        /* F_[TOP_ROTATION][LAST][1]; */
1055                                 F_[BACK_ROTATION][LAST][LAST] = T3;     /* F_[TOP_ROTATION][LAST][LAST]; */
1056                         } else {
1057                                 T1 = F_[FRONT_ROTATION][LASTX][0];
1058                                 T2 = F_[FRONT_ROTATION][LASTX][1];
1059                                 T3 = F_[FRONT_ROTATION][LASTX][LASTY];
1060                                 F_[FRONT_ROTATION][LASTX][0] = F_[TOP_ROTATION][LAST][0];
1061                                 F_[FRONT_ROTATION][LASTX][1] = F_[TOP_ROTATION][LAST][1];
1062                                 F_[FRONT_ROTATION][LASTX][LASTY] = F_[TOP_ROTATION][LAST][LAST];
1063                                 F_[TOP_ROTATION][LAST][0] = F_[BACK_ROTATION][LAST][0];
1064                                 F_[TOP_ROTATION][LAST][1] = F_[BACK_ROTATION][LAST][1];
1065                                 F_[TOP_ROTATION][LAST][LAST] = F_[BACK_ROTATION][LAST][LAST];
1066                                 F_[BACK_ROTATION][LAST][0] = F_[BOTTOM_ROTATION][LAST][0];
1067                                 F_[BACK_ROTATION][LAST][1] = F_[BOTTOM_ROTATION][LAST][1];
1068                                 F_[BACK_ROTATION][LAST][LAST] = F_[BOTTOM_ROTATION][LAST][LAST];
1069                                 F_[BOTTOM_ROTATION][LAST][0] = T1;      /* F_[FRONT_ROTATION][LASTX][0]; */
1070                                 F_[BOTTOM_ROTATION][LAST][1] = T2;      /* F_[FRONT_ROTATION][LASTX][1]; */
1071                                 F_[BOTTOM_ROTATION][LAST][LAST] = T3;   /* F_[FRONT_ROTATION][LASTX][LASTY]; */
1072                         }
1073                         break;
1074                 case BOTTOM_ROTATION:
1075                         if (orient == CLOCK_WISE) {
1076                                 T1 = F_[FRONT_ROTATION][0][0];
1077                                 T2 = F_[FRONT_ROTATION][1][0];
1078                                 T3 = F_[FRONT_ROTATION][LASTX][0];
1079                                 F_[FRONT_ROTATION][0][0] = F_[LEFT_ROTATION][0][0];
1080                                 F_[FRONT_ROTATION][1][0] = F_[LEFT_ROTATION][1][0];
1081                                 F_[FRONT_ROTATION][LASTX][0] = F_[LEFT_ROTATION][LAST][0];
1082                                 F_[LEFT_ROTATION][0][0] = F_[BACK_ROTATION][LAST][LAST];
1083                                 F_[LEFT_ROTATION][1][0] = F_[BACK_ROTATION][1][LAST];
1084                                 F_[LEFT_ROTATION][LAST][0] = F_[BACK_ROTATION][0][LAST];
1085                                 F_[BACK_ROTATION][LAST][LAST] = F_[RIGHT_ROTATION][0][0];
1086                                 F_[BACK_ROTATION][1][LAST] = F_[RIGHT_ROTATION][1][0];
1087                                 F_[BACK_ROTATION][0][LAST] = F_[RIGHT_ROTATION][LAST][0];
1088                                 F_[RIGHT_ROTATION][0][0] = T1;  /* F_[FRONT_ROTATION][0][0]; */
1089                                 F_[RIGHT_ROTATION][1][0] = T2;  /* F_[FRONT_ROTATION][1][0]; */
1090                                 F_[RIGHT_ROTATION][LAST][0] = T3;       /* F_[FRONT_ROTATION][LASTX][0]; */
1091                         } else {
1092                                 T1 = F_[BACK_ROTATION][LAST][LAST];
1093                                 T2 = F_[BACK_ROTATION][1][LAST];
1094                                 T3 = F_[BACK_ROTATION][0][LAST];
1095                                 F_[BACK_ROTATION][LAST][LAST] = F_[LEFT_ROTATION][0][0];
1096                                 F_[BACK_ROTATION][1][LAST] = F_[LEFT_ROTATION][1][0];
1097                                 F_[BACK_ROTATION][0][LAST] = F_[LEFT_ROTATION][LAST][0];
1098                                 F_[LEFT_ROTATION][0][0] = F_[FRONT_ROTATION][0][0];
1099                                 F_[LEFT_ROTATION][1][0] = F_[FRONT_ROTATION][1][0];
1100                                 F_[LEFT_ROTATION][LAST][0] = F_[FRONT_ROTATION][LASTX][0];
1101                                 F_[FRONT_ROTATION][0][0] = F_[RIGHT_ROTATION][0][0];
1102                                 F_[FRONT_ROTATION][1][0] = F_[RIGHT_ROTATION][1][0];
1103                                 F_[FRONT_ROTATION][LASTX][0] = F_[RIGHT_ROTATION][LAST][0];
1104                                 F_[RIGHT_ROTATION][0][0] = T1;  /* F_[BACK_ROTATION][LAST][LAST]; */
1105                                 F_[RIGHT_ROTATION][1][0] = T2;  /* F_[BACK_ROTATION][1][LAST]; */
1106                                 F_[RIGHT_ROTATION][LAST][0] = T3;       /* F_[BACK_ROTATION][0][LAST]; */
1107                         }
1108                         break;
1109                 case TOP_ROTATION:
1110                         if (orient == CLOCK_WISE) {
1111                                 T1 = F_[BACK_ROTATION][0][0];
1112                                 T2 = F_[BACK_ROTATION][1][0];
1113                                 T3 = F_[BACK_ROTATION][LAST][0];
1114                                 F_[BACK_ROTATION][0][0] = F_[LEFT_ROTATION][LAST][LAST];
1115                                 F_[BACK_ROTATION][1][0] = F_[LEFT_ROTATION][1][LAST];
1116                                 F_[BACK_ROTATION][LAST][0] = F_[LEFT_ROTATION][0][LAST];
1117                                 F_[LEFT_ROTATION][LAST][LAST] = F_[FRONT_ROTATION][LASTX][LASTY];
1118                                 F_[LEFT_ROTATION][1][LAST] = F_[FRONT_ROTATION][1][LASTY];
1119                                 F_[LEFT_ROTATION][0][LAST] = F_[FRONT_ROTATION][0][LASTY];
1120                                 F_[FRONT_ROTATION][LASTX][LASTY] = F_[RIGHT_ROTATION][LAST][LAST];
1121                                 F_[FRONT_ROTATION][1][LASTY] = F_[RIGHT_ROTATION][1][LAST];
1122                                 F_[FRONT_ROTATION][0][LASTY] = F_[RIGHT_ROTATION][0][LAST];
1123                                 F_[RIGHT_ROTATION][LAST][LAST] = T1;    /* F_[BACK_ROTATION][0][0]; */
1124                                 F_[RIGHT_ROTATION][1][LAST] = T2;       /* F_[BACK_ROTATION][1][0]; */
1125                                 F_[RIGHT_ROTATION][0][LAST] = T3;       /* F_[BACK_ROTATION][LAST][0]; */
1126                         } else {
1127                                 T1 = F_[RIGHT_ROTATION][LAST][LAST];
1128                                 T2 = F_[RIGHT_ROTATION][1][LAST];
1129                                 T3 = F_[RIGHT_ROTATION][0][LAST];
1130                                 F_[RIGHT_ROTATION][LAST][LAST] = F_[FRONT_ROTATION][LASTX][LASTY];
1131                                 F_[RIGHT_ROTATION][1][LAST] = F_[FRONT_ROTATION][1][LASTY];
1132                                 F_[RIGHT_ROTATION][0][LAST] = F_[FRONT_ROTATION][0][LASTY];
1133                                 F_[FRONT_ROTATION][LASTX][LASTY] = F_[LEFT_ROTATION][LAST][LAST];
1134                                 F_[FRONT_ROTATION][1][LASTY] = F_[LEFT_ROTATION][1][LAST];
1135                                 F_[FRONT_ROTATION][0][LASTY] = F_[LEFT_ROTATION][0][LAST];
1136                                 F_[LEFT_ROTATION][LAST][LAST] = F_[BACK_ROTATION][0][0];
1137                                 F_[LEFT_ROTATION][1][LAST] = F_[BACK_ROTATION][1][0];
1138                                 F_[LEFT_ROTATION][0][LAST] = F_[BACK_ROTATION][LAST][0];
1139                                 F_[BACK_ROTATION][0][0] = T1;   /* F_[RIGHT_ROTATION][LAST][LAST]; */
1140                                 F_[BACK_ROTATION][1][0] = T2;   /* F_[RIGHT_ROTATION][1][LAST]; */
1141                                 F_[BACK_ROTATION][LAST][0] = T3;        /* F_[RIGHT_ROTATION][0][LAST]; */
1142                         }
1143                         break;
1144         }
1145 }
1146
1147 static void
1148 shuffle(ModeInfo * mi)
1149 {
1150         rubikstruct *rp = &rubik[MI_SCREEN(mi)];
1151         int         i, mov, ori;
1152
1153         memset(F_[TOP_ROTATION], 'R', MAXSIZEXZ);
1154         memset(F_[LEFT_ROTATION], 'Y', MAXSIZEZY);
1155         memset(F_[FRONT_ROTATION], 'W', MAXSIZEXY);
1156         memset(F_[RIGHT_ROTATION], 'G', MAXSIZEZY);
1157         memset(F_[BOTTOM_ROTATION], 'O', MAXSIZEXZ);
1158         memset(F_[BACK_ROTATION], 'B', MAXSIZEXY);
1159
1160         rp->storedmoves = MI_BATCHCOUNT(mi);
1161         if (rp->storedmoves < 0) {
1162                 if (rp->movedfaces != NULL)
1163                         (void) free((void *) rp->movedfaces);
1164                 if (rp->movedorient != NULL)
1165                         (void) free((void *) rp->movedorient);
1166                 rp->movedfaces = NULL;
1167                 rp->movedorient = NULL;
1168                 rp->storedmoves = NRAND(-rp->storedmoves) + 1;
1169         }
1170         if ((rp->storedmoves) && (rp->movedfaces == NULL))
1171                 if ((rp->movedfaces =
1172                 (char *) calloc(rp->storedmoves + 1, sizeof (char))) == NULL)
1173                                     (void) fprintf(stderr,
1174                         "Could not allocate memory for rubik move buffer\n");
1175
1176         if ((rp->storedmoves) && (rp->movedorient == NULL))
1177                 if ((rp->movedorient =
1178                 (char *) calloc(rp->storedmoves + 1, sizeof (char))) == NULL)
1179                                     (void) fprintf(stderr,
1180                                                    "Could not allocate memory for rubik orient buffer\n");
1181
1182         if (MI_CYCLES(mi) <= 1) {
1183                 rp->anglestep = 90.0;
1184         } else {
1185                 rp->anglestep = 90.0 / (GLfloat) (MI_CYCLES(mi));
1186         }
1187
1188         for (i = 0; i < rp->storedmoves; i++) {
1189                 int         condition;
1190
1191                 do {
1192                         mov = NRAND(6);
1193                         ori = NRAND(2);
1194                         condition = 1;
1195                         if (i > 0)      /* avoid immediate undoing moves */
1196                                 if (mov == rp->movedfaces[i - 1] &&
1197                                     ori == rp->movedorient[i - 1])
1198                                         condition = 0;
1199                         if (i > 1)      /* avoid 3 consecutive identical moves */
1200                                 if (mov == rp->movedfaces[i - 1] &&
1201                                     ori != rp->movedorient[i - 1] &&
1202                                     rp->movedfaces[i - 1] == rp->movedfaces[i - 2] &&
1203                                     rp->movedorient[i - 1] == rp->movedorient[i - 2])
1204                                         condition = 0;
1205                 } while (!condition);
1206                 if (hideshuffling)
1207                         evalmovement(mi, mov, ori);
1208                 rp->movedfaces[i] = mov;
1209                 rp->movedorient[i] = (ori == CLOCK_WISE) ? C_CLOCK_WISE : CLOCK_WISE;
1210         }
1211         rp->movement = NO_ROTATION;
1212         rp->rotatestep = 0;
1213         rp->action = hideshuffling ? ACTION_SOLVE : ACTION_SHUFFLE;
1214         rp->shufflingmoves = 0;
1215         rp->done = 0;
1216 }
1217
1218 void
1219 draw_rubik(ModeInfo * mi)
1220 {
1221         rubikstruct *rp = &rubik[MI_SCREEN(mi)];
1222
1223         Display    *display = MI_DISPLAY(mi);
1224         Window      window = MI_WINDOW(mi);
1225
1226         glDrawBuffer(GL_BACK);
1227         glXMakeCurrent(display, window, rp->glx_context);
1228
1229         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1230
1231         glPushMatrix();
1232
1233         glTranslatef(0.0, 0.0, -10.0);
1234
1235         if (!MI_WIN_IS_ICONIC(mi)) {
1236                 glScalef(Scale4Window * rp->WindH / rp->WindW, Scale4Window, Scale4Window);
1237         } else {
1238                 glScalef(Scale4Iconic * rp->WindH / rp->WindW, Scale4Iconic, Scale4Iconic);
1239         }
1240
1241         glRotatef(rp->step * 100, 1, 0, 0);
1242         glRotatef(rp->step * 95, 0, 1, 0);
1243         glRotatef(rp->step * 90, 0, 0, 1);
1244
1245         if (rp->action == ACTION_SHUFFLE) {
1246                 if (rp->done) {
1247                         if (++rp->rotatestep > DELAY_AFTER_SHUFFLING) {
1248                                 rp->movement = NO_ROTATION;
1249                                 rp->rotatestep = 0;
1250                                 rp->action = ACTION_SOLVE;
1251                                 rp->done = 0;
1252                         }
1253                 } else {
1254                         if (rp->movement == NO_ROTATION) {
1255                                 if (rp->shufflingmoves < rp->storedmoves) {
1256                                         rp->rotatestep = 0;
1257                                         rp->movement = rp->movedfaces[rp->shufflingmoves];
1258                                         rp->orientation =
1259                                                 (rp->movedorient[rp->shufflingmoves] == CLOCK_WISE) ?
1260                                                 C_CLOCK_WISE : CLOCK_WISE;
1261                                 } else {
1262                                         rp->rotatestep = 0;
1263                                         rp->done = 1;
1264                                 }
1265                         } else {
1266                                 rp->rotatestep += (rp->orientation == CLOCK_WISE) ?
1267                                         -rp->anglestep : rp->anglestep;
1268                                 if (rp->rotatestep > 90 || rp->rotatestep < -90) {
1269                                         evalmovement(mi, rp->movement, rp->orientation);
1270                                         rp->shufflingmoves++;
1271                                         rp->movement = NO_ROTATION;
1272                                 }
1273                         }
1274                 }
1275         } else {
1276                 if (rp->done) {
1277                         if (++rp->rotatestep > DELAY_AFTER_SOLVING)
1278                                 shuffle(mi);
1279                 } else {
1280                         if (rp->movement == NO_ROTATION) {
1281                                 if (rp->storedmoves > 0) {
1282                                         rp->rotatestep = 0;
1283                                         rp->movement = rp->movedfaces[rp->storedmoves - 1];
1284                                         rp->orientation = rp->movedorient[rp->storedmoves - 1];
1285                                 } else {
1286                                         rp->rotatestep = 0;
1287                                         rp->done = 1;
1288                                 }
1289                         } else {
1290                                 rp->rotatestep += (rp->orientation == CLOCK_WISE) ?
1291                                         -rp->anglestep : rp->anglestep;
1292                                 if (rp->rotatestep > 90 || rp->rotatestep < -90) {
1293                                         evalmovement(mi, rp->movement, rp->orientation);
1294                                         rp->storedmoves--;
1295                                         rp->movement = NO_ROTATION;
1296                                 }
1297                         }
1298                 }
1299         }
1300
1301         draw_cube(mi);
1302
1303         glPopMatrix();
1304
1305         glFlush();
1306
1307         glXSwapBuffers(display, window);
1308
1309         rp->step += 0.05;
1310 }
1311
1312 static void
1313 reshape(ModeInfo * mi, int width, int height)
1314 {
1315         rubikstruct *rp = &rubik[MI_SCREEN(mi)];
1316
1317         glViewport(0, 0, rp->WindW = (GLint) width, rp->WindH = (GLint) height);
1318         glMatrixMode(GL_PROJECTION);
1319         glLoadIdentity();
1320         glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
1321         glMatrixMode(GL_MODELVIEW);
1322
1323         rp->AreObjectsDefined[ObjCubit] = 0;
1324 }
1325
1326 static void
1327 pinit(ModeInfo * mi)
1328 {
1329         glClearDepth(1.0);
1330         glClearColor(0.0, 0.0, 0.0, 1.0);
1331         glColor3f(1.0, 1.0, 1.0);
1332
1333         glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
1334         glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
1335         glLightfv(GL_LIGHT0, GL_POSITION, position0);
1336         glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
1337         glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
1338         glLightfv(GL_LIGHT1, GL_POSITION, position1);
1339         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
1340         glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
1341         glEnable(GL_LIGHTING);
1342         glEnable(GL_LIGHT0);
1343         glEnable(GL_LIGHT1);
1344         glEnable(GL_DEPTH_TEST);
1345         glEnable(GL_NORMALIZE);
1346         glEnable(GL_CULL_FACE);
1347
1348         glShadeModel(GL_FLAT);
1349         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
1350         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
1351
1352         shuffle(mi);
1353 }
1354
1355 void
1356 init_rubik(ModeInfo * mi)
1357 {
1358         int         screen = MI_SCREEN(mi);
1359         rubikstruct *rp;
1360
1361         if (rubik == NULL) {
1362                 if ((rubik = (rubikstruct *) calloc(MI_NUM_SCREENS(mi),
1363                                               sizeof (rubikstruct))) == NULL)
1364                         return;
1365         }
1366         rp = &rubik[screen];
1367         rp->step = NRAND(90);
1368
1369         rp->glx_context = init_GL(mi);
1370
1371         reshape(mi, MI_WIN_WIDTH(mi), MI_WIN_HEIGHT(mi));
1372         objects = glGenLists(1);
1373         pinit(mi);
1374 }
1375
1376 void
1377 change_rubik(ModeInfo * mi)
1378 {
1379         pinit(mi);
1380 }
1381
1382 void
1383 release_rubik(ModeInfo * mi)
1384 {
1385         if (rubik != NULL) {
1386                 int         screen;
1387
1388                 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
1389                         rubikstruct *rp = &rubik[screen];
1390
1391                         if (rp->movedfaces != NULL)
1392                                 (void) free((void *) rp->movedfaces);
1393                         if (rp->movedorient != NULL)
1394                                 (void) free((void *) rp->movedorient);
1395                 }
1396                 (void) free((void *) rubik);
1397                 rubik = NULL;
1398         }
1399 }
1400
1401 #undef F_
1402 #endif