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 */
32 # define HAVE_GETTIMEOFDAY
41 #endif /* HAVE_JWZGLES */
44 # include "xlockmoreI.h"
58 #ifdef HAVE_GETTIMEOFDAY
59 # ifdef GETTIMEOFDAY_TWO_ARGS
61 # include <sys/time.h>
63 typedef struct timeval snaketime;
64 # define GETSECS(t) ((t).tv_sec)
65 # define GETMSECS(t) ((t).tv_usec/1000)
67 # else /* !GETTIMEOFDAY_TWO_ARGS */
69 # include <sys/time.h>
71 typedef struct timeval snaketime;
72 # define GETSECS(t) ((t).tv_sec)
73 # define GETMSECS(t) ((t).tv_usec/1000)
75 # endif /* GETTIMEOFDAY_TWO_ARGS */
77 #else /* !HAVE_GETTIMEOFDAY */
80 # include <sys/timeb.h>
81 typedef struct timeb snaketime;
82 # define GETSECS(t) ((long)(t).time)
83 # define GETMSECS(t) ((t).millitm/1000)
85 # endif /* HAVE_FTIME */
86 #endif /* HAVE_GETTIMEOFDAY */
90 #ifndef M_SQRT1_2 /* Win32 doesn't have this constant */
91 #define M_SQRT1_2 0.70710678118654752440084436210485
97 #define DEF_YANGVEL 0.10
98 #define DEF_ZANGVEL 0.14
99 #define DEF_EXPLODE 0.03
100 #define DEF_ANGVEL 1.0
101 #define DEF_STATICTIME 5000
102 #define DEF_ALTCOLOUR 0
104 #define DEF_INTERACTIVE 0
105 #define DEF_ZOOM 25.0
106 #define DEF_WIREFRAME 0
107 #define DEF_TRANSPARENT 1
109 /* xscreensaver options doobies prefer strings */
110 #define DEF_YANGVEL "0.10"
111 #define DEF_ZANGVEL "0.14"
112 #define DEF_EXPLODE "0.03"
113 #define DEF_ANGVEL "1.0"
114 #define DEF_STATICTIME "5000"
115 #define DEF_ALTCOLOUR "False"
116 #define DEF_TITLES "False"
117 #define DEF_INTERACTIVE "False"
118 #define DEF_ZOOM "25.0"
119 #define DEF_WIREFRAME "False"
120 #define DEF_TRANSPARENT "True"
123 /* static variables */
125 static GLfloat explode;
126 static long statictime;
127 static GLfloat yspin = 60.0;
128 static GLfloat zspin = -45.0;
129 static GLfloat yangvel;
130 static GLfloat zangvel;
131 static Bool altcolour;
133 static Bool interactive;
134 static Bool wireframe;
135 static Bool transparent;
137 static GLfloat angvel;
141 #define glsnake_init init_glsnake
142 #define glsnake_display draw_glsnake
143 #define glsnake_reshape reshape_glsnake
144 #define refresh_glsnake 0
145 #define release_glsnake 0
146 #define glsnake_handle_event 0
148 /* xscreensaver defaults */
149 #define DEFAULTS "*delay: 30000 \n" \
151 "*showFPS: False \n" \
152 "*labelfont: -*-helvetica-medium-r-normal-*-180-*\n" \
157 #define countof(x) (sizeof((x))/sizeof((*x)))
159 #include "xlockmore.h"
160 #include "glxfonts.h"
162 static XrmOptionDescRec opts[] = {
163 { "-explode", ".explode", XrmoptionSepArg, DEF_EXPLODE },
164 { "-angvel", ".angvel", XrmoptionSepArg, DEF_ANGVEL },
165 { "-statictime", ".statictime", XrmoptionSepArg, DEF_STATICTIME },
166 { "-yangvel", ".yangvel", XrmoptionSepArg, DEF_YANGVEL },
167 { "-zangvel", ".zangvel", XrmoptionSepArg, DEF_ZANGVEL },
168 { "-altcolour", ".altcolour", XrmoptionNoArg, "True" },
169 { "-no-altcolour", ".altcolour", XrmoptionNoArg, "False" },
170 { "-titles", ".titles", XrmoptionNoArg, "True" },
171 { "-no-titles", ".titles", XrmoptionNoArg, "False" },
172 { "-zoom", ".zoom", XrmoptionSepArg, DEF_ZOOM },
173 { "-wireframe", ".wireframe", XrmoptionNoArg, "true" },
174 { "-no-wireframe", ".wireframe", XrmoptionNoArg, "false" },
175 { "-transparent", ".transparent", XrmoptionNoArg, "true" },
176 { "-no-transparent", ".transparent", XrmoptionNoArg, "false" },
179 static argtype vars[] = {
180 {&explode, "explode", "Explode", DEF_EXPLODE, t_Float},
181 {&angvel, "angvel", "Angular Velocity", DEF_ANGVEL, t_Float},
182 {&statictime, "statictime", "Static Time", DEF_STATICTIME, t_Int},
183 {&yangvel, "yangvel", "Angular Velocity about Y axis", DEF_YANGVEL, t_Float},
184 {&zangvel, "zangvel", "Angular Velocity about X axis", DEF_ZANGVEL, t_Float},
185 {&interactive, "interactive", "Interactive", DEF_INTERACTIVE, t_Bool},
186 {&altcolour, "altcolour", "Alternate Colour Scheme", DEF_ALTCOLOUR, t_Bool},
187 {&titles, "titles", "Titles", DEF_TITLES, t_Bool},
188 {&zoom, "zoom", "Zoom", DEF_ZOOM, t_Float},
189 {&wireframe, "wireframe", "Wireframe", DEF_WIREFRAME, t_Bool},
190 {&transparent, "transparent", "Transparent!", DEF_TRANSPARENT, t_Bool},
193 ENTRYPOINT ModeSpecOpt glsnake_opts = {countof(opts), opts, countof(vars), vars, NULL};
198 float node[NODE_COUNT];
203 GLXContext * glx_context;
204 # ifdef HAVE_GLBITMAP
208 texture_font_data *font_data;
211 /* font list number */
218 /* is a morph in progress? */
221 /* has the model been paused? */
230 /* the shape of the model */
231 float node[NODE_COUNT];
233 /* currently selected node for interactive mode */
237 unsigned int prev_model;
238 unsigned int next_model;
248 /* timing variables */
249 snaketime last_iteration;
250 snaketime last_morph;
254 int old_width, old_height;
256 /* the id of the display lists for drawing a node */
257 GLuint node_solid, node_wire;
260 /* is the window fullscreen? */
264 #define COLOUR_CYCLIC 0
265 #define COLOUR_ACYCLIC 1
266 #define COLOUR_INVALID 2
267 #define COLOUR_AUTHENTIC 3
268 #define COLOUR_ORIGLOGO 4
270 static const float colour[][2][4] = {
272 { { 0.4, 0.8, 0.2, 0.6 },
273 { 1.0, 1.0, 1.0, 0.6 } },
275 { { 0.3, 0.1, 0.9, 0.6 },
276 { 1.0, 1.0, 1.0, 0.6 } },
278 { { 0.3, 0.1, 0.9, 0.6 },
279 { 1.0, 1.0, 1.0, 0.6 } },
280 /* authentic - purple and green */
281 { { 0.38, 0.0, 0.55, 0.7 },
282 { 0.0, 0.5, 0.34, 0.7 } },
283 /* old "authentic" colours from the logo */
284 { { 171/255.0, 0, 1.0, 1.0 },
285 { 46/255.0, 205/255.0, 227/255.0, 1.0 } }
288 static const struct model_s model[] = {
289 #define STRAIGHT_MODEL 0
291 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
292 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
295 /* the models in the Rubik's snake manual */
297 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT,
298 RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT,
299 RIGHT, LEFT, RIGHT, LEFT, ZERO }
301 #define START_MODEL 2
303 { RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT,
304 RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT,
305 RIGHT, LEFT, LEFT, LEFT, ZERO }
308 { ZERO, ZERO, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO, ZERO,
309 ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO, ZERO, ZERO, RIGHT,
310 LEFT, RIGHT, ZERO, LEFT }
313 { ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, RIGHT, PIN,
314 RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, ZERO, ZERO,
318 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN,
319 ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
323 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, LEFT, RIGHT, PIN, RIGHT,
324 ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, LEFT, ZERO,
327 /* These models were taken from Andrew and Peter's original snake.c
328 * as well as some newer ones made up by Jamie, Andrew and Peter. */
330 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT,
331 LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT,
332 RIGHT, LEFT, LEFT, LEFT, ZERO }
335 { RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT,
336 LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT,
337 RIGHT, RIGHT, LEFT, LEFT, ZERO }
340 { PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN,
341 ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN,
345 { PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN,
346 LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN,
350 { RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT,
351 LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN,
355 { RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT,
356 LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT,
357 RIGHT, RIGHT, LEFT, LEFT, ZERO }
360 { ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT,
361 LEFT, RIGHT, LEFT, LEFT, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT,
362 RIGHT, RIGHT, RIGHT, ZERO }
365 { RIGHT, PIN, ZERO, ZERO, PIN, LEFT, ZERO, LEFT, LEFT, ZERO,
366 LEFT, PIN, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO,
370 { PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT,
371 LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT,
372 RIGHT, LEFT, LEFT, ZERO }
375 { ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO,
376 ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO,
377 LEFT, ZERO, ZERO, RIGHT }
380 { ZERO, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO, RIGHT, ZERO, ZERO,
381 LEFT, RIGHT, ZERO, LEFT, ZERO, RIGHT, ZERO, ZERO, LEFT, RIGHT,
382 ZERO, LEFT, ZERO, RIGHT }
385 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO,
386 ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO,
387 ZERO, ZERO, LEFT, RIGHT }
390 { ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT,
391 RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN,
395 { ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN,
396 PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN }
399 { PIN, RIGHT, LEFT, PIN, LEFT, PIN, ZERO, ZERO, RIGHT, PIN, LEFT,
400 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
404 { ZERO, ZERO, ZERO, ZERO, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT,
405 ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT,
406 LEFT, ZERO, PIN, ZERO }
409 { RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO,
410 LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, PIN, RIGHT,
414 { ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN,
415 ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO }
418 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, LEFT, PIN,
419 RIGHT, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT,
420 RIGHT, LEFT, LEFT, ZERO }
423 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, ZERO, ZERO,
424 RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO, LEFT, LEFT,
425 RIGHT, LEFT, RIGHT, RIGHT, ZERO }
428 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, PIN, ZERO, ZERO,
429 LEFT, PIN, RIGHT, ZERO, ZERO, PIN, ZERO, LEFT, LEFT, RIGHT, LEFT,
433 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO,
434 RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT,
438 { LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT,
439 ZERO, ZERO, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN,
443 { RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN,
444 LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT,
448 { RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN,
449 LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT,
450 LEFT, PIN, LEFT, PIN }
453 { ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN,
454 ZERO, PIN, ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT,
458 { ZERO, PIN, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, PIN,
459 ZERO, PIN, ZERO, PIN, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO,
463 { ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN,
464 ZERO, PIN, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
468 { ZERO, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT,
469 ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
473 { ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO,
474 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
478 { ZERO, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, ZERO,
479 ZERO, PIN, ZERO, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO,
483 { RIGHT, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, ZERO,
484 LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT,
485 ZERO, ZERO, LEFT, PIN }
488 { RIGHT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT,
489 ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT,
490 LEFT, RIGHT, ZERO, LEFT, PIN }
493 { RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO,
494 LEFT, PIN, RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT,
498 { ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, ZERO,
499 ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT,
503 { ZERO, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN,
504 RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT,
508 { LEFT, PIN, LEFT, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, LEFT,
509 PIN, RIGHT, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN,
513 { RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, ZERO,
514 ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, RIGHT, RIGHT, LEFT,
515 RIGHT, LEFT, LEFT, LEFT, PIN }
518 { ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, RIGHT,
519 RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT,
520 PIN, LEFT, LEFT, LEFT }
523 { PIN, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, LEFT,
524 ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, LEFT, ZERO,
525 LEFT, RIGHT, ZERO, ZERO }
528 { PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, RIGHT,
529 RIGHT, PIN, RIGHT, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO,
530 ZERO, PIN, PIN, ZERO }
533 /* the following modesl were created during the slug/compsoc codefest
535 { "cool looking gegl",
536 { PIN, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT,
537 ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, ZERO,
541 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN,
542 PIN, ZERO, RIGHT, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO,
546 { RIGHT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT,
547 RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN,
548 RIGHT, LEFT, RIGHT, PIN, ZERO }
551 { ZERO, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO,
552 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
556 { LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO,
557 RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT,
558 RIGHT, ZERO, LEFT, ZERO }
560 { "not very good (but accurate) gegl",
561 { ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO,
562 PIN, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO, PIN, PIN, ZERO,
566 { ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
567 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO,
571 { PIN, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
572 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO,
575 { "erect penis", /* thanks benno */
576 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, PIN,
577 PIN, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
581 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, PIN,
582 PIN, ZERO, ZERO, ZERO, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
586 { RIGHT, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO,
587 LEFT, ZERO, ZERO, ZERO, LEFT, ZERO, LEFT, PIN, LEFT, PIN, RIGHT,
591 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN,
592 ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO,
595 { "poles or columns or something",
596 { LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
597 ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
601 { ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
602 ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
606 { ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO,
607 LEFT, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
611 { ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO,
612 LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO,
613 LEFT, PIN, ZERO, ZERO }
616 { ZERO, ZERO, PIN, RIGHT, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO,
617 LEFT, PIN, ZERO, ZERO, PIN, ZERO, LEFT, ZERO, RIGHT, LEFT, ZERO,
621 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
622 RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
626 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
627 ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
631 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
632 LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
636 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
637 PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
641 { RIGHT, ZERO, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT,
642 RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT,
643 ZERO, ZERO, RIGHT, ZERO }
646 { RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT,
647 ZERO, RIGHT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, ZERO,
648 RIGHT, ZERO, RIGHT, ZERO, ZERO }
651 /* These models come from the website at
652 * http://www.geocities.com/stigeide/snake */
655 { RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO }
659 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, ZERO }
662 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, ZERO }
665 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, ZERO }
668 { ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, ZERO, ZERO }
671 { RIGHT, LEFT, RIGHT, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO, PIN, PIN, ZERO }
674 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO }
677 { LEFT, PIN, RIGHT, ZERO, ZERO, PIN, RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO }
680 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT , ZERO }
683 { ZERO, RIGHT, RIGHT, ZERO, RIGHT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, ZERO, LEFT , ZERO }
686 { PIN, LEFT, RIGHT, ZERO, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, LEFT, RIGHT, PIN, RIGHT , ZERO }
689 { PIN, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, PIN , ZERO }
692 { LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT , ZERO }
695 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT , ZERO }
698 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, PIN , ZERO }
701 { PIN, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, ZERO , ZERO }
704 { RIGHT, ZERO, PIN, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, ZERO, ZERO, LEFT , ZERO }
707 { LEFT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT , ZERO }
710 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO , ZERO }
713 { RIGHT, ZERO, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO , ZERO }
716 { PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO , ZERO }
719 { RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, LEFT, RIGHT, LEFT, LEFT , ZERO }
722 { RIGHT, RIGHT, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, LEFT, LEFT , ZERO }
725 { RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT , ZERO }
728 { ZERO, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, LEFT, ZERO, LEFT, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT , ZERO }
732 { LEFT, ZERO, PIN, ZERO, PIN, LEFT, ZERO, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, PIN, ZERO, RIGHT , ZERO }
736 { ZERO, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, LEFT , ZERO }
739 { ZERO, ZERO, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN , ZERO }
742 { LEFT, PIN, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO , ZERO }
745 { ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN , ZERO }
748 { PIN, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO , ZERO }
751 { LEFT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT , ZERO }
754 { PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, RIGHT, PIN , ZERO }
757 { RIGHT, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, LEFT , ZERO }
760 { ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO, PIN , ZERO }
762 { "Counterclockwise",
763 { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT , ZERO }
766 { LEFT, LEFT, ZERO, PIN, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, RIGHT, LEFT, LEFT, ZERO, ZERO, RIGHT , ZERO }
769 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, PIN, RIGHT , ZERO }
772 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN , ZERO }
775 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO , ZERO }
778 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, ZERO }
781 { PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, ZERO }
784 { RIGHT, LEFT, PIN, LEFT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, LEFT, PIN, LEFT, RIGHT, ZERO }
787 { LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, PIN, ZERO, ZERO }
790 { RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, ZERO }
793 { ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO }
796 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, LEFT, RIGHT, ZERO }
799 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, LEFT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, RIGHT, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
802 { ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, LEFT, ZERO, PIN, ZERO, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, ZERO }
805 { ZERO, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO }
808 { ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO }
811 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO }
814 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO, RIGHT, ZERO, RIGHT, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO }
817 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, RIGHT, ZERO, RIGHT, LEFT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO }
820 { PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, ZERO }
823 { PIN, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO }
826 { ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO }
829 { LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, ZERO }
832 { LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, ZERO }
835 { RIGHT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, ZERO }
838 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, ZERO }
841 { ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO }
844 { LEFT, LEFT, RIGHT, PIN, ZERO, RIGHT, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, LEFT, ZERO, PIN, LEFT, RIGHT, RIGHT, RIGHT, PIN, ZERO }
847 { PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
850 { ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, RIGHT, ZERO, PIN, ZERO }
853 { ZERO, RIGHT, ZERO, PIN, LEFT, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, RIGHT, PIN, ZERO, LEFT, ZERO, ZERO }
856 { ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, ZERO, ZERO, ZERO, PIN, ZERO }
859 { ZERO, PIN, PIN, ZERO, PIN, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO }
862 { ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO }
865 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO }
868 { LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, RIGHT, LEFT, RIGHT, RIGHT, ZERO }
871 { LEFT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, ZERO, RIGHT, ZERO }
874 { PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO }
877 { ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO }
880 { LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO }
883 { RIGHT, LEFT, ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, LEFT, ZERO, ZERO }
886 { PIN, PIN, ZERO, LEFT, RIGHT, LEFT, ZERO, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO }
889 { PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO }
892 { PIN, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO }
895 { RIGHT, ZERO, ZERO, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, RIGHT, ZERO, PIN, ZERO, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO, ZERO, ZERO, LEFT, ZERO }
898 { ZERO, PIN, ZERO, ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO }
901 { ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO }
903 { "HoleInTheMiddle1",
904 { ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO }
906 { "HoleInTheMiddle2",
907 { ZERO, LEFT, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO }
910 { RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, ZERO }
913 { LEFT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, ZERO }
916 { LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO }
919 { RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
922 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO }
925 { RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, LEFT, ZERO }
928 { ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO }
931 { LEFT, LEFT, PIN, LEFT, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, RIGHT, PIN, RIGHT, RIGHT, LEFT, ZERO }
934 { ZERO, PIN, PIN, ZERO, ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO }
937 { RIGHT, PIN, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, PIN, LEFT, ZERO }
940 { PIN, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO }
943 { PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, ZERO }
945 { "magnifying glass",
946 { ZERO, ZERO, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, ZERO }
949 { ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, ZERO }
952 { PIN, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO }
955 { PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO }
958 { ZERO, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, LEFT, PIN, RIGHT, RIGHT, ZERO, RIGHT, ZERO }
961 { ZERO, RIGHT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, ZERO, RIGHT, RIGHT, PIN, LEFT, ZERO }
964 { LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
967 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, LEFT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO }
970 { ZERO, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO }
972 { "MouseWithoutTail",
973 { ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO }
976 { PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, ZERO }
979 { ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO }
982 { LEFT, ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, ZERO }
985 { ZERO, RIGHT, PIN, LEFT, LEFT, LEFT, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO }
988 { LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, ZERO }
991 { PIN, ZERO, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, ZERO, ZERO }
994 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, ZERO }
997 { PIN, PIN, ZERO, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
1000 { ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
1003 { ZERO, ZERO, ZERO, ZERO, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO }
1006 { PIN, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, PIN, ZERO }
1008 { "PictureComingSoon",
1009 { LEFT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, RIGHT, RIGHT, ZERO }
1012 { LEFT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, ZERO }
1015 { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, ZERO }
1018 { RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO }
1021 { ZERO, PIN, ZERO, PIN, RIGHT, PIN, ZERO, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, ZERO, PIN, LEFT, ZERO }
1025 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO }
1029 { RIGHT, PIN, ZERO, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, PIN, ZERO, PIN, LEFT, ZERO }
1032 { ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, ZERO }
1035 { ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, LEFT, ZERO }
1037 { "QuarterbackTiltedAndReadyToHut",
1038 { PIN, ZERO, RIGHT, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, LEFT, ZERO, PIN, ZERO }
1041 { PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1044 { LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, PIN, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, ZERO }
1047 { ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, ZERO }
1050 { LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, ZERO }
1053 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1056 { RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, ZERO }
1059 { ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO }
1062 { PIN, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, PIN, ZERO }
1065 { RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1068 { RIGHT, LEFT, PIN, ZERO, ZERO, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO }
1071 { LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO }
1074 { RIGHT, PIN, ZERO, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO }
1077 { RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, ZERO }
1080 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO }
1083 { PIN, RIGHT, LEFT, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, LEFT, ZERO, PIN, PIN, ZERO }
1086 { LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO }
1089 { LEFT, RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, RIGHT, LEFT, ZERO }
1092 { ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO }
1094 { "SnakeReadyToStrike",
1095 { LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO }
1098 { RIGHT, RIGHT, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO }
1101 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO }
1104 { PIN, PIN, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
1107 { LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, ZERO }
1110 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO }
1113 { PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, ZERO }
1116 { PIN, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, PIN, ZERO }
1119 { PIN, PIN, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, LEFT, LEFT, PIN, PIN, ZERO }
1122 { LEFT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, ZERO }
1125 { PIN, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, ZERO, RIGHT, PIN, LEFT, ZERO }
1128 { RIGHT, RIGHT, ZERO, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, RIGHT, LEFT, RIGHT, ZERO, ZERO, LEFT, ZERO }
1131 { PIN, LEFT, ZERO, RIGHT, RIGHT, LEFT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, LEFT, LEFT, ZERO, ZERO }
1134 { ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, ZERO }
1137 { PIN, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO }
1140 { RIGHT, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, ZERO }
1143 { ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO }
1146 { ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
1149 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO }
1152 { ZERO, PIN, ZERO, PIN, LEFT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, ZERO }
1155 { PIN, ZERO, PIN, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO }
1158 { PIN, PIN, ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO }
1161 { RIGHT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, RIGHT, ZERO }
1164 { RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO }
1167 { ZERO, PIN, LEFT, LEFT, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1170 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, RIGHT, PIN, ZERO }
1173 { ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO }
1176 { ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO }
1179 { RIGHT, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, ZERO }
1182 { RIGHT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO }
1185 { RIGHT, LEFT, ZERO, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO }
1188 { PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO }
1191 { RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, PIN, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO }
1194 { RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, ZERO }
1197 { ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, LEFT, LEFT, PIN, ZERO, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, ZERO }
1200 { PIN, LEFT, LEFT, PIN, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO }
1203 { PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO }
1206 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO }
1209 { PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, ZERO }
1213 { RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO }
1217 { ZERO, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO, ZERO }
1220 { ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, ZERO }
1223 { PIN, LEFT, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, ZERO, ZERO }
1226 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1229 { LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO }
1232 { ZERO, PIN, ZERO, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, ZERO }
1235 { ZERO, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, ZERO }
1238 { PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO }
1241 { ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO }
1244 { PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, PIN, RIGHT, ZERO, RIGHT, RIGHT, ZERO, RIGHT, PIN, ZERO, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, ZERO }
1247 { ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1250 { LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO }
1253 { PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO }
1256 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO }
1258 { "WindowToTheWorld",
1259 { PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
1262 { PIN, PIN, ZERO, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, PIN, ZERO }
1265 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO }
1268 { RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO }
1271 { PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, ZERO }
1274 { ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO }
1277 { LEFT, ZERO, ZERO, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, ZERO, ZERO, ZERO }
1281 static size_t models = sizeof(model) / sizeof(struct model_s);
1283 #define VOFFSET 0.045
1289 /* the connecting string that holds the snake together */
1290 #define MAGICAL_RED_STRING 0
1292 #define GETSCALAR(vec,mask) ((vec)==(mask) ? 1 : ((vec)==-(mask) ? -1 : 0 ))
1295 # define MAX(x, y) ((x) > (y) ? (x) : (y))
1298 # define MIN(x, y) ((x) < (y) ? (x) : (y))
1301 #define RAND(n) ((random() & 0x7fffffff) % ((long) (n)))
1302 #define RANDSIGN() ((random() & 1) ? 1 : -1)
1304 /* the triangular prism what makes up the basic unit */
1305 static const float solid_prism_v[][3] = {
1306 /* first corner, bottom left front */
1307 { VOFFSET, VOFFSET, 1.0 },
1308 { VOFFSET, 0.00, 1.0 - VOFFSET },
1309 { 0.00, VOFFSET, 1.0 - VOFFSET },
1310 /* second corner, rear */
1311 { VOFFSET, VOFFSET, 0.00 },
1312 { VOFFSET, 0.00, VOFFSET },
1313 { 0.00, VOFFSET, VOFFSET },
1314 /* third, right front */
1315 { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 1.0 },
1316 { 1.0 - VOFFSET / M_SQRT1_2, 0.0, 1.0 - VOFFSET },
1317 { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, 1.0 - VOFFSET },
1318 /* fourth, right rear */
1319 { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 0.0 },
1320 { 1.0 - VOFFSET / M_SQRT1_2, 0.0, VOFFSET },
1321 { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, VOFFSET },
1322 /* fifth, upper front */
1323 { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 1.0 },
1324 { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, 1.0 - VOFFSET },
1325 { 0.0, 1.0 - VOFFSET / M_SQRT1_2, 1.0 - VOFFSET},
1326 /* sixth, upper rear */
1327 { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 0.0 },
1328 { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, VOFFSET },
1329 { 0.0, 1.0 - VOFFSET / M_SQRT1_2, VOFFSET }};
1331 static const float solid_prism_n[][3] = {/* corners */
1332 { -VOFFSET, -VOFFSET, VOFFSET },
1333 { VOFFSET, -VOFFSET, VOFFSET },
1334 { -VOFFSET, VOFFSET, VOFFSET },
1335 { -VOFFSET, -VOFFSET, -VOFFSET },
1336 { VOFFSET, -VOFFSET, -VOFFSET },
1337 { -VOFFSET, VOFFSET, -VOFFSET },
1339 { -VOFFSET, 0.0, VOFFSET },
1340 { 0.0, -VOFFSET, VOFFSET },
1341 { VOFFSET, VOFFSET, VOFFSET },
1342 { -VOFFSET, 0.0, -VOFFSET },
1343 { 0.0, -VOFFSET, -VOFFSET },
1344 { VOFFSET, VOFFSET, -VOFFSET },
1345 { -VOFFSET, -VOFFSET, 0.0 },
1346 { VOFFSET, -VOFFSET, 0.0 },
1347 { -VOFFSET, VOFFSET, 0.0 },
1351 { M_SQRT1_2, M_SQRT1_2, 0.0 },
1353 { 0.0, 0.0, -1.0 }};
1355 static const float wire_prism_v[][3] = {{ 0.0, 0.0, 1.0 },
1363 static const float wire_prism_n[][3] = {{ 0.0, 0.0, 1.0},
1365 { M_SQRT1_2, M_SQRT1_2, 0.0},
1370 static struct glsnake_cfg * glc = NULL;
1375 typedef float (*morphFunc)(long);
1378 /* forward definitions for GLUT functions */
1379 static void calc_rotation();
1380 static inline void ui_mousedrag();
1383 static const GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };
1384 static const GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
1385 static const GLfloat mat_specular[] = { 0.1, 0.1, 0.1, 1.0 };
1386 static const GLfloat mat_shininess[] = { 20.0 };
1388 static void gl_init(
1394 float light_pos[][3] = {{0.0, 10.0, 20.0}, {0.0, 20.0, -1.0}};
1395 float light_dir[][3] = {{0.0, -10.0,-20.0}, {0.0,-20.0, 1.0}};
1397 glEnable(GL_DEPTH_TEST);
1398 glShadeModel(GL_SMOOTH);
1399 glCullFace(GL_BACK);
1400 /*glEnable(GL_CULL_FACE);*/
1401 glEnable(GL_NORMALIZE);
1403 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1408 /*glColor4f(1.0, 1.0, 1.0, 1.0);*/
1409 glLightfv(GL_LIGHT0, GL_POSITION, light_pos[0]);
1410 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_dir[0]);
1411 glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
1412 /*glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);*/
1414 glLightfv(GL_LIGHT1, GL_POSITION, light_pos[1]);
1415 glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light_dir[1]);
1416 glLightfv(GL_LIGHT1, GL_DIFFUSE, white_light);
1417 glLightfv(GL_LIGHT1, GL_SPECULAR, white_light);
1419 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
1420 glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
1421 glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
1422 glEnable(GL_LIGHTING);
1423 glEnable(GL_LIGHT0);
1424 glEnable(GL_LIGHT1);
1425 /*glEnable(GL_COLOR_MATERIAL);*/
1429 static void gettime(snaketime *t)
1431 #ifdef HAVE_GETTIMEOFDAY
1432 #ifdef GETTIMEOFDAY_TWO_ARGS
1433 struct timezone tzp;
1434 gettimeofday(t, &tzp);
1435 #else /* !GETTIMEOFDAY_TWO_ARGS */
1437 #endif /* !GETTIMEOFDAY_TWO_ARGS */
1438 #else /* !HAVE_GETTIMEOFDAY */
1441 #endif /* HAVE_FTIME */
1442 #endif /* !HAVE_GETTIMEOFDAY */
1446 ENTRYPOINT void glsnake_reshape(
1452 static void start_morph(struct glsnake_cfg *,
1453 unsigned int model_index, int immediate);
1455 /* wot initialises it */
1456 ENTRYPOINT void glsnake_init(
1463 struct glsnake_cfg * bp;
1465 /* set up the conf struct and glx contexts */
1467 glc = (struct glsnake_cfg *) calloc(MI_NUM_SCREENS(mi), sizeof(struct glsnake_cfg));
1469 fprintf(stderr, "%s: out of memory\n", progname);
1473 bp = &glc[MI_SCREEN(mi)];
1475 if ((bp->glx_context = init_GL(mi)) != NULL) {
1477 glsnake_reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1483 /* initialise conf struct */
1484 memset(&bp->node, 0, sizeof(float) * NODE_COUNT);
1494 gettime(&bp->last_iteration);
1495 memcpy(&bp->last_morph, &bp->last_iteration, sizeof(bp->last_morph));
1497 bp->prev_colour = bp->next_colour = COLOUR_ACYCLIC;
1498 bp->next_model = RAND(models);
1499 bp->prev_model = START_MODEL;
1500 start_morph(bp, bp->prev_model, 1);
1502 /* set up a font for the labels */
1505 # ifdef HAVE_GLBITMAP
1506 load_font(mi->dpy, "labelfont", &bp->font, &bp->font_list);
1508 bp->font_data = load_texture_font (mi->dpy, "labelFont");
1512 /* build a solid display list */
1513 bp->node_solid = glGenLists(1);
1514 glNewList(bp->node_solid, GL_COMPILE);
1516 glBegin(GL_TRIANGLES);
1517 glNormal3fv(solid_prism_n[0]);
1518 glVertex3fv(solid_prism_v[0]);
1519 glVertex3fv(solid_prism_v[2]);
1520 glVertex3fv(solid_prism_v[1]);
1523 glNormal3fv(solid_prism_n[1]);
1524 glVertex3fv(solid_prism_v[6]);
1525 glVertex3fv(solid_prism_v[7]);
1526 glVertex3fv(solid_prism_v[8]);
1529 glNormal3fv(solid_prism_n[2]);
1530 glVertex3fv(solid_prism_v[12]);
1531 glVertex3fv(solid_prism_v[13]);
1532 glVertex3fv(solid_prism_v[14]);
1535 glNormal3fv(solid_prism_n[3]);
1536 glVertex3fv(solid_prism_v[3]);
1537 glVertex3fv(solid_prism_v[4]);
1538 glVertex3fv(solid_prism_v[5]);
1541 glNormal3fv(solid_prism_n[4]);
1542 glVertex3fv(solid_prism_v[9]);
1543 glVertex3fv(solid_prism_v[11]);
1544 glVertex3fv(solid_prism_v[10]);
1547 glNormal3fv(solid_prism_n[5]);
1548 glVertex3fv(solid_prism_v[16]);
1549 glVertex3fv(solid_prism_v[15]);
1550 glVertex3fv(solid_prism_v[17]);
1556 glNormal3fv(solid_prism_n[6]);
1557 glVertex3fv(solid_prism_v[0]);
1558 glVertex3fv(solid_prism_v[12]);
1559 glVertex3fv(solid_prism_v[14]);
1560 glVertex3fv(solid_prism_v[2]);
1563 glNormal3fv(solid_prism_n[7]);
1564 glVertex3fv(solid_prism_v[0]);
1565 glVertex3fv(solid_prism_v[1]);
1566 glVertex3fv(solid_prism_v[7]);
1567 glVertex3fv(solid_prism_v[6]);
1570 glNormal3fv(solid_prism_n[8]);
1571 glVertex3fv(solid_prism_v[6]);
1572 glVertex3fv(solid_prism_v[8]);
1573 glVertex3fv(solid_prism_v[13]);
1574 glVertex3fv(solid_prism_v[12]);
1577 glNormal3fv(solid_prism_n[9]);
1578 glVertex3fv(solid_prism_v[3]);
1579 glVertex3fv(solid_prism_v[5]);
1580 glVertex3fv(solid_prism_v[17]);
1581 glVertex3fv(solid_prism_v[15]);
1584 glNormal3fv(solid_prism_n[10]);
1585 glVertex3fv(solid_prism_v[3]);
1586 glVertex3fv(solid_prism_v[9]);
1587 glVertex3fv(solid_prism_v[10]);
1588 glVertex3fv(solid_prism_v[4]);
1591 glNormal3fv(solid_prism_n[11]);
1592 glVertex3fv(solid_prism_v[15]);
1593 glVertex3fv(solid_prism_v[16]);
1594 glVertex3fv(solid_prism_v[11]);
1595 glVertex3fv(solid_prism_v[9]);
1598 glNormal3fv(solid_prism_n[12]);
1599 glVertex3fv(solid_prism_v[1]);
1600 glVertex3fv(solid_prism_v[2]);
1601 glVertex3fv(solid_prism_v[5]);
1602 glVertex3fv(solid_prism_v[4]);
1605 glNormal3fv(solid_prism_n[13]);
1606 glVertex3fv(solid_prism_v[8]);
1607 glVertex3fv(solid_prism_v[7]);
1608 glVertex3fv(solid_prism_v[10]);
1609 glVertex3fv(solid_prism_v[11]);
1612 glNormal3fv(solid_prism_n[14]);
1613 glVertex3fv(solid_prism_v[13]);
1614 glVertex3fv(solid_prism_v[16]);
1615 glVertex3fv(solid_prism_v[17]);
1616 glVertex3fv(solid_prism_v[14]);
1621 glBegin(GL_TRIANGLES);
1622 glNormal3fv(solid_prism_n[15]);
1623 glVertex3fv(solid_prism_v[0]);
1624 glVertex3fv(solid_prism_v[6]);
1625 glVertex3fv(solid_prism_v[12]);
1628 glNormal3fv(solid_prism_n[19]);
1629 glVertex3fv(solid_prism_v[3]);
1630 glVertex3fv(solid_prism_v[15]);
1631 glVertex3fv(solid_prism_v[9]);
1636 glNormal3fv(solid_prism_n[16]);
1637 glVertex3fv(solid_prism_v[1]);
1638 glVertex3fv(solid_prism_v[4]);
1639 glVertex3fv(solid_prism_v[10]);
1640 glVertex3fv(solid_prism_v[7]);
1643 glNormal3fv(solid_prism_n[17]);
1644 glVertex3fv(solid_prism_v[8]);
1645 glVertex3fv(solid_prism_v[11]);
1646 glVertex3fv(solid_prism_v[16]);
1647 glVertex3fv(solid_prism_v[13]);
1650 glNormal3fv(solid_prism_n[18]);
1651 glVertex3fv(solid_prism_v[2]);
1652 glVertex3fv(solid_prism_v[14]);
1653 glVertex3fv(solid_prism_v[17]);
1654 glVertex3fv(solid_prism_v[5]);
1659 /* build wire display list */
1660 bp->node_wire = glGenLists(1);
1661 glNewList(bp->node_wire, GL_COMPILE);
1662 glBegin(GL_LINE_STRIP);
1663 glVertex3fv(wire_prism_v[0]);
1664 glVertex3fv(wire_prism_v[1]);
1666 glVertex3fv(wire_prism_v[2]);
1667 glVertex3fv(wire_prism_v[0]);
1669 glVertex3fv(wire_prism_v[3]);
1670 glVertex3fv(wire_prism_v[4]);
1672 glVertex3fv(wire_prism_v[5]);
1673 glVertex3fv(wire_prism_v[3]);
1677 glVertex3fv(wire_prism_v[1]);
1678 glVertex3fv(wire_prism_v[4]);
1680 glVertex3fv(wire_prism_v[2]);
1681 glVertex3fv(wire_prism_v[5]);
1687 /* initialise the rotation */
1692 static void draw_title(
1699 struct glsnake_cfg * bp = &glc[MI_SCREEN(mi)];
1702 /* draw some text */
1704 /* glPushAttrib((GLbitfield) GL_TRANSFORM_BIT | GL_ENABLE_BIT);*/
1705 glDisable(GL_LIGHTING);
1706 glDisable(GL_DEPTH_TEST);
1708 glDisable(GL_BLEND);
1710 glMatrixMode(GL_PROJECTION);
1713 glMatrixMode(GL_MODELVIEW);
1717 glOrtho((GLdouble) 0., (GLdouble) bp->width, (GLdouble) 0., (GLdouble) bp->height, -1, 1);
1719 glOrtho((GLdouble) 0., (GLdouble) mi->xgwa.width, (GLdouble) 0., (GLdouble) mi->xgwa.height, -1, 1);
1722 glColor4f(1.0, 1.0, 1.0, 1.0);
1724 char interactstr[] = "interactive";
1733 s = model[bp->next_model].name;
1739 w = glutBitmapLength(GLUT_BITMAP_HELVETICA_12, (const unsigned char *) s);
1740 glRasterPos2f((GLfloat) (bp->width - w - 3), 4.0);
1741 while (s[i] != '\0')
1742 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, s[i++]);
1745 print_gl_string(mi->dpy,
1746 # ifdef HAVE_GLBITMAP
1747 bp->font, bp->font_list,
1751 mi->xgwa.width, mi->xgwa.height,
1752 10.0, (float) mi->xgwa.height - 10.0,
1757 glMatrixMode(GL_PROJECTION);
1764 /* apply the matrix to the origin and stick it in vec */
1765 static void matmult_origin(float rotmat[16], float vec[4])
1768 vec[0] = 0.5 * rotmat[0] + 0.5 * rotmat[4] + 0.5 * rotmat [8] + 1 * rotmat[12];
1769 vec[1] = 0.5 * rotmat[1] + 0.5 * rotmat[5] + 0.5 * rotmat [9] + 1 * rotmat[13];
1770 vec[2] = 0.5 * rotmat[2] + 0.5 * rotmat[6] + 0.5 * rotmat[10] + 1 * rotmat[14];
1771 vec[3] = 0.5 * rotmat[3] + 0.5 * rotmat[7] + 0.5 * rotmat[11] + 1 * rotmat[15];
1773 vec[0] = 0 * rotmat [0] + 0 * rotmat [1] + 0 * rotmat [2] + 1 * rotmat [3];
1774 vec[1] = 0 * rotmat [4] + 0 * rotmat [5] + 0 * rotmat [6] + 1 * rotmat [7];
1775 vec[2] = 0 * rotmat [8] + 0 * rotmat [9] + 0 * rotmat[10] + 1 * rotmat[11];
1776 vec[3] = 0 * rotmat[12] + 0 * rotmat[13] + 0 * rotmat[14] + 1 * rotmat[15];
1784 /* wot gets called when the winder is resized */
1785 ENTRYPOINT void glsnake_reshape(
1791 glViewport(0, 0, (GLint) w, (GLint) h);
1792 glMatrixMode(GL_PROJECTION);
1794 /* jwz: 0.05 was too close (left black rectangles) */
1795 gluPerspective(zoom, (GLdouble) w / (GLdouble) h, 1.0, 100.0);
1796 gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
1797 glMatrixMode(GL_MODELVIEW);
1798 /*gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);*/
1806 /* Returns the new dst_dir for the given src_dir and dst_dir */
1807 static int cross_product(int src_dir, int dst_dir)
1809 return X_MASK*(GETSCALAR(src_dir,Y_MASK) * GETSCALAR(dst_dir,Z_MASK) -
1810 GETSCALAR(src_dir,Z_MASK) * GETSCALAR(dst_dir,Y_MASK))+
1811 Y_MASK*(GETSCALAR(src_dir,Z_MASK) * GETSCALAR(dst_dir,X_MASK) -
1812 GETSCALAR(src_dir,X_MASK) * GETSCALAR(dst_dir,Z_MASK))+
1813 Z_MASK*(GETSCALAR(src_dir,X_MASK) * GETSCALAR(dst_dir,Y_MASK) -
1814 GETSCALAR(src_dir,Y_MASK) * GETSCALAR(dst_dir,X_MASK));
1817 /* calculate orthogonal snake metrics
1818 * is_legal = true if model does not pass through itself
1819 * is_cyclic = true if last node connects back to first node
1820 * last_turn = for cyclic snakes, specifes what the 24th turn would be
1822 static void calc_snake_metrics(struct glsnake_cfg *bp)
1826 int prevSrcDir = -Y_MASK;
1827 int prevDstDir = Z_MASK;
1828 int grid[25][25][25];
1831 memset(&grid, 0, sizeof(int) * 25*25*25);
1836 /* trace path of snake - and keep record for is_legal */
1837 for (i = 0; i < NODE_COUNT - 1; i++) {
1838 /*int ang_card;*/ /* cardinal direction of node angle */
1839 /* establish new state vars */
1840 srcDir = -prevDstDir;
1841 x += GETSCALAR(prevDstDir, X_MASK);
1842 y += GETSCALAR(prevDstDir, Y_MASK);
1843 z += GETSCALAR(prevDstDir, Z_MASK);
1845 switch ((int) model[bp->next_model].node[i]) {
1847 dstDir = -prevSrcDir;
1850 dstDir = prevSrcDir;
1854 dstDir = cross_product(prevSrcDir, prevDstDir);
1855 if (model[bp->next_model].node[i] == (int) (RIGHT))
1859 /* Prevent spurious "might be used
1860 * uninitialised" warnings when compiling
1866 if (grid[x][y][z] == 0)
1867 grid[x][y][z] = srcDir + dstDir;
1868 else if (grid[x][y][z] + srcDir + dstDir == 0)
1873 prevSrcDir = srcDir;
1874 prevDstDir = dstDir;
1877 /* determine if the snake is cyclic */
1878 bp->is_cyclic = (dstDir == Y_MASK && x == 12 && y == 11 && z == 12);
1880 /* determine last_turn */
1884 case -Z_MASK: bp->last_turn = ZERO; break;
1885 case Z_MASK: bp->last_turn = PIN; break;
1886 case X_MASK: bp->last_turn = LEFT; break;
1887 case -X_MASK: bp->last_turn = RIGHT; break;
1891 /* work out how far through the current morph we are */
1892 static float morph_percent(struct glsnake_cfg *bp)
1897 /* extend this function later with a case statement for each of the
1900 /* when morphing all nodes at once, the longest morph will be the node
1901 * that needs to rotate 180 degrees. For each node, work out how far it
1902 * has to go, and store the maximum rotation and current largest angular
1903 * difference, returning the angular difference over the maximum. */
1905 float rot_max = 0.0, ang_diff_max = 0.0;
1907 for (i = 0; i < NODE_COUNT - 1; i++) {
1908 float rot, ang_diff;
1910 /* work out the maximum rotation this node has to go through
1911 * from the previous to the next model, taking into account that
1912 * the snake always morphs through the smaller angle */
1913 rot = fabs(model[bp->prev_model].node[i] -
1914 model[bp->next_model].node[i]);
1915 if (rot > 180.0) rot = 180.0 - rot;
1916 /* work out the difference between the current position and the
1918 ang_diff = fabs(bp->node[i] -
1919 model[bp->next_model].node[i]);
1920 if (ang_diff > 180.0) ang_diff = 180.0 - ang_diff;
1921 /* if it's the biggest so far, record it */
1922 if (rot > rot_max) rot_max = rot;
1923 if (ang_diff > ang_diff_max) ang_diff_max = ang_diff;
1926 /* ang_diff / rot approaches 0, we want the complement */
1927 retval = 1.0 - (ang_diff_max / rot_max);
1928 /* protect against naan */
1930 /* Apparently some systems (Solaris) don't have isinf() */
1932 #define isinf(x) (((x) > 999999999999.9) || ((x) < -999999999999.9))
1934 if (isnan(retval) || isinf(retval)) retval = 1.0;
1936 /*printf("morph_pct = %f\n", retval);*/
1940 static void morph_colour(struct glsnake_cfg *bp)
1942 float percent, compct; /* complement of percentage */
1944 percent = morph_percent(bp);
1945 compct = 1.0 - percent;
1947 bp->colour[0][0] = colour[bp->prev_colour][0][0] * compct + colour[bp->next_colour][0][0] * percent;
1948 bp->colour[0][1] = colour[bp->prev_colour][0][1] * compct + colour[bp->next_colour][0][1] * percent;
1949 bp->colour[0][2] = colour[bp->prev_colour][0][2] * compct + colour[bp->next_colour][0][2] * percent;
1950 bp->colour[0][3] = colour[bp->prev_colour][0][3] * compct + colour[bp->next_colour][0][3] * percent;
1952 bp->colour[1][0] = colour[bp->prev_colour][1][0] * compct + colour[bp->next_colour][1][0] * percent;
1953 bp->colour[1][1] = colour[bp->prev_colour][1][1] * compct + colour[bp->next_colour][1][1] * percent;
1954 bp->colour[1][2] = colour[bp->prev_colour][1][2] * compct + colour[bp->next_colour][1][2] * percent;
1955 bp->colour[1][3] = colour[bp->prev_colour][1][3] * compct + colour[bp->next_colour][1][3] * percent;
1958 /* Start morph process to this model */
1959 static void start_morph(struct glsnake_cfg *bp,
1960 unsigned int model_index, int immediate)
1962 /* if immediate, don't bother morphing, go straight to the next model */
1966 for (i = 0; i < NODE_COUNT; i++)
1967 bp->node[i] = model[model_index].node[i];
1970 bp->prev_model = bp->next_model;
1971 bp->next_model = model_index;
1972 bp->prev_colour = bp->next_colour;
1974 calc_snake_metrics(bp);
1976 bp->next_colour = COLOUR_INVALID;
1978 bp->next_colour = COLOUR_AUTHENTIC;
1979 else if (bp->is_cyclic)
1980 bp->next_colour = COLOUR_CYCLIC;
1982 bp->next_colour = COLOUR_ACYCLIC;
1985 bp->colour[0][0] = colour[bp->next_colour][0][0];
1986 bp->colour[0][1] = colour[bp->next_colour][0][1];
1987 bp->colour[0][2] = colour[bp->next_colour][0][2];
1988 bp->colour[0][3] = colour[bp->next_colour][0][3];
1989 bp->colour[1][0] = colour[bp->next_colour][1][0];
1990 bp->colour[1][1] = colour[bp->next_colour][1][1];
1991 bp->colour[1][2] = colour[bp->next_colour][1][2];
1992 bp->colour[1][3] = colour[bp->next_colour][1][3];
2000 /* Returns morph progress */
2001 static float morph(long iter_msec)
2003 /* work out the maximum angle for this iteration */
2005 float iter_angle_max, largest_diff, largest_progress;
2011 iter_angle_max = 90.0 * (angvel/1000.0) * iter_msec;
2014 largest_diff = largest_progress = 0.0;
2015 for (i = 0; i < NODE_COUNT; i++) {
2016 float curAngle = bp->node[i];
2017 float destAngle = model[bp->next_model].node[i];
2018 if (curAngle != destAngle) {
2020 if (fabs(curAngle-destAngle) <= iter_angle_max)
2021 bp->node[i] = destAngle;
2022 else if (fmod(curAngle-destAngle+360,360) > 180)
2023 bp->node[i] = fmod(curAngle + iter_angle_max, 360);
2025 bp->node[i] = fmod(curAngle+360 - iter_angle_max, 360);
2026 largest_diff = MAX(largest_diff, fabs(destAngle-bp->node[i]));
2027 largest_progress = MAX(largest_diff, fabs(bp->node[i] - model[bp->prev_model].node[i]));
2031 return MIN(largest_diff / largest_progress, 1.0);
2037 static void glsnake_idle();
2039 static restore_idle(int v __attribute__((__unused__)))
2041 glutIdleFunc(glsnake_idle);
2045 static void quick_sleep(void)
2048 /* By using glutTimerFunc we can keep responding to
2049 * mouse and keyboard events, unlike using something like
2052 glutTimerFunc(1, restore_idle, 0);
2058 static void glsnake_idle(
2060 struct glsnake_cfg * bp
2064 /* time since last iteration */
2066 /* time since the beginning of last morph */
2068 float iter_angle_max;
2069 snaketime current_time;
2070 /* morphFunc transition; */
2074 /* Do nothing to the model if we are paused */
2076 /* Avoid busy waiting when nothing is changing */
2080 glutPostRedisplay();
2085 /* <spiv> Well, ftime gives time with millisecond resolution.
2086 * <spiv> (or worse, perhaps... who knows what the OS will do)
2087 * <spiv> So if no discernable amount of time has passed:
2088 * <spiv> a) There's no point updating the screen, because
2089 * it would be the same
2090 * <spiv> b) The code will divide by zero
2092 gettime(¤t_time);
2094 iter_msec = (long) GETMSECS(current_time) - GETMSECS(bp->last_iteration) +
2095 ((long) GETSECS(current_time) - GETSECS(bp->last_iteration)) * 1000L;
2098 /* save the current time */
2099 memcpy(&bp->last_iteration, ¤t_time, sizeof(snaketime));
2101 /* work out if we have to switch models */
2102 morf_msec = GETMSECS(bp->last_iteration) - GETMSECS(bp->last_morph) +
2103 ((long) (GETSECS(bp->last_iteration)-GETSECS(bp->last_morph)) * 1000L);
2105 if ((morf_msec > statictime) && !interactive && !bp->morphing) {
2106 /*printf("starting morph\n");*/
2107 memcpy(&bp->last_morph, &(bp->last_iteration), sizeof(bp->last_morph));
2108 start_morph(bp, RAND(models), 0);
2111 if (interactive && !bp->morphing) {
2116 /* if (!bp->dragging && !bp->interactive) { */
2119 yspin += 360/((1000/yangvel)/iter_msec);
2120 zspin += 360/((1000/zangvel)/iter_msec);
2122 yspin += 360 * (yangvel/1000.0) * iter_msec;
2123 zspin += 360 * (zangvel/1000.0) * iter_msec;
2126 /*printf("yspin: %f, zspin: %f\n", yspin, zspin);*/
2130 /* work out the maximum angle we could turn this node in this
2131 * timeslice, iter_msec milliseconds long */
2132 iter_angle_max = 90.0 * (angvel/1000.0) * iter_msec;
2135 for (i = 0; i < NODE_COUNT; i++) {
2136 float cur_angle = bp->node[i];
2137 float dest_angle = model[bp->next_model].node[i];
2138 if (cur_angle != dest_angle) {
2140 if (fabs(cur_angle - dest_angle) <= iter_angle_max)
2141 bp->node[i] = dest_angle;
2142 else if (fmod(cur_angle - dest_angle + 360, 360) > 180)
2143 bp->node[i] = fmod(cur_angle + iter_angle_max, 360);
2145 bp->node[i] = fmod(cur_angle + 360 - iter_angle_max, 360);
2149 if (!still_morphing)
2152 /* colour cycling */
2157 glutPostRedisplay();
2160 /* We are going too fast, so we may as well let the
2161 * cpu relax a little by sleeping for a millisecond. */
2167 ENTRYPOINT void glsnake_display(
2174 struct glsnake_cfg * bp = &glc[MI_SCREEN(mi)];
2175 Display * dpy = MI_DISPLAY(mi);
2176 Window window = MI_WINDOW(mi);
2181 float positions[NODE_COUNT][4]; /* origin points for each node */
2182 float com[4]; /* it's the CENTRE of MASS */
2185 if (!bp->glx_context)
2188 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
2193 /* clear the buffer */
2194 glClear((GLbitfield) GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2196 /* go into the modelview stack */
2197 glMatrixMode(GL_MODELVIEW);
2200 /* get the centre of each node, by moving through the snake and
2201 * performing the rotations, then grabbing the matrix at each point
2202 * and applying it to the origin */
2206 /* apply the mouse drag rotation */
2210 /* apply the continuous rotation */
2211 glRotatef(yspin, 0.0, 1.0, 0.0);
2212 glRotatef(zspin, 0.0, 0.0, 1.0);
2218 for (i = 0; i < NODE_COUNT; i++) {
2223 /*printf("ang = %f\n", ang);*/
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 */
2231 glGetFloatv(GL_MODELVIEW_MATRIX, rotmat);
2233 matmult_origin(rotmat, positions[i]);
2235 /*printf("positions %f %f %f %f\n", positions[i][0], positions[i][1], positions[i][2], positions[i][3]);*/
2237 com[0] += positions[i][0];
2238 com[1] += positions[i][1];
2239 com[2] += positions[i][2];
2240 com[3] += positions[i][3];
2243 com[0] /= NODE_COUNT;
2244 com[1] /= NODE_COUNT;
2245 com[2] /= NODE_COUNT;
2246 com[3] /= NODE_COUNT;
2252 /*printf("com: %f, %f, %f, %f\n", com[0], com[1], com[2], com[3]);*/
2254 #if MAGICAL_RED_STRING
2256 glTranslatef(-com[0], -com[1], -com[2]);
2258 glDisable(GL_LIGHTING);
2259 glColor4f(1.0, 0.0, 0.0, 1.0);
2260 glBegin(GL_LINE_STRIP);
2261 for (i = 0; i < NODE_COUNT - 1; i++) {
2262 glVertex3fv(positions[i]);
2265 glEnable(GL_LIGHTING);
2266 /*glTranslatef(com[0], com[1], com[2]);*/
2271 glTranslatef(-com[0], -com[1], -com[2]);
2274 /* apply the mouse drag rotation */
2278 /* apply the continuous rotation */
2279 glRotatef(yspin, 0.0, 1.0, 0.0);
2280 glRotatef(zspin, 0.0, 0.0, 1.0);
2282 /* now draw each node along the snake -- this is quite ugly :p */
2283 mi->polygon_count = 0;
2284 for (i = 0; i < NODE_COUNT; i++) {
2285 /* choose a colour for this node */
2286 if ((i == bp->selected || i == bp->selected+1) && interactive)
2288 glColor4f(1.0, 1.0, 0.0, 1.0);
2290 /*glColor4fv(bp->colour[(i+1)%2]);*/
2291 glMaterialfv(GL_FRONT, GL_AMBIENT, bp->colour[(i+1)%2]);
2292 glMaterialfv(GL_FRONT, GL_DIFFUSE, bp->colour[(i+1)%2]);
2293 /*glMaterialfv(GL_FRONT, GL_SPECULAR, bp->colour[(i+1)%2]);*/
2298 glCallList(bp->node_wire);
2300 glCallList(bp->node_solid);
2301 mi->polygon_count += bp->node_polys;
2303 /* now work out where to draw the next one */
2305 /* Interpolate between models */
2308 glTranslatef(0.5, 0.5, 0.5); /* move to center */
2309 glRotatef(90.0, 0.0, 0.0, -1.0); /* reorient */
2310 glTranslatef(1.0 + explode, 0.0, 0.0); /* move to new pos. */
2311 glRotatef(180.0 + ang, 1.0, 0.0, 0.0); /* pivot to new angle */
2312 glTranslatef(-0.5, -0.5, -0.5); /* return from center */
2326 if (mi->fps_p) do_fps(mi);
2333 glXSwapBuffers(dpy, window);
2338 /* anything that needs to be cleaned up goes here */
2339 static void unmain()
2341 glutDestroyWindow(bp->window);
2345 static void ui_init(int *, char **);
2347 int main(int argc, char ** argv)
2349 bp = malloc(sizeof(struct glsnake_cfg));
2350 memset(bp, 0, sizeof(struct glsnake_cfg));
2355 ui_init(&argc, argv);
2357 gettime(&bp->last_iteration);
2358 memcpy(&bp->last_morph, &bp->last_iteration, sizeof(snaketime));
2359 srand((unsigned int)GETSECS(bp->last_iteration));
2361 bp->prev_colour = bp->next_colour = COLOUR_ACYCLIC;
2362 bp->next_model = RAND(models);
2364 start_morph(bp->prev_model, 1);
2382 /* trackball quaternions */
2383 static float cumquat[4] = {0.0,0.0,0.0,0.0}, oldquat[4] = {0.0,0.0,0.0,0.1};
2385 /* rotation matrix */
2386 static float rotation[16];
2388 /* mouse drag vectors: start and end */
2389 static float mouse_start[3], mouse_end[3];
2391 /* dragging boolean */
2392 static int dragging = 0;
2394 /* this function calculates the rotation matrix based on the quaternions
2395 * generated from the mouse drag vectors */
2396 static void calc_rotation()
2399 double xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
2401 /* this bit ripped from Shoemake's quaternion notes from SIGGRAPH */
2402 Nq = cumquat[0] * cumquat[0] + cumquat[1] * cumquat[1] +
2403 cumquat[2] * cumquat[2] + cumquat[3] * cumquat[3];
2404 s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
2405 xs = cumquat[0] * s; ys = cumquat[1] * s; zs = cumquat[2] * s;
2406 wx = cumquat[3] * xs; wy = cumquat[3] * ys; wz = cumquat[3] * zs;
2407 xx = cumquat[0] * xs; xy = cumquat[0] * ys; xz = cumquat[0] * zs;
2408 yy = cumquat[1] * ys; yz = cumquat[1] * zs; zz = cumquat[2] * zs;
2410 rotation[0] = 1.0 - (yy + zz);
2411 rotation[1] = xy + wz;
2412 rotation[2] = xz - wy;
2413 rotation[4] = xy - wz;
2414 rotation[5] = 1.0 - (xx + zz);
2415 rotation[6] = yz + wx;
2416 rotation[8] = xz + wy;
2417 rotation[9] = yz - wx;
2418 rotation[10] = 1.0 - (xx + yy);
2419 rotation[3] = rotation[7] = rotation[11] = 0.0;
2420 rotation[12] = rotation[13] = rotation[14] = 0.0;
2424 static inline void ui_mousedrag()
2426 glMultMatrixf(rotation);
2429 static void ui_keyboard(unsigned char c, int x__attribute__((__unused__)), int y __attribute__((__unused__)))
2439 explode += DEF_EXPLODE;
2440 glutPostRedisplay();
2443 explode -= DEF_EXPLODE;
2444 if (explode < 0.0) explode = 0.0;
2445 glutPostRedisplay();
2450 bp->next_model %= models;
2451 start_morph(bp->next_model, 0);
2453 /* Reset last_morph time */
2454 gettime(&bp->last_morph);
2457 /* previous model */
2458 bp->next_model = (bp->next_model + (int)models - 1) % (int)models;
2459 start_morph(bp->next_model, 0);
2461 /* Reset bp->last_morph time */
2462 gettime(&bp->last_morph);
2465 angvel += DEF_ANGVEL;
2468 if (angvel > DEF_ANGVEL)
2469 angvel -= DEF_ANGVEL;
2473 /* Reset last_iteration and last_morph time */
2474 gettime(&bp->last_iteration);
2475 gettime(&bp->last_morph);
2477 interactive = 1 - interactive;
2478 glutPostRedisplay();
2481 wireframe = 1 - wireframe;
2483 glDisable(GL_LIGHTING);
2485 glEnable(GL_LIGHTING);
2486 glutPostRedisplay();
2489 transparent = 1 - transparent;
2493 glDisable(GL_BLEND);
2498 /* unpausing, reset last_iteration and last_morph time */
2499 gettime(&bp->last_iteration);
2500 gettime(&bp->last_morph);
2502 bp->paused = 1 - bp->paused;
2505 /* dump the current model so we can add it! */
2506 printf("# %s\nnoname:\t", model[bp->next_model].name);
2510 for (i = 0; i < NODE_COUNT; i++) {
2511 if (bp->node[i] == ZERO)
2513 else if (bp->node[i] == LEFT)
2515 else if (bp->node[i] == PIN)
2517 else if (bp->node[i] == RIGHT)
2521 printf("%f", node[i].curAngle);
2523 if (i < NODE_COUNT - 1)
2530 bp->fullscreen = 1 - bp->fullscreen;
2531 if (bp->fullscreen) {
2532 bp->old_width = bp->width;
2533 bp->old_height = bp->height;
2536 glutReshapeWindow(bp->old_width, bp->old_height);
2537 glutPositionWindow(50,50);
2541 titles = 1 - titles;
2542 if (interactive || bp->paused)
2543 glutPostRedisplay();
2546 altcolour = 1 - altcolour;
2550 glsnake_reshape(bp->width, bp->height);
2554 glsnake_reshape(bp->width, bp->height);
2561 static void ui_special(int key, int x__attribute__((__unused__)), int y __attribute__((__unused__)))
2563 float *destAngle = &(model[bp->next_model].node[bp->selected]);
2564 int unknown_key = 0;
2569 bp->selected = (bp->selected + (NODE_COUNT - 2)) % (NODE_COUNT - 1);
2572 bp->selected = (bp->selected + 1) % (NODE_COUNT - 1);
2575 *destAngle = fmod(*destAngle+(LEFT), 360);
2576 bp->morphing = bp->new_morph = 1;
2578 case GLUT_KEY_RIGHT:
2579 *destAngle = fmod(*destAngle+(RIGHT), 360);
2580 bp->morphing = bp->new_morph = 1;
2583 start_morph(STRAIGHT_MODEL, 0);
2590 calc_snake_metrics();
2593 glutPostRedisplay();
2596 static void ui_mouse(int button, int state, int x, int y)
2602 mouse_start[0] = M_SQRT1_2 *
2603 (x - (bp->width / 2.0)) / (bp->width / 2.0);
2604 mouse_start[1] = M_SQRT1_2 *
2605 ((bp->height / 2.0) - y) / (bp->height / 2.0);
2606 mouse_start[2] = sqrt((double)(1-(mouse_start[0]*mouse_start[0]+mouse_start[1]*mouse_start[1])));
2610 oldquat[0] = cumquat[0];
2611 oldquat[1] = cumquat[1];
2612 oldquat[2] = cumquat[2];
2613 oldquat[3] = cumquat[3];
2619 glutPostRedisplay();
2622 static void ui_motion(int x, int y)
2628 /* construct the motion end vector from the x,y position on the
2630 mouse_end[0] = M_SQRT1_2 * (x - (bp->width/ 2.0)) / (bp->width / 2.0);
2631 mouse_end[1] = M_SQRT1_2 * ((bp->height / 2.0) - y) / (bp->height / 2.0);
2632 /* calculate the normal of the vector... */
2633 norm = mouse_end[0] * mouse_end[0] + mouse_end[1] * mouse_end[1];
2634 /* check if norm is outside the sphere and wraparound if necessary */
2636 mouse_end[0] = -mouse_end[0];
2637 mouse_end[1] = -mouse_end[1];
2638 mouse_end[2] = sqrt(norm - 1);
2640 /* the z value comes from projecting onto an elliptical spheroid */
2641 mouse_end[2] = sqrt(1 - norm);
2644 /* now here, build a quaternion from mouse_start and mouse_end */
2645 q[0] = mouse_start[1] * mouse_end[2] - mouse_start[2] * mouse_end[1];
2646 q[1] = mouse_start[2] * mouse_end[0] - mouse_start[0] * mouse_end[2];
2647 q[2] = mouse_start[0] * mouse_end[1] - mouse_start[1] * mouse_end[0];
2648 q[3] = mouse_start[0] * mouse_end[0] + mouse_start[1] * mouse_end[1] + mouse_start[2] * mouse_end[2];
2650 /* new rotation is the product of the new one and the old one */
2651 cumquat[0] = q[3] * oldquat[0] + q[0] * oldquat[3] +
2652 q[1] * oldquat[2] - q[2] * oldquat[1];
2653 cumquat[1] = q[3] * oldquat[1] + q[1] * oldquat[3] +
2654 q[2] * oldquat[0] - q[0] * oldquat[2];
2655 cumquat[2] = q[3] * oldquat[2] + q[2] * oldquat[3] +
2656 q[0] * oldquat[1] - q[1] * oldquat[0];
2657 cumquat[3] = q[3] * oldquat[3] - q[0] * oldquat[0] -
2658 q[1] * oldquat[1] - q[2] * oldquat[2];
2662 glutPostRedisplay();
2665 static void ui_init(int * argc, char ** argv)
2667 glutInit(argc, argv);
2668 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
2669 glutInitWindowSize(bp->width, bp->height);
2670 bp->window = glutCreateWindow("glsnake");
2672 glutDisplayFunc(glsnake_display);
2673 glutReshapeFunc(glsnake_reshape);
2674 glutIdleFunc(glsnake_idle);
2675 glutKeyboardFunc(ui_keyboard);
2676 glutSpecialFunc(ui_special);
2677 glutMouseFunc(ui_mouse);
2678 glutMotionFunc(ui_motion);
2680 yangvel = DEF_YANGVEL;
2681 zangvel = DEF_ZANGVEL;
2682 explode = DEF_EXPLODE;
2683 angvel = DEF_ANGVEL;
2684 statictime = DEF_STATICTIME;
2685 altcolour = DEF_ALTCOLOUR;
2686 titles = DEF_TITLES;
2687 interactive = DEF_INTERACTIVE;
2689 wireframe = DEF_WIREFRAME;
2690 transparent = DEF_TRANSPARENT;
2692 #endif /* HAVE_GLUT */
2694 XSCREENSAVER_MODULE ("GLSnake", glsnake)