1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* rubik --- Shows a auto-solving Rubik's cube */
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)rubik.c 4.07 97/11/24 xlockmore";
13 * Permission to use, copy, modify, and distribute this software and its
14 * documentation for any purpose and without fee is hereby granted,
15 * provided that the above copyright notice appear in all copies and that
16 * both that copyright notice and this permission notice appear in
17 * supporting documentation.
19 * This file is provided AS IS with no warranties of any kind. The author
20 * shall have no liability with respect to the infringement of copyrights,
21 * trade secrets or any patents by this file or any part thereof. In no
22 * event will the author be liable for any lost revenue or profits or
23 * other special, indirect and consequential damages.
25 * This mode shows an auto-solving rubik's cube "puzzle". If somebody
26 * intends to make a game or something based on this code, please let me
27 * know first, my e-mail address is provided in this comment. Marcelo.
29 * Thanks goes also to Brian Paul for making it possible and inexpensive
30 * to use OpenGL at home.
32 * Since I'm not a native English speaker, my apologies for any grammatical
35 * My e-mail address is
38 * Marcelo F. Vianna (Jul-31-1997)
41 * 26-Sep-98: Added some more movement (the cube do not stays in the screen
42 * center anymore. Also fixed the scale problem imediatelly after
43 * shuffling when the puzzle is solved.
44 * 08-Aug-97: Now has some internals from xrubik by David Bagley
45 * This should make it easier to add features.
46 * 02-Aug-97: Now behaves more like puzzle.c: first show the cube being
47 * shuffled and then being solved. A mode specific option was added:
48 * "+/-hideshuffling" to provide the original behavior (in which
49 * only the solution is shown).
50 * The color labels corners are now rounded.
51 * Optimized the cubit() routine using glLists.
52 * 01-Aug-97: Shuffling now avoids movements that undoes the previous movement
53 * and three consecutive identical moves (which is pretty stupid).
54 * improved the "cycles" option in replacement of David's hack,
55 * now rp->anglestep is a GLfloat, so this option selects the
56 * "exact" number of frames that a rotation (movement) takes to
58 * 30-Jul-97: Initial release, there is no algorithm to solve the puzzle,
59 * instead, it randomly shuffle the cube and then make the
60 * movements in the reverse order.
61 * The mode was written in 1 day (I got sick and had the day off).
62 * There was not much to do since I could not leave home... :)
67 * Color labels mapping:
68 * =====================
78 * +-----------+------------+-----------+
82 * | LEFT(1) | FRONT(2) | RIGHT(3) |
86 * +-----------+------------+-----------+
90 * | BOTTOM(4) | rp->faces[N][X+AVSIZE*Y]=
91 * | | rp->cubeLoc[N][X+AVSIZE*Y]=
94 * +------------+ | | | |
95 * |0--> | | 0 | 1 | 2 |
98 * | BACK(5) | | 3 | 4 | 5 |
102 * +------------+ +---+---+---+
114 * PURIFY 3.0a on SunOS4 reports an unitialized memory read on each of
115 * the glCallList() functions below when using MesaGL 2.1. This has
116 * been fixed in MesaGL 2.2 and later releases.
120 * due to a Bug/feature in VMS X11/Intrinsic.h has to be placed before xlock.
121 * otherwise caddr_t is not defined correctly
123 #include <X11/Intrinsic.h>
126 # define PROGCLASS "Rubik"
127 # define HACK_INIT init_rubik
128 # define HACK_DRAW draw_rubik
129 # define rubik_opts xlockmore_opts
130 # define DEFAULTS "*delay: 40000 \n" \
134 # include "xlockmore.h" /* from the xscreensaver distribution */
135 #else /* !STANDALONE */
136 # include "xlock.h" /* from the xlockmore distribution */
138 #endif /* !STANDALONE */
142 #define DEF_HIDESHUFFLING "False"
144 static Bool hideshuffling;
146 static XrmOptionDescRec opts[] =
148 {"-hideshuffling", ".rubik.hideshuffling", XrmoptionNoArg, (caddr_t) "on"},
149 {"+hideshuffling", ".rubik.hideshuffling", XrmoptionNoArg, (caddr_t) "off"}
152 static argtype vars[] =
154 {(caddr_t *) & hideshuffling, "hideshuffling", "Hideshuffling", DEF_HIDESHUFFLING, t_Bool}
157 static OptionStruct desc[] =
159 {"-/+hideshuffling", "turn on/off hidden shuffle phase"}
162 ModeSpecOpt rubik_opts =
163 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
166 ModStruct rubik_description =
167 {"rubik", "init_rubik", "draw_rubik", "release_rubik",
168 "draw_rubik", "change_rubik", NULL, &rubik_opts,
169 10000, -30, 5, -6, 4, 1.0, "",
170 "Shows an auto-solving Rubik's Cube", 0, NULL};
174 #define VectMul(X1,Y1,Z1,X2,Y2,Z2) (Y1)*(Z2)-(Z1)*(Y2),(Z1)*(X2)-(X1)*(Z2),(X1)*(Y2)-(Y1)*(X2)
175 #define sqr(A) ((A)*(A))
182 #define ACTION_SOLVE 1
183 #define ACTION_SHUFFLE 0
185 #define DELAY_AFTER_SHUFFLING 5
186 #define DELAY_AFTER_SOLVING 20
188 /*************************************************************************/
191 #ifdef LMN /* LxMxN not completed yet... */
192 #define MAXSIZEX (rp->sizex)
193 #define MAXSIZEY (rp->sizey)
194 #define MAXSIZEZ (rp->sizez)
195 #define AVSIZE (rp->avsize)
196 #define MAXSIZE (rp->maxsize)
197 #define AVSIZESQ (rp->avsizeSq)
198 #define MAXSIZESQ (rp->maxsizeSq)
200 #define MAXSIZEX (rp->size)
201 #define MAXSIZEY (rp->size)
202 #define MAXSIZEZ (rp->size)
203 #define AVSIZE (rp->size)
204 #define MAXSIZE (rp->size)
205 #define AVSIZESQ (rp->sizeSq)
206 #define MAXSIZESQ (rp->sizeSq)
208 #define MAXSIZEXY (MAXSIZEX*MAXSIZEY)
209 #define MAXSIZEZY (MAXSIZEZ*MAXSIZEY)
210 #define MAXSIZEXZ (MAXSIZEX*MAXSIZEZ)
211 #define LASTX (MAXSIZEX-1)
212 #define LASTY (MAXSIZEY-1)
213 #define LASTZ (MAXSIZEZ-1)
214 /* These are not likely to change but... */
219 #define Scale4Window (0.9/AVSIZE)
220 #define Scale4Iconic (2.1/AVSIZE)
222 #define MAXORIENT 4 /* Number of orientations of a square */
223 #define MAXFACES 6 /* Number of faces */
225 /* Directions relative to the face of a cubie */
230 #define CW (MAXORIENT+1)
231 #define CCW (2*MAXORIENT-1)
237 #define BOTTOM_FACE 4
239 #define NO_FACE (MAXFACES)
240 #define NO_ROTATION (2*MAXORIENT)
241 #define NO_DEPTH MAXSIZE
243 #define REVX(a) (MAXSIZEX - a - 1)
244 #define REVY(a) (MAXSIZEY - a - 1)
245 #define REVZ(a) (MAXSIZEZ - a - 1)
247 typedef struct _RubikLoc {
249 int rotation; /* Not used yet */
252 typedef struct _RubikRowNext {
253 int face, direction, sideFace;
256 typedef struct _RubikMove {
261 typedef struct _RubikSlice {
267 * Pick a face and a direction on face the next face and orientation
270 static RubikLoc slideNextRow[MAXFACES][MAXORIENT] =
305 * Examine cubie 0 on each face, its 4 movements (well only 2 since the
306 * other 2 will be opposites) and translate it into slice movements).
307 * Beware.. using this for NxNxN makes some assumptions that referenced
308 * cubes are along the diagonal top-left to bottom-right.
309 * CW = DEEP Depth CCW == SHALLOW Depth with reference to faces 0, 1, and 2
311 static RubikLoc rotateSlice[MAXFACES][MAXORIENT / 2] =
340 * Rotate face clockwise by a number of orients, then the top of the
341 * face then points to this face
343 static int rowToRotate[MAXFACES][MAXORIENT] =
354 * This translates a clockwise move to something more manageable
356 static RubikRowNext rotateToRow[MAXFACES] = /*CW to min face */
372 #ifdef LMN /* Under construction */
373 int sizex, sizey, sizez;
375 int avsizeSq, maxsizeSq;
382 RubikLoc *cubeLoc[MAXFACES];
383 RubikLoc *rowLoc[MAXORIENT];
386 GLfloat PX, PY, VX, VY;
387 GLXContext *glx_context;
388 int AreObjectsDefined[1];
391 static float front_shininess[] =
393 static float front_specular[] =
394 {0.7, 0.7, 0.7, 1.0};
395 static float ambient[] =
396 {0.0, 0.0, 0.0, 1.0};
397 static float diffuse[] =
398 {1.0, 1.0, 1.0, 1.0};
399 static float position0[] =
400 {1.0, 1.0, 1.0, 0.0};
401 static float position1[] =
402 {-1.0, -1.0, 1.0, 0.0};
403 static float lmodel_ambient[] =
404 {0.5, 0.5, 0.5, 1.0};
405 static float lmodel_twoside[] =
408 static float MaterialRed[] =
409 {0.5, 0.0, 0.0, 1.0};
410 static float MaterialGreen[] =
411 {0.0, 0.5, 0.0, 1.0};
412 static float MaterialBlue[] =
413 {0.0, 0.0, 0.5, 1.0};
414 static float MaterialYellow[] =
415 {0.7, 0.7, 0.0, 1.0};
416 static float MaterialOrange[] =
417 {0.9, 0.45, 0.36, 1.0};
420 static float MaterialMagenta[] =
421 {0.7, 0.0, 0.7, 1.0};
422 static float MaterialCyan[] =
423 {0.0, 0.7, 0.7, 1.0};
426 static float MaterialWhite[] =
427 {0.8, 0.8, 0.8, 1.0};
428 static float MaterialGray[] =
429 {0.2, 0.2, 0.2, 1.0};
430 static float MaterialGray3[] =
431 {0.3, 0.3, 0.3, 1.0};
432 static float MaterialGray4[] =
433 {0.4, 0.4, 0.4, 1.0};
434 static float MaterialGray5[] =
435 {0.5, 0.5, 0.5, 1.0};
436 static float MaterialGray6[] =
437 {0.6, 0.6, 0.6, 1.0};
438 static float MaterialGray7[] =
439 {0.7, 0.7, 0.7, 1.0};
441 static rubikstruct *rubik = NULL;
442 static GLuint objects;
447 pickcolor(int C, int mono)
452 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray3);
454 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
458 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray6);
460 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialYellow);
463 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
467 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray4);
469 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGreen);
473 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray7);
475 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialOrange);
479 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5);
481 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialBlue);
484 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialCyan);
485 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialMagenta);
492 draw_cubit(ModeInfo * mi,
493 int back, int front, int left, int right, int bottom, int top)
495 rubikstruct *rp = &rubik[MI_SCREEN(mi)];
496 int mono = MI_IS_MONO(mi);
498 if (!rp->AreObjectsDefined[ObjCubit]) {
499 glNewList(objects + ObjCubit, GL_COMPILE_AND_EXECUTE);
501 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
502 glNormal3f(0.00, 0.00, 1.00);
503 glVertex3f(-0.45, -0.45, 0.50);
504 glVertex3f(0.45, -0.45, 0.50);
505 glVertex3f(0.45, 0.45, 0.50);
506 glVertex3f(-0.45, 0.45, 0.50);
507 glNormal3f(0.00, 0.00, -1.00);
508 glVertex3f(-0.45, 0.45, -0.50);
509 glVertex3f(0.45, 0.45, -0.50);
510 glVertex3f(0.45, -0.45, -0.50);
511 glVertex3f(-0.45, -0.45, -0.50);
512 glNormal3f(-1.00, 0.00, 0.00);
513 glVertex3f(-0.50, -0.45, 0.45);
514 glVertex3f(-0.50, 0.45, 0.45);
515 glVertex3f(-0.50, 0.45, -0.45);
516 glVertex3f(-0.50, -0.45, -0.45);
517 glNormal3f(1.00, 0.00, 0.00);
518 glVertex3f(0.50, -0.45, -0.45);
519 glVertex3f(0.50, 0.45, -0.45);
520 glVertex3f(0.50, 0.45, 0.45);
521 glVertex3f(0.50, -0.45, 0.45);
522 glNormal3f(0.00, -1.00, 0.00);
523 glVertex3f(0.45, -0.50, -0.45);
524 glVertex3f(0.45, -0.50, 0.45);
525 glVertex3f(-0.45, -0.50, 0.45);
526 glVertex3f(-0.45, -0.50, -0.45);
527 glNormal3f(0.00, 1.00, 0.00);
528 glVertex3f(-0.45, 0.50, -0.45);
529 glVertex3f(-0.45, 0.50, 0.45);
530 glVertex3f(0.45, 0.50, 0.45);
531 glVertex3f(0.45, 0.50, -0.45);
532 glNormal3f(-1.00, -1.00, 0.00);
533 glVertex3f(-0.45, -0.50, -0.45);
534 glVertex3f(-0.45, -0.50, 0.45);
535 glVertex3f(-0.50, -0.45, 0.45);
536 glVertex3f(-0.50, -0.45, -0.45);
537 glNormal3f(1.00, 1.00, 0.00);
538 glVertex3f(0.45, 0.50, -0.45);
539 glVertex3f(0.45, 0.50, 0.45);
540 glVertex3f(0.50, 0.45, 0.45);
541 glVertex3f(0.50, 0.45, -0.45);
542 glNormal3f(-1.00, 1.00, 0.00);
543 glVertex3f(-0.50, 0.45, -0.45);
544 glVertex3f(-0.50, 0.45, 0.45);
545 glVertex3f(-0.45, 0.50, 0.45);
546 glVertex3f(-0.45, 0.50, -0.45);
547 glNormal3f(1.00, -1.00, 0.00);
548 glVertex3f(0.50, -0.45, -0.45);
549 glVertex3f(0.50, -0.45, 0.45);
550 glVertex3f(0.45, -0.50, 0.45);
551 glVertex3f(0.45, -0.50, -0.45);
552 glNormal3f(0.00, -1.00, -1.00);
553 glVertex3f(-0.45, -0.45, -0.50);
554 glVertex3f(0.45, -0.45, -0.50);
555 glVertex3f(0.45, -0.50, -0.45);
556 glVertex3f(-0.45, -0.50, -0.45);
557 glNormal3f(0.00, 1.00, 1.00);
558 glVertex3f(-0.45, 0.45, 0.50);
559 glVertex3f(0.45, 0.45, 0.50);
560 glVertex3f(0.45, 0.50, 0.45);
561 glVertex3f(-0.45, 0.50, 0.45);
562 glNormal3f(0.00, -1.00, 1.00);
563 glVertex3f(-0.45, -0.50, 0.45);
564 glVertex3f(0.45, -0.50, 0.45);
565 glVertex3f(0.45, -0.45, 0.50);
566 glVertex3f(-0.45, -0.45, 0.50);
567 glNormal3f(0.00, 1.00, -1.00);
568 glVertex3f(-0.45, 0.50, -0.45);
569 glVertex3f(0.45, 0.50, -0.45);
570 glVertex3f(0.45, 0.45, -0.50);
571 glVertex3f(-0.45, 0.45, -0.50);
572 glNormal3f(-1.00, 0.00, -1.00);
573 glVertex3f(-0.50, -0.45, -0.45);
574 glVertex3f(-0.50, 0.45, -0.45);
575 glVertex3f(-0.45, 0.45, -0.50);
576 glVertex3f(-0.45, -0.45, -0.50);
577 glNormal3f(1.00, 0.00, 1.00);
578 glVertex3f(0.50, -0.45, 0.45);
579 glVertex3f(0.50, 0.45, 0.45);
580 glVertex3f(0.45, 0.45, 0.50);
581 glVertex3f(0.45, -0.45, 0.50);
582 glNormal3f(1.00, 0.00, -1.00);
583 glVertex3f(0.45, -0.45, -0.50);
584 glVertex3f(0.45, 0.45, -0.50);
585 glVertex3f(0.50, 0.45, -0.45);
586 glVertex3f(0.50, -0.45, -0.45);
587 glNormal3f(-1.00, 0.00, 1.00);
588 glVertex3f(-0.45, -0.45, 0.50);
589 glVertex3f(-0.45, 0.45, 0.50);
590 glVertex3f(-0.50, 0.45, 0.45);
591 glVertex3f(-0.50, -0.45, 0.45);
593 glBegin(GL_TRIANGLES);
594 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
595 glNormal3f(1.00, 1.00, 1.00);
596 glVertex3f(0.45, 0.45, 0.50);
597 glVertex3f(0.50, 0.45, 0.45);
598 glVertex3f(0.45, 0.50, 0.45);
599 glNormal3f(-1.00, -1.00, -1.00);
600 glVertex3f(-0.45, -0.50, -0.45);
601 glVertex3f(-0.50, -0.45, -0.45);
602 glVertex3f(-0.45, -0.45, -0.50);
603 glNormal3f(-1.00, 1.00, 1.00);
604 glVertex3f(-0.45, 0.45, 0.50);
605 glVertex3f(-0.45, 0.50, 0.45);
606 glVertex3f(-0.50, 0.45, 0.45);
607 glNormal3f(1.00, -1.00, -1.00);
608 glVertex3f(0.50, -0.45, -0.45);
609 glVertex3f(0.45, -0.50, -0.45);
610 glVertex3f(0.45, -0.45, -0.50);
611 glNormal3f(1.00, -1.00, 1.00);
612 glVertex3f(0.45, -0.45, 0.50);
613 glVertex3f(0.45, -0.50, 0.45);
614 glVertex3f(0.50, -0.45, 0.45);
615 glNormal3f(-1.00, 1.00, -1.00);
616 glVertex3f(-0.50, 0.45, -0.45);
617 glVertex3f(-0.45, 0.50, -0.45);
618 glVertex3f(-0.45, 0.45, -0.50);
619 glNormal3f(-1.00, -1.00, 1.00);
620 glVertex3f(-0.45, -0.45, 0.50);
621 glVertex3f(-0.50, -0.45, 0.45);
622 glVertex3f(-0.45, -0.50, 0.45);
623 glNormal3f(1.00, 1.00, -1.00);
624 glVertex3f(0.50, 0.45, -0.45);
625 glVertex3f(0.45, 0.45, -0.50);
626 glVertex3f(0.45, 0.50, -0.45);
629 rp->AreObjectsDefined[ObjCubit] = 1;
631 (void) printf("Cubit drawn SLOWLY\n");
634 glCallList(objects + ObjCubit);
636 (void) printf("Cubit drawn quickly\n");
640 if (back != NO_FACE) {
642 pickcolor(back, mono);
643 glNormal3f(0.00, 0.00, -1.00);
644 glVertex3f(-0.35, 0.40, -0.51);
645 glVertex3f(0.35, 0.40, -0.51);
646 glVertex3f(0.40, 0.35, -0.51);
647 glVertex3f(0.40, -0.35, -0.51);
648 glVertex3f(0.35, -0.40, -0.51);
649 glVertex3f(-0.35, -0.40, -0.51);
650 glVertex3f(-0.40, -0.35, -0.51);
651 glVertex3f(-0.40, 0.35, -0.51);
654 if (front != NO_FACE) {
656 pickcolor(front, mono);
657 glNormal3f(0.00, 0.00, 1.00);
658 glVertex3f(-0.35, -0.40, 0.51);
659 glVertex3f(0.35, -0.40, 0.51);
660 glVertex3f(0.40, -0.35, 0.51);
661 glVertex3f(0.40, 0.35, 0.51);
662 glVertex3f(0.35, 0.40, 0.51);
663 glVertex3f(-0.35, 0.40, 0.51);
664 glVertex3f(-0.40, 0.35, 0.51);
665 glVertex3f(-0.40, -0.35, 0.51);
668 if (left != NO_FACE) {
670 pickcolor(left, mono);
671 glNormal3f(-1.00, 0.00, 0.00);
672 glVertex3f(-0.51, -0.35, 0.40);
673 glVertex3f(-0.51, 0.35, 0.40);
674 glVertex3f(-0.51, 0.40, 0.35);
675 glVertex3f(-0.51, 0.40, -0.35);
676 glVertex3f(-0.51, 0.35, -0.40);
677 glVertex3f(-0.51, -0.35, -0.40);
678 glVertex3f(-0.51, -0.40, -0.35);
679 glVertex3f(-0.51, -0.40, 0.35);
682 if (right != NO_FACE) {
684 pickcolor(right, mono);
685 glNormal3f(1.00, 0.00, 0.00);
686 glVertex3f(0.51, -0.35, -0.40);
687 glVertex3f(0.51, 0.35, -0.40);
688 glVertex3f(0.51, 0.40, -0.35);
689 glVertex3f(0.51, 0.40, 0.35);
690 glVertex3f(0.51, 0.35, 0.40);
691 glVertex3f(0.51, -0.35, 0.40);
692 glVertex3f(0.51, -0.40, 0.35);
693 glVertex3f(0.51, -0.40, -0.35);
696 if (bottom != NO_FACE) {
698 pickcolor(bottom, mono);
699 glNormal3f(0.00, -1.00, 0.00);
700 glVertex3f(0.40, -0.51, -0.35);
701 glVertex3f(0.40, -0.51, 0.35);
702 glVertex3f(0.35, -0.51, 0.40);
703 glVertex3f(-0.35, -0.51, 0.40);
704 glVertex3f(-0.40, -0.51, 0.35);
705 glVertex3f(-0.40, -0.51, -0.35);
706 glVertex3f(-0.35, -0.51, -0.40);
707 glVertex3f(0.35, -0.51, -0.40);
710 if (top != NO_FACE) {
712 pickcolor(top, mono);
713 glNormal3f(0.00, 1.00, 0.00);
714 glVertex3f(-0.40, 0.51, -0.35);
715 glVertex3f(-0.40, 0.51, 0.35);
716 glVertex3f(-0.35, 0.51, 0.40);
717 glVertex3f(0.35, 0.51, 0.40);
718 glVertex3f(0.40, 0.51, 0.35);
719 glVertex3f(0.40, 0.51, -0.35);
720 glVertex3f(0.35, 0.51, -0.40);
721 glVertex3f(-0.35, 0.51, -0.40);
728 convertMove(rubikstruct * rp, RubikMove move)
733 plane = rotateSlice[(int) move.face][move.direction % 2];
734 slice.face = plane.face;
735 slice.rotation = plane.rotation;
736 if (slice.rotation == CW) /* I just know this to be true... */
737 slice.depth = AVSIZESQ - 1 - move.position;
739 slice.depth = move.position;
740 slice.depth = slice.depth / AVSIZE;
741 /* If slice.depth = 0 then face 0, face 1, or face 2 moves */
742 if (move.direction / 2)
743 slice.rotation = (plane.rotation == CW) ? CCW : CW;
747 /* Assume for the moment that the size is at least 2 */
749 draw_cube(ModeInfo * mi)
752 #define SX ((GLint)S1*(MAXSIZEX-1))
753 #define SY ((GLint)S1*(MAXSIZEY-1))
754 #define SZ ((GLint)S1*(MAXSIZEZ-1))
755 #define HALFX (((GLfloat)MAXSIZEX-1.0)/2.0)
756 #define HALFY (((GLfloat)MAXSIZEY-1.0)/2.0)
757 #define HALFZ (((GLfloat)MAXSIZEZ-1.0)/2.0)
758 #define MIDX(a) (((GLfloat)(2*a-MAXSIZEX+1))/2.0)
759 #define MIDY(a) (((GLfloat)(2*a-MAXSIZEY+1))/2.0)
760 #define MIDZ(a) (((GLfloat)(2*a-MAXSIZEZ+1))/2.0)
761 rubikstruct *rp = &rubik[MI_SCREEN(mi)];
766 if (rp->movement.face == NO_FACE) {
767 slice.face = NO_FACE;
768 slice.rotation = NO_ROTATION;
769 slice.depth = NO_DEPTH;
771 slice = convertMove(rp, rp->movement);
773 rotatestep = (slice.rotation == CCW) ? rp->rotatestep : -rp->rotatestep;
776 * The glRotatef() routine transforms the coordinate system for every future
777 * vertex specification (this is not so simple, but by now comprehending this
778 * is sufficient). So if you want to rotate the inner slice, you can draw
779 * one slice, rotate the anglestep for the centerslice, draw the inner slice,
780 * rotate reversely and draw the other slice.
781 * There is a sequence for drawing cubies for each axis being moved...
783 switch (slice.face) {
785 case TOP_FACE: /* BOTTOM_FACE too */
787 if (slice.depth == MAXSIZEY - 1)
788 glRotatef(rotatestep, 0, HALFY, 0);
790 glTranslatef(-HALFX, -HALFY, -HALFZ);
792 rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * FIRSTY].face, NO_FACE,
793 rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * LASTY].face, NO_FACE,
794 rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * LASTZ].face, NO_FACE);
795 for (k = 1; k < MAXSIZEZ - 1; k++) {
796 glTranslatef(0, 0, S1);
799 rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * LASTY].face, NO_FACE,
800 rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * REVZ(k)].face, NO_FACE);
802 glTranslatef(0, 0, S1);
804 NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * LASTY].face,
805 rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * LASTY].face, NO_FACE,
806 rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * FIRSTZ].face, NO_FACE);
807 for (i = 1; i < MAXSIZEX - 1; i++) {
808 glTranslatef(S1, 0, -SZ);
810 rp->cubeLoc[BACK_FACE][i + MAXSIZEX * FIRSTY].face, NO_FACE,
812 rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * LASTZ].face, NO_FACE);
813 for (k = 1; k < MAXSIZEZ - 1; k++) {
814 glTranslatef(0, 0, S1);
818 rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * REVZ(k)].face, NO_FACE);
820 glTranslatef(0, 0, S1);
822 NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * LASTY].face,
824 rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * FIRSTZ].face, NO_FACE);
826 glTranslatef(1, 0, -SZ);
828 rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * FIRSTY].face, NO_FACE,
829 NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * LASTY].face,
830 rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * LASTZ].face, NO_FACE);
831 for (k = 1; k < MAXSIZEZ - 1; k++) {
832 glTranslatef(0, 0, S1);
835 NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * LASTY].face,
836 rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * REVZ(k)].face, NO_FACE);
838 glTranslatef(0, 0, S1);
840 NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * LASTY].face,
841 NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * LASTY].face,
842 rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * FIRSTZ].face, NO_FACE);
844 for (j = 1; j < MAXSIZEY - 1; j++) {
846 if (slice.depth == REVY(j))
847 glRotatef(rotatestep, 0, HALFY, 0);
848 glTranslatef(-HALFX, MIDY(j), -HALFZ);
850 rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * j].face, NO_FACE,
851 rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * REVY(j)].face, NO_FACE,
853 for (k = 1; k < MAXSIZEZ - 1; k++) {
854 glTranslatef(0, 0, S1);
857 rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * REVY(j)].face, NO_FACE,
860 glTranslatef(0, 0, S1);
862 NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * REVY(j)].face,
863 rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * REVY(j)].face, NO_FACE,
865 for (i = 1; i < MAXSIZEX - 1; i++) {
866 glTranslatef(1, 0, -SZ);
868 rp->cubeLoc[BACK_FACE][i + MAXSIZEX * j].face, NO_FACE,
872 glTranslatef(0, 0, SZ);
874 NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * REVY(j)].face,
878 glTranslatef(S1, 0, -SZ);
880 rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * j].face, NO_FACE,
881 NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * REVY(j)].face,
883 for (k = 1; k < MAXSIZEZ - 1; k++) {
884 glTranslatef(0, 0, S1);
887 NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * REVY(j)].face,
890 glTranslatef(0, 0, S1);
892 NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * REVY(j)].face,
893 NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * REVY(j)].face,
897 if (slice.depth == 0)
898 glRotatef(rotatestep, 0, HALFY, 0);
900 glTranslatef(-HALFX, HALFY, -HALFZ);
902 rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * LASTY].face, NO_FACE,
903 rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * FIRSTY].face, NO_FACE,
904 NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * FIRSTZ].face);
905 for (k = 1; k < MAXSIZEZ - 1; k++) {
906 glTranslatef(0, 0, S1);
909 rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * FIRSTY].face, NO_FACE,
910 NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * k].face);
912 glTranslatef(0, 0, S1);
914 NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * FIRSTY].face,
915 rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * FIRSTY].face, NO_FACE,
916 NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * LASTZ].face);
917 for (i = 1; i < MAXSIZEX - 1; i++) {
918 glTranslatef(S1, 0, -SZ);
920 rp->cubeLoc[BACK_FACE][i + MAXSIZEX * LASTY].face, NO_FACE,
922 NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * FIRSTZ].face);
923 for (k = 1; k < MAXSIZEZ - 1; k++) {
924 glTranslatef(0, 0, S1);
928 NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * k].face);
930 glTranslatef(0, 0, S1);
932 NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * FIRSTY].face,
934 NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * LASTZ].face);
936 glTranslatef(S1, 0, -SZ);
938 rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * LASTY].face, NO_FACE,
939 NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * FIRSTY].face,
940 NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * FIRSTZ].face);
941 for (k = 1; k < MAXSIZEZ - 1; k++) {
942 glTranslatef(0, 0, S1);
945 NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * FIRSTY].face,
946 NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * k].face);
948 glTranslatef(0, 0, S1);
950 NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * FIRSTY].face,
951 NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * FIRSTY].face,
952 NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * LASTZ].face);
954 case LEFT_FACE: /* RIGHT_FACE too */
955 /* rotatestep is negative because the RIGHT face is the default here */
957 if (slice.depth == 0)
958 glRotatef(-rotatestep, HALFX, 0, 0);
960 glTranslatef(-HALFX, -HALFY, -HALFZ);
962 rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * FIRSTY].face, NO_FACE,
963 rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * LASTY].face, NO_FACE,
964 rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * LASTZ].face, NO_FACE);
965 for (j = 1; j < MAXSIZEY - 1; j++) {
966 glTranslatef(0, S1, 0);
968 rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * j].face, NO_FACE,
969 rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * REVY(j)].face, NO_FACE,
972 glTranslatef(0, S1, 0);
974 rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * LASTY].face, NO_FACE,
975 rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * FIRSTY].face, NO_FACE,
976 NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * FIRSTZ].face);
977 for (k = 1; k < MAXSIZEZ - 1; k++) {
978 glTranslatef(0, -SY, S1);
981 rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * LASTY].face, NO_FACE,
982 rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * REVZ(k)].face, NO_FACE);
983 for (j = 1; j < MAXSIZEY - 1; j++) {
984 glTranslatef(0, S1, 0);
987 rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * REVY(j)].face, NO_FACE,
990 glTranslatef(0, S1, 0);
993 rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * FIRSTY].face, NO_FACE,
994 NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * k].face);
996 glTranslatef(0, -SY, S1);
998 NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * LASTY].face,
999 rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * LASTY].face, NO_FACE,
1000 rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * FIRSTZ].face, NO_FACE);
1001 for (j = 1; j < MAXSIZEY - 1; j++) {
1002 glTranslatef(0, S1, 0);
1004 NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * REVY(j)].face,
1005 rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * REVY(j)].face, NO_FACE,
1008 glTranslatef(0, S1, 0);
1010 NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * FIRSTY].face,
1011 rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * FIRSTY].face, NO_FACE,
1012 NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * LASTZ].face);
1014 for (i = 1; i < MAXSIZEX - 1; i++) {
1016 if (slice.depth == i)
1017 glRotatef(-rotatestep, HALFX, 0, 0);
1018 glTranslatef(MIDX(i), -HALFY, -HALFZ);
1020 rp->cubeLoc[BACK_FACE][i + MAXSIZEX * FIRSTY].face, NO_FACE,
1022 rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * LASTZ].face, NO_FACE);
1023 for (j = 1; j < MAXSIZEY - 1; j++) {
1024 glTranslatef(0, S1, 0);
1026 rp->cubeLoc[BACK_FACE][i + MAXSIZEX * j].face, NO_FACE,
1030 glTranslatef(0, S1, 0);
1032 rp->cubeLoc[BACK_FACE][i + MAXSIZEX * LASTY].face, NO_FACE,
1034 NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * FIRSTZ].face);
1035 for (k = 1; k < MAXSIZEZ - 1; k++) {
1036 glTranslatef(0, -SY, S1);
1040 rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * REVZ(k)].face, NO_FACE);
1042 glTranslatef(0, SY, 0);
1046 NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * k].face);
1048 glTranslatef(0, -SY, S1);
1050 NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * LASTY].face,
1052 rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * FIRSTZ].face, NO_FACE);
1053 for (j = 1; j < MAXSIZEY - 1; j++) {
1054 glTranslatef(0, S1, 0);
1056 NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * REVY(j)].face,
1060 glTranslatef(0, S1, 0);
1062 NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * FIRSTY].face,
1064 NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * LASTZ].face);
1067 if (slice.depth == MAXSIZEX - 1)
1068 glRotatef(-rotatestep, HALFX, 0, 0);
1069 glTranslatef(HALFX, -HALFY, -HALFZ);
1071 rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * FIRSTY].face, NO_FACE,
1072 NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * LASTY].face,
1073 rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * LASTZ].face, NO_FACE);
1074 for (j = 1; j < MAXSIZEY - 1; j++) {
1075 glTranslatef(0, S1, 0);
1077 rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * j].face, NO_FACE,
1078 NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * REVY(j)].face,
1081 glTranslatef(0, S1, 0);
1083 rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * LASTY].face, NO_FACE,
1084 NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * FIRSTY].face,
1085 NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * FIRSTZ].face);
1086 for (k = 1; k < MAXSIZEZ - 1; k++) {
1087 glTranslatef(0, -SY, S1);
1090 NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * LASTY].face,
1091 rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * REVZ(k)].face, NO_FACE);
1092 for (j = 1; j < MAXSIZEY - 1; j++) {
1093 glTranslatef(0, S1, 0);
1096 NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * REVY(j)].face,
1099 glTranslatef(0, S1, 0);
1102 NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * FIRSTY].face,
1103 NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * k].face);
1105 glTranslatef(0, -SY, S1);
1107 NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * LASTY].face,
1108 NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * LASTY].face,
1109 rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * FIRSTZ].face, NO_FACE);
1110 for (j = 1; j < MAXSIZEY - 1; j++) {
1111 glTranslatef(0, S1, 0);
1113 NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * REVY(j)].face,
1114 NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * REVY(j)].face,
1117 glTranslatef(0, S1, 0);
1119 NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * FIRSTY].face,
1120 NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * FIRSTY].face,
1121 NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * LASTZ].face);
1123 case FRONT_FACE: /* BACK_FACE too */
1125 if (slice.depth == MAXSIZEZ - 1)
1126 glRotatef(rotatestep, 0, 0, HALFZ);
1128 glTranslatef(-HALFX, -HALFY, -HALFZ);
1130 rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * FIRSTY].face, NO_FACE,
1131 rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * LASTY].face, NO_FACE,
1132 rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * LASTZ].face, NO_FACE);
1133 for (i = 1; i < MAXSIZEX - 1; i++) {
1134 glTranslatef(S1, 0, 0);
1136 rp->cubeLoc[BACK_FACE][i + MAXSIZEX * FIRSTY].face, NO_FACE,
1138 rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * LASTZ].face, NO_FACE);
1140 glTranslatef(S1, 0, 0);
1142 rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * FIRSTY].face, NO_FACE,
1143 NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * LASTY].face,
1144 rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * LASTZ].face, NO_FACE);
1145 for (j = 1; j < MAXSIZEY - 1; j++) {
1146 glTranslatef(-SX, S1, 0);
1148 rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * j].face, NO_FACE,
1149 rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * REVY(j)].face, NO_FACE,
1151 for (i = 1; i < MAXSIZEX - 1; i++) {
1152 glTranslatef(S1, 0, 0);
1154 rp->cubeLoc[BACK_FACE][i + MAXSIZEX * j].face, NO_FACE,
1158 glTranslatef(S1, 0, 0);
1160 rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * j].face, NO_FACE,
1161 NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * REVY(j)].face,
1164 glTranslatef(-SX, S1, 0);
1166 rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * LASTY].face, NO_FACE,
1167 rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * FIRSTY].face, NO_FACE,
1168 NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * FIRSTZ].face);
1169 for (i = 1; i < MAXSIZEX - 1; i++) {
1170 glTranslatef(S1, 0, 0);
1172 rp->cubeLoc[BACK_FACE][i + MAXSIZEX * LASTY].face, NO_FACE,
1174 NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * FIRSTZ].face);
1176 glTranslatef(S1, 0, 0);
1178 rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * LASTY].face, NO_FACE,
1179 NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * FIRSTY].face,
1180 NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * FIRSTZ].face);
1182 for (k = 1; k < MAXSIZEZ - 1; k++) {
1184 if (slice.depth == REVZ(k))
1185 glRotatef(rotatestep, 0, 0, HALFZ);
1186 glTranslatef(-HALFX, -HALFY, MIDZ(k));
1189 rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * LASTY].face, NO_FACE,
1190 rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * REVZ(k)].face, NO_FACE);
1191 for (i = 1; i < MAXSIZEX - 1; i++) {
1192 glTranslatef(S1, 0, 0);
1196 rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * REVZ(k)].face, NO_FACE);
1198 glTranslatef(S1, 0, 0);
1201 NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * LASTY].face,
1202 rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * REVZ(k)].face, NO_FACE);
1203 for (j = 1; j < MAXSIZEY - 1; j++) {
1204 glTranslatef(-SX, S1, 0);
1207 rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * REVY(j)].face, NO_FACE,
1210 glTranslatef(SX, 0, 0);
1213 NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * REVY(j)].face,
1216 glTranslatef(-SX, S1, 0);
1219 rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * FIRSTY].face, NO_FACE,
1220 NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * k].face);
1221 for (i = 1; i < MAXSIZEX - 1; i++) {
1222 glTranslatef(S1, 0, 0);
1226 NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * k].face);
1228 glTranslatef(S1, 0, 0);
1231 NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * FIRSTY].face,
1232 NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * k].face);
1235 if (slice.depth == 0)
1236 glRotatef(rotatestep, 0, 0, HALFZ);
1237 glTranslatef(-HALFX, -HALFY, HALFZ);
1239 NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * LASTY].face,
1240 rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * LASTY].face, NO_FACE,
1241 rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * FIRSTZ].face, NO_FACE);
1242 for (i = 1; i < MAXSIZEX - 1; i++) {
1243 glTranslatef(S1, 0, 0);
1245 NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * LASTY].face,
1247 rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * FIRSTZ].face, NO_FACE);
1249 glTranslatef(S1, 0, 0);
1251 NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * LASTY].face,
1252 NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * LASTY].face,
1253 rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * FIRSTZ].face, NO_FACE);
1254 for (j = 1; j < MAXSIZEY - 1; j++) {
1255 glTranslatef(-SX, S1, 0);
1257 NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * REVY(j)].face,
1258 rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * REVY(j)].face, NO_FACE,
1260 for (i = 1; i < MAXSIZEX - 1; i++) {
1261 glTranslatef(S1, 0, 0);
1263 NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * REVY(j)].face,
1267 glTranslatef(S1, 0, 0);
1269 NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * REVY(j)].face,
1270 NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * REVY(j)].face,
1273 glTranslatef(-SX, S1, 0);
1275 NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * FIRSTY].face,
1276 rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * FIRSTY].face, NO_FACE,
1277 NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * LASTZ].face);
1278 for (i = 1; i < MAXSIZEX - 1; i++) {
1279 glTranslatef(S1, 0, 0);
1281 NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * FIRSTY].face,
1283 NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * LASTZ].face);
1285 glTranslatef(S1, 0, 0);
1287 NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * FIRSTY].face,
1288 NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * FIRSTY].face,
1289 NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * LASTZ].face);
1295 /* From David Bagley's xrubik. Used by permission. ;) */
1297 readRC(rubikstruct * rp, int face, int dir, int h, int orient, int size)
1301 if (dir == TOP || dir == BOTTOM)
1302 for (g = 0; g < size; g++)
1303 rp->rowLoc[orient][g] =
1304 rp->cubeLoc[face][g * size + h];
1305 else /* dir == RIGHT || dir == LEFT */
1306 for (g = 0; g < size; g++)
1307 rp->rowLoc[orient][g] =
1308 rp->cubeLoc[face][h * size + g];
1312 rotateRC(rubikstruct * rp, int rotate, int orient, int size)
1316 for (g = 0; g < size; g++)
1317 rp->rowLoc[orient][g].rotation =
1318 (rp->rowLoc[orient][g].rotation + rotate) % MAXORIENT;
1322 reverseRC(rubikstruct * rp, int orient, int size)
1327 for (g = 0; g < size / 2; g++) {
1328 temp = rp->rowLoc[orient][size - 1 - g];
1329 rp->rowLoc[orient][size - 1 - g] = rp->rowLoc[orient][g];
1330 rp->rowLoc[orient][g] = temp;
1335 writeRC(rubikstruct * rp, int face, int dir, int h, int orient, int size)
1339 if (dir == TOP || dir == BOTTOM) {
1340 for (g = 0; g < size; g++) {
1341 position = g * size + h;
1342 rp->cubeLoc[face][position] = rp->rowLoc[orient][g];
1343 /* DrawSquare(face, position); */
1345 } else { /* dir == RIGHT || dir == LEFT */
1346 for (g = 0; g < size; g++) {
1347 position = h * size + g;
1348 rp->cubeLoc[face][position] = rp->rowLoc[orient][g];
1349 /* DrawSquare(face, position); */
1355 rotateFace(rubikstruct * rp, int face, int direction)
1358 RubikLoc *faceLoc = NULL;
1360 if ((faceLoc = (RubikLoc *) malloc(AVSIZESQ * sizeof (RubikLoc))) == NULL)
1361 (void) fprintf(stderr,
1362 "Could not allocate memory for rubik face position info\n");
1364 for (position = 0; position < AVSIZESQ; position++)
1365 faceLoc[position] = rp->cubeLoc[face][position];
1367 for (position = 0; position < AVSIZESQ; position++) {
1368 i = position % AVSIZE;
1369 j = position / AVSIZE;
1370 rp->cubeLoc[face][position] = (direction == CW) ?
1371 faceLoc[(AVSIZE - i - 1) * AVSIZE + j] :
1372 faceLoc[i * AVSIZE + AVSIZE - j - 1];
1373 rp->cubeLoc[face][position].rotation =
1374 (rp->cubeLoc[face][position].rotation + direction - MAXORIENT) %
1376 /* DrawSquare(face, position); */
1378 if (faceLoc != NULL)
1379 (void) free((void *) faceLoc);
1383 moveRubik(rubikstruct * rp, int face, int direction, int position)
1385 int newFace, newDirection, rotate, reverse = False;
1389 if (direction == CW || direction == CCW) {
1390 direction = (direction == CCW) ?
1391 (rotateToRow[face].direction + 2) % MAXORIENT :
1392 rotateToRow[face].direction;
1393 i = j = (rotateToRow[face].sideFace == RIGHT ||
1394 rotateToRow[face].sideFace == BOTTOM) ? AVSIZE - 1 : 0;
1395 face = rotateToRow[face].face;
1396 position = j * AVSIZE + i;
1398 i = position % AVSIZE;
1399 j = position / AVSIZE;
1400 h = (direction == TOP || direction == BOTTOM) ? i : j;
1401 /* rotate sides CW or CCW */
1402 if (h == AVSIZE - 1) {
1403 newDirection = (direction == TOP || direction == BOTTOM) ?
1405 if (direction == TOP || direction == RIGHT)
1406 rotateFace(rp, rowToRotate[face][newDirection], CW);
1407 else /* direction == BOTTOM || direction == LEFT */
1408 rotateFace(rp, rowToRotate[face][newDirection], CCW);
1411 newDirection = (direction == TOP || direction == BOTTOM) ?
1413 if (direction == TOP || direction == RIGHT)
1414 rotateFace(rp, rowToRotate[face][newDirection], CCW);
1415 else /* direction == BOTTOM || direction == LEFT */
1416 rotateFace(rp, rowToRotate[face][newDirection], CW);
1419 readRC(rp, face, direction, h, 0, AVSIZE);
1420 for (k = 1; k <= MAXORIENT; k++) {
1421 newFace = slideNextRow[face][direction].face;
1422 rotate = slideNextRow[face][direction].rotation;
1423 newDirection = (rotate + direction) % MAXORIENT;
1430 if (newDirection == TOP || newDirection == BOTTOM) {
1431 newH = AVSIZE - 1 - h;
1433 } else { /* newDirection == RIGHT || newDirection == LEFT */
1439 newH = AVSIZE - 1 - h;
1443 if (newDirection == TOP || newDirection == BOTTOM) {
1446 } else { /* newDirection == RIGHT || newDirection == LEFT */
1447 newH = AVSIZE - 1 - h;
1452 (void) printf("moveRubik: rotate %d\n", rotate);
1455 readRC(rp, newFace, newDirection, newH, k, AVSIZE);
1456 rotateRC(rp, rotate, k - 1, AVSIZE);
1457 if (reverse == True)
1458 reverseRC(rp, k - 1, AVSIZE);
1459 writeRC(rp, newFace, newDirection, newH, k - 1, AVSIZE);
1461 direction = newDirection;
1468 printCube(rubikstruct * rp)
1472 for (face = 0; face < MAXFACES; face++) {
1473 for (position = 0; position < AVSIZESQ; position++) {
1474 (void) printf("%d %d ", rp->cubeLoc[face][position].face,
1475 rp->cubeLoc[face][position].rotation);
1476 if (!((position + 1) % AVSIZE))
1477 (void) printf("\n");
1479 (void) printf("\n");
1481 (void) printf("\n");
1487 evalmovement(ModeInfo * mi, RubikMove movement)
1489 rubikstruct *rp = &rubik[MI_SCREEN(mi)];
1494 if (movement.face < 0 || movement.face >= MAXFACES)
1497 moveRubik(rp, movement.face, movement.direction, movement.position);
1502 compare_moves(rubikstruct * rp, RubikMove move1, RubikMove move2, Bool opp)
1504 RubikSlice slice1, slice2;
1506 slice1 = convertMove(rp, move1);
1507 slice2 = convertMove(rp, move2);
1508 if (slice1.face == slice2.face &&
1509 slice1.depth == slice2.depth) {
1510 if (slice1.rotation == slice2.rotation) { /* CW or CCW */
1522 shuffle(ModeInfo * mi)
1524 rubikstruct *rp = &rubik[MI_SCREEN(mi)];
1525 int i, face, position;
1528 AVSIZE = MI_SIZE(mi);
1529 if (AVSIZE < -MINSIZE)
1530 AVSIZE = NRAND(-AVSIZE - MINSIZE + 1) + MINSIZE;
1531 else if (AVSIZE < MINSIZE)
1533 /* Let me waste a little space for the moment */
1534 /* Future cube to be LxMxN and not just NxNxN, but not done yet */
1535 AVSIZESQ = AVSIZE * AVSIZE;
1541 MAXSIZESQ = AVSIZESQ;
1544 for (face = 0; face < MAXFACES; face++) {
1545 if (rp->cubeLoc[face] != NULL)
1546 (void) free((void *) rp->cubeLoc[face]);
1547 if ((rp->cubeLoc[face] =
1548 (RubikLoc *) malloc(AVSIZESQ * sizeof (RubikLoc))) == NULL)
1549 (void) fprintf(stderr,
1550 "Could not allocate memory for rubik cube position info\n");
1551 for (position = 0; position < AVSIZESQ; position++) {
1552 rp->cubeLoc[face][position].face = face;
1553 rp->cubeLoc[face][position].rotation = TOP;
1556 for (i = 0; i < MAXORIENT; i++) {
1557 if (rp->rowLoc[i] != NULL)
1558 (void) free((void *) rp->rowLoc[i]);
1559 if ((rp->rowLoc[i] =
1560 (RubikLoc *) malloc(AVSIZE * sizeof (RubikLoc))) == NULL)
1561 (void) fprintf(stderr,
1562 "Could not allocate memory for rubik row position info\n");
1564 rp->storedmoves = MI_COUNT(mi);
1565 if (rp->storedmoves < 0) {
1566 if (rp->moves != NULL)
1567 (void) free((void *) rp->moves);
1569 rp->storedmoves = NRAND(-rp->storedmoves) + 1;
1571 if ((rp->storedmoves) && (rp->moves == NULL))
1573 (RubikMove *) calloc(rp->storedmoves + 1, sizeof (RubikMove))) == NULL)
1574 (void) fprintf(stderr,
1575 "Could not allocate memory for rubik move buffer\n");
1577 if (MI_CYCLES(mi) <= 1) {
1578 rp->anglestep = 90.0;
1580 rp->anglestep = 90.0 / (GLfloat) (MI_CYCLES(mi));
1583 for (i = 0; i < rp->storedmoves; i++) {
1587 move.face = NRAND(6);
1588 move.direction = NRAND(4); /* Exclude CW and CCW, its ok */
1590 * Randomize position along diagonal, each plane gets an equal chance.
1591 * This trick will only work for NxNxN cubes
1592 * draw_cube DEPENDS on that they are chosen this way.
1594 move.position = NRAND(AVSIZE) * (AVSIZE + 1);
1599 if (i > 0) /* avoid immediate undoing moves */
1600 if (compare_moves(rp, move, rp->moves[i - 1], True))
1602 if (i > 1) /* avoid 3 consecutive identical moves */
1603 if (compare_moves(rp, move, rp->moves[i - 1], False) &&
1604 compare_moves(rp, move, rp->moves[i - 2], False))
1607 * Still some silly moves being made....
1609 } while (!condition);
1611 evalmovement(mi, move);
1612 rp->moves[i] = move;
1615 if (NRAND(100) < 50)
1618 if (NRAND(100) < 50)
1620 rp->movement.face = NO_FACE;
1622 rp->action = hideshuffling ? ACTION_SOLVE : ACTION_SHUFFLE;
1623 rp->shufflingmoves = 0;
1628 reshape(ModeInfo * mi, int width, int height)
1630 rubikstruct *rp = &rubik[MI_SCREEN(mi)];
1632 glViewport(0, 0, rp->WindW = (GLint) width, rp->WindH = (GLint) height);
1633 glMatrixMode(GL_PROJECTION);
1635 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
1636 glMatrixMode(GL_MODELVIEW);
1638 rp->AreObjectsDefined[ObjCubit] = 0;
1642 pinit(ModeInfo * mi)
1645 glClearColor(0.0, 0.0, 0.0, 1.0);
1646 glColor3f(1.0, 1.0, 1.0);
1648 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
1649 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
1650 glLightfv(GL_LIGHT0, GL_POSITION, position0);
1651 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
1652 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
1653 glLightfv(GL_LIGHT1, GL_POSITION, position1);
1654 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
1655 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
1656 glEnable(GL_LIGHTING);
1657 glEnable(GL_LIGHT0);
1658 glEnable(GL_LIGHT1);
1659 glEnable(GL_DEPTH_TEST);
1660 glEnable(GL_NORMALIZE);
1661 glEnable(GL_CULL_FACE);
1663 glShadeModel(GL_FLAT);
1664 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
1665 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
1671 init_rubik(ModeInfo * mi)
1673 int screen = MI_SCREEN(mi);
1676 if (rubik == NULL) {
1677 if ((rubik = (rubikstruct *) calloc(MI_NUM_SCREENS(mi),
1678 sizeof (rubikstruct))) == NULL)
1681 rp = &rubik[screen];
1682 rp->step = NRAND(90);
1684 rp->PX = ((float) LRAND() / (float) RAND_MAX) * 2 - 1;
1685 rp->PY = ((float) LRAND() / (float) RAND_MAX) * 2 - 1;
1687 if ((rp->glx_context = init_GL(mi)) != NULL) {
1689 reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1690 objects = glGenLists(1);
1698 draw_rubik(ModeInfo * mi)
1702 rubikstruct *rp = &rubik[MI_SCREEN(mi)];
1703 Display *display = MI_DISPLAY(mi);
1704 Window window = MI_WINDOW(mi);
1706 MI_IS_DRAWN(mi) = True;
1708 if (!rp->glx_context)
1711 glDrawBuffer(GL_BACK);
1712 glXMakeCurrent(display, window, *(rp->glx_context));
1714 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1718 glTranslatef(0.0, 0.0, -10.0);
1724 rp->PY += (-1) - (rp->PY);
1729 rp->PY -= (rp->PY) - 1;
1734 rp->PX += (-1) - (rp->PX);
1739 rp->PX -= (rp->PX) - 1;
1744 rp->VX += ((float) LRAND() / (float) RAND_MAX) * 0.02 - 0.01;
1745 rp->VX += ((float) LRAND() / (float) RAND_MAX) * 0.02 - 0.01;
1755 if (!MI_IS_ICONIC(mi)) {
1756 glTranslatef(rp->PX, rp->PY, 0);
1757 glScalef(Scale4Window * rp->WindH / rp->WindW, Scale4Window, Scale4Window);
1759 glScalef(Scale4Iconic * rp->WindH / rp->WindW, Scale4Iconic, Scale4Iconic);
1762 glRotatef(rp->step * 100, 1, 0, 0);
1763 glRotatef(rp->step * 95, 0, 1, 0);
1764 glRotatef(rp->step * 90, 0, 0, 1);
1767 glXSwapBuffers(display, window);
1769 if (rp->action == ACTION_SHUFFLE) {
1771 if (++rp->rotatestep > DELAY_AFTER_SHUFFLING) {
1772 rp->movement.face = NO_FACE;
1774 rp->action = ACTION_SOLVE;
1778 if (rp->movement.face == NO_FACE) {
1779 if (rp->shufflingmoves < rp->storedmoves) {
1781 rp->movement = rp->moves[rp->shufflingmoves];
1787 rp->rotatestep += rp->anglestep;
1788 if (rp->rotatestep > 90) {
1789 evalmovement(mi, rp->movement);
1790 rp->shufflingmoves++;
1791 rp->movement.face = NO_FACE;
1797 if (++rp->rotatestep > DELAY_AFTER_SOLVING)
1800 if (rp->movement.face == NO_FACE) {
1801 if (rp->storedmoves > 0) {
1803 rp->movement = rp->moves[rp->storedmoves - 1];
1804 rp->movement.direction = (rp->movement.direction + (MAXORIENT / 2)) %
1811 rp->rotatestep += rp->anglestep;
1812 if (rp->rotatestep > 90) {
1813 evalmovement(mi, rp->movement);
1815 rp->movement.face = NO_FACE;
1829 change_rubik(ModeInfo * mi)
1831 rubikstruct *rp = &rubik[MI_SCREEN(mi)];
1833 if (!rp->glx_context)
1839 release_rubik(ModeInfo * mi)
1841 if (rubik != NULL) {
1844 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
1845 rubikstruct *rp = &rubik[screen];
1848 for (i = 0; i < MAXFACES; i++)
1849 if (rp->cubeLoc[i] != NULL)
1850 (void) free((void *) rp->cubeLoc[i]);
1851 for (i = 0; i < MAXORIENT; i++)
1852 if (rp->rowLoc[i] != NULL)
1853 (void) free((void *) rp->rowLoc[i]);
1854 if (rp->moves != NULL)
1855 (void) free((void *) rp->moves);
1857 (void) free((void *) rubik);