1 /* glsnake.c - OpenGL imitation of Rubik's Snake
3 * (c) 2001-2005 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 */
46 #ifdef HAVE_GETTIMEOFDAY
47 # 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)
55 # else /* !GETTIMEOFDAY_TWO_ARGS */
57 # include <sys/time.h>
59 typedef struct timeval snaketime;
60 # define GETSECS(t) ((t).tv_sec)
61 # define GETMSECS(t) ((t).tv_usec/1000)
63 # endif /* GETTIMEOFDAY_TWO_ARGS */
65 #else /* !HAVE_GETTIMEOFDAY */
68 # include <sys/timeb.h>
69 typedef struct timeb snaketime;
70 # define GETSECS(t) ((long)(t).time)
71 # define GETMSECS(t) ((t).millitm/1000)
73 # endif /* HAVE_FTIME */
74 #endif /* HAVE_GETTIMEOFDAY */
78 #ifndef M_SQRT1_2 /* Win32 doesn't have this constant */
79 #define M_SQRT1_2 0.70710678118654752440084436210485
85 #define DEF_YANGVEL 0.10
86 #define DEF_ZANGVEL 0.14
87 #define DEF_EXPLODE 0.03
88 #define DEF_ANGVEL 1.0
89 #define DEF_STATICTIME 5000
90 #define DEF_ALTCOLOUR 0
92 #define DEF_INTERACTIVE 0
94 #define DEF_WIREFRAME 0
95 #define DEF_TRANSPARENT 1
97 /* xscreensaver options doobies prefer strings */
98 #define DEF_YANGVEL "0.10"
99 #define DEF_ZANGVEL "0.14"
100 #define DEF_EXPLODE "0.03"
101 #define DEF_ANGVEL "1.0"
102 #define DEF_STATICTIME "5000"
103 #define DEF_ALTCOLOUR "False"
104 #define DEF_TITLES "True"
105 #define DEF_INTERACTIVE "False"
106 #define DEF_ZOOM "25.0"
107 #define DEF_WIREFRAME "False"
108 #define DEF_TRANSPARENT "True"
111 /* static variables */
113 # include <X11/Intrinsic.h>
115 /* xscreensaver boolean type */
119 static GLfloat explode;
120 static long statictime;
121 static GLfloat yspin = 60.0;
122 static GLfloat zspin = -45.0;
123 static GLfloat yangvel;
124 static GLfloat zangvel;
125 static Bool altcolour;
127 static Bool interactive;
128 static Bool wireframe;
129 static Bool transparent;
131 static GLfloat angvel;
134 /* xscreensaver setup */
135 extern XtAppContext app;
137 #define PROGCLASS "glsnake"
138 #define HACK_INIT glsnake_init
139 #define HACK_DRAW glsnake_display
140 #define HACK_RESHAPE glsnake_reshape
141 #define sws_opts xlockmore_opts
144 /* xscreensaver defaults */
145 #define DEFAULTS "*delay: 30000 \n" \
147 "*showFPS: False \n" \
148 "*labelfont: -*-times-bold-r-normal-*-180-*\n" \
153 #define countof(x) (sizeof((x))/sizeof((*x)))
155 #include "xlockmore.h"
156 #include "glxfonts.h"
158 static XrmOptionDescRec opts[] = {
159 { "-explode", ".explode", XrmoptionSepArg, DEF_EXPLODE },
160 { "-angvel", ".angvel", XrmoptionSepArg, DEF_ANGVEL },
161 { "-statictime", ".statictime", XrmoptionSepArg, DEF_STATICTIME },
162 { "-yangvel", ".yangvel", XrmoptionSepArg, DEF_YANGVEL },
163 { "-zangvel", ".zangvel", XrmoptionSepArg, DEF_ZANGVEL },
164 { "-altcolour", ".altcolour", XrmoptionNoArg, (caddr_t) "True" },
165 { "-no-altcolour", ".altcolour", XrmoptionNoArg, (caddr_t) "False" },
166 { "-titles", ".titles", XrmoptionNoArg, (caddr_t) "True" },
167 { "-no-titles", ".titles", XrmoptionNoArg, (caddr_t) "False" },
168 { "-zoom", ".zoom", XrmoptionSepArg, DEF_ZOOM },
169 { "-wireframe", ".wireframe", XrmoptionNoArg, (caddr_t) "true" },
170 { "-no-wireframe", ".wireframe", XrmoptionNoArg, (caddr_t) "false" },
171 { "-transparent", ".transparent", XrmoptionNoArg, (caddr_t) "true" },
172 { "-no-transparent", ".transparent", XrmoptionNoArg, (caddr_t) "false" },
175 static argtype vars[] = {
176 {&explode, "explode", "Explode", DEF_EXPLODE, t_Float},
177 {&angvel, "angvel", "Angular Velocity", DEF_ANGVEL, t_Float},
178 {&statictime, "statictime", "Static Time", DEF_STATICTIME, t_Int},
179 {&yangvel, "yangvel", "Angular Velocity about Y axis", DEF_YANGVEL, t_Float},
180 {&zangvel, "zangvel", "Angular Velocity about X axis", DEF_ZANGVEL, t_Float},
181 {&interactive, "interactive", "Interactive", DEF_INTERACTIVE, t_Bool},
182 {&altcolour, "altcolour", "Alternate Colour Scheme", DEF_ALTCOLOUR, t_Bool},
183 {&titles, "titles", "Titles", DEF_TITLES, t_Bool},
184 {&zoom, "zoom", "Zoom", DEF_ZOOM, t_Float},
185 {&wireframe, "wireframe", "Wireframe", DEF_WIREFRAME, t_Bool},
186 {&transparent, "transparent", "Transparent!", DEF_TRANSPARENT, t_Bool},
189 ModeSpecOpt sws_opts = {(int)countof(opts), opts, (int)countof(vars), vars, NULL};
194 float node[NODE_COUNT];
199 GLXContext * glx_context;
203 /* font list number */
210 /* is a morph in progress? */
213 /* has the model been paused? */
222 /* the shape of the model */
223 float node[NODE_COUNT];
225 /* currently selected node for interactive mode */
229 unsigned int prev_model;
230 unsigned int next_model;
240 /* timing variables */
241 snaketime last_iteration;
242 snaketime last_morph;
246 int old_width, old_height;
248 /* the id of the display lists for drawing a node */
249 GLuint node_solid, node_wire;
251 /* is the window fullscreen? */
255 #define COLOUR_CYCLIC 0
256 #define COLOUR_ACYCLIC 1
257 #define COLOUR_INVALID 2
258 #define COLOUR_AUTHENTIC 3
259 #define COLOUR_ORIGLOGO 4
261 float colour[][2][4] = {
263 { { 0.4, 0.8, 0.2, 0.6 },
264 { 1.0, 1.0, 1.0, 0.6 } },
266 { { 0.3, 0.1, 0.9, 0.6 },
267 { 1.0, 1.0, 1.0, 0.6 } },
269 { { 0.3, 0.1, 0.9, 0.6 },
270 { 1.0, 1.0, 1.0, 0.6 } },
271 /* authentic - purple and green */
272 { { 0.38, 0.0, 0.55, 0.7 },
273 { 0.0, 0.5, 0.34, 0.7 } },
274 /* old "authentic" colours from the logo */
275 { { 171/255.0, 0, 1.0, 1.0 },
276 { 46/255.0, 205/255.0, 227/255.0, 1.0 } }
279 struct model_s model[] = {
280 #define STRAIGHT_MODEL 0
282 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
283 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
286 /* the models in the Rubik's snake manual */
288 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT,
289 RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT,
290 RIGHT, LEFT, RIGHT, LEFT, ZERO }
292 #define START_MODEL 2
294 { RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT,
295 RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT,
296 RIGHT, LEFT, LEFT, LEFT, ZERO }
299 { ZERO, ZERO, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO, ZERO,
300 ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO, ZERO, ZERO, RIGHT,
301 LEFT, RIGHT, ZERO, LEFT }
304 { ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, RIGHT, PIN,
305 RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, ZERO, ZERO,
309 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN,
310 ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
314 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, LEFT, RIGHT, PIN, RIGHT,
315 ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, LEFT, ZERO,
318 /* These models were taken from Andrew and Peter's original snake.c
319 * as well as some newer ones made up by Jamie, Andrew and Peter. */
321 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT,
322 LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT,
323 RIGHT, LEFT, LEFT, LEFT, ZERO }
326 { RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT,
327 LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT,
328 RIGHT, RIGHT, LEFT, LEFT, ZERO }
331 { PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN,
332 ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN,
336 { PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN,
337 LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN,
341 { RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT,
342 LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN,
346 { RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT,
347 LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT,
348 RIGHT, RIGHT, LEFT, LEFT, ZERO }
351 { ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT,
352 LEFT, RIGHT, LEFT, LEFT, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT,
353 RIGHT, RIGHT, RIGHT, ZERO }
356 { RIGHT, PIN, ZERO, ZERO, PIN, LEFT, ZERO, LEFT, LEFT, ZERO,
357 LEFT, PIN, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO,
361 { PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT,
362 LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT,
363 RIGHT, LEFT, LEFT, ZERO }
366 { ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO,
367 ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO,
368 LEFT, ZERO, ZERO, RIGHT }
371 { ZERO, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO, RIGHT, ZERO, ZERO,
372 LEFT, RIGHT, ZERO, LEFT, ZERO, RIGHT, ZERO, ZERO, LEFT, RIGHT,
373 ZERO, LEFT, ZERO, RIGHT }
376 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO,
377 ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO,
378 ZERO, ZERO, LEFT, RIGHT }
381 { ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT,
382 RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN,
386 { ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN,
387 PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN }
390 { PIN, RIGHT, LEFT, PIN, LEFT, PIN, ZERO, ZERO, RIGHT, PIN, LEFT,
391 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
395 { ZERO, ZERO, ZERO, ZERO, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT,
396 ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT,
397 LEFT, ZERO, PIN, ZERO }
400 { RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO,
401 LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, PIN, RIGHT,
405 { ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN,
406 ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO }
409 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, LEFT, PIN,
410 RIGHT, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT,
411 RIGHT, LEFT, LEFT, ZERO }
414 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, ZERO, ZERO,
415 RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO, LEFT, LEFT,
416 RIGHT, LEFT, RIGHT, RIGHT, ZERO }
419 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, PIN, ZERO, ZERO,
420 LEFT, PIN, RIGHT, ZERO, ZERO, PIN, ZERO, LEFT, LEFT, RIGHT, LEFT,
424 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO,
425 RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT,
429 { LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT,
430 ZERO, ZERO, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN,
434 { RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN,
435 LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT,
439 { RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN,
440 LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT,
441 LEFT, PIN, LEFT, PIN }
444 { ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN,
445 ZERO, PIN, ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT,
449 { ZERO, PIN, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, PIN,
450 ZERO, PIN, ZERO, PIN, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO,
454 { ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN,
455 ZERO, PIN, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
459 { ZERO, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT,
460 ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
464 { ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO,
465 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
469 { ZERO, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, ZERO,
470 ZERO, PIN, ZERO, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO,
474 { RIGHT, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, ZERO,
475 LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT,
476 ZERO, ZERO, LEFT, PIN }
479 { RIGHT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT,
480 ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT,
481 LEFT, RIGHT, ZERO, LEFT, PIN }
484 { RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO,
485 LEFT, PIN, RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT,
489 { ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, ZERO,
490 ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT,
494 { ZERO, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN,
495 RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT,
499 { LEFT, PIN, LEFT, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, LEFT,
500 PIN, RIGHT, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN,
504 { RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, ZERO,
505 ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, RIGHT, RIGHT, LEFT,
506 RIGHT, LEFT, LEFT, LEFT, PIN }
509 { ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, RIGHT,
510 RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT,
511 PIN, LEFT, LEFT, LEFT }
514 { PIN, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, LEFT,
515 ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, LEFT, ZERO,
516 LEFT, RIGHT, ZERO, ZERO }
519 { PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, RIGHT,
520 RIGHT, PIN, RIGHT, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO,
521 ZERO, PIN, PIN, ZERO }
524 /* the following modesl were created during the slug/compsoc codefest
526 { "cool looking gegl",
527 { PIN, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT,
528 ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, ZERO,
532 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN,
533 PIN, ZERO, RIGHT, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO,
537 { RIGHT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT,
538 RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN,
539 RIGHT, LEFT, RIGHT, PIN, ZERO }
542 { ZERO, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO,
543 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
547 { LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO,
548 RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT,
549 RIGHT, ZERO, LEFT, ZERO }
551 { "not very good (but accurate) gegl",
552 { ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO,
553 PIN, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO, PIN, PIN, ZERO,
557 { ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
558 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO,
562 { PIN, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
563 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO,
566 { "erect penis", /* thanks benno */
567 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, PIN,
568 PIN, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
572 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, PIN,
573 PIN, ZERO, ZERO, ZERO, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
577 { RIGHT, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO,
578 LEFT, ZERO, ZERO, ZERO, LEFT, ZERO, LEFT, PIN, LEFT, PIN, RIGHT,
582 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN,
583 ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO,
586 { "poles or columns or something",
587 { LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
588 ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
592 { ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
593 ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
597 { ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO,
598 LEFT, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
602 { ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO,
603 LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO,
604 LEFT, PIN, ZERO, ZERO }
607 { ZERO, ZERO, PIN, RIGHT, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO,
608 LEFT, PIN, ZERO, ZERO, PIN, ZERO, LEFT, ZERO, RIGHT, LEFT, ZERO,
612 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
613 RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
617 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
618 ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
622 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
623 LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
627 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
628 PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
632 { RIGHT, ZERO, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT,
633 RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT,
634 ZERO, ZERO, RIGHT, ZERO }
637 { RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT,
638 ZERO, RIGHT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, ZERO,
639 RIGHT, ZERO, RIGHT, ZERO, ZERO }
642 /* These models come from the website at
643 * http://www.geocities.com/stigeide/snake */
646 { RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO }
650 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, ZERO }
653 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, ZERO }
656 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, ZERO }
659 { ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, ZERO, ZERO }
662 { RIGHT, LEFT, RIGHT, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO, PIN, PIN, ZERO }
665 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO }
668 { LEFT, PIN, RIGHT, ZERO, ZERO, PIN, RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO }
671 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT , ZERO }
674 { ZERO, RIGHT, RIGHT, ZERO, RIGHT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, ZERO, LEFT , ZERO }
677 { PIN, LEFT, RIGHT, ZERO, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, LEFT, RIGHT, PIN, RIGHT , ZERO }
680 { PIN, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, PIN , ZERO }
683 { LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT , ZERO }
686 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT , ZERO }
689 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, PIN , ZERO }
692 { PIN, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, ZERO , ZERO }
695 { RIGHT, ZERO, PIN, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, ZERO, ZERO, LEFT , ZERO }
698 { LEFT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT , ZERO }
701 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO , ZERO }
704 { RIGHT, ZERO, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO , ZERO }
707 { PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO , ZERO }
710 { RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, LEFT, RIGHT, LEFT, LEFT , ZERO }
713 { RIGHT, RIGHT, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, LEFT, LEFT , ZERO }
716 { RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT , ZERO }
719 { ZERO, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, LEFT, ZERO, LEFT, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT , ZERO }
723 { LEFT, ZERO, PIN, ZERO, PIN, LEFT, ZERO, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, PIN, ZERO, RIGHT , ZERO }
727 { ZERO, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, LEFT , ZERO }
730 { ZERO, ZERO, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN , ZERO }
733 { LEFT, PIN, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO , ZERO }
736 { ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN , ZERO }
739 { PIN, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO , ZERO }
742 { LEFT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT , ZERO }
745 { PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, RIGHT, PIN , ZERO }
748 { RIGHT, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, LEFT , ZERO }
751 { ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO, PIN , ZERO }
753 { "Counterclockwise",
754 { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT , ZERO }
757 { LEFT, LEFT, ZERO, PIN, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, RIGHT, LEFT, LEFT, ZERO, ZERO, RIGHT , ZERO }
760 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, PIN, RIGHT , ZERO }
763 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN , ZERO }
766 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO , ZERO }
769 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, ZERO }
772 { PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, ZERO }
775 { RIGHT, LEFT, PIN, LEFT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, LEFT, PIN, LEFT, RIGHT, ZERO }
778 { LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, PIN, ZERO, ZERO }
781 { RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, ZERO }
784 { ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO }
787 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, LEFT, RIGHT, ZERO }
790 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, LEFT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, RIGHT, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
793 { ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, LEFT, ZERO, PIN, ZERO, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, ZERO }
796 { ZERO, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO }
799 { ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO }
802 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO }
805 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO, RIGHT, ZERO, RIGHT, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO }
808 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, RIGHT, ZERO, RIGHT, LEFT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO }
811 { PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, ZERO }
814 { PIN, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO }
817 { ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO }
820 { LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, ZERO }
823 { LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, ZERO }
826 { RIGHT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, ZERO }
829 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, ZERO }
832 { ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO }
835 { LEFT, LEFT, RIGHT, PIN, ZERO, RIGHT, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, LEFT, ZERO, PIN, LEFT, RIGHT, RIGHT, RIGHT, PIN, ZERO }
838 { PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
841 { ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, RIGHT, ZERO, PIN, ZERO }
844 { ZERO, RIGHT, ZERO, PIN, LEFT, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, RIGHT, PIN, ZERO, LEFT, ZERO, ZERO }
847 { ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, ZERO, ZERO, ZERO, PIN, ZERO }
850 { ZERO, PIN, PIN, ZERO, PIN, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO }
853 { ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO }
856 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO }
859 { LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, RIGHT, LEFT, RIGHT, RIGHT, ZERO }
862 { LEFT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, ZERO, RIGHT, ZERO }
865 { PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO }
868 { ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO }
871 { LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO }
874 { RIGHT, LEFT, ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, LEFT, ZERO, ZERO }
877 { PIN, PIN, ZERO, LEFT, RIGHT, LEFT, ZERO, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO }
880 { PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO }
883 { PIN, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO }
886 { RIGHT, ZERO, ZERO, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, RIGHT, ZERO, PIN, ZERO, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO, ZERO, ZERO, LEFT, ZERO }
889 { ZERO, PIN, ZERO, ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO }
892 { ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO }
894 { "HoleInTheMiddle1",
895 { ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO }
897 { "HoleInTheMiddle2",
898 { ZERO, LEFT, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO }
901 { RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, ZERO }
904 { LEFT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, ZERO }
907 { LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO }
910 { RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
913 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO }
916 { RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, LEFT, ZERO }
919 { ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO }
922 { LEFT, LEFT, PIN, LEFT, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, RIGHT, PIN, RIGHT, RIGHT, LEFT, ZERO }
925 { ZERO, PIN, PIN, ZERO, ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO }
928 { RIGHT, PIN, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, PIN, LEFT, ZERO }
931 { PIN, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO }
934 { PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, ZERO }
936 { "magnifying glass",
937 { ZERO, ZERO, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, ZERO }
940 { ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, ZERO }
943 { PIN, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO }
946 { PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO }
949 { ZERO, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, LEFT, PIN, RIGHT, RIGHT, ZERO, RIGHT, ZERO }
952 { ZERO, RIGHT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, ZERO, RIGHT, RIGHT, PIN, LEFT, ZERO }
955 { LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
958 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, LEFT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO }
961 { ZERO, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO }
963 { "MouseWithoutTail",
964 { ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO }
967 { PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, ZERO }
970 { ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO }
973 { LEFT, ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, ZERO }
976 { ZERO, RIGHT, PIN, LEFT, LEFT, LEFT, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO }
979 { LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, ZERO }
982 { PIN, ZERO, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, ZERO, ZERO }
985 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, ZERO }
988 { PIN, PIN, ZERO, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
991 { ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
994 { ZERO, ZERO, ZERO, ZERO, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO }
997 { PIN, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, PIN, ZERO }
999 { "PictureCommingSoon",
1000 { LEFT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, RIGHT, RIGHT, ZERO }
1003 { LEFT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, ZERO }
1006 { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, ZERO }
1009 { RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO }
1012 { ZERO, PIN, ZERO, PIN, RIGHT, PIN, ZERO, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, ZERO, PIN, LEFT, ZERO }
1016 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO }
1020 { RIGHT, PIN, ZERO, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, PIN, ZERO, PIN, LEFT, ZERO }
1023 { ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, ZERO }
1026 { ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, LEFT, ZERO }
1028 { "QuarterbackTiltedAndReadyToHut",
1029 { PIN, ZERO, RIGHT, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, LEFT, ZERO, PIN, ZERO }
1032 { PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1035 { LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, PIN, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, ZERO }
1038 { ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, ZERO }
1041 { LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, ZERO }
1044 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1047 { RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, ZERO }
1050 { ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO }
1053 { PIN, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, PIN, ZERO }
1056 { RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1059 { RIGHT, LEFT, PIN, ZERO, ZERO, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO }
1062 { LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO }
1065 { RIGHT, PIN, ZERO, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO }
1068 { RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, ZERO }
1071 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO }
1074 { PIN, RIGHT, LEFT, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, LEFT, ZERO, PIN, PIN, ZERO }
1077 { LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO }
1080 { LEFT, RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, RIGHT, LEFT, ZERO }
1083 { ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO }
1085 { "SnakeReadyToStrike",
1086 { LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO }
1089 { RIGHT, RIGHT, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO }
1092 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO }
1095 { PIN, PIN, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
1098 { LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, ZERO }
1101 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO }
1104 { PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, ZERO }
1107 { PIN, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, PIN, ZERO }
1110 { PIN, PIN, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, LEFT, LEFT, PIN, PIN, ZERO }
1113 { LEFT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, ZERO }
1116 { PIN, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, ZERO, RIGHT, PIN, LEFT, ZERO }
1119 { RIGHT, RIGHT, ZERO, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, RIGHT, LEFT, RIGHT, ZERO, ZERO, LEFT, ZERO }
1122 { PIN, LEFT, ZERO, RIGHT, RIGHT, LEFT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, LEFT, LEFT, ZERO, ZERO }
1125 { ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, ZERO }
1128 { PIN, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO }
1131 { RIGHT, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, ZERO }
1134 { ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO }
1137 { ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
1140 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO }
1143 { ZERO, PIN, ZERO, PIN, LEFT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, ZERO }
1146 { PIN, ZERO, PIN, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO }
1149 { PIN, PIN, ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO }
1152 { RIGHT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, RIGHT, ZERO }
1155 { RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO }
1158 { ZERO, PIN, LEFT, LEFT, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1161 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, RIGHT, PIN, ZERO }
1164 { ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO }
1167 { ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO }
1170 { RIGHT, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, ZERO }
1173 { RIGHT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO }
1176 { RIGHT, LEFT, ZERO, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO }
1179 { PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO }
1182 { RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, PIN, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO }
1185 { RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, ZERO }
1188 { ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, LEFT, LEFT, PIN, ZERO, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, ZERO }
1191 { PIN, LEFT, LEFT, PIN, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO }
1194 { PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO }
1197 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO }
1200 { PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, ZERO }
1204 { RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO }
1208 { ZERO, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO, ZERO }
1211 { ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, ZERO }
1214 { PIN, LEFT, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, ZERO, ZERO }
1217 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1220 { LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO }
1223 { ZERO, PIN, ZERO, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, ZERO }
1226 { ZERO, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, ZERO }
1229 { PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO }
1232 { ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO }
1235 { PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, PIN, RIGHT, ZERO, RIGHT, RIGHT, ZERO, RIGHT, PIN, ZERO, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, ZERO }
1238 { ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1241 { LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO }
1244 { PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO }
1247 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO }
1249 { "WindowToTheWorld",
1250 { PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
1253 { PIN, PIN, ZERO, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, PIN, ZERO }
1256 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO }
1259 { RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO }
1262 { PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, ZERO }
1265 { ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO }
1268 { LEFT, ZERO, ZERO, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, ZERO, ZERO, ZERO }
1272 size_t models = sizeof(model) / sizeof(struct model_s);
1274 #define VOFFSET 0.045
1280 /* the connecting string that holds the snake together */
1281 #define MAGICAL_RED_STRING 0
1283 #define GETSCALAR(vec,mask) ((vec)==(mask) ? 1 : ((vec)==-(mask) ? -1 : 0 ))
1286 # define MAX(x, y) ((x) > (y) ? (x) : (y))
1289 # define MIN(x, y) ((x) < (y) ? (x) : (y))
1292 #define RAND(n) ((random() & 0x7fffffff) % ((long) (n)))
1293 #define RANDSIGN() ((random() & 1) ? 1 : -1)
1295 /* the triangular prism what makes up the basic unit */
1296 float solid_prism_v[][3] = {
1297 /* first corner, bottom left front */
1298 { VOFFSET, VOFFSET, 1.0 },
1299 { VOFFSET, 0.00, 1.0 - VOFFSET },
1300 { 0.00, VOFFSET, 1.0 - VOFFSET },
1301 /* second corner, rear */
1302 { VOFFSET, VOFFSET, 0.00 },
1303 { VOFFSET, 0.00, VOFFSET },
1304 { 0.00, VOFFSET, VOFFSET },
1305 /* third, right front */
1306 { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 1.0 },
1307 { 1.0 - VOFFSET / M_SQRT1_2, 0.0, 1.0 - VOFFSET },
1308 { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, 1.0 - VOFFSET },
1309 /* fourth, right rear */
1310 { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 0.0 },
1311 { 1.0 - VOFFSET / M_SQRT1_2, 0.0, VOFFSET },
1312 { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, VOFFSET },
1313 /* fifth, upper front */
1314 { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 1.0 },
1315 { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, 1.0 - VOFFSET },
1316 { 0.0, 1.0 - VOFFSET / M_SQRT1_2, 1.0 - VOFFSET},
1317 /* sixth, upper rear */
1318 { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 0.0 },
1319 { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, VOFFSET },
1320 { 0.0, 1.0 - VOFFSET / M_SQRT1_2, VOFFSET }};
1322 float solid_prism_n[][3] = {/* corners */
1323 { -VOFFSET, -VOFFSET, VOFFSET },
1324 { VOFFSET, -VOFFSET, VOFFSET },
1325 { -VOFFSET, VOFFSET, VOFFSET },
1326 { -VOFFSET, -VOFFSET, -VOFFSET },
1327 { VOFFSET, -VOFFSET, -VOFFSET },
1328 { -VOFFSET, VOFFSET, -VOFFSET },
1330 { -VOFFSET, 0.0, VOFFSET },
1331 { 0.0, -VOFFSET, VOFFSET },
1332 { VOFFSET, VOFFSET, VOFFSET },
1333 { -VOFFSET, 0.0, -VOFFSET },
1334 { 0.0, -VOFFSET, -VOFFSET },
1335 { VOFFSET, VOFFSET, -VOFFSET },
1336 { -VOFFSET, -VOFFSET, 0.0 },
1337 { VOFFSET, -VOFFSET, 0.0 },
1338 { -VOFFSET, VOFFSET, 0.0 },
1342 { M_SQRT1_2, M_SQRT1_2, 0.0 },
1344 { 0.0, 0.0, -1.0 }};
1346 float wire_prism_v[][3] = {{ 0.0, 0.0, 1.0 },
1353 float wire_prism_n[][3] = {{ 0.0, 0.0, 1.0},
1355 { M_SQRT1_2, M_SQRT1_2, 0.0},
1359 static struct glsnake_cfg * glc = NULL;
1364 typedef float (*morphFunc)(long);
1367 /* forward definitions for GLUT functions */
1368 void calc_rotation();
1369 inline void ui_mousedrag();
1372 GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };
1373 GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
1374 GLfloat mat_specular[] = { 0.1, 0.1, 0.1, 1.0 };
1375 GLfloat mat_shininess[] = { 20.0 };
1382 float light_pos[][3] = {{0.0, 10.0, 20.0}, {0.0, 20.0, -1.0}};
1383 float light_dir[][3] = {{0.0, -10.0,-20.0}, {0.0,-20.0, 1.0}};
1385 glEnable(GL_DEPTH_TEST);
1386 glShadeModel(GL_SMOOTH);
1387 glCullFace(GL_BACK);
1388 /*glEnable(GL_CULL_FACE);*/
1389 glEnable(GL_NORMALIZE);
1391 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1396 /*glColor4f(1.0, 1.0, 1.0, 1.0);*/
1397 glLightfv(GL_LIGHT0, GL_POSITION, light_pos[0]);
1398 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_dir[0]);
1399 glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
1400 /*glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);*/
1402 glLightfv(GL_LIGHT1, GL_POSITION, light_pos[1]);
1403 glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light_dir[1]);
1404 glLightfv(GL_LIGHT1, GL_DIFFUSE, white_light);
1405 glLightfv(GL_LIGHT1, GL_SPECULAR, white_light);
1407 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
1408 glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
1409 glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
1410 glEnable(GL_LIGHTING);
1411 glEnable(GL_LIGHT0);
1412 glEnable(GL_LIGHT1);
1413 /*glEnable(GL_COLOR_MATERIAL);*/
1417 void gettime(snaketime *t)
1419 #ifdef HAVE_GETTIMEOFDAY
1420 #ifdef GETTIMEOFDAY_TWO_ARGS
1421 struct timezone tzp;
1422 gettimeofday(t, &tzp);
1423 #else /* !GETTIMEOFDAY_TWO_ARGS */
1425 #endif /* !GETTIMEOFDAY_TWO_ARGS */
1426 #else /* !HAVE_GETTIMEOFDAY */
1429 #endif /* HAVE_FTIME */
1430 #endif /* !HAVE_GETTIMEOFDAY */
1433 void start_morph(unsigned int model_index, int immediate);
1435 /* wot initialises it */
1442 struct glsnake_cfg * bp;
1444 /* set up the conf struct and glx contexts */
1446 glc = (struct glsnake_cfg *) calloc(MI_NUM_SCREENS(mi), sizeof(struct glsnake_cfg));
1448 fprintf(stderr, "%s: out of memory\n", progname);
1452 bp = &glc[MI_SCREEN(mi)];
1454 if ((bp->glx_context = init_GL(mi)) != NULL) {
1456 glsnake_reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1462 /* initialise conf struct */
1463 memset(&bp->node, 0, sizeof(float) * NODE_COUNT);
1473 gettime(&bp->last_iteration);
1474 memcpy(&bp->last_morph, &bp->last_iteration, sizeof(bp->last_morph));
1476 bp->prev_colour = bp->next_colour = COLOUR_ACYCLIC;
1477 bp->next_model = RAND(models);
1478 bp->prev_model = START_MODEL;
1479 start_morph(bp->prev_model, 1);
1481 /* set up a font for the labels */
1484 load_font(mi->dpy, "labelfont", &bp->font, &bp->font_list);
1487 /* build a solid display list */
1488 glc->node_solid = glGenLists(1);
1489 glNewList(glc->node_solid, GL_COMPILE);
1491 glBegin(GL_TRIANGLES);
1492 glNormal3fv(solid_prism_n[0]);
1493 glVertex3fv(solid_prism_v[0]);
1494 glVertex3fv(solid_prism_v[2]);
1495 glVertex3fv(solid_prism_v[1]);
1497 glNormal3fv(solid_prism_n[1]);
1498 glVertex3fv(solid_prism_v[6]);
1499 glVertex3fv(solid_prism_v[7]);
1500 glVertex3fv(solid_prism_v[8]);
1502 glNormal3fv(solid_prism_n[2]);
1503 glVertex3fv(solid_prism_v[12]);
1504 glVertex3fv(solid_prism_v[13]);
1505 glVertex3fv(solid_prism_v[14]);
1507 glNormal3fv(solid_prism_n[3]);
1508 glVertex3fv(solid_prism_v[3]);
1509 glVertex3fv(solid_prism_v[4]);
1510 glVertex3fv(solid_prism_v[5]);
1512 glNormal3fv(solid_prism_n[4]);
1513 glVertex3fv(solid_prism_v[9]);
1514 glVertex3fv(solid_prism_v[11]);
1515 glVertex3fv(solid_prism_v[10]);
1517 glNormal3fv(solid_prism_n[5]);
1518 glVertex3fv(solid_prism_v[16]);
1519 glVertex3fv(solid_prism_v[15]);
1520 glVertex3fv(solid_prism_v[17]);
1524 glNormal3fv(solid_prism_n[6]);
1525 glVertex3fv(solid_prism_v[0]);
1526 glVertex3fv(solid_prism_v[12]);
1527 glVertex3fv(solid_prism_v[14]);
1528 glVertex3fv(solid_prism_v[2]);
1530 glNormal3fv(solid_prism_n[7]);
1531 glVertex3fv(solid_prism_v[0]);
1532 glVertex3fv(solid_prism_v[1]);
1533 glVertex3fv(solid_prism_v[7]);
1534 glVertex3fv(solid_prism_v[6]);
1536 glNormal3fv(solid_prism_n[8]);
1537 glVertex3fv(solid_prism_v[6]);
1538 glVertex3fv(solid_prism_v[8]);
1539 glVertex3fv(solid_prism_v[13]);
1540 glVertex3fv(solid_prism_v[12]);
1542 glNormal3fv(solid_prism_n[9]);
1543 glVertex3fv(solid_prism_v[3]);
1544 glVertex3fv(solid_prism_v[5]);
1545 glVertex3fv(solid_prism_v[17]);
1546 glVertex3fv(solid_prism_v[15]);
1548 glNormal3fv(solid_prism_n[10]);
1549 glVertex3fv(solid_prism_v[3]);
1550 glVertex3fv(solid_prism_v[9]);
1551 glVertex3fv(solid_prism_v[10]);
1552 glVertex3fv(solid_prism_v[4]);
1554 glNormal3fv(solid_prism_n[11]);
1555 glVertex3fv(solid_prism_v[15]);
1556 glVertex3fv(solid_prism_v[16]);
1557 glVertex3fv(solid_prism_v[11]);
1558 glVertex3fv(solid_prism_v[9]);
1560 glNormal3fv(solid_prism_n[12]);
1561 glVertex3fv(solid_prism_v[1]);
1562 glVertex3fv(solid_prism_v[2]);
1563 glVertex3fv(solid_prism_v[5]);
1564 glVertex3fv(solid_prism_v[4]);
1566 glNormal3fv(solid_prism_n[13]);
1567 glVertex3fv(solid_prism_v[8]);
1568 glVertex3fv(solid_prism_v[7]);
1569 glVertex3fv(solid_prism_v[10]);
1570 glVertex3fv(solid_prism_v[11]);
1572 glNormal3fv(solid_prism_n[14]);
1573 glVertex3fv(solid_prism_v[13]);
1574 glVertex3fv(solid_prism_v[16]);
1575 glVertex3fv(solid_prism_v[17]);
1576 glVertex3fv(solid_prism_v[14]);
1580 glBegin(GL_TRIANGLES);
1581 glNormal3fv(solid_prism_n[15]);
1582 glVertex3fv(solid_prism_v[0]);
1583 glVertex3fv(solid_prism_v[6]);
1584 glVertex3fv(solid_prism_v[12]);
1586 glNormal3fv(solid_prism_n[19]);
1587 glVertex3fv(solid_prism_v[3]);
1588 glVertex3fv(solid_prism_v[15]);
1589 glVertex3fv(solid_prism_v[9]);
1593 glNormal3fv(solid_prism_n[16]);
1594 glVertex3fv(solid_prism_v[1]);
1595 glVertex3fv(solid_prism_v[4]);
1596 glVertex3fv(solid_prism_v[10]);
1597 glVertex3fv(solid_prism_v[7]);
1599 glNormal3fv(solid_prism_n[17]);
1600 glVertex3fv(solid_prism_v[8]);
1601 glVertex3fv(solid_prism_v[11]);
1602 glVertex3fv(solid_prism_v[16]);
1603 glVertex3fv(solid_prism_v[13]);
1605 glNormal3fv(solid_prism_n[18]);
1606 glVertex3fv(solid_prism_v[2]);
1607 glVertex3fv(solid_prism_v[14]);
1608 glVertex3fv(solid_prism_v[17]);
1609 glVertex3fv(solid_prism_v[5]);
1613 /* build wire display list */
1614 glc->node_wire = glGenLists(1);
1615 glNewList(glc->node_wire, GL_COMPILE);
1616 glBegin(GL_LINE_STRIP);
1617 glVertex3fv(wire_prism_v[0]);
1618 glVertex3fv(wire_prism_v[1]);
1619 glVertex3fv(wire_prism_v[2]);
1620 glVertex3fv(wire_prism_v[0]);
1621 glVertex3fv(wire_prism_v[3]);
1622 glVertex3fv(wire_prism_v[4]);
1623 glVertex3fv(wire_prism_v[5]);
1624 glVertex3fv(wire_prism_v[3]);
1627 glVertex3fv(wire_prism_v[1]);
1628 glVertex3fv(wire_prism_v[4]);
1629 glVertex3fv(wire_prism_v[2]);
1630 glVertex3fv(wire_prism_v[5]);
1635 /* initialise the rotation */
1646 struct glsnake_cfg * bp = &glc[MI_SCREEN(mi)];
1649 /* draw some text */
1650 glPushAttrib((GLbitfield) GL_TRANSFORM_BIT | GL_ENABLE_BIT);
1651 glDisable(GL_LIGHTING);
1652 glDisable(GL_DEPTH_TEST);
1654 glDisable(GL_BLEND);
1656 glMatrixMode(GL_PROJECTION);
1659 glMatrixMode(GL_MODELVIEW);
1663 gluOrtho2D((GLdouble) 0., (GLdouble) glc->width, (GLdouble) 0., (GLdouble) glc->height);
1665 gluOrtho2D((GLdouble) 0., (GLdouble) mi->xgwa.width, (GLdouble) 0., (GLdouble) mi->xgwa.height);
1667 glColor4f(1.0, 1.0, 1.0, 1.0);
1669 char interactstr[] = "interactive";
1678 s = model[glc->next_model].name;
1684 w = glutBitmapLength(GLUT_BITMAP_HELVETICA_12, (const unsigned char *) s);
1685 glRasterPos2f((GLfloat) (glc->width - w - 3), 4.0);
1686 while (s[i] != '\0')
1687 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, s[i++]);
1690 print_gl_string(mi->dpy, bp->font, bp->font_list,
1691 mi->xgwa.width, mi->xgwa.height,
1692 10.0, (float) mi->xgwa.height - 10.0,
1697 glMatrixMode(GL_PROJECTION);
1702 /* apply the matrix to the origin and stick it in vec */
1703 void matmult_origin(float rotmat[16], float vec[4]) {
1705 vec[0] = 0.5 * rotmat[0] + 0.5 * rotmat[4] + 0.5 * rotmat [8] + 1 * rotmat[12];
1706 vec[1] = 0.5 * rotmat[1] + 0.5 * rotmat[5] + 0.5 * rotmat [9] + 1 * rotmat[13];
1707 vec[2] = 0.5 * rotmat[2] + 0.5 * rotmat[6] + 0.5 * rotmat[10] + 1 * rotmat[14];
1708 vec[3] = 0.5 * rotmat[3] + 0.5 * rotmat[7] + 0.5 * rotmat[11] + 1 * rotmat[15];
1710 vec[0] = 0 * rotmat [0] + 0 * rotmat [1] + 0 * rotmat [2] + 1 * rotmat [3];
1711 vec[1] = 0 * rotmat [4] + 0 * rotmat [5] + 0 * rotmat [6] + 1 * rotmat [7];
1712 vec[2] = 0 * rotmat [8] + 0 * rotmat [9] + 0 * rotmat[10] + 1 * rotmat[11];
1713 vec[3] = 0 * rotmat[12] + 0 * rotmat[13] + 0 * rotmat[14] + 1 * rotmat[15];
1721 /* wot gets called when the winder is resized */
1722 void glsnake_reshape(
1727 glViewport(0, 0, (GLint) w, (GLint) h);
1728 glMatrixMode(GL_PROJECTION);
1730 gluPerspective(zoom, (GLdouble) w / (GLdouble) h, 0.05, 100.0);
1731 gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
1732 glMatrixMode(GL_MODELVIEW);
1733 /*gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);*/
1741 /* Returns the new dst_dir for the given src_dir and dst_dir */
1742 int cross_product(int src_dir, int dst_dir) {
1743 return X_MASK*(GETSCALAR(src_dir,Y_MASK) * GETSCALAR(dst_dir,Z_MASK) -
1744 GETSCALAR(src_dir,Z_MASK) * GETSCALAR(dst_dir,Y_MASK))+
1745 Y_MASK*(GETSCALAR(src_dir,Z_MASK) * GETSCALAR(dst_dir,X_MASK) -
1746 GETSCALAR(src_dir,X_MASK) * GETSCALAR(dst_dir,Z_MASK))+
1747 Z_MASK*(GETSCALAR(src_dir,X_MASK) * GETSCALAR(dst_dir,Y_MASK) -
1748 GETSCALAR(src_dir,Y_MASK) * GETSCALAR(dst_dir,X_MASK));
1751 /* calculate orthogonal snake metrics
1752 * is_legal = true if model does not pass through itself
1753 * is_cyclic = true if last node connects back to first node
1754 * last_turn = for cyclic snakes, specifes what the 24th turn would be
1756 void calc_snake_metrics(void) {
1759 int prevSrcDir = -Y_MASK;
1760 int prevDstDir = Z_MASK;
1761 int grid[25][25][25];
1764 memset(&grid, 0, sizeof(int) * 25*25*25);
1769 /* trace path of snake - and keep record for is_legal */
1770 for (i = 0; i < NODE_COUNT - 1; i++) {
1771 /*int ang_card;*/ /* cardinal direction of node angle */
1772 /* establish new state vars */
1773 srcDir = -prevDstDir;
1774 x += GETSCALAR(prevDstDir, X_MASK);
1775 y += GETSCALAR(prevDstDir, Y_MASK);
1776 z += GETSCALAR(prevDstDir, Z_MASK);
1778 switch ((int) model[glc->next_model].node[i]) {
1780 dstDir = -prevSrcDir;
1783 dstDir = prevSrcDir;
1787 dstDir = cross_product(prevSrcDir, prevDstDir);
1788 if (model[glc->next_model].node[i] == (int) (RIGHT))
1792 /* Prevent spurious "might be used
1793 * uninitialised" warnings when compiling
1799 if (grid[x][y][z] == 0)
1800 grid[x][y][z] = srcDir + dstDir;
1801 else if (grid[x][y][z] + srcDir + dstDir == 0)
1806 prevSrcDir = srcDir;
1807 prevDstDir = dstDir;
1810 /* determine if the snake is cyclic */
1811 glc->is_cyclic = (dstDir == Y_MASK && x == 12 && y == 11 && z == 12);
1813 /* determine last_turn */
1814 glc->last_turn = -1;
1817 case -Z_MASK: glc->last_turn = ZERO; break;
1818 case Z_MASK: glc->last_turn = PIN; break;
1819 case X_MASK: glc->last_turn = LEFT; break;
1820 case -X_MASK: glc->last_turn = RIGHT; break;
1824 /* work out how far through the current morph we are */
1825 float morph_percent(void) {
1829 /* extend this function later with a case statement for each of the
1832 /* when morphing all nodes at once, the longest morph will be the node
1833 * that needs to rotate 180 degrees. For each node, work out how far it
1834 * has to go, and store the maximum rotation and current largest angular
1835 * difference, returning the angular difference over the maximum. */
1837 float rot_max = 0.0, ang_diff_max = 0.0;
1839 for (i = 0; i < NODE_COUNT - 1; i++) {
1840 float rot, ang_diff;
1842 /* work out the maximum rotation this node has to go through
1843 * from the previous to the next model, taking into account that
1844 * the snake always morphs through the smaller angle */
1845 rot = fabs(model[glc->prev_model].node[i] -
1846 model[glc->next_model].node[i]);
1847 if (rot > 180.0) rot = 180.0 - rot;
1848 /* work out the difference between the current position and the
1850 ang_diff = fabs(glc->node[i] -
1851 model[glc->next_model].node[i]);
1852 if (ang_diff > 180.0) ang_diff = 180.0 - ang_diff;
1853 /* if it's the biggest so far, record it */
1854 if (rot > rot_max) rot_max = rot;
1855 if (ang_diff > ang_diff_max) ang_diff_max = ang_diff;
1858 /* ang_diff / rot approaches 0, we want the complement */
1859 retval = 1.0 - (ang_diff_max / rot_max);
1860 /* protect against naan */
1862 /* Apparently some systems (Solaris) don't have isinf() */
1864 #define isinf(x) (((x) > 999999999999.9) || ((x) < -999999999999.9))
1866 if (isnan(retval) || isinf(retval)) retval = 1.0;
1868 /*printf("morph_pct = %f\n", retval);*/
1872 void morph_colour(void) {
1873 float percent, compct; /* complement of percentage */
1875 percent = morph_percent();
1876 compct = 1.0 - percent;
1878 glc->colour[0][0] = colour[glc->prev_colour][0][0] * compct + colour[glc->next_colour][0][0] * percent;
1879 glc->colour[0][1] = colour[glc->prev_colour][0][1] * compct + colour[glc->next_colour][0][1] * percent;
1880 glc->colour[0][2] = colour[glc->prev_colour][0][2] * compct + colour[glc->next_colour][0][2] * percent;
1881 glc->colour[0][3] = colour[glc->prev_colour][0][3] * compct + colour[glc->next_colour][0][3] * percent;
1883 glc->colour[1][0] = colour[glc->prev_colour][1][0] * compct + colour[glc->next_colour][1][0] * percent;
1884 glc->colour[1][1] = colour[glc->prev_colour][1][1] * compct + colour[glc->next_colour][1][1] * percent;
1885 glc->colour[1][2] = colour[glc->prev_colour][1][2] * compct + colour[glc->next_colour][1][2] * percent;
1886 glc->colour[1][3] = colour[glc->prev_colour][1][3] * compct + colour[glc->next_colour][1][3] * percent;
1889 /* Start morph process to this model */
1890 void start_morph(unsigned int model_index, int immediate) {
1891 /* if immediate, don't bother morphing, go straight to the next model */
1895 for (i = 0; i < NODE_COUNT; i++)
1896 glc->node[i] = model[model_index].node[i];
1899 glc->prev_model = glc->next_model;
1900 glc->next_model = model_index;
1901 glc->prev_colour = glc->next_colour;
1903 calc_snake_metrics();
1905 glc->next_colour = COLOUR_INVALID;
1907 glc->next_colour = COLOUR_AUTHENTIC;
1908 else if (glc->is_cyclic)
1909 glc->next_colour = COLOUR_CYCLIC;
1911 glc->next_colour = COLOUR_ACYCLIC;
1914 glc->colour[0][0] = colour[glc->next_colour][0][0];
1915 glc->colour[0][1] = colour[glc->next_colour][0][1];
1916 glc->colour[0][2] = colour[glc->next_colour][0][2];
1917 glc->colour[0][3] = colour[glc->next_colour][0][3];
1918 glc->colour[1][0] = colour[glc->next_colour][1][0];
1919 glc->colour[1][1] = colour[glc->next_colour][1][1];
1920 glc->colour[1][2] = colour[glc->next_colour][1][2];
1921 glc->colour[1][3] = colour[glc->next_colour][1][3];
1928 /* Returns morph progress */
1929 float morph(long iter_msec) {
1930 /* work out the maximum angle for this iteration */
1932 float iter_angle_max, largest_diff, largest_progress;
1938 iter_angle_max = 90.0 * (angvel/1000.0) * iter_msec;
1941 largest_diff = largest_progress = 0.0;
1942 for (i = 0; i < NODE_COUNT; i++) {
1943 float curAngle = glc->node[i];
1944 float destAngle = model[glc->next_model].node[i];
1945 if (curAngle != destAngle) {
1947 if (fabs(curAngle-destAngle) <= iter_angle_max)
1948 glc->node[i] = destAngle;
1949 else if (fmod(curAngle-destAngle+360,360) > 180)
1950 glc->node[i] = fmod(curAngle + iter_angle_max, 360);
1952 glc->node[i] = fmod(curAngle+360 - iter_angle_max, 360);
1953 largest_diff = MAX(largest_diff, fabs(destAngle-glc->node[i]));
1954 largest_progress = MAX(largest_diff, fabs(glc->node[i] - model[glc->prev_model].node[i]));
1958 return MIN(largest_diff / largest_progress, 1.0);
1962 void glsnake_idle();
1964 void restore_idle(int v __attribute__((__unused__)))
1966 glutIdleFunc(glsnake_idle);
1970 void quick_sleep(void)
1973 /* By using glutTimerFunc we can keep responding to
1974 * mouse and keyboard events, unlike using something like
1977 glutTimerFunc(1, restore_idle, 0);
1985 struct glsnake_cfg * bp
1988 /* time since last iteration */
1990 /* time since the beginning of last morph */
1992 float iter_angle_max;
1993 snaketime current_time;
1994 /* morphFunc transition; */
1998 /* Do nothing to the model if we are paused */
2000 /* Avoid busy waiting when nothing is changing */
2004 glutPostRedisplay();
2009 /* <spiv> Well, ftime gives time with millisecond resolution.
2010 * <spiv> (or worse, perhaps... who knows what the OS will do)
2011 * <spiv> So if no discernable amount of time has passed:
2012 * <spiv> a) There's no point updating the screen, because
2013 * it would be the same
2014 * <spiv> b) The code will divide by zero
2016 gettime(¤t_time);
2018 iter_msec = (long) GETMSECS(current_time) - GETMSECS(glc->last_iteration) +
2019 ((long) GETSECS(current_time) - GETSECS(glc->last_iteration)) * 1000L;
2022 /* save the current time */
2023 memcpy(&glc->last_iteration, ¤t_time, sizeof(snaketime));
2025 /* work out if we have to switch models */
2026 morf_msec = GETMSECS(glc->last_iteration) - GETMSECS(glc->last_morph) +
2027 ((long) (GETSECS(glc->last_iteration)-GETSECS(glc->last_morph)) * 1000L);
2029 if ((morf_msec > statictime) && !interactive && !glc->morphing) {
2030 /*printf("starting morph\n");*/
2031 memcpy(&glc->last_morph, &(glc->last_iteration), sizeof(glc->last_morph));
2032 start_morph(RAND(models), 0);
2035 if (interactive && !glc->morphing) {
2040 /* if (!glc->dragging && !glc->interactive) { */
2043 yspin += 360/((1000/yangvel)/iter_msec);
2044 zspin += 360/((1000/zangvel)/iter_msec);
2046 yspin += 360 * (yangvel/1000.0) * iter_msec;
2047 zspin += 360 * (zangvel/1000.0) * iter_msec;
2050 /*printf("yspin: %f, zspin: %f\n", yspin, zspin);*/
2054 /* work out the maximum angle we could turn this node in this
2055 * timeslice, iter_msec milliseconds long */
2056 iter_angle_max = 90.0 * (angvel/1000.0) * iter_msec;
2059 for (i = 0; i < NODE_COUNT; i++) {
2060 float cur_angle = glc->node[i];
2061 float dest_angle = model[glc->next_model].node[i];
2062 if (cur_angle != dest_angle) {
2064 if (fabs(cur_angle - dest_angle) <= iter_angle_max)
2065 glc->node[i] = dest_angle;
2066 else if (fmod(cur_angle - dest_angle + 360, 360) > 180)
2067 glc->node[i] = fmod(cur_angle + iter_angle_max, 360);
2069 glc->node[i] = fmod(cur_angle + 360 - iter_angle_max, 360);
2073 if (!still_morphing)
2076 /* colour cycling */
2081 glutPostRedisplay();
2084 /* We are going too fast, so we may as well let the
2085 * cpu relax a little by sleeping for a millisecond. */
2091 void glsnake_display(
2097 struct glsnake_cfg * bp = &glc[MI_SCREEN(mi)];
2098 Display * dpy = MI_DISPLAY(mi);
2099 Window window = MI_WINDOW(mi);
2104 float positions[NODE_COUNT][4]; /* origin points for each node */
2105 float com[4]; /* it's the CENTRE of MASS */
2108 if (!bp->glx_context)
2112 /* clear the buffer */
2113 glClear((GLbitfield) GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2115 /* go into the modelview stack */
2116 glMatrixMode(GL_MODELVIEW);
2119 /* get the centre of each node, by moving through the snake and
2120 * performing the rotations, then grabbing the matrix at each point
2121 * and applying it to the origin */
2125 /* apply the mouse drag rotation */
2129 /* apply the continuous rotation */
2130 glRotatef(yspin, 0.0, 1.0, 0.0);
2131 glRotatef(zspin, 0.0, 0.0, 1.0);
2137 for (i = 0; i < NODE_COUNT; i++) {
2142 /*printf("ang = %f\n", ang);*/
2144 glTranslatef(0.5, 0.5, 0.5); /* move to center */
2145 glRotatef(90.0, 0.0, 0.0, -1.0); /* reorient */
2146 glTranslatef(1.0 + explode, 0.0, 0.0); /* move to new pos. */
2147 glRotatef(180.0 + ang, 1.0, 0.0, 0.0); /* pivot to new angle */
2148 glTranslatef(-0.5, -0.5, -0.5); /* return from center */
2150 glGetFloatv(GL_MODELVIEW_MATRIX, rotmat);
2152 matmult_origin(rotmat, positions[i]);
2154 /*printf("positions %f %f %f %f\n", positions[i][0], positions[i][1], positions[i][2], positions[i][3]);*/
2156 com[0] += positions[i][0];
2157 com[1] += positions[i][1];
2158 com[2] += positions[i][2];
2159 com[3] += positions[i][3];
2162 com[0] /= NODE_COUNT;
2163 com[1] /= NODE_COUNT;
2164 com[2] /= NODE_COUNT;
2165 com[3] /= NODE_COUNT;
2171 /*printf("com: %f, %f, %f, %f\n", com[0], com[1], com[2], com[3]);*/
2173 #if MAGICAL_RED_STRING
2175 glTranslatef(-com[0], -com[1], -com[2]);
2177 glDisable(GL_LIGHTING);
2178 glColor4f(1.0, 0.0, 0.0, 1.0);
2179 glBegin(GL_LINE_STRIP);
2180 for (i = 0; i < NODE_COUNT - 1; i++) {
2181 glVertex3fv(positions[i]);
2184 glEnable(GL_LIGHTING);
2185 /*glTranslatef(com[0], com[1], com[2]);*/
2190 glTranslatef(-com[0], -com[1], -com[2]);
2193 /* apply the mouse drag rotation */
2197 /* apply the continuous rotation */
2198 glRotatef(yspin, 0.0, 1.0, 0.0);
2199 glRotatef(zspin, 0.0, 0.0, 1.0);
2201 /* now draw each node along the snake -- this is quite ugly :p */
2202 for (i = 0; i < NODE_COUNT; i++) {
2203 /* choose a colour for this node */
2204 if ((i == glc->selected || i == glc->selected+1) && interactive)
2206 glColor4f(1.0, 1.0, 0.0, 1.0);
2208 /*glColor4fv(glc->colour[(i+1)%2]);*/
2209 glMaterialfv(GL_FRONT, GL_AMBIENT, glc->colour[(i+1)%2]);
2210 glMaterialfv(GL_FRONT, GL_DIFFUSE, glc->colour[(i+1)%2]);
2211 /*glMaterialfv(GL_FRONT, GL_SPECULAR, glc->colour[(i+1)%2]);*/
2216 glCallList(glc->node_wire);
2218 glCallList(glc->node_solid);
2220 /* now work out where to draw the next one */
2222 /* Interpolate between models */
2225 glTranslatef(0.5, 0.5, 0.5); /* move to center */
2226 glRotatef(90.0, 0.0, 0.0, -1.0); /* reorient */
2227 glTranslatef(1.0 + explode, 0.0, 0.0); /* move to new pos. */
2228 glRotatef(180.0 + ang, 1.0, 0.0, 0.0); /* pivot to new angle */
2229 glTranslatef(-0.5, -0.5, -0.5); /* return from center */
2249 glXSwapBuffers(dpy, window);
2254 /* anything that needs to be cleaned up goes here */
2256 glutDestroyWindow(glc->window);
2260 void ui_init(int *, char **);
2262 int main(int argc, char ** argv) {
2263 glc = malloc(sizeof(struct glsnake_cfg));
2264 memset(glc, 0, sizeof(struct glsnake_cfg));
2269 ui_init(&argc, argv);
2271 gettime(&glc->last_iteration);
2272 memcpy(&glc->last_morph, &glc->last_iteration, sizeof(snaketime));
2273 srand((unsigned int)GETSECS(glc->last_iteration));
2275 glc->prev_colour = glc->next_colour = COLOUR_ACYCLIC;
2276 glc->next_model = RAND(models);
2277 glc->prev_model = 0;
2278 start_morph(glc->prev_model, 1);
2296 /* trackball quaternions */
2297 float cumquat[4] = {0.0,0.0,0.0,0.0}, oldquat[4] = {0.0,0.0,0.0,0.1};
2299 /* rotation matrix */
2302 /* mouse drag vectors: start and end */
2303 float mouse_start[3], mouse_end[3];
2305 /* dragging boolean */
2308 /* this function calculates the rotation matrix based on the quaternions
2309 * generated from the mouse drag vectors */
2310 void calc_rotation() {
2312 double xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
2314 /* this bit ripped from Shoemake's quaternion notes from SIGGRAPH */
2315 Nq = cumquat[0] * cumquat[0] + cumquat[1] * cumquat[1] +
2316 cumquat[2] * cumquat[2] + cumquat[3] * cumquat[3];
2317 s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
2318 xs = cumquat[0] * s; ys = cumquat[1] * s; zs = cumquat[2] * s;
2319 wx = cumquat[3] * xs; wy = cumquat[3] * ys; wz = cumquat[3] * zs;
2320 xx = cumquat[0] * xs; xy = cumquat[0] * ys; xz = cumquat[0] * zs;
2321 yy = cumquat[1] * ys; yz = cumquat[1] * zs; zz = cumquat[2] * zs;
2323 rotation[0] = 1.0 - (yy + zz);
2324 rotation[1] = xy + wz;
2325 rotation[2] = xz - wy;
2326 rotation[4] = xy - wz;
2327 rotation[5] = 1.0 - (xx + zz);
2328 rotation[6] = yz + wx;
2329 rotation[8] = xz + wy;
2330 rotation[9] = yz - wx;
2331 rotation[10] = 1.0 - (xx + yy);
2332 rotation[3] = rotation[7] = rotation[11] = 0.0;
2333 rotation[12] = rotation[13] = rotation[14] = 0.0;
2337 inline void ui_mousedrag() {
2338 glMultMatrixf(rotation);
2341 void ui_keyboard(unsigned char c, int x __attribute__((__unused__)), int y __attribute__((__unused__))) {
2348 explode += DEF_EXPLODE;
2349 glutPostRedisplay();
2352 explode -= DEF_EXPLODE;
2353 if (explode < 0.0) explode = 0.0;
2354 glutPostRedisplay();
2359 glc->next_model %= models;
2360 start_morph(glc->next_model, 0);
2362 /* Reset last_morph time */
2363 gettime(&glc->last_morph);
2366 /* previous model */
2367 glc->next_model = (glc->next_model + (int)models - 1) % (int)models;
2368 start_morph(glc->next_model, 0);
2370 /* Reset glc->last_morph time */
2371 gettime(&glc->last_morph);
2374 angvel += DEF_ANGVEL;
2377 if (angvel > DEF_ANGVEL)
2378 angvel -= DEF_ANGVEL;
2382 /* Reset last_iteration and last_morph time */
2383 gettime(&glc->last_iteration);
2384 gettime(&glc->last_morph);
2386 interactive = 1 - interactive;
2387 glutPostRedisplay();
2390 wireframe = 1 - wireframe;
2392 glDisable(GL_LIGHTING);
2394 glEnable(GL_LIGHTING);
2395 glutPostRedisplay();
2398 transparent = 1 - transparent;
2402 glDisable(GL_BLEND);
2407 /* unpausing, reset last_iteration and last_morph time */
2408 gettime(&glc->last_iteration);
2409 gettime(&glc->last_morph);
2411 glc->paused = 1 - glc->paused;
2414 /* dump the current model so we can add it! */
2415 printf("# %s\nnoname:\t", model[glc->next_model].name);
2419 for (i = 0; i < NODE_COUNT; i++) {
2420 if (glc->node[i] == ZERO)
2422 else if (glc->node[i] == LEFT)
2424 else if (glc->node[i] == PIN)
2426 else if (glc->node[i] == RIGHT)
2430 printf("%f", node[i].curAngle);
2432 if (i < NODE_COUNT - 1)
2439 glc->fullscreen = 1 - glc->fullscreen;
2440 if (glc->fullscreen) {
2441 glc->old_width = glc->width;
2442 glc->old_height = glc->height;
2445 glutReshapeWindow(glc->old_width, glc->old_height);
2446 glutPositionWindow(50,50);
2450 titles = 1 - titles;
2451 if (interactive || glc->paused)
2452 glutPostRedisplay();
2455 altcolour = 1 - altcolour;
2459 glsnake_reshape(glc->width, glc->height);
2463 glsnake_reshape(glc->width, glc->height);
2470 void ui_special(int key, int x __attribute__((__unused__)), int y __attribute__((__unused__))) {
2471 float *destAngle = &(model[glc->next_model].node[glc->selected]);
2472 int unknown_key = 0;
2477 glc->selected = (glc->selected + (NODE_COUNT - 2)) % (NODE_COUNT - 1);
2480 glc->selected = (glc->selected + 1) % (NODE_COUNT - 1);
2483 *destAngle = fmod(*destAngle+(LEFT), 360);
2484 glc->morphing = glc->new_morph = 1;
2486 case GLUT_KEY_RIGHT:
2487 *destAngle = fmod(*destAngle+(RIGHT), 360);
2488 glc->morphing = glc->new_morph = 1;
2491 start_morph(STRAIGHT_MODEL, 0);
2498 calc_snake_metrics();
2501 glutPostRedisplay();
2504 void ui_mouse(int button, int state, int x, int y) {
2509 mouse_start[0] = M_SQRT1_2 *
2510 (x - (glc->width / 2.0)) / (glc->width / 2.0);
2511 mouse_start[1] = M_SQRT1_2 *
2512 ((glc->height / 2.0) - y) / (glc->height / 2.0);
2513 mouse_start[2] = sqrt((double)(1-(mouse_start[0]*mouse_start[0]+mouse_start[1]*mouse_start[1])));
2517 oldquat[0] = cumquat[0];
2518 oldquat[1] = cumquat[1];
2519 oldquat[2] = cumquat[2];
2520 oldquat[3] = cumquat[3];
2526 glutPostRedisplay();
2529 void ui_motion(int x, int y) {
2534 /* construct the motion end vector from the x,y position on the
2536 mouse_end[0] = M_SQRT1_2 * (x - (glc->width/ 2.0)) / (glc->width / 2.0);
2537 mouse_end[1] = M_SQRT1_2 * ((glc->height / 2.0) - y) / (glc->height / 2.0);
2538 /* calculate the normal of the vector... */
2539 norm = mouse_end[0] * mouse_end[0] + mouse_end[1] * mouse_end[1];
2540 /* check if norm is outside the sphere and wraparound if necessary */
2542 mouse_end[0] = -mouse_end[0];
2543 mouse_end[1] = -mouse_end[1];
2544 mouse_end[2] = sqrt(norm - 1);
2546 /* the z value comes from projecting onto an elliptical spheroid */
2547 mouse_end[2] = sqrt(1 - norm);
2550 /* now here, build a quaternion from mouse_start and mouse_end */
2551 q[0] = mouse_start[1] * mouse_end[2] - mouse_start[2] * mouse_end[1];
2552 q[1] = mouse_start[2] * mouse_end[0] - mouse_start[0] * mouse_end[2];
2553 q[2] = mouse_start[0] * mouse_end[1] - mouse_start[1] * mouse_end[0];
2554 q[3] = mouse_start[0] * mouse_end[0] + mouse_start[1] * mouse_end[1] + mouse_start[2] * mouse_end[2];
2556 /* new rotation is the product of the new one and the old one */
2557 cumquat[0] = q[3] * oldquat[0] + q[0] * oldquat[3] +
2558 q[1] * oldquat[2] - q[2] * oldquat[1];
2559 cumquat[1] = q[3] * oldquat[1] + q[1] * oldquat[3] +
2560 q[2] * oldquat[0] - q[0] * oldquat[2];
2561 cumquat[2] = q[3] * oldquat[2] + q[2] * oldquat[3] +
2562 q[0] * oldquat[1] - q[1] * oldquat[0];
2563 cumquat[3] = q[3] * oldquat[3] - q[0] * oldquat[0] -
2564 q[1] * oldquat[1] - q[2] * oldquat[2];
2568 glutPostRedisplay();
2571 void ui_init(int * argc, char ** argv) {
2572 glutInit(argc, argv);
2573 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
2574 glutInitWindowSize(glc->width, glc->height);
2575 glc->window = glutCreateWindow("glsnake");
2577 glutDisplayFunc(glsnake_display);
2578 glutReshapeFunc(glsnake_reshape);
2579 glutIdleFunc(glsnake_idle);
2580 glutKeyboardFunc(ui_keyboard);
2581 glutSpecialFunc(ui_special);
2582 glutMouseFunc(ui_mouse);
2583 glutMotionFunc(ui_motion);
2585 yangvel = DEF_YANGVEL;
2586 zangvel = DEF_ZANGVEL;
2587 explode = DEF_EXPLODE;
2588 angvel = DEF_ANGVEL;
2589 statictime = DEF_STATICTIME;
2590 altcolour = DEF_ALTCOLOUR;
2591 titles = DEF_TITLES;
2592 interactive = DEF_INTERACTIVE;
2594 wireframe = DEF_WIREFRAME;
2595 transparent = DEF_TRANSPARENT;
2597 #endif /* HAVE_GLUT */