1 /* glsnake.c - OpenGL imitation of Rubik's Snake
3 * (c) 2001-2003 Jamie Wilkinson <jaq@spacepants.org>
4 * (c) 2001-2003 Andrew Bennetts <andrew@puzzling.org>
5 * (c) 2001-2003 Peter Aylett <peter@ylett.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* HAVE_GLUT defined if we're building a standalone glsnake,
27 * and not defined if we're building as an xscreensaver hack */
47 #ifdef HAVE_GETTIMEOFDAY
48 #ifdef GETTIMEOFDAY_TWO_ARGS
49 # include <sys/time.h>
51 typedef struct timeval snaketime;
52 # define GETSECS(t) ((t).tv_sec)
53 # define GETMSECS(t) ((t).tv_usec/1000)
54 #else /* GETTIMEOFDAY_TWO_ARGS */
55 # include <sys/time.h>
57 typedef struct timeval snaketime;
58 # define GETSECS(t) ((t).tv_sec)
59 # define GETMSECS(t) ((t).tv_usec/1000)
61 #else /* HAVE_GETTIMEOFDAY */
63 # include <sys/timeb.h>
64 typedef struct timeb snaketime;
65 # define GETSECS(t) ((long)(t).time)
66 # define GETMSECS(t) ((t).millitm/1000)
67 #endif /* HAVE_FTIME */
68 #endif /* HAVE_GETTIMEOFDAY */
72 #ifndef M_SQRT1_2 /* Win32 doesn't have this constant */
73 #define M_SQRT1_2 0.70710678118654752440084436210485
79 #define DEF_YANGVEL 0.10
80 #define DEF_ZANGVEL 0.14
81 #define DEF_EXPLODE 0.03
82 #define DEF_ANGVEL 1.0
84 #define DEF_STATICTIME 5000
85 #define DEF_ALTCOLOUR 0
87 #define DEF_INTERACTIVE 0
89 #define DEF_WIREFRAME 0
91 /* xscreensaver options doobies prefer strings */
92 #define DEF_YANGVEL "0.10"
93 #define DEF_ZANGVEL "0.14"
94 #define DEF_EXPLODE "0.03"
95 #define DEF_ANGVEL "1.0"
96 #define DEF_ACCEL "0.1"
97 #define DEF_STATICTIME "5000"
98 #define DEF_ALTCOLOUR "False"
99 #define DEF_TITLES "True"
100 #define DEF_INTERACTIVE "False"
101 #define DEF_ZOOM "25.0"
102 #define DEF_WIREFRAME "False"
105 /* static variables */
107 # include <X11/Intrinsic.h>
109 /* xscreensaver boolean type */
113 static GLfloat explode;
114 static GLfloat accel;
115 static long statictime;
116 static GLfloat yspin = 0;
117 static GLfloat zspin = 0;
118 static GLfloat yangvel;
119 static GLfloat zangvel;
120 static Bool altcolour;
122 static Bool interactive;
123 static Bool wireframe;
125 static GLfloat angvel;
128 /* xscreensaver setup */
129 extern XtAppContext app;
131 #define PROGCLASS "glsnake"
132 #define HACK_INIT glsnake_init
133 #define HACK_DRAW glsnake_display
134 #define HACK_RESHAPE glsnake_reshape
135 #define sws_opts xlockmore_opts
138 /* xscreensaver defaults */
139 #define DEFAULTS "*delay: 30000 \n" \
141 "*showFPS: False \n" \
142 "*wireframe: False \n" \
143 "*explode: " DEF_EXPLODE " \n" \
144 "*angvel: " DEF_ANGVEL " \n" \
145 "*accel: " DEF_ACCEL " \n" \
146 "*statictime: " DEF_STATICTIME " \n" \
147 "*yangvel: " DEF_YANGVEL " \n" \
148 "*zangvel: " DEF_ZANGVEL " \n" \
149 "*altcolour: " DEF_ALTCOLOUR " \n" \
151 "*labelfont: -*-times-bold-r-normal-*-180-*\n" \
152 "*zoom: " DEF_ZOOM " \n" \
157 #define countof(x) (sizeof((x))/sizeof((*x)))
159 #include "xlockmore.h"
161 static XrmOptionDescRec opts[] = {
162 { "-explode", ".explode", XrmoptionSepArg, DEF_EXPLODE },
163 { "-angvel", ".angvel", XrmoptionSepArg, DEF_ANGVEL },
164 { "-accel", ".accel", XrmoptionSepArg, DEF_ACCEL },
165 { "-statictime", ".statictime", XrmoptionSepArg, DEF_STATICTIME },
166 { "-yangvel", ".yangvel", XrmoptionSepArg, DEF_YANGVEL },
167 { "-zangvel", ".zangvel", XrmoptionSepArg, DEF_ZANGVEL },
168 { "-altcolour", ".altcolour", XrmoptionNoArg, (caddr_t) "True" },
169 { "-no-altcolour", ".altcolour", XrmoptionNoArg, (caddr_t) "False" },
170 { "-titles", ".titles", XrmoptionNoArg, (caddr_t) "True" },
171 { "-no-titles", ".titles", XrmoptionNoArg, (caddr_t) "False" },
172 { "-zoom", ".zoom", XrmoptionSepArg, DEF_ZOOM },
173 { "-wireframe", ".wireframe", XrmoptionNoArg, (caddr_t) "true" },
174 { "-no-wireframe", ".wireframe", XrmoptionNoArg, (caddr_t) "false" },
177 static argtype vars[] = {
178 {(caddr_t *) &explode, "explode", "Explode", DEF_EXPLODE, t_Float},
179 {(caddr_t *) &angvel, "angvel", "Angular Velocity", DEF_ANGVEL, t_Float},
180 {(caddr_t *) &accel, "accel", "Acceleration", DEF_ACCEL, t_Float},
181 {(caddr_t *) &statictime, "statictime", "Static Time", DEF_STATICTIME, t_Int},
182 {(caddr_t *) &yangvel, "yangvel", "Angular Velocity about Y axis", DEF_YANGVEL, t_Float},
183 {(caddr_t *) &zangvel, "zangvel", "Angular Velocity about X axis", DEF_ZANGVEL, t_Float},
184 {(caddr_t *) &interactive, "interactive", "Interactive", DEF_INTERACTIVE, t_Bool},
185 {(caddr_t *) &altcolour, "altcolour", "Alternate Colour Scheme", DEF_ALTCOLOUR, t_Bool},
186 {(caddr_t *) &titles, "titles", "Titles", DEF_TITLES, t_Bool},
187 {(caddr_t *) &zoom, "zoom", "Zoom", DEF_ZOOM, t_Float},
188 {(caddr_t *) &wireframe, "wireframe", "Wireframe", DEF_WIREFRAME, t_Bool},
191 ModeSpecOpt sws_opts = {countof(opts), opts, countof(vars), vars, NULL};
196 float node[NODE_COUNT];
201 GLXContext * glx_context;
205 /* font list number */
212 /* is a morph in progress? */
215 /* has the model been paused? */
224 /* the shape of the model */
225 float node[NODE_COUNT];
227 /* currently selected node for interactive mode */
242 /* timing variables */
243 snaketime last_iteration;
244 snaketime last_morph;
248 int old_width, old_height;
250 /* the id of the display lists for drawing a node */
251 int node_solid, node_wire;
253 /* is the window fullscreen? */
257 #define COLOUR_CYCLIC 0
258 #define COLOUR_ACYCLIC 1
259 #define COLOUR_INVALID 2
260 #define COLOUR_AUTHENTIC 3
262 float colour[][2][3] = {
272 /* authentic - purple and green */
273 { { 0.38, 0.0, 0.55 },
277 struct model_s model[] = {
278 #define STRAIGHT_MODEL 0
280 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
281 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
284 /* the models in the Rubik's snake manual */
285 #define START_MODEL 1
287 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT,
288 RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT,
289 RIGHT, LEFT, RIGHT, LEFT }
292 { RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT,
293 RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT,
294 RIGHT, LEFT, LEFT, LEFT }
297 { ZERO, ZERO, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO, ZERO,
298 ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO, ZERO, ZERO, RIGHT,
299 LEFT, RIGHT, ZERO, LEFT }
302 { ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, RIGHT, PIN,
303 RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, ZERO, ZERO,
307 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN,
308 ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
312 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, LEFT, RIGHT, PIN, RIGHT,
313 ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, LEFT, ZERO,
316 /* These models were taken from Andrew and Peter's original snake.c
317 * as well as some newer ones made up by Jamie, Andrew and Peter. */
319 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT,
320 LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT,
321 RIGHT, LEFT, LEFT, LEFT }
324 { RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT,
325 LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT,
326 RIGHT, RIGHT, LEFT, LEFT }
329 { PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN,
330 ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN }
333 { PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN,
334 LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN }
337 { RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT,
338 LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN,
342 { RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT,
343 LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT,
344 RIGHT, RIGHT, LEFT, LEFT }
347 { ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT,
348 LEFT, RIGHT, LEFT, LEFT, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT,
349 RIGHT, RIGHT, RIGHT }
352 { RIGHT, PIN, ZERO, ZERO, PIN, LEFT, ZERO, LEFT, LEFT, ZERO,
353 LEFT, PIN, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO,
357 { PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT,
358 LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT,
362 { ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO,
363 ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO,
364 LEFT, ZERO, ZERO, RIGHT }
367 { ZERO, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO, RIGHT, ZERO, ZERO,
368 LEFT, RIGHT, ZERO, LEFT, ZERO, RIGHT, ZERO, ZERO, LEFT, RIGHT,
369 ZERO, LEFT, ZERO, RIGHT }
372 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO,
373 ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO,
374 ZERO, ZERO, LEFT, RIGHT }
377 { ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT,
378 RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN,
382 { ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN,
383 PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN }
386 { PIN, RIGHT, LEFT, PIN, LEFT, PIN, ZERO, ZERO, RIGHT, PIN, LEFT,
387 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
391 { ZERO, ZERO, ZERO, ZERO, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT,
392 ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT,
396 { RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO,
397 LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, PIN, RIGHT,
401 { ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN,
402 ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN }
405 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, LEFT, PIN,
406 RIGHT, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT,
410 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, ZERO, ZERO,
411 RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO, LEFT, LEFT,
412 RIGHT, LEFT, RIGHT, RIGHT }
415 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, PIN, ZERO, ZERO,
416 LEFT, PIN, RIGHT, ZERO, ZERO, PIN, ZERO, LEFT, LEFT, RIGHT, LEFT,
420 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO,
421 RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT,
425 { LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT,
426 ZERO, ZERO, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN,
430 { RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN,
431 LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT,
435 { RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN,
436 LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT,
437 LEFT, PIN, LEFT, PIN }
440 { ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN,
441 ZERO, PIN, ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT,
445 { ZERO, PIN, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, PIN,
446 ZERO, PIN, ZERO, PIN, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO,
450 { ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN,
451 ZERO, PIN, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
455 { ZERO, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT,
456 ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
460 { ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO,
461 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
465 { ZERO, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, ZERO,
466 ZERO, PIN, ZERO, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO,
470 { RIGHT, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, ZERO,
471 LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT,
472 ZERO, ZERO, LEFT, PIN }
475 { RIGHT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT,
476 ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT,
477 LEFT, RIGHT, ZERO, LEFT, PIN }
480 { RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO,
481 LEFT, PIN, RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT,
485 { ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, ZERO,
486 ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT,
490 { ZERO, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN,
491 RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT,
495 { LEFT, PIN, LEFT, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, LEFT,
496 PIN, RIGHT, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN,
500 { RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, ZERO,
501 ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, RIGHT, RIGHT, LEFT,
502 RIGHT, LEFT, LEFT, LEFT, PIN }
505 { ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, RIGHT,
506 RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT,
507 PIN, LEFT, LEFT, LEFT }
510 { PIN, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, LEFT,
511 ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, LEFT, ZERO,
515 { PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, RIGHT,
516 RIGHT, PIN, RIGHT, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO,
517 ZERO, PIN, PIN, ZERO }
520 /* the following modesl were created during the slug/compsoc codefest
523 { PIN, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT,
524 ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, ZERO,
528 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN,
529 PIN, ZERO, RIGHT, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO,
533 { RIGHT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT,
534 RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN,
535 RIGHT, LEFT, RIGHT, PIN, ZERO }
538 { ZERO, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO,
539 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
543 { LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO,
544 RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT,
545 RIGHT, ZERO, LEFT, ZERO }
548 { ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO,
549 PIN, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO, PIN, PIN, ZERO,
553 { ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
554 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO,
558 { PIN, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
559 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO,
562 { "erect penis", /* thanks benno */
563 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, PIN,
564 PIN, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
568 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, PIN,
569 PIN, ZERO, ZERO, ZERO, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
573 { RIGHT, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO,
574 LEFT, ZERO, ZERO, ZERO, LEFT, ZERO, LEFT, PIN, LEFT, PIN, RIGHT,
578 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN,
579 ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO,
582 { "poles or columns or something",
583 { LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
584 ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
588 { ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
589 ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
593 { ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO,
594 LEFT, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
598 { ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO,
599 LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO,
600 LEFT, PIN, ZERO, ZERO }
603 { ZERO, ZERO, PIN, RIGHT, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO,
604 LEFT, PIN, ZERO, ZERO, PIN, ZERO, LEFT, ZERO, RIGHT, LEFT, ZERO,
608 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
609 RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
613 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
614 ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
618 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
619 LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
623 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
624 PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
628 { RIGHT, ZERO, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT,
629 RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT,
630 ZERO, ZERO, RIGHT, ZERO }
633 { RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT,
634 ZERO, RIGHT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, ZERO,
635 RIGHT, ZERO, RIGHT, ZERO, ZERO }
638 /* These models come from the website at
639 * http://www.geocities.com/stigeide/snake */
641 { RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO }
644 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN }
647 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT }
650 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN }
653 { ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, ZERO }
656 { RIGHT, LEFT, RIGHT, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO, PIN, PIN }
659 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT }
662 { LEFT, PIN, RIGHT, ZERO, ZERO, PIN, RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, ZERO }
665 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT }
668 { ZERO, RIGHT, RIGHT, ZERO, RIGHT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, ZERO, LEFT }
671 { PIN, LEFT, RIGHT, ZERO, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, LEFT, RIGHT, PIN, RIGHT }
674 { PIN, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, PIN }
677 { LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT }
680 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT }
683 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, PIN }
686 { PIN, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, ZERO }
689 { RIGHT, ZERO, PIN, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, ZERO, ZERO, LEFT }
692 { LEFT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT }
695 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO }
698 { RIGHT, ZERO, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO }
701 { PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO }
704 { RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, LEFT, RIGHT, LEFT, LEFT }
707 { RIGHT, RIGHT, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, LEFT, LEFT }
710 { RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT }
713 { ZERO, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, LEFT, ZERO, LEFT, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT }
716 { LEFT, ZERO, PIN, ZERO, PIN, LEFT, ZERO, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, PIN, ZERO, RIGHT }
719 { ZERO, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, LEFT }
722 { ZERO, ZERO, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN }
725 { LEFT, PIN, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO }
728 { ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN }
731 { PIN, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
734 { LEFT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT }
737 { PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, RIGHT, PIN }
740 { RIGHT, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, LEFT }
743 { ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO, PIN }
745 { "Counterclockwise",
746 { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT }
749 { LEFT, LEFT, ZERO, PIN, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, RIGHT, LEFT, LEFT, ZERO, ZERO, RIGHT }
752 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, PIN, RIGHT }
755 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN }
758 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO }
761 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO }
764 { PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN }
767 { RIGHT, LEFT, PIN, LEFT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, LEFT, PIN, LEFT, RIGHT }
770 { LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, PIN, ZERO }
773 { RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT }
776 { ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, LEFT }
779 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, LEFT, RIGHT }
782 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, LEFT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, RIGHT, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, PIN }
785 { ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, LEFT, ZERO, PIN, ZERO, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT }
788 { ZERO, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT }
791 { ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN }
794 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT }
797 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO, RIGHT, ZERO, RIGHT, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT }
800 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, RIGHT, ZERO, RIGHT, LEFT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT }
803 { PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO }
806 { PIN, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO }
809 { ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, RIGHT }
812 { LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT }
815 { LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT }
818 { RIGHT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT }
821 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT }
824 { ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT }
827 { LEFT, LEFT, RIGHT, PIN, ZERO, RIGHT, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, LEFT, ZERO, PIN, LEFT, RIGHT, RIGHT, RIGHT, PIN }
830 { PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN }
833 { ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, RIGHT, ZERO, PIN }
836 { ZERO, RIGHT, ZERO, PIN, LEFT, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, RIGHT, PIN, ZERO, LEFT, ZERO }
839 { ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, ZERO, ZERO, ZERO, PIN }
842 { ZERO, PIN, PIN, ZERO, PIN, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, PIN }
845 { ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT }
848 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN }
851 { LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, RIGHT, LEFT, RIGHT, RIGHT }
854 { LEFT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, ZERO, RIGHT }
857 { PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN }
860 { ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, ZERO, PIN, PIN, ZERO }
863 { LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT }
866 { RIGHT, LEFT, ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, LEFT, ZERO }
869 { PIN, PIN, ZERO, LEFT, RIGHT, LEFT, ZERO, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, RIGHT, LEFT, RIGHT }
872 { PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO }
875 { PIN, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO }
878 { RIGHT, ZERO, ZERO, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, RIGHT, ZERO, PIN, ZERO, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO, ZERO, ZERO, LEFT }
881 { ZERO, PIN, ZERO, ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO }
884 { ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO }
886 { "HoleInTheMiddle1",
887 { ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT }
889 { "HoleInTheMiddle2",
890 { ZERO, LEFT, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT }
893 { RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, PIN }
896 { LEFT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT }
899 { LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT }
902 { RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT }
905 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, RIGHT }
908 { RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, LEFT }
911 { ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO }
914 { LEFT, LEFT, PIN, LEFT, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, RIGHT, PIN, RIGHT, RIGHT, LEFT }
917 { ZERO, PIN, PIN, ZERO, ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO }
920 { RIGHT, PIN, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, PIN, LEFT }
923 { PIN, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO }
926 { PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT }
929 { ZERO, ZERO, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO }
932 { ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT }
935 { PIN, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN }
938 { PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, PIN, ZERO }
941 { ZERO, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, LEFT, PIN, RIGHT, RIGHT, ZERO, RIGHT }
944 { ZERO, RIGHT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, ZERO, RIGHT, RIGHT, PIN, LEFT }
947 { LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT }
950 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, LEFT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO }
953 { ZERO, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO }
955 { "MouseWithoutTail",
956 { ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO }
959 { PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN }
962 { ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO }
965 { LEFT, ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT }
968 { ZERO, RIGHT, PIN, LEFT, LEFT, LEFT, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, RIGHT, RIGHT, PIN, LEFT, ZERO }
971 { LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT }
974 { PIN, ZERO, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, ZERO }
977 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN }
980 { PIN, PIN, ZERO, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO }
983 { ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO }
986 { ZERO, ZERO, ZERO, ZERO, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, ZERO, PIN }
989 { PIN, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, PIN }
991 { "PictureCommingSoon",
992 { LEFT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, RIGHT, RIGHT }
995 { LEFT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT }
998 { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT }
1001 { RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT }
1004 { ZERO, PIN, ZERO, PIN, RIGHT, PIN, ZERO, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, ZERO, PIN, LEFT }
1007 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT }
1010 { RIGHT, PIN, ZERO, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, PIN, ZERO, PIN, LEFT }
1013 { ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT }
1016 { ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, LEFT }
1018 { "QuarterbackTiltedAndReadyToHut",
1019 { PIN, ZERO, RIGHT, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, LEFT, ZERO, PIN }
1022 { PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT }
1025 { LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, PIN, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT }
1028 { ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN }
1031 { LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT }
1034 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT }
1037 { RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT }
1040 { ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, ZERO, PIN, ZERO, RIGHT }
1043 { PIN, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, PIN }
1046 { RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT }
1049 { RIGHT, LEFT, PIN, ZERO, ZERO, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT }
1052 { LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, LEFT }
1055 { RIGHT, PIN, ZERO, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO }
1058 { RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT }
1061 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT }
1064 { PIN, RIGHT, LEFT, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, LEFT, ZERO, PIN, PIN }
1067 { LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO }
1070 { LEFT, RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, RIGHT, LEFT }
1073 { ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, LEFT }
1075 { "SnakeReadyToStrike",
1076 { LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, LEFT }
1079 { RIGHT, RIGHT, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, LEFT, RIGHT }
1082 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, PIN, RIGHT }
1085 { PIN, PIN, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, PIN }
1088 { LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT }
1091 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO }
1094 { PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN }
1097 { PIN, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, PIN }
1100 { PIN, PIN, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, LEFT, LEFT, PIN, PIN }
1103 { LEFT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT }
1106 { PIN, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, ZERO, RIGHT, PIN, LEFT }
1109 { RIGHT, RIGHT, ZERO, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, RIGHT, LEFT, RIGHT, ZERO, ZERO, LEFT }
1112 { PIN, LEFT, ZERO, RIGHT, RIGHT, LEFT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, LEFT, LEFT, ZERO }
1115 { ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO }
1118 { PIN, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN }
1121 { RIGHT, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO }
1124 { ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO }
1127 { ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
1130 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO }
1133 { ZERO, PIN, ZERO, PIN, LEFT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT }
1136 { PIN, ZERO, PIN, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, PIN }
1139 { PIN, PIN, ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, RIGHT }
1142 { RIGHT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, RIGHT }
1145 { RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT }
1148 { ZERO, PIN, LEFT, LEFT, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, PIN, LEFT }
1151 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, RIGHT, PIN }
1154 { ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO }
1157 { ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO }
1160 { RIGHT, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN }
1163 { RIGHT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO }
1166 { RIGHT, LEFT, ZERO, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT }
1169 { PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO }
1172 { RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, PIN, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT }
1175 { RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT }
1178 { ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, LEFT, LEFT, PIN, ZERO, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT }
1181 { PIN, LEFT, LEFT, PIN, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, ZERO }
1184 { PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO }
1187 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT }
1190 { PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN }
1193 { RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO }
1196 { ZERO, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO }
1199 { ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN }
1202 { PIN, LEFT, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, ZERO }
1205 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT }
1208 { LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, ZERO }
1211 { ZERO, PIN, ZERO, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO }
1214 { ZERO, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1217 { PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN }
1220 { ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1223 { PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, PIN, RIGHT, ZERO, RIGHT, RIGHT, ZERO, RIGHT, PIN, ZERO, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO }
1226 { ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT }
1229 { LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT }
1232 { PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO }
1235 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO }
1237 { "WindowToTheWorld",
1238 { PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO }
1241 { PIN, PIN, ZERO, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, PIN }
1244 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO }
1247 { RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, ZERO }
1250 { PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN }
1253 { ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN }
1256 { LEFT, ZERO, ZERO, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, ZERO, ZERO }
1260 int models = (sizeof(model) / sizeof(struct model_s));
1262 #define VOFFSET 0.045
1268 /* the connecting string that holds the snake together */
1269 #define MAGICAL_RED_STRING 0
1271 #define GETSCALAR(vec,mask) ((vec)==(mask) ? 1 : ((vec)==-(mask) ? -1 : 0 ))
1274 # define MAX(x, y) ((x) > (y) ? (x) : (y))
1277 # define MIN(x, y) ((x) < (y) ? (x) : (y))
1280 #define RAND(n) ((random() & 0x7fffffff) % ((long) (n)))
1281 #define RANDSIGN() ((random() & 1) ? 1 : -1)
1283 /* the triangular prism what makes up the basic unit */
1284 float solid_prism_v[][3] = {
1285 /* first corner, bottom left front */
1286 { VOFFSET, VOFFSET, 1.0 },
1287 { VOFFSET, 0.00, 1.0 - VOFFSET },
1288 { 0.00, VOFFSET, 1.0 - VOFFSET },
1289 /* second corner, rear */
1290 { VOFFSET, VOFFSET, 0.00 },
1291 { VOFFSET, 0.00, VOFFSET },
1292 { 0.00, VOFFSET, VOFFSET },
1293 /* third, right front */
1294 { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 1.0 },
1295 { 1.0 - VOFFSET / M_SQRT1_2, 0.0, 1.0 - VOFFSET },
1296 { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, 1.0 - VOFFSET },
1297 /* fourth, right rear */
1298 { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 0.0 },
1299 { 1.0 - VOFFSET / M_SQRT1_2, 0.0, VOFFSET },
1300 { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, VOFFSET },
1301 /* fifth, upper front */
1302 { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 1.0 },
1303 { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, 1.0 - VOFFSET },
1304 { 0.0, 1.0 - VOFFSET / M_SQRT1_2, 1.0 - VOFFSET},
1305 /* sixth, upper rear */
1306 { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 0.0 },
1307 { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, VOFFSET },
1308 { 0.0, 1.0 - VOFFSET / M_SQRT1_2, VOFFSET }};
1310 float solid_prism_n[][3] = {/* corners */
1311 { -VOFFSET, -VOFFSET, VOFFSET },
1312 { VOFFSET, -VOFFSET, VOFFSET },
1313 { -VOFFSET, VOFFSET, VOFFSET },
1314 { -VOFFSET, -VOFFSET, -VOFFSET },
1315 { VOFFSET, -VOFFSET, -VOFFSET },
1316 { -VOFFSET, VOFFSET, -VOFFSET },
1318 { -VOFFSET, 0.0, VOFFSET },
1319 { 0.0, -VOFFSET, VOFFSET },
1320 { VOFFSET, VOFFSET, VOFFSET },
1321 { -VOFFSET, 0.0, -VOFFSET },
1322 { 0.0, -VOFFSET, -VOFFSET },
1323 { VOFFSET, VOFFSET, -VOFFSET },
1324 { -VOFFSET, -VOFFSET, 0.0 },
1325 { VOFFSET, -VOFFSET, 0.0 },
1326 { -VOFFSET, VOFFSET, 0.0 },
1330 { M_SQRT1_2, M_SQRT1_2, 0.0 },
1332 { 0.0, 0.0, -1.0 }};
1334 float wire_prism_v[][3] = {{ 0.0, 0.0, 1.0 },
1341 float wire_prism_n[][3] = {{ 0.0, 0.0, 1.0},
1343 { M_SQRT1_2, M_SQRT1_2, 0.0},
1347 static struct glsnake_cfg * glc = NULL;
1352 typedef float (*morphFunc)(long);
1355 /* forward definitions for GLUT functions */
1356 void calc_rotation();
1357 inline void ui_mousedrag();
1365 float light_pos[][3] = {{0.0, 0.0, 20.0}, {0.0, 20.0, 0.0}};
1366 float light_dir[][3] = {{0.0, 0.0,-20.0}, {0.0,-20.0, 0.0}};
1368 glClearColor(0.0, 0.0, 0.0, 0.0);
1369 glEnable(GL_DEPTH_TEST);
1370 glShadeModel(GL_SMOOTH);
1371 glCullFace(GL_BACK);
1372 glEnable(GL_CULL_FACE);
1373 glEnable(GL_NORMALIZE);
1376 glColor3f(1.0, 1.0, 1.0);
1377 glLightfv(GL_LIGHT0, GL_POSITION, light_pos[0]);
1378 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_dir[0]);
1379 glLightfv(GL_LIGHT1, GL_POSITION, light_pos[1]);
1380 glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light_dir[1]);
1381 glEnable(GL_LIGHTING);
1382 glEnable(GL_LIGHT0);
1383 glEnable(GL_LIGHT1);
1384 glEnable(GL_COLOR_MATERIAL);
1388 void gettime(snaketime *t)
1390 #ifdef HAVE_GETTIMEOFDAY
1391 #ifdef GETTIMEOFDAY_TWO_ARGS
1392 struct timezone tzp;
1393 gettimeofday(t, &tzp);
1394 #else /* !GETTIMEOFDAY_TWO_ARGS */
1396 #endif /* !GETTIMEOFDAY_TWO_ARGS */
1397 #else /* !HAVE_GETTIMEOFDAY */
1400 #endif /* HAVE_FTIME */
1401 #endif /* !HAVE_GETTIMEOFDAY */
1405 static void load_font(ModeInfo * mi, char * res, XFontStruct ** fontp, GLuint * dlistp) {
1406 const char * font = get_string_resource(res, "Font");
1412 font = "-*-helvetica-medium-r-*-*-*-120-*";
1414 f = XLoadQueryFont(mi->dpy, font);
1416 f = XLoadQueryFont(mi->dpy, "fixed");
1419 first = f->min_char_or_byte2;
1420 last = f->max_char_or_byte2;
1423 *dlistp = glGenLists((GLuint) last + 1);
1424 check_gl_error("glGenLists");
1425 glXUseXFont(id, first, last - first + 1, *dlistp + first);
1426 check_gl_error("glXUseXFont");
1432 void start_morph(int model_index, int immediate);
1434 /* wot initialises it */
1441 struct glsnake_cfg * bp;
1443 /* set up the conf struct and glx contexts */
1445 glc = (struct glsnake_cfg *) calloc(MI_NUM_SCREENS(mi), sizeof(struct glsnake_cfg));
1447 fprintf(stderr, "%s: out of memory\n", progname);
1451 bp = &glc[MI_SCREEN(mi)];
1453 if ((bp->glx_context = init_GL(mi)) != NULL) {
1455 glsnake_reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1461 /* initialise conf struct */
1462 memset(&bp->node, 0, sizeof(float) * NODE_COUNT);
1472 gettime(&bp->last_iteration);
1473 memcpy(&bp->last_morph, &bp->last_iteration, sizeof(bp->last_morph));
1475 bp->prev_colour = bp->next_colour = COLOUR_ACYCLIC;
1476 bp->next_model = RAND(models);
1477 bp->prev_model = START_MODEL;
1478 start_morph(bp->prev_model, 1);
1480 /* set up a font for the labels */
1483 load_font(mi, "labelfont", &bp->font, &bp->font_list);
1486 /* build a solid display list */
1487 glc->node_solid = glGenLists(1);
1488 glNewList(glc->node_solid, GL_COMPILE);
1490 glBegin(GL_TRIANGLES);
1491 glNormal3fv(solid_prism_n[0]);
1492 glVertex3fv(solid_prism_v[0]);
1493 glVertex3fv(solid_prism_v[2]);
1494 glVertex3fv(solid_prism_v[1]);
1496 glNormal3fv(solid_prism_n[1]);
1497 glVertex3fv(solid_prism_v[6]);
1498 glVertex3fv(solid_prism_v[7]);
1499 glVertex3fv(solid_prism_v[8]);
1501 glNormal3fv(solid_prism_n[2]);
1502 glVertex3fv(solid_prism_v[12]);
1503 glVertex3fv(solid_prism_v[13]);
1504 glVertex3fv(solid_prism_v[14]);
1506 glNormal3fv(solid_prism_n[3]);
1507 glVertex3fv(solid_prism_v[3]);
1508 glVertex3fv(solid_prism_v[4]);
1509 glVertex3fv(solid_prism_v[5]);
1511 glNormal3fv(solid_prism_n[4]);
1512 glVertex3fv(solid_prism_v[9]);
1513 glVertex3fv(solid_prism_v[11]);
1514 glVertex3fv(solid_prism_v[10]);
1516 glNormal3fv(solid_prism_n[5]);
1517 glVertex3fv(solid_prism_v[16]);
1518 glVertex3fv(solid_prism_v[15]);
1519 glVertex3fv(solid_prism_v[17]);
1523 glNormal3fv(solid_prism_n[6]);
1524 glVertex3fv(solid_prism_v[0]);
1525 glVertex3fv(solid_prism_v[12]);
1526 glVertex3fv(solid_prism_v[14]);
1527 glVertex3fv(solid_prism_v[2]);
1529 glNormal3fv(solid_prism_n[7]);
1530 glVertex3fv(solid_prism_v[0]);
1531 glVertex3fv(solid_prism_v[1]);
1532 glVertex3fv(solid_prism_v[7]);
1533 glVertex3fv(solid_prism_v[6]);
1535 glNormal3fv(solid_prism_n[8]);
1536 glVertex3fv(solid_prism_v[6]);
1537 glVertex3fv(solid_prism_v[8]);
1538 glVertex3fv(solid_prism_v[13]);
1539 glVertex3fv(solid_prism_v[12]);
1541 glNormal3fv(solid_prism_n[9]);
1542 glVertex3fv(solid_prism_v[3]);
1543 glVertex3fv(solid_prism_v[5]);
1544 glVertex3fv(solid_prism_v[17]);
1545 glVertex3fv(solid_prism_v[15]);
1547 glNormal3fv(solid_prism_n[10]);
1548 glVertex3fv(solid_prism_v[3]);
1549 glVertex3fv(solid_prism_v[9]);
1550 glVertex3fv(solid_prism_v[10]);
1551 glVertex3fv(solid_prism_v[4]);
1553 glNormal3fv(solid_prism_n[11]);
1554 glVertex3fv(solid_prism_v[15]);
1555 glVertex3fv(solid_prism_v[16]);
1556 glVertex3fv(solid_prism_v[11]);
1557 glVertex3fv(solid_prism_v[9]);
1559 glNormal3fv(solid_prism_n[12]);
1560 glVertex3fv(solid_prism_v[1]);
1561 glVertex3fv(solid_prism_v[2]);
1562 glVertex3fv(solid_prism_v[5]);
1563 glVertex3fv(solid_prism_v[4]);
1565 glNormal3fv(solid_prism_n[13]);
1566 glVertex3fv(solid_prism_v[8]);
1567 glVertex3fv(solid_prism_v[7]);
1568 glVertex3fv(solid_prism_v[10]);
1569 glVertex3fv(solid_prism_v[11]);
1571 glNormal3fv(solid_prism_n[14]);
1572 glVertex3fv(solid_prism_v[13]);
1573 glVertex3fv(solid_prism_v[16]);
1574 glVertex3fv(solid_prism_v[17]);
1575 glVertex3fv(solid_prism_v[14]);
1579 glBegin(GL_TRIANGLES);
1580 glNormal3fv(solid_prism_n[15]);
1581 glVertex3fv(solid_prism_v[0]);
1582 glVertex3fv(solid_prism_v[6]);
1583 glVertex3fv(solid_prism_v[12]);
1585 glNormal3fv(solid_prism_n[19]);
1586 glVertex3fv(solid_prism_v[3]);
1587 glVertex3fv(solid_prism_v[15]);
1588 glVertex3fv(solid_prism_v[9]);
1592 glNormal3fv(solid_prism_n[16]);
1593 glVertex3fv(solid_prism_v[1]);
1594 glVertex3fv(solid_prism_v[4]);
1595 glVertex3fv(solid_prism_v[10]);
1596 glVertex3fv(solid_prism_v[7]);
1598 glNormal3fv(solid_prism_n[17]);
1599 glVertex3fv(solid_prism_v[8]);
1600 glVertex3fv(solid_prism_v[11]);
1601 glVertex3fv(solid_prism_v[16]);
1602 glVertex3fv(solid_prism_v[13]);
1604 glNormal3fv(solid_prism_n[18]);
1605 glVertex3fv(solid_prism_v[2]);
1606 glVertex3fv(solid_prism_v[14]);
1607 glVertex3fv(solid_prism_v[17]);
1608 glVertex3fv(solid_prism_v[5]);
1612 /* build wire display list */
1613 glc->node_wire = glGenLists(1);
1614 glNewList(glc->node_wire, GL_COMPILE);
1615 glBegin(GL_LINE_STRIP);
1616 glVertex3fv(wire_prism_v[0]);
1617 glVertex3fv(wire_prism_v[1]);
1618 glVertex3fv(wire_prism_v[2]);
1619 glVertex3fv(wire_prism_v[0]);
1620 glVertex3fv(wire_prism_v[3]);
1621 glVertex3fv(wire_prism_v[4]);
1622 glVertex3fv(wire_prism_v[5]);
1623 glVertex3fv(wire_prism_v[3]);
1626 glVertex3fv(wire_prism_v[1]);
1627 glVertex3fv(wire_prism_v[4]);
1628 glVertex3fv(wire_prism_v[2]);
1629 glVertex3fv(wire_prism_v[5]);
1634 /* initialise the rotation */
1645 struct glsnake_cfg * bp = &glc[MI_SCREEN(mi)];
1648 /* draw some text */
1649 glPushAttrib(GL_TRANSFORM_BIT | GL_ENABLE_BIT);
1650 glDisable(GL_LIGHTING);
1651 glDisable(GL_DEPTH_TEST);
1652 glMatrixMode(GL_PROJECTION);
1655 glMatrixMode(GL_MODELVIEW);
1659 gluOrtho2D(0, glc->width, 0, glc->height);
1661 gluOrtho2D(0, mi->xgwa.width, 0, mi->xgwa.height);
1663 glColor3f(1.0, 1.0, 1.0);
1665 char interactstr[] = "interactive";
1675 s = model[glc->next_model].name;
1677 w = glutBitmapLength(GLUT_BITMAP_HELVETICA_12, (unsigned char *) s);
1678 glRasterPos2f(glc->width - w - 3, 4);
1679 while (s[i] != '\0')
1680 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, s[i++]);
1682 glRasterPos2f(10, mi->xgwa.height - 10 - (bp->font->ascent + bp->font->descent));
1683 while (s[i] != '\0')
1684 glCallList(bp->font_list + (int)s[i++]);
1688 glMatrixMode(GL_PROJECTION);
1693 /* apply the matrix to the origin and stick it in vec */
1694 void matmult_origin(float rotmat[16], float vec[4]) {
1696 vec[0] = 0.5 * rotmat[0] + 0.5 * rotmat[4] + 0.5 * rotmat [8] + 1 * rotmat[12];
1697 vec[1] = 0.5 * rotmat[1] + 0.5 * rotmat[5] + 0.5 * rotmat [9] + 1 * rotmat[13];
1698 vec[2] = 0.5 * rotmat[2] + 0.5 * rotmat[6] + 0.5 * rotmat[10] + 1 * rotmat[14];
1699 vec[3] = 0.5 * rotmat[3] + 0.5 * rotmat[7] + 0.5 * rotmat[11] + 1 * rotmat[15];
1701 vec[0] = 0 * rotmat [0] + 0 * rotmat [1] + 0 * rotmat [2] + 1 * rotmat [3];
1702 vec[1] = 0 * rotmat [4] + 0 * rotmat [5] + 0 * rotmat [6] + 1 * rotmat [7];
1703 vec[2] = 0 * rotmat [8] + 0 * rotmat [9] + 0 * rotmat[10] + 1 * rotmat[11];
1704 vec[3] = 0 * rotmat[12] + 0 * rotmat[13] + 0 * rotmat[14] + 1 * rotmat[15];
1712 /* wot gets called when the winder is resized */
1713 void glsnake_reshape(
1718 glViewport(0, 0, (GLint) w, (GLint) h);
1719 glMatrixMode(GL_PROJECTION);
1721 gluPerspective(zoom, w/(GLfloat)h, 0.05, 100.0);
1722 gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
1723 glMatrixMode(GL_MODELVIEW);
1724 /*gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);*/
1732 /* Returns the new dst_dir for the given src_dir and dst_dir */
1733 int cross_product(int src_dir, int dst_dir) {
1734 return X_MASK*(GETSCALAR(src_dir,Y_MASK) * GETSCALAR(dst_dir,Z_MASK) -
1735 GETSCALAR(src_dir,Z_MASK) * GETSCALAR(dst_dir,Y_MASK))+
1736 Y_MASK*(GETSCALAR(src_dir,Z_MASK) * GETSCALAR(dst_dir,X_MASK) -
1737 GETSCALAR(src_dir,X_MASK) * GETSCALAR(dst_dir,Z_MASK))+
1738 Z_MASK*(GETSCALAR(src_dir,X_MASK) * GETSCALAR(dst_dir,Y_MASK) -
1739 GETSCALAR(src_dir,Y_MASK) * GETSCALAR(dst_dir,X_MASK));
1742 /* calculate orthogonal snake metrics
1743 * is_legal = true if model does not pass through itself
1744 * is_cyclic = true if last node connects back to first node
1745 * last_turn = for cyclic snakes, specifes what the 24th turn would be
1747 void calc_snake_metrics(void) {
1750 int prevSrcDir = -Y_MASK;
1751 int prevDstDir = Z_MASK;
1752 int grid[25][25][25];
1755 memset(&grid, 0, sizeof(int) * 25*25*25);
1760 /* trace path of snake - and keep record for is_legal */
1761 for (i = 0; i < NODE_COUNT - 1; i++) {
1762 /*int ang_card;*/ /* cardinal direction of node angle */
1763 /* establish new state vars */
1764 srcDir = -prevDstDir;
1765 x += GETSCALAR(prevDstDir, X_MASK);
1766 y += GETSCALAR(prevDstDir, Y_MASK);
1767 z += GETSCALAR(prevDstDir, Z_MASK);
1769 switch ((int) model[glc->next_model].node[i]) {
1771 dstDir = -prevSrcDir;
1774 dstDir = prevSrcDir;
1778 dstDir = cross_product(prevSrcDir, prevDstDir);
1779 if (model[glc->next_model].node[i] == (int) (RIGHT))
1783 /* Prevent spurious "might be used
1784 * uninitialised" warnings when compiling
1790 if (grid[x][y][z] == 0)
1791 grid[x][y][z] = srcDir + dstDir;
1792 else if (grid[x][y][z] + srcDir + dstDir == 0)
1797 prevSrcDir = srcDir;
1798 prevDstDir = dstDir;
1801 /* determine if the snake is cyclic */
1802 glc->is_cyclic = (dstDir == Y_MASK && x == 12 && y == 11 && z == 12);
1804 /* determine last_turn */
1805 glc->last_turn = -1;
1808 case -Z_MASK: glc->last_turn = ZERO; break;
1809 case Z_MASK: glc->last_turn = PIN; break;
1810 case X_MASK: glc->last_turn = LEFT; break;
1811 case -X_MASK: glc->last_turn = RIGHT; break;
1815 /* work out how far through the current morph we are */
1816 float morph_percent(void) {
1820 /* extend this function later with a case statement for each of the
1823 /* when morphing all nodes at once, the longest morph will be the node
1824 * that needs to rotate 180 degrees. For each node, work out how far it
1825 * has to go, and store the maximum rotation and current largest angular
1826 * difference, returning the angular difference over the maximum. */
1828 float rot_max = 0.0, ang_diff_max = 0.0;
1830 for (i = 0; i < NODE_COUNT - 1; i++) {
1831 float rot, ang_diff;
1833 /* work out the maximum rotation this node has to go through
1834 * from the previous to the next model, taking into account that
1835 * the snake always morphs through the smaller angle */
1836 rot = fabs(model[glc->prev_model].node[i] -
1837 model[glc->next_model].node[i]);
1838 if (rot > 180.0) rot = 180.0 - rot;
1839 /* work out the difference between the current position and the
1841 ang_diff = fabs(glc->node[i] -
1842 model[glc->next_model].node[i]);
1843 if (ang_diff > 180.0) ang_diff = 180 - ang_diff;
1844 /* if it's the biggest so far, record it */
1845 if (rot > rot_max) rot_max = rot;
1846 if (ang_diff > ang_diff_max) ang_diff_max = ang_diff;
1849 /* ang_diff / rot approaches 0, we want the complement */
1850 retval = 1.0 - (ang_diff_max / rot_max);
1851 /* protect against naan */
1852 if (isnan(retval) || isinf(retval)) retval = 1.0;
1854 /*printf("morph_pct = %f\n", retval);*/
1858 void morph_colour(void) {
1859 float percent, compct; /* complement of percentage */
1861 percent = morph_percent();
1862 compct = 1.0 - percent;
1864 glc->colour[0][0] = colour[glc->prev_colour][0][0] * compct + colour[glc->next_colour][0][0] * percent;
1865 glc->colour[0][1] = colour[glc->prev_colour][0][1] * compct + colour[glc->next_colour][0][1] * percent;
1866 glc->colour[0][2] = colour[glc->prev_colour][0][2] * compct + colour[glc->next_colour][0][2] * percent;
1868 glc->colour[1][0] = colour[glc->prev_colour][1][0] * compct + colour[glc->next_colour][1][0] * percent;
1869 glc->colour[1][1] = colour[glc->prev_colour][1][1] * compct + colour[glc->next_colour][1][1] * percent;
1870 glc->colour[1][2] = colour[glc->prev_colour][1][2] * compct + colour[glc->next_colour][1][2] * percent;
1873 /* Start morph process to this model */
1874 void start_morph(int model_index, int immediate) {
1875 /* if immediate, don't bother morphing, go straight to the next model */
1879 for (i = 0; i < NODE_COUNT; i++)
1880 glc->node[i] = model[model_index].node[i];
1883 glc->prev_model = glc->next_model;
1884 glc->next_model = model_index;
1885 glc->prev_colour = glc->next_colour;
1887 calc_snake_metrics();
1889 glc->next_colour = COLOUR_INVALID;
1891 glc->next_colour = COLOUR_AUTHENTIC;
1892 else if (glc->is_cyclic)
1893 glc->next_colour = COLOUR_CYCLIC;
1895 glc->next_colour = COLOUR_ACYCLIC;
1898 glc->colour[0][0] = colour[glc->next_colour][0][0];
1899 glc->colour[0][1] = colour[glc->next_colour][0][1];
1900 glc->colour[0][2] = colour[glc->next_colour][0][2];
1901 glc->colour[1][0] = colour[glc->next_colour][1][0];
1902 glc->colour[1][1] = colour[glc->next_colour][1][1];
1903 glc->colour[1][2] = colour[glc->next_colour][1][2];
1910 /* Returns morph progress */
1911 float morph(long iter_msec) {
1912 /* work out the maximum angle for this iteration */
1914 float iter_angle_max, largest_diff, largest_progress;
1920 iter_angle_max = 90.0 * (angvel/1000.0) * iter_msec;
1923 largest_diff = largest_progress = 0.0;
1924 for (i = 0; i < NODE_COUNT; i++) {
1925 float curAngle = glc->node[i];
1926 float destAngle = model[glc->next_model].node[i];
1927 if (curAngle != destAngle) {
1929 if (fabs(curAngle-destAngle) <= iter_angle_max)
1930 glc->node[i] = destAngle;
1931 else if (fmod(curAngle-destAngle+360,360) > 180)
1932 glc->node[i] = fmod(curAngle + iter_angle_max, 360);
1934 glc->node[i] = fmod(curAngle+360 - iter_angle_max, 360);
1935 largest_diff = MAX(largest_diff, fabs(destAngle-glc->node[i]));
1936 largest_progress = MAX(largest_diff, fabs(glc->node[i] - model[glc->prev_model].node[i]));
1940 return MIN(largest_diff / largest_progress, 1.0);
1944 void glsnake_idle();
1946 void restore_idle(int value)
1948 glutIdleFunc(glsnake_idle);
1952 void quick_sleep(void)
1955 /* By using glutTimerFunc we can keep responding to
1956 * mouse and keyboard events, unlike using something like
1959 glutTimerFunc(1, restore_idle, 0);
1967 struct glsnake_cfg * bp
1970 /* time since last iteration */
1972 /* time since the beginning of last morph */
1974 float iter_angle_max;
1975 snaketime current_time;
1976 /* morphFunc transition; */
1980 /* Do nothing to the model if we are paused */
1982 /* Avoid busy waiting when nothing is changing */
1986 glutPostRedisplay();
1991 /* <spiv> Well, ftime gives time with millisecond resolution.
1992 * <spiv> (or worse, perhaps... who knows what the OS will do)
1993 * <spiv> So if no discernable amount of time has passed:
1994 * <spiv> a) There's no point updating the screen, because
1995 * it would be the same
1996 * <spiv> b) The code will divide by zero
1998 gettime(¤t_time);
2000 iter_msec = (long) GETMSECS(current_time) - GETMSECS(glc->last_iteration) +
2001 ((long) GETSECS(current_time) - GETSECS(glc->last_iteration)) * 1000L;
2004 /* save the current time */
2005 memcpy(&glc->last_iteration, ¤t_time, sizeof(snaketime));
2007 /* work out if we have to switch models */
2008 morf_msec = GETMSECS(glc->last_iteration) - GETMSECS(glc->last_morph) +
2009 ((long) (GETSECS(glc->last_iteration)-GETSECS(glc->last_morph)) * 1000L);
2011 if ((morf_msec > statictime) && !interactive && !glc->morphing) {
2012 /*printf("starting morph\n");*/
2013 memcpy(&glc->last_morph, &(glc->last_iteration), sizeof(glc->last_morph));
2014 start_morph(RAND(models), 0);
2017 if (interactive && !glc->morphing) {
2022 /* if (!glc->dragging && !glc->interactive) { */
2025 yspin += 360/((1000/yangvel)/iter_msec);
2026 zspin += 360/((1000/zangvel)/iter_msec);
2028 yspin += 360 * (yangvel/1000.0) * iter_msec;
2029 zspin += 360 * (zangvel/1000.0) * iter_msec;
2032 /*printf("yspin: %f, zspin: %f\n", yspin, zspin);*/
2036 /* work out the maximum angle we could turn this node in this
2037 * timeslice, iter_msec milliseconds long */
2038 iter_angle_max = 90.0 * (angvel/1000.0) * iter_msec;
2041 for (i = 0; i < NODE_COUNT; i++) {
2042 float cur_angle = glc->node[i];
2043 float dest_angle = model[glc->next_model].node[i];
2044 if (cur_angle != dest_angle) {
2046 if (fabs(cur_angle - dest_angle) <= iter_angle_max)
2047 glc->node[i] = dest_angle;
2048 else if (fmod(cur_angle - dest_angle + 360, 360) > 180)
2049 glc->node[i] = fmod(cur_angle + iter_angle_max, 360);
2051 glc->node[i] = fmod(cur_angle + 360 - iter_angle_max, 360);
2055 if (!still_morphing)
2058 /* colour cycling */
2063 glutPostRedisplay();
2066 /* We are going too fast, so we may as well let the
2067 * cpu relax a little by sleeping for a millisecond. */
2073 void glsnake_display(
2079 struct glsnake_cfg * bp = &glc[MI_SCREEN(mi)];
2080 Display * dpy = MI_DISPLAY(mi);
2081 Window window = MI_WINDOW(mi);
2086 float positions[NODE_COUNT][4]; /* origin points for each node */
2087 float com[4]; /* it's the CENTRE of MASS */
2090 if (!bp->glx_context)
2094 /* clear the buffer */
2095 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2097 /* go into the modelview stack */
2098 glMatrixMode(GL_MODELVIEW);
2101 /* get the centre of each node, by moving through the snake and
2102 * performing the rotations, then grabbing the matrix at each point
2103 * and applying it to the origin */
2107 /* apply the mouse drag rotation */
2111 /* apply the continuous rotation */
2112 glRotatef(yspin, 0.0, 1.0, 0.0);
2113 glRotatef(zspin, 0.0, 0.0, 1.0);
2119 for (i = 0; i < NODE_COUNT; i++) {
2124 /*printf("ang = %f\n", ang);*/
2126 glTranslatef(0.5, 0.5, 0.5); /* move to center */
2127 glRotatef(90, 0.0, 0.0, -1.0); /* reorient */
2128 glTranslatef(1.0 + explode, 0.0, 0.0); /* move to new pos. */
2129 glRotatef(180 + ang, 1.0, 0.0, 0.0); /* pivot to new angle */
2130 glTranslatef(-0.5, -0.5, -0.5); /* return from center */
2132 glGetFloatv(GL_MODELVIEW_MATRIX, rotmat);
2134 matmult_origin(rotmat, positions[i]);
2136 /*printf("positions %f %f %f %f\n", positions[i][0], positions[i][1], positions[i][2], positions[i][3]);*/
2138 com[0] += positions[i][0];
2139 com[1] += positions[i][1];
2140 com[2] += positions[i][2];
2141 com[3] += positions[i][3];
2144 com[0] /= NODE_COUNT;
2145 com[1] /= NODE_COUNT;
2146 com[2] /= NODE_COUNT;
2147 com[3] /= NODE_COUNT;
2153 /*printf("com: %f, %f, %f, %f\n", com[0], com[1], com[2], com[3]);*/
2155 #if MAGICAL_RED_STRING
2157 glTranslatef(-com[0], -com[1], -com[2]);
2159 glDisable(GL_LIGHTING);
2160 glColor3f(1.0, 0.0, 0.0);
2161 glBegin(GL_LINE_STRIP);
2162 for (i = 0; i < NODE_COUNT - 1; i++) {
2163 glVertex3fv(positions[i]);
2166 glEnable(GL_LIGHTING);
2167 /*glTranslatef(com[0], com[1], com[2]);*/
2172 glTranslatef(-com[0], -com[1], -com[2]);
2175 /* apply the mouse drag rotation */
2179 /* apply the continuous rotation */
2180 glRotatef(yspin, 0.0, 1.0, 0.0);
2181 glRotatef(zspin, 0.0, 0.0, 1.0);
2183 /* now draw each node along the snake -- this is quite ugly :p */
2184 for (i = 0; i < NODE_COUNT; i++) {
2185 /* choose a colour for this node */
2186 if ((i == glc->selected || i == glc->selected+1) && interactive)
2188 glColor3f(1.0, 1.0, 0.0);
2190 glColor3fv(glc->colour[(i+1)%2]);
2194 glCallList(glc->node_wire);
2196 glCallList(glc->node_solid);
2198 /* now work out where to draw the next one */
2200 /* Interpolate between models */
2203 glTranslatef(0.5, 0.5, 0.5); /* move to center */
2204 glRotatef(90, 0.0, 0.0, -1.0); /* reorient */
2205 glTranslatef(1.0 + explode, 0.0, 0.0); /* move to new pos. */
2206 glRotatef(180 + ang, 1.0, 0.0, 0.0); /* pivot to new angle */
2207 glTranslatef(-0.5, -0.5, -0.5); /* return from center */
2227 glXSwapBuffers(dpy, window);
2232 /* anything that needs to be cleaned up goes here */
2234 glutDestroyWindow(glc->window);
2238 void ui_init(int *, char **);
2240 int main(int argc, char ** argv) {
2241 glc = malloc(sizeof(struct glsnake_cfg));
2242 memset(glc, 0, sizeof(struct glsnake_cfg));
2247 ui_init(&argc, argv);
2249 gettime(&glc->last_iteration);
2250 memcpy(&glc->last_morph, &glc->last_iteration, sizeof(snaketime));
2251 srand((unsigned int)GETSECS(glc->last_iteration));
2253 glc->prev_colour = glc->next_colour = COLOUR_ACYCLIC;
2254 glc->next_model = RAND(models);
2255 glc->prev_model = 0;
2256 start_morph(glc->prev_model, 1);
2274 /* trackball quaternions */
2275 float cumquat[4] = {0.0,0.0,0.0,0.0}, oldquat[4] = {0.0,0.0,0.0,0.1};
2277 /* rotation matrix */
2280 /* mouse drag vectors: start and end */
2281 float m_s[3], m_e[3];
2283 /* dragging boolean */
2286 /* this function calculates the rotation matrix based on the quaternions
2287 * generated from the mouse drag vectors */
2288 void calc_rotation() {
2290 double xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
2292 /* this bit ripped from Shoemake's quaternion notes from SIGGRAPH */
2293 Nq = cumquat[0] * cumquat[0] + cumquat[1] * cumquat[1] +
2294 cumquat[2] * cumquat[2] + cumquat[3] * cumquat[3];
2295 s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
2296 xs = cumquat[0] * s; ys = cumquat[1] * s; zs = cumquat[2] * s;
2297 wx = cumquat[3] * xs; wy = cumquat[3] * ys; wz = cumquat[3] * zs;
2298 xx = cumquat[0] * xs; xy = cumquat[0] * ys; xz = cumquat[0] * zs;
2299 yy = cumquat[1] * ys; yz = cumquat[1] * zs; zz = cumquat[2] * zs;
2301 rotation[0] = 1.0 - (yy + zz);
2302 rotation[1] = xy + wz;
2303 rotation[2] = xz - wy;
2304 rotation[4] = xy - wz;
2305 rotation[5] = 1.0 - (xx + zz);
2306 rotation[6] = yz + wx;
2307 rotation[8] = xz + wy;
2308 rotation[9] = yz - wx;
2309 rotation[10] = 1.0 - (xx + yy);
2310 rotation[3] = rotation[7] = rotation[11] = 0.0;
2311 rotation[12] = rotation[13] = rotation[14] = 0.0;
2315 inline void ui_mousedrag() {
2316 glMultMatrixf(rotation);
2319 void ui_keyboard(unsigned char c, int x, int y) {
2328 explode += DEF_EXPLODE;
2329 glutPostRedisplay();
2332 explode -= DEF_EXPLODE;
2333 if (explode < 0.0) explode = 0.0;
2334 glutPostRedisplay();
2339 glc->next_model %= models;
2340 start_morph(glc->next_model, 0);
2342 /* Reset last_morph time */
2343 gettime(&glc->last_morph);
2346 /* previous model */
2347 glc->next_model = (glc->next_model + models - 1) % models;
2348 start_morph(glc->next_model, 0);
2350 /* Reset glc->last_morph time */
2351 gettime(&glc->last_morph);
2354 angvel += DEF_ACCEL;
2357 if (angvel > DEF_ACCEL)
2358 angvel -= DEF_ACCEL;
2362 /* Reset last_iteration and last_morph time */
2363 gettime(&glc->last_iteration);
2364 gettime(&glc->last_morph);
2366 interactive = 1 - interactive;
2367 glutPostRedisplay();
2370 wireframe = 1 - wireframe;
2372 glDisable(GL_LIGHTING);
2374 glEnable(GL_LIGHTING);
2375 glutPostRedisplay();
2379 /* unpausing, reset last_iteration and last_morph time */
2380 gettime(&glc->last_iteration);
2381 gettime(&glc->last_morph);
2383 glc->paused = 1 - glc->paused;
2386 /* dump the current model so we can add it! */
2387 printf("# %s\nnoname:\t", model[glc->next_model].name);
2388 for (i = 0; i < NODE_COUNT; i++) {
2389 if (glc->node[i] == ZERO)
2391 else if (glc->node[i] == LEFT)
2393 else if (glc->node[i] == PIN)
2395 else if (glc->node[i] == RIGHT)
2399 printf("%f", node[i].curAngle);
2401 if (i < NODE_COUNT - 1)
2407 glc->fullscreen = 1 - glc->fullscreen;
2408 if (glc->fullscreen) {
2409 glc->old_width = glc->width;
2410 glc->old_height = glc->height;
2413 glutReshapeWindow(glc->old_width, glc->old_height);
2414 glutPositionWindow(50,50);
2418 titles = 1 - titles;
2419 if (interactive || glc->paused)
2420 glutPostRedisplay();
2423 altcolour = 1 - altcolour;
2427 glsnake_reshape(glc->width, glc->height);
2431 glsnake_reshape(glc->width, glc->height);
2438 void ui_special(int key, int x, int y) {
2440 float *destAngle = &(model[glc->next_model].node[glc->selected]);
2441 int unknown_key = 0;
2446 glc->selected = (glc->selected + (NODE_COUNT - 2)) % (NODE_COUNT - 1);
2449 glc->selected = (glc->selected + 1) % (NODE_COUNT - 1);
2452 *destAngle = fmod(*destAngle+(LEFT), 360);
2453 glc->morphing = glc->new_morph = 1;
2455 case GLUT_KEY_RIGHT:
2456 *destAngle = fmod(*destAngle+(RIGHT), 360);
2457 glc->morphing = glc->new_morph = 1;
2460 start_morph(STRAIGHT_MODEL, 0);
2467 calc_snake_metrics();
2470 glutPostRedisplay();
2473 void ui_mouse(int button, int state, int x, int y) {
2478 m_s[0] = M_SQRT1_2 *
2479 (x - (glc->width / 2.0)) / (glc->width / 2.0);
2480 m_s[1] = M_SQRT1_2 *
2481 ((glc->height / 2.0) - y) / (glc->height / 2.0);
2482 m_s[2] = sqrt(1-(m_s[0]*m_s[0]+m_s[1]*m_s[1]));
2486 oldquat[0] = cumquat[0];
2487 oldquat[1] = cumquat[1];
2488 oldquat[2] = cumquat[2];
2489 oldquat[3] = cumquat[3];
2495 glutPostRedisplay();
2498 void ui_motion(int x, int y) {
2503 /* construct the motion end vector from the x,y position on the
2505 m_e[0] = (x - (glc->width/ 2.0)) / (glc->width / 2.0);
2506 m_e[1] = ((glc->height / 2.0) - y) / (glc->height / 2.0);
2507 /* calculate the normal of the vector... */
2508 norm = m_e[0] * m_e[0] + m_e[1] * m_e[1];
2509 /* check if norm is outside the sphere and wraparound if necessary */
2513 m_e[2] = sqrt(norm - 1);
2515 /* the z value comes from projecting onto an elliptical spheroid */
2516 m_e[2] = sqrt(1 - norm);
2519 /* now here, build a quaternion from m_s and m_e */
2520 q[0] = m_s[1] * m_e[2] - m_s[2] * m_e[1];
2521 q[1] = m_s[2] * m_e[0] - m_s[0] * m_e[2];
2522 q[2] = m_s[0] * m_e[1] - m_s[1] * m_e[0];
2523 q[3] = m_s[0] * m_e[0] + m_s[1] * m_e[1] + m_s[2] * m_e[2];
2525 /* new rotation is the product of the new one and the old one */
2526 cumquat[0] = q[3] * oldquat[0] + q[0] * oldquat[3] +
2527 q[1] * oldquat[2] - q[2] * oldquat[1];
2528 cumquat[1] = q[3] * oldquat[1] + q[1] * oldquat[3] +
2529 q[2] * oldquat[0] - q[0] * oldquat[2];
2530 cumquat[2] = q[3] * oldquat[2] + q[2] * oldquat[3] +
2531 q[0] * oldquat[1] - q[1] * oldquat[0];
2532 cumquat[3] = q[3] * oldquat[3] - q[0] * oldquat[0] -
2533 q[1] * oldquat[1] - q[2] * oldquat[2];
2537 glutPostRedisplay();
2540 void ui_init(int * argc, char ** argv) {
2541 glutInit(argc, argv);
2542 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
2543 glutInitWindowSize(glc->width, glc->height);
2544 glc->window = glutCreateWindow("glsnake");
2546 glutDisplayFunc(glsnake_display);
2547 glutReshapeFunc(glsnake_reshape);
2548 glutIdleFunc(glsnake_idle);
2549 glutKeyboardFunc(ui_keyboard);
2550 glutSpecialFunc(ui_special);
2551 glutMouseFunc(ui_mouse);
2552 glutMotionFunc(ui_motion);
2554 yangvel = DEF_YANGVEL;
2555 zangvel = DEF_ZANGVEL;
2556 explode = DEF_EXPLODE;
2557 angvel = DEF_ANGVEL;
2558 statictime = DEF_STATICTIME;
2559 altcolour = DEF_ALTCOLOUR;
2560 titles = DEF_TITLES;
2561 interactive = DEF_INTERACTIVE;
2563 wireframe = DEF_WIREFRAME;
2565 #endif /* HAVE_GLUT */