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.
27 # include "xlockmoreI.h"
30 /* HAVE_GLUT defined if we're building a standalone glsnake,
31 * and not defined if we're building as an xscreensaver hack */
36 # include <OpenGL/gl.h>
37 # include <OpenGL/glu.h>
38 # define HAVE_GETTIMEOFDAY
56 #ifdef HAVE_GETTIMEOFDAY
57 # ifdef GETTIMEOFDAY_TWO_ARGS
59 # include <sys/time.h>
61 typedef struct timeval snaketime;
62 # define GETSECS(t) ((t).tv_sec)
63 # define GETMSECS(t) ((t).tv_usec/1000)
65 # else /* !GETTIMEOFDAY_TWO_ARGS */
67 # include <sys/time.h>
69 typedef struct timeval snaketime;
70 # define GETSECS(t) ((t).tv_sec)
71 # define GETMSECS(t) ((t).tv_usec/1000)
73 # endif /* GETTIMEOFDAY_TWO_ARGS */
75 #else /* !HAVE_GETTIMEOFDAY */
78 # include <sys/timeb.h>
79 typedef struct timeb snaketime;
80 # define GETSECS(t) ((long)(t).time)
81 # define GETMSECS(t) ((t).millitm/1000)
83 # endif /* HAVE_FTIME */
84 #endif /* HAVE_GETTIMEOFDAY */
88 #ifndef M_SQRT1_2 /* Win32 doesn't have this constant */
89 #define M_SQRT1_2 0.70710678118654752440084436210485
95 #define DEF_YANGVEL 0.10
96 #define DEF_ZANGVEL 0.14
97 #define DEF_EXPLODE 0.03
98 #define DEF_ANGVEL 1.0
99 #define DEF_STATICTIME 5000
100 #define DEF_ALTCOLOUR 0
102 #define DEF_INTERACTIVE 0
103 #define DEF_ZOOM 25.0
104 #define DEF_WIREFRAME 0
105 #define DEF_TRANSPARENT 1
107 /* xscreensaver options doobies prefer strings */
108 #define DEF_YANGVEL "0.10"
109 #define DEF_ZANGVEL "0.14"
110 #define DEF_EXPLODE "0.03"
111 #define DEF_ANGVEL "1.0"
112 #define DEF_STATICTIME "5000"
113 #define DEF_ALTCOLOUR "False"
114 #define DEF_TITLES "False"
115 #define DEF_INTERACTIVE "False"
116 #define DEF_ZOOM "25.0"
117 #define DEF_WIREFRAME "False"
118 #define DEF_TRANSPARENT "True"
121 /* static variables */
123 static GLfloat explode;
124 static long statictime;
125 static GLfloat yspin = 60.0;
126 static GLfloat zspin = -45.0;
127 static GLfloat yangvel;
128 static GLfloat zangvel;
129 static Bool altcolour;
131 static Bool interactive;
132 static Bool wireframe;
133 static Bool transparent;
135 static GLfloat angvel;
139 #define glsnake_init init_glsnake
140 #define glsnake_display draw_glsnake
141 #define glsnake_reshape reshape_glsnake
142 #define refresh_glsnake 0
143 #define release_glsnake 0
144 #define glsnake_handle_event 0
146 /* xscreensaver defaults */
147 #define DEFAULTS "*delay: 30000 \n" \
149 "*showFPS: False \n" \
150 "*labelfont: -*-helvetica-medium-r-normal-*-180-*\n" \
155 #define countof(x) (sizeof((x))/sizeof((*x)))
157 #include "xlockmore.h"
158 #include "glxfonts.h"
160 static XrmOptionDescRec opts[] = {
161 { "-explode", ".explode", XrmoptionSepArg, DEF_EXPLODE },
162 { "-angvel", ".angvel", XrmoptionSepArg, DEF_ANGVEL },
163 { "-statictime", ".statictime", XrmoptionSepArg, DEF_STATICTIME },
164 { "-yangvel", ".yangvel", XrmoptionSepArg, DEF_YANGVEL },
165 { "-zangvel", ".zangvel", XrmoptionSepArg, DEF_ZANGVEL },
166 { "-altcolour", ".altcolour", XrmoptionNoArg, "True" },
167 { "-no-altcolour", ".altcolour", XrmoptionNoArg, "False" },
168 { "-titles", ".titles", XrmoptionNoArg, "True" },
169 { "-no-titles", ".titles", XrmoptionNoArg, "False" },
170 { "-zoom", ".zoom", XrmoptionSepArg, DEF_ZOOM },
171 { "-wireframe", ".wireframe", XrmoptionNoArg, "true" },
172 { "-no-wireframe", ".wireframe", XrmoptionNoArg, "false" },
173 { "-transparent", ".transparent", XrmoptionNoArg, "true" },
174 { "-no-transparent", ".transparent", XrmoptionNoArg, "false" },
177 static argtype vars[] = {
178 {&explode, "explode", "Explode", DEF_EXPLODE, t_Float},
179 {&angvel, "angvel", "Angular Velocity", DEF_ANGVEL, t_Float},
180 {&statictime, "statictime", "Static Time", DEF_STATICTIME, t_Int},
181 {&yangvel, "yangvel", "Angular Velocity about Y axis", DEF_YANGVEL, t_Float},
182 {&zangvel, "zangvel", "Angular Velocity about X axis", DEF_ZANGVEL, t_Float},
183 {&interactive, "interactive", "Interactive", DEF_INTERACTIVE, t_Bool},
184 {&altcolour, "altcolour", "Alternate Colour Scheme", DEF_ALTCOLOUR, t_Bool},
185 {&titles, "titles", "Titles", DEF_TITLES, t_Bool},
186 {&zoom, "zoom", "Zoom", DEF_ZOOM, t_Float},
187 {&wireframe, "wireframe", "Wireframe", DEF_WIREFRAME, t_Bool},
188 {&transparent, "transparent", "Transparent!", DEF_TRANSPARENT, t_Bool},
191 ENTRYPOINT ModeSpecOpt glsnake_opts = {countof(opts), opts, countof(vars), vars, NULL};
196 float node[NODE_COUNT];
201 GLXContext * glx_context;
205 /* font list number */
212 /* is a morph in progress? */
215 /* has the model been paused? */
224 /* the shape of the model */
225 float node[NODE_COUNT];
227 /* currently selected node for interactive mode */
231 unsigned int prev_model;
232 unsigned int next_model;
242 /* timing variables */
243 snaketime last_iteration;
244 snaketime last_morph;
248 int old_width, old_height;
250 /* the id of the display lists for drawing a node */
251 GLuint node_solid, node_wire;
253 /* is the window fullscreen? */
257 #define COLOUR_CYCLIC 0
258 #define COLOUR_ACYCLIC 1
259 #define COLOUR_INVALID 2
260 #define COLOUR_AUTHENTIC 3
261 #define COLOUR_ORIGLOGO 4
263 static const float colour[][2][4] = {
265 { { 0.4, 0.8, 0.2, 0.6 },
266 { 1.0, 1.0, 1.0, 0.6 } },
268 { { 0.3, 0.1, 0.9, 0.6 },
269 { 1.0, 1.0, 1.0, 0.6 } },
271 { { 0.3, 0.1, 0.9, 0.6 },
272 { 1.0, 1.0, 1.0, 0.6 } },
273 /* authentic - purple and green */
274 { { 0.38, 0.0, 0.55, 0.7 },
275 { 0.0, 0.5, 0.34, 0.7 } },
276 /* old "authentic" colours from the logo */
277 { { 171/255.0, 0, 1.0, 1.0 },
278 { 46/255.0, 205/255.0, 227/255.0, 1.0 } }
281 static const struct model_s model[] = {
282 #define STRAIGHT_MODEL 0
284 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
285 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
288 /* the models in the Rubik's snake manual */
290 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT,
291 RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT,
292 RIGHT, LEFT, RIGHT, LEFT, ZERO }
294 #define START_MODEL 2
296 { RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT,
297 RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT,
298 RIGHT, LEFT, LEFT, LEFT, ZERO }
301 { ZERO, ZERO, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO, ZERO,
302 ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO, ZERO, ZERO, RIGHT,
303 LEFT, RIGHT, ZERO, LEFT }
306 { ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, RIGHT, PIN,
307 RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, ZERO, ZERO,
311 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN,
312 ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
316 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, LEFT, RIGHT, PIN, RIGHT,
317 ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, LEFT, ZERO,
320 /* These models were taken from Andrew and Peter's original snake.c
321 * as well as some newer ones made up by Jamie, Andrew and Peter. */
323 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT,
324 LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT,
325 RIGHT, LEFT, LEFT, LEFT, ZERO }
328 { RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT,
329 LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT,
330 RIGHT, RIGHT, LEFT, LEFT, ZERO }
333 { PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN,
334 ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN,
338 { PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN,
339 LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN,
343 { RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT,
344 LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN,
348 { RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT,
349 LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT,
350 RIGHT, RIGHT, LEFT, LEFT, ZERO }
353 { ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT,
354 LEFT, RIGHT, LEFT, LEFT, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT,
355 RIGHT, RIGHT, RIGHT, ZERO }
358 { RIGHT, PIN, ZERO, ZERO, PIN, LEFT, ZERO, LEFT, LEFT, ZERO,
359 LEFT, PIN, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO,
363 { PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT,
364 LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT,
365 RIGHT, LEFT, LEFT, ZERO }
368 { ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO,
369 ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO,
370 LEFT, ZERO, ZERO, RIGHT }
373 { ZERO, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO, RIGHT, ZERO, ZERO,
374 LEFT, RIGHT, ZERO, LEFT, ZERO, RIGHT, ZERO, ZERO, LEFT, RIGHT,
375 ZERO, LEFT, ZERO, RIGHT }
378 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO,
379 ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO,
380 ZERO, ZERO, LEFT, RIGHT }
383 { ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT,
384 RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN,
388 { ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN,
389 PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN }
392 { PIN, RIGHT, LEFT, PIN, LEFT, PIN, ZERO, ZERO, RIGHT, PIN, LEFT,
393 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
397 { ZERO, ZERO, ZERO, ZERO, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT,
398 ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT,
399 LEFT, ZERO, PIN, ZERO }
402 { RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO,
403 LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, PIN, RIGHT,
407 { ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN,
408 ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO }
411 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, LEFT, PIN,
412 RIGHT, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT,
413 RIGHT, LEFT, LEFT, ZERO }
416 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, ZERO, ZERO,
417 RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO, LEFT, LEFT,
418 RIGHT, LEFT, RIGHT, RIGHT, ZERO }
421 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, PIN, ZERO, ZERO,
422 LEFT, PIN, RIGHT, ZERO, ZERO, PIN, ZERO, LEFT, LEFT, RIGHT, LEFT,
426 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO,
427 RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT,
431 { LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT,
432 ZERO, ZERO, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN,
436 { RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN,
437 LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT,
441 { RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN,
442 LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT,
443 LEFT, PIN, LEFT, PIN }
446 { ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN,
447 ZERO, PIN, ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT,
451 { ZERO, PIN, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, PIN,
452 ZERO, PIN, ZERO, PIN, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO,
456 { ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN,
457 ZERO, PIN, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
461 { ZERO, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT,
462 ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
466 { ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO,
467 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
471 { ZERO, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, ZERO,
472 ZERO, PIN, ZERO, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO,
476 { RIGHT, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, ZERO,
477 LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT,
478 ZERO, ZERO, LEFT, PIN }
481 { RIGHT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT,
482 ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT,
483 LEFT, RIGHT, ZERO, LEFT, PIN }
486 { RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO,
487 LEFT, PIN, RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT,
491 { ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, ZERO,
492 ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT,
496 { ZERO, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN,
497 RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT,
501 { LEFT, PIN, LEFT, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, LEFT,
502 PIN, RIGHT, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN,
506 { RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, ZERO,
507 ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, RIGHT, RIGHT, LEFT,
508 RIGHT, LEFT, LEFT, LEFT, PIN }
511 { ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, RIGHT,
512 RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT,
513 PIN, LEFT, LEFT, LEFT }
516 { PIN, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, LEFT,
517 ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, LEFT, ZERO,
518 LEFT, RIGHT, ZERO, ZERO }
521 { PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, RIGHT,
522 RIGHT, PIN, RIGHT, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO,
523 ZERO, PIN, PIN, ZERO }
526 /* the following modesl were created during the slug/compsoc codefest
528 { "cool looking gegl",
529 { PIN, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT,
530 ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, ZERO,
534 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN,
535 PIN, ZERO, RIGHT, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO,
539 { RIGHT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT,
540 RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN,
541 RIGHT, LEFT, RIGHT, PIN, ZERO }
544 { ZERO, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO,
545 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
549 { LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO,
550 RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT,
551 RIGHT, ZERO, LEFT, ZERO }
553 { "not very good (but accurate) gegl",
554 { ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO,
555 PIN, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO, PIN, PIN, ZERO,
559 { ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
560 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO,
564 { PIN, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
565 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO,
568 { "erect penis", /* thanks benno */
569 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, PIN,
570 PIN, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
574 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, PIN,
575 PIN, ZERO, ZERO, ZERO, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
579 { RIGHT, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO,
580 LEFT, ZERO, ZERO, ZERO, LEFT, ZERO, LEFT, PIN, LEFT, PIN, RIGHT,
584 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN,
585 ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO,
588 { "poles or columns or something",
589 { LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
590 ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
594 { ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
595 ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
599 { ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO,
600 LEFT, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
604 { ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO,
605 LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO,
606 LEFT, PIN, ZERO, ZERO }
609 { ZERO, ZERO, PIN, RIGHT, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO,
610 LEFT, PIN, ZERO, ZERO, PIN, ZERO, LEFT, ZERO, RIGHT, LEFT, ZERO,
614 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
615 RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
619 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
620 ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
624 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
625 LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
629 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
630 PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
634 { RIGHT, ZERO, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT,
635 RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT,
636 ZERO, ZERO, RIGHT, ZERO }
639 { RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT,
640 ZERO, RIGHT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, ZERO,
641 RIGHT, ZERO, RIGHT, ZERO, ZERO }
644 /* These models come from the website at
645 * http://www.geocities.com/stigeide/snake */
648 { RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO }
652 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, ZERO }
655 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, ZERO }
658 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, ZERO }
661 { ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, ZERO, ZERO }
664 { RIGHT, LEFT, RIGHT, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO, PIN, PIN, ZERO }
667 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO }
670 { LEFT, PIN, RIGHT, ZERO, ZERO, PIN, RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO }
673 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT , ZERO }
676 { ZERO, RIGHT, RIGHT, ZERO, RIGHT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, ZERO, LEFT , ZERO }
679 { PIN, LEFT, RIGHT, ZERO, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, LEFT, RIGHT, PIN, RIGHT , ZERO }
682 { PIN, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, PIN , ZERO }
685 { LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT , ZERO }
688 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT , ZERO }
691 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, PIN , ZERO }
694 { PIN, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, ZERO , ZERO }
697 { RIGHT, ZERO, PIN, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, ZERO, ZERO, LEFT , ZERO }
700 { LEFT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT , ZERO }
703 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO , ZERO }
706 { RIGHT, ZERO, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO , ZERO }
709 { PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO , ZERO }
712 { RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, LEFT, RIGHT, LEFT, LEFT , ZERO }
715 { RIGHT, RIGHT, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, LEFT, LEFT , ZERO }
718 { RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT , ZERO }
721 { ZERO, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, LEFT, ZERO, LEFT, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT , ZERO }
725 { LEFT, ZERO, PIN, ZERO, PIN, LEFT, ZERO, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, PIN, ZERO, RIGHT , ZERO }
729 { ZERO, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, LEFT , ZERO }
732 { ZERO, ZERO, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN , ZERO }
735 { LEFT, PIN, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO , ZERO }
738 { ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN , ZERO }
741 { PIN, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO , ZERO }
744 { LEFT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT , ZERO }
747 { PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, RIGHT, PIN , ZERO }
750 { RIGHT, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, LEFT , ZERO }
753 { ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO, PIN , ZERO }
755 { "Counterclockwise",
756 { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT , ZERO }
759 { LEFT, LEFT, ZERO, PIN, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, RIGHT, LEFT, LEFT, ZERO, ZERO, RIGHT , ZERO }
762 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, PIN, RIGHT , ZERO }
765 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN , ZERO }
768 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO , ZERO }
771 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, ZERO }
774 { PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, ZERO }
777 { RIGHT, LEFT, PIN, LEFT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, LEFT, PIN, LEFT, RIGHT, ZERO }
780 { LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, PIN, ZERO, ZERO }
783 { RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, ZERO }
786 { ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO }
789 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, LEFT, RIGHT, ZERO }
792 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, LEFT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, RIGHT, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
795 { ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, LEFT, ZERO, PIN, ZERO, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, ZERO }
798 { ZERO, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO }
801 { ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO }
804 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO }
807 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO, RIGHT, ZERO, RIGHT, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO }
810 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, RIGHT, ZERO, RIGHT, LEFT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO }
813 { PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, ZERO }
816 { PIN, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO }
819 { ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO }
822 { LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, ZERO }
825 { LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, ZERO }
828 { RIGHT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, ZERO }
831 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, ZERO }
834 { ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO }
837 { LEFT, LEFT, RIGHT, PIN, ZERO, RIGHT, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, LEFT, ZERO, PIN, LEFT, RIGHT, RIGHT, RIGHT, PIN, ZERO }
840 { PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
843 { ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, RIGHT, ZERO, PIN, ZERO }
846 { ZERO, RIGHT, ZERO, PIN, LEFT, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, RIGHT, PIN, ZERO, LEFT, ZERO, ZERO }
849 { ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, ZERO, ZERO, ZERO, PIN, ZERO }
852 { ZERO, PIN, PIN, ZERO, PIN, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO }
855 { ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO }
858 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO }
861 { LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, RIGHT, LEFT, RIGHT, RIGHT, ZERO }
864 { LEFT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, ZERO, RIGHT, ZERO }
867 { PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO }
870 { ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO }
873 { LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO }
876 { RIGHT, LEFT, ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, LEFT, ZERO, ZERO }
879 { PIN, PIN, ZERO, LEFT, RIGHT, LEFT, ZERO, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO }
882 { PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO }
885 { PIN, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO }
888 { RIGHT, ZERO, ZERO, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, RIGHT, ZERO, PIN, ZERO, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO, ZERO, ZERO, LEFT, ZERO }
891 { ZERO, PIN, ZERO, ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO }
894 { ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO }
896 { "HoleInTheMiddle1",
897 { ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO }
899 { "HoleInTheMiddle2",
900 { ZERO, LEFT, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO }
903 { RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, ZERO }
906 { LEFT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, ZERO }
909 { LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO }
912 { RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
915 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO }
918 { RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, LEFT, ZERO }
921 { ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO }
924 { LEFT, LEFT, PIN, LEFT, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, RIGHT, PIN, RIGHT, RIGHT, LEFT, ZERO }
927 { ZERO, PIN, PIN, ZERO, ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO }
930 { RIGHT, PIN, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, PIN, LEFT, ZERO }
933 { PIN, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO }
936 { PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, ZERO }
938 { "magnifying glass",
939 { ZERO, ZERO, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, ZERO }
942 { ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, ZERO }
945 { PIN, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO }
948 { PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO }
951 { ZERO, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, LEFT, PIN, RIGHT, RIGHT, ZERO, RIGHT, ZERO }
954 { ZERO, RIGHT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, ZERO, RIGHT, RIGHT, PIN, LEFT, ZERO }
957 { LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
960 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, LEFT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO }
963 { ZERO, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO }
965 { "MouseWithoutTail",
966 { ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO }
969 { PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, ZERO }
972 { ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO }
975 { LEFT, ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, ZERO }
978 { ZERO, RIGHT, PIN, LEFT, LEFT, LEFT, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO }
981 { LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, ZERO }
984 { PIN, ZERO, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, ZERO, ZERO }
987 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, ZERO }
990 { PIN, PIN, ZERO, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
993 { ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
996 { ZERO, ZERO, ZERO, ZERO, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO }
999 { PIN, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, PIN, ZERO }
1001 { "PictureComingSoon",
1002 { LEFT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, RIGHT, RIGHT, ZERO }
1005 { LEFT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, ZERO }
1008 { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, ZERO }
1011 { RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO }
1014 { ZERO, PIN, ZERO, PIN, RIGHT, PIN, ZERO, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, ZERO, PIN, LEFT, ZERO }
1018 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO }
1022 { RIGHT, PIN, ZERO, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, PIN, ZERO, PIN, LEFT, ZERO }
1025 { ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, ZERO }
1028 { ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, LEFT, ZERO }
1030 { "QuarterbackTiltedAndReadyToHut",
1031 { PIN, ZERO, RIGHT, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, LEFT, ZERO, PIN, ZERO }
1034 { PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1037 { LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, PIN, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, ZERO }
1040 { ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, ZERO }
1043 { LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, ZERO }
1046 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1049 { RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, ZERO }
1052 { ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO }
1055 { PIN, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, PIN, ZERO }
1058 { RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1061 { RIGHT, LEFT, PIN, ZERO, ZERO, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO }
1064 { LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO }
1067 { RIGHT, PIN, ZERO, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO }
1070 { RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, ZERO }
1073 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO }
1076 { PIN, RIGHT, LEFT, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, LEFT, ZERO, PIN, PIN, ZERO }
1079 { LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO }
1082 { LEFT, RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, RIGHT, LEFT, ZERO }
1085 { ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO }
1087 { "SnakeReadyToStrike",
1088 { LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO }
1091 { RIGHT, RIGHT, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO }
1094 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO }
1097 { PIN, PIN, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
1100 { LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, ZERO }
1103 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO }
1106 { PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, ZERO }
1109 { PIN, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, PIN, ZERO }
1112 { PIN, PIN, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, LEFT, LEFT, PIN, PIN, ZERO }
1115 { LEFT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, ZERO }
1118 { PIN, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, ZERO, RIGHT, PIN, LEFT, ZERO }
1121 { RIGHT, RIGHT, ZERO, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, RIGHT, LEFT, RIGHT, ZERO, ZERO, LEFT, ZERO }
1124 { PIN, LEFT, ZERO, RIGHT, RIGHT, LEFT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, LEFT, LEFT, ZERO, ZERO }
1127 { ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, ZERO }
1130 { PIN, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO }
1133 { RIGHT, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, ZERO }
1136 { ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO }
1139 { ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
1142 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO }
1145 { ZERO, PIN, ZERO, PIN, LEFT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, ZERO }
1148 { PIN, ZERO, PIN, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO }
1151 { PIN, PIN, ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO }
1154 { RIGHT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, RIGHT, ZERO }
1157 { RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO }
1160 { ZERO, PIN, LEFT, LEFT, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1163 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, RIGHT, PIN, ZERO }
1166 { ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO }
1169 { ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO }
1172 { RIGHT, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, ZERO }
1175 { RIGHT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO }
1178 { RIGHT, LEFT, ZERO, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO }
1181 { PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO }
1184 { RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, PIN, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO }
1187 { RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, ZERO }
1190 { ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, LEFT, LEFT, PIN, ZERO, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, ZERO }
1193 { PIN, LEFT, LEFT, PIN, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO }
1196 { PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO }
1199 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO }
1202 { PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, ZERO }
1206 { RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO }
1210 { ZERO, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO, ZERO }
1213 { ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, ZERO }
1216 { PIN, LEFT, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, ZERO, ZERO }
1219 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1222 { LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO }
1225 { ZERO, PIN, ZERO, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, ZERO }
1228 { ZERO, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, ZERO }
1231 { PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO }
1234 { ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO }
1237 { PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, PIN, RIGHT, ZERO, RIGHT, RIGHT, ZERO, RIGHT, PIN, ZERO, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, ZERO }
1240 { ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1243 { LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO }
1246 { PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO }
1249 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO }
1251 { "WindowToTheWorld",
1252 { PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
1255 { PIN, PIN, ZERO, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, PIN, ZERO }
1258 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO }
1261 { RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO }
1264 { PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, ZERO }
1267 { ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO }
1270 { LEFT, ZERO, ZERO, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, ZERO, ZERO, ZERO }
1274 static size_t models = sizeof(model) / sizeof(struct model_s);
1276 #define VOFFSET 0.045
1282 /* the connecting string that holds the snake together */
1283 #define MAGICAL_RED_STRING 0
1285 #define GETSCALAR(vec,mask) ((vec)==(mask) ? 1 : ((vec)==-(mask) ? -1 : 0 ))
1288 # define MAX(x, y) ((x) > (y) ? (x) : (y))
1291 # define MIN(x, y) ((x) < (y) ? (x) : (y))
1294 #define RAND(n) ((random() & 0x7fffffff) % ((long) (n)))
1295 #define RANDSIGN() ((random() & 1) ? 1 : -1)
1297 /* the triangular prism what makes up the basic unit */
1298 static const float solid_prism_v[][3] = {
1299 /* first corner, bottom left front */
1300 { VOFFSET, VOFFSET, 1.0 },
1301 { VOFFSET, 0.00, 1.0 - VOFFSET },
1302 { 0.00, VOFFSET, 1.0 - VOFFSET },
1303 /* second corner, rear */
1304 { VOFFSET, VOFFSET, 0.00 },
1305 { VOFFSET, 0.00, VOFFSET },
1306 { 0.00, VOFFSET, VOFFSET },
1307 /* third, right front */
1308 { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 1.0 },
1309 { 1.0 - VOFFSET / M_SQRT1_2, 0.0, 1.0 - VOFFSET },
1310 { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, 1.0 - VOFFSET },
1311 /* fourth, right rear */
1312 { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 0.0 },
1313 { 1.0 - VOFFSET / M_SQRT1_2, 0.0, VOFFSET },
1314 { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, VOFFSET },
1315 /* fifth, upper front */
1316 { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 1.0 },
1317 { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, 1.0 - VOFFSET },
1318 { 0.0, 1.0 - VOFFSET / M_SQRT1_2, 1.0 - VOFFSET},
1319 /* sixth, upper rear */
1320 { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 0.0 },
1321 { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, VOFFSET },
1322 { 0.0, 1.0 - VOFFSET / M_SQRT1_2, VOFFSET }};
1324 static const float solid_prism_n[][3] = {/* corners */
1325 { -VOFFSET, -VOFFSET, VOFFSET },
1326 { VOFFSET, -VOFFSET, VOFFSET },
1327 { -VOFFSET, VOFFSET, VOFFSET },
1328 { -VOFFSET, -VOFFSET, -VOFFSET },
1329 { VOFFSET, -VOFFSET, -VOFFSET },
1330 { -VOFFSET, VOFFSET, -VOFFSET },
1332 { -VOFFSET, 0.0, VOFFSET },
1333 { 0.0, -VOFFSET, VOFFSET },
1334 { VOFFSET, VOFFSET, VOFFSET },
1335 { -VOFFSET, 0.0, -VOFFSET },
1336 { 0.0, -VOFFSET, -VOFFSET },
1337 { VOFFSET, VOFFSET, -VOFFSET },
1338 { -VOFFSET, -VOFFSET, 0.0 },
1339 { VOFFSET, -VOFFSET, 0.0 },
1340 { -VOFFSET, VOFFSET, 0.0 },
1344 { M_SQRT1_2, M_SQRT1_2, 0.0 },
1346 { 0.0, 0.0, -1.0 }};
1348 static const float wire_prism_v[][3] = {{ 0.0, 0.0, 1.0 },
1356 static const float wire_prism_n[][3] = {{ 0.0, 0.0, 1.0},
1358 { M_SQRT1_2, M_SQRT1_2, 0.0},
1363 static struct glsnake_cfg * glc = NULL;
1368 typedef float (*morphFunc)(long);
1371 /* forward definitions for GLUT functions */
1372 static void calc_rotation();
1373 static inline void ui_mousedrag();
1376 static const GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };
1377 static const GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
1378 static const GLfloat mat_specular[] = { 0.1, 0.1, 0.1, 1.0 };
1379 static const GLfloat mat_shininess[] = { 20.0 };
1381 static void gl_init(
1387 float light_pos[][3] = {{0.0, 10.0, 20.0}, {0.0, 20.0, -1.0}};
1388 float light_dir[][3] = {{0.0, -10.0,-20.0}, {0.0,-20.0, 1.0}};
1390 glEnable(GL_DEPTH_TEST);
1391 glShadeModel(GL_SMOOTH);
1392 glCullFace(GL_BACK);
1393 /*glEnable(GL_CULL_FACE);*/
1394 glEnable(GL_NORMALIZE);
1396 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1401 /*glColor4f(1.0, 1.0, 1.0, 1.0);*/
1402 glLightfv(GL_LIGHT0, GL_POSITION, light_pos[0]);
1403 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_dir[0]);
1404 glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
1405 /*glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);*/
1407 glLightfv(GL_LIGHT1, GL_POSITION, light_pos[1]);
1408 glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light_dir[1]);
1409 glLightfv(GL_LIGHT1, GL_DIFFUSE, white_light);
1410 glLightfv(GL_LIGHT1, GL_SPECULAR, white_light);
1412 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
1413 glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
1414 glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
1415 glEnable(GL_LIGHTING);
1416 glEnable(GL_LIGHT0);
1417 glEnable(GL_LIGHT1);
1418 /*glEnable(GL_COLOR_MATERIAL);*/
1422 static void gettime(snaketime *t)
1424 #ifdef HAVE_GETTIMEOFDAY
1425 #ifdef GETTIMEOFDAY_TWO_ARGS
1426 struct timezone tzp;
1427 gettimeofday(t, &tzp);
1428 #else /* !GETTIMEOFDAY_TWO_ARGS */
1430 #endif /* !GETTIMEOFDAY_TWO_ARGS */
1431 #else /* !HAVE_GETTIMEOFDAY */
1434 #endif /* HAVE_FTIME */
1435 #endif /* !HAVE_GETTIMEOFDAY */
1439 ENTRYPOINT void glsnake_reshape(
1445 static void start_morph(struct glsnake_cfg *,
1446 unsigned int model_index, int immediate);
1448 /* wot initialises it */
1449 ENTRYPOINT void glsnake_init(
1456 struct glsnake_cfg * bp;
1458 /* set up the conf struct and glx contexts */
1460 glc = (struct glsnake_cfg *) calloc(MI_NUM_SCREENS(mi), sizeof(struct glsnake_cfg));
1462 fprintf(stderr, "%s: out of memory\n", progname);
1466 bp = &glc[MI_SCREEN(mi)];
1468 if ((bp->glx_context = init_GL(mi)) != NULL) {
1470 glsnake_reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1476 /* initialise conf struct */
1477 memset(&bp->node, 0, sizeof(float) * NODE_COUNT);
1487 gettime(&bp->last_iteration);
1488 memcpy(&bp->last_morph, &bp->last_iteration, sizeof(bp->last_morph));
1490 bp->prev_colour = bp->next_colour = COLOUR_ACYCLIC;
1491 bp->next_model = RAND(models);
1492 bp->prev_model = START_MODEL;
1493 start_morph(bp, bp->prev_model, 1);
1495 /* set up a font for the labels */
1498 load_font(mi->dpy, "labelfont", &bp->font, &bp->font_list);
1501 /* build a solid display list */
1502 bp->node_solid = glGenLists(1);
1503 glNewList(bp->node_solid, GL_COMPILE);
1505 glBegin(GL_TRIANGLES);
1506 glNormal3fv(solid_prism_n[0]);
1507 glVertex3fv(solid_prism_v[0]);
1508 glVertex3fv(solid_prism_v[2]);
1509 glVertex3fv(solid_prism_v[1]);
1511 glNormal3fv(solid_prism_n[1]);
1512 glVertex3fv(solid_prism_v[6]);
1513 glVertex3fv(solid_prism_v[7]);
1514 glVertex3fv(solid_prism_v[8]);
1516 glNormal3fv(solid_prism_n[2]);
1517 glVertex3fv(solid_prism_v[12]);
1518 glVertex3fv(solid_prism_v[13]);
1519 glVertex3fv(solid_prism_v[14]);
1521 glNormal3fv(solid_prism_n[3]);
1522 glVertex3fv(solid_prism_v[3]);
1523 glVertex3fv(solid_prism_v[4]);
1524 glVertex3fv(solid_prism_v[5]);
1526 glNormal3fv(solid_prism_n[4]);
1527 glVertex3fv(solid_prism_v[9]);
1528 glVertex3fv(solid_prism_v[11]);
1529 glVertex3fv(solid_prism_v[10]);
1531 glNormal3fv(solid_prism_n[5]);
1532 glVertex3fv(solid_prism_v[16]);
1533 glVertex3fv(solid_prism_v[15]);
1534 glVertex3fv(solid_prism_v[17]);
1538 glNormal3fv(solid_prism_n[6]);
1539 glVertex3fv(solid_prism_v[0]);
1540 glVertex3fv(solid_prism_v[12]);
1541 glVertex3fv(solid_prism_v[14]);
1542 glVertex3fv(solid_prism_v[2]);
1544 glNormal3fv(solid_prism_n[7]);
1545 glVertex3fv(solid_prism_v[0]);
1546 glVertex3fv(solid_prism_v[1]);
1547 glVertex3fv(solid_prism_v[7]);
1548 glVertex3fv(solid_prism_v[6]);
1550 glNormal3fv(solid_prism_n[8]);
1551 glVertex3fv(solid_prism_v[6]);
1552 glVertex3fv(solid_prism_v[8]);
1553 glVertex3fv(solid_prism_v[13]);
1554 glVertex3fv(solid_prism_v[12]);
1556 glNormal3fv(solid_prism_n[9]);
1557 glVertex3fv(solid_prism_v[3]);
1558 glVertex3fv(solid_prism_v[5]);
1559 glVertex3fv(solid_prism_v[17]);
1560 glVertex3fv(solid_prism_v[15]);
1562 glNormal3fv(solid_prism_n[10]);
1563 glVertex3fv(solid_prism_v[3]);
1564 glVertex3fv(solid_prism_v[9]);
1565 glVertex3fv(solid_prism_v[10]);
1566 glVertex3fv(solid_prism_v[4]);
1568 glNormal3fv(solid_prism_n[11]);
1569 glVertex3fv(solid_prism_v[15]);
1570 glVertex3fv(solid_prism_v[16]);
1571 glVertex3fv(solid_prism_v[11]);
1572 glVertex3fv(solid_prism_v[9]);
1574 glNormal3fv(solid_prism_n[12]);
1575 glVertex3fv(solid_prism_v[1]);
1576 glVertex3fv(solid_prism_v[2]);
1577 glVertex3fv(solid_prism_v[5]);
1578 glVertex3fv(solid_prism_v[4]);
1580 glNormal3fv(solid_prism_n[13]);
1581 glVertex3fv(solid_prism_v[8]);
1582 glVertex3fv(solid_prism_v[7]);
1583 glVertex3fv(solid_prism_v[10]);
1584 glVertex3fv(solid_prism_v[11]);
1586 glNormal3fv(solid_prism_n[14]);
1587 glVertex3fv(solid_prism_v[13]);
1588 glVertex3fv(solid_prism_v[16]);
1589 glVertex3fv(solid_prism_v[17]);
1590 glVertex3fv(solid_prism_v[14]);
1594 glBegin(GL_TRIANGLES);
1595 glNormal3fv(solid_prism_n[15]);
1596 glVertex3fv(solid_prism_v[0]);
1597 glVertex3fv(solid_prism_v[6]);
1598 glVertex3fv(solid_prism_v[12]);
1600 glNormal3fv(solid_prism_n[19]);
1601 glVertex3fv(solid_prism_v[3]);
1602 glVertex3fv(solid_prism_v[15]);
1603 glVertex3fv(solid_prism_v[9]);
1607 glNormal3fv(solid_prism_n[16]);
1608 glVertex3fv(solid_prism_v[1]);
1609 glVertex3fv(solid_prism_v[4]);
1610 glVertex3fv(solid_prism_v[10]);
1611 glVertex3fv(solid_prism_v[7]);
1613 glNormal3fv(solid_prism_n[17]);
1614 glVertex3fv(solid_prism_v[8]);
1615 glVertex3fv(solid_prism_v[11]);
1616 glVertex3fv(solid_prism_v[16]);
1617 glVertex3fv(solid_prism_v[13]);
1619 glNormal3fv(solid_prism_n[18]);
1620 glVertex3fv(solid_prism_v[2]);
1621 glVertex3fv(solid_prism_v[14]);
1622 glVertex3fv(solid_prism_v[17]);
1623 glVertex3fv(solid_prism_v[5]);
1627 /* build wire display list */
1628 bp->node_wire = glGenLists(1);
1629 glNewList(bp->node_wire, GL_COMPILE);
1630 glBegin(GL_LINE_STRIP);
1631 glVertex3fv(wire_prism_v[0]);
1632 glVertex3fv(wire_prism_v[1]);
1633 glVertex3fv(wire_prism_v[2]);
1634 glVertex3fv(wire_prism_v[0]);
1635 glVertex3fv(wire_prism_v[3]);
1636 glVertex3fv(wire_prism_v[4]);
1637 glVertex3fv(wire_prism_v[5]);
1638 glVertex3fv(wire_prism_v[3]);
1641 glVertex3fv(wire_prism_v[1]);
1642 glVertex3fv(wire_prism_v[4]);
1643 glVertex3fv(wire_prism_v[2]);
1644 glVertex3fv(wire_prism_v[5]);
1649 /* initialise the rotation */
1654 static void draw_title(
1661 struct glsnake_cfg * bp = &glc[MI_SCREEN(mi)];
1664 /* draw some text */
1665 glPushAttrib((GLbitfield) GL_TRANSFORM_BIT | GL_ENABLE_BIT);
1666 glDisable(GL_LIGHTING);
1667 glDisable(GL_DEPTH_TEST);
1669 glDisable(GL_BLEND);
1671 glMatrixMode(GL_PROJECTION);
1674 glMatrixMode(GL_MODELVIEW);
1678 gluOrtho2D((GLdouble) 0., (GLdouble) bp->width, (GLdouble) 0., (GLdouble) bp->height);
1680 gluOrtho2D((GLdouble) 0., (GLdouble) mi->xgwa.width, (GLdouble) 0., (GLdouble) mi->xgwa.height);
1683 glColor4f(1.0, 1.0, 1.0, 1.0);
1685 char interactstr[] = "interactive";
1694 s = model[bp->next_model].name;
1700 w = glutBitmapLength(GLUT_BITMAP_HELVETICA_12, (const unsigned char *) s);
1701 glRasterPos2f((GLfloat) (bp->width - w - 3), 4.0);
1702 while (s[i] != '\0')
1703 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, s[i++]);
1706 print_gl_string(mi->dpy, bp->font, bp->font_list,
1707 mi->xgwa.width, mi->xgwa.height,
1708 10.0, (float) mi->xgwa.height - 10.0,
1713 glMatrixMode(GL_PROJECTION);
1718 /* apply the matrix to the origin and stick it in vec */
1719 static void matmult_origin(float rotmat[16], float vec[4])
1722 vec[0] = 0.5 * rotmat[0] + 0.5 * rotmat[4] + 0.5 * rotmat [8] + 1 * rotmat[12];
1723 vec[1] = 0.5 * rotmat[1] + 0.5 * rotmat[5] + 0.5 * rotmat [9] + 1 * rotmat[13];
1724 vec[2] = 0.5 * rotmat[2] + 0.5 * rotmat[6] + 0.5 * rotmat[10] + 1 * rotmat[14];
1725 vec[3] = 0.5 * rotmat[3] + 0.5 * rotmat[7] + 0.5 * rotmat[11] + 1 * rotmat[15];
1727 vec[0] = 0 * rotmat [0] + 0 * rotmat [1] + 0 * rotmat [2] + 1 * rotmat [3];
1728 vec[1] = 0 * rotmat [4] + 0 * rotmat [5] + 0 * rotmat [6] + 1 * rotmat [7];
1729 vec[2] = 0 * rotmat [8] + 0 * rotmat [9] + 0 * rotmat[10] + 1 * rotmat[11];
1730 vec[3] = 0 * rotmat[12] + 0 * rotmat[13] + 0 * rotmat[14] + 1 * rotmat[15];
1738 /* wot gets called when the winder is resized */
1739 ENTRYPOINT void glsnake_reshape(
1745 glViewport(0, 0, (GLint) w, (GLint) h);
1746 glMatrixMode(GL_PROJECTION);
1748 /* jwz: 0.05 was too close (left black rectangles) */
1749 gluPerspective(zoom, (GLdouble) w / (GLdouble) h, 1.0, 100.0);
1750 gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
1751 glMatrixMode(GL_MODELVIEW);
1752 /*gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);*/
1760 /* Returns the new dst_dir for the given src_dir and dst_dir */
1761 static int cross_product(int src_dir, int dst_dir)
1763 return X_MASK*(GETSCALAR(src_dir,Y_MASK) * GETSCALAR(dst_dir,Z_MASK) -
1764 GETSCALAR(src_dir,Z_MASK) * GETSCALAR(dst_dir,Y_MASK))+
1765 Y_MASK*(GETSCALAR(src_dir,Z_MASK) * GETSCALAR(dst_dir,X_MASK) -
1766 GETSCALAR(src_dir,X_MASK) * GETSCALAR(dst_dir,Z_MASK))+
1767 Z_MASK*(GETSCALAR(src_dir,X_MASK) * GETSCALAR(dst_dir,Y_MASK) -
1768 GETSCALAR(src_dir,Y_MASK) * GETSCALAR(dst_dir,X_MASK));
1771 /* calculate orthogonal snake metrics
1772 * is_legal = true if model does not pass through itself
1773 * is_cyclic = true if last node connects back to first node
1774 * last_turn = for cyclic snakes, specifes what the 24th turn would be
1776 static void calc_snake_metrics(struct glsnake_cfg *bp)
1780 int prevSrcDir = -Y_MASK;
1781 int prevDstDir = Z_MASK;
1782 int grid[25][25][25];
1785 memset(&grid, 0, sizeof(int) * 25*25*25);
1790 /* trace path of snake - and keep record for is_legal */
1791 for (i = 0; i < NODE_COUNT - 1; i++) {
1792 /*int ang_card;*/ /* cardinal direction of node angle */
1793 /* establish new state vars */
1794 srcDir = -prevDstDir;
1795 x += GETSCALAR(prevDstDir, X_MASK);
1796 y += GETSCALAR(prevDstDir, Y_MASK);
1797 z += GETSCALAR(prevDstDir, Z_MASK);
1799 switch ((int) model[bp->next_model].node[i]) {
1801 dstDir = -prevSrcDir;
1804 dstDir = prevSrcDir;
1808 dstDir = cross_product(prevSrcDir, prevDstDir);
1809 if (model[bp->next_model].node[i] == (int) (RIGHT))
1813 /* Prevent spurious "might be used
1814 * uninitialised" warnings when compiling
1820 if (grid[x][y][z] == 0)
1821 grid[x][y][z] = srcDir + dstDir;
1822 else if (grid[x][y][z] + srcDir + dstDir == 0)
1827 prevSrcDir = srcDir;
1828 prevDstDir = dstDir;
1831 /* determine if the snake is cyclic */
1832 bp->is_cyclic = (dstDir == Y_MASK && x == 12 && y == 11 && z == 12);
1834 /* determine last_turn */
1838 case -Z_MASK: bp->last_turn = ZERO; break;
1839 case Z_MASK: bp->last_turn = PIN; break;
1840 case X_MASK: bp->last_turn = LEFT; break;
1841 case -X_MASK: bp->last_turn = RIGHT; break;
1845 /* work out how far through the current morph we are */
1846 static float morph_percent(struct glsnake_cfg *bp)
1851 /* extend this function later with a case statement for each of the
1854 /* when morphing all nodes at once, the longest morph will be the node
1855 * that needs to rotate 180 degrees. For each node, work out how far it
1856 * has to go, and store the maximum rotation and current largest angular
1857 * difference, returning the angular difference over the maximum. */
1859 float rot_max = 0.0, ang_diff_max = 0.0;
1861 for (i = 0; i < NODE_COUNT - 1; i++) {
1862 float rot, ang_diff;
1864 /* work out the maximum rotation this node has to go through
1865 * from the previous to the next model, taking into account that
1866 * the snake always morphs through the smaller angle */
1867 rot = fabs(model[bp->prev_model].node[i] -
1868 model[bp->next_model].node[i]);
1869 if (rot > 180.0) rot = 180.0 - rot;
1870 /* work out the difference between the current position and the
1872 ang_diff = fabs(bp->node[i] -
1873 model[bp->next_model].node[i]);
1874 if (ang_diff > 180.0) ang_diff = 180.0 - ang_diff;
1875 /* if it's the biggest so far, record it */
1876 if (rot > rot_max) rot_max = rot;
1877 if (ang_diff > ang_diff_max) ang_diff_max = ang_diff;
1880 /* ang_diff / rot approaches 0, we want the complement */
1881 retval = 1.0 - (ang_diff_max / rot_max);
1882 /* protect against naan */
1884 /* Apparently some systems (Solaris) don't have isinf() */
1886 #define isinf(x) (((x) > 999999999999.9) || ((x) < -999999999999.9))
1888 if (isnan(retval) || isinf(retval)) retval = 1.0;
1890 /*printf("morph_pct = %f\n", retval);*/
1894 static void morph_colour(struct glsnake_cfg *bp)
1896 float percent, compct; /* complement of percentage */
1898 percent = morph_percent(bp);
1899 compct = 1.0 - percent;
1901 bp->colour[0][0] = colour[bp->prev_colour][0][0] * compct + colour[bp->next_colour][0][0] * percent;
1902 bp->colour[0][1] = colour[bp->prev_colour][0][1] * compct + colour[bp->next_colour][0][1] * percent;
1903 bp->colour[0][2] = colour[bp->prev_colour][0][2] * compct + colour[bp->next_colour][0][2] * percent;
1904 bp->colour[0][3] = colour[bp->prev_colour][0][3] * compct + colour[bp->next_colour][0][3] * percent;
1906 bp->colour[1][0] = colour[bp->prev_colour][1][0] * compct + colour[bp->next_colour][1][0] * percent;
1907 bp->colour[1][1] = colour[bp->prev_colour][1][1] * compct + colour[bp->next_colour][1][1] * percent;
1908 bp->colour[1][2] = colour[bp->prev_colour][1][2] * compct + colour[bp->next_colour][1][2] * percent;
1909 bp->colour[1][3] = colour[bp->prev_colour][1][3] * compct + colour[bp->next_colour][1][3] * percent;
1912 /* Start morph process to this model */
1913 static void start_morph(struct glsnake_cfg *bp,
1914 unsigned int model_index, int immediate)
1916 /* if immediate, don't bother morphing, go straight to the next model */
1920 for (i = 0; i < NODE_COUNT; i++)
1921 bp->node[i] = model[model_index].node[i];
1924 bp->prev_model = bp->next_model;
1925 bp->next_model = model_index;
1926 bp->prev_colour = bp->next_colour;
1928 calc_snake_metrics(bp);
1930 bp->next_colour = COLOUR_INVALID;
1932 bp->next_colour = COLOUR_AUTHENTIC;
1933 else if (bp->is_cyclic)
1934 bp->next_colour = COLOUR_CYCLIC;
1936 bp->next_colour = COLOUR_ACYCLIC;
1939 bp->colour[0][0] = colour[bp->next_colour][0][0];
1940 bp->colour[0][1] = colour[bp->next_colour][0][1];
1941 bp->colour[0][2] = colour[bp->next_colour][0][2];
1942 bp->colour[0][3] = colour[bp->next_colour][0][3];
1943 bp->colour[1][0] = colour[bp->next_colour][1][0];
1944 bp->colour[1][1] = colour[bp->next_colour][1][1];
1945 bp->colour[1][2] = colour[bp->next_colour][1][2];
1946 bp->colour[1][3] = colour[bp->next_colour][1][3];
1954 /* Returns morph progress */
1955 static float morph(long iter_msec)
1957 /* work out the maximum angle for this iteration */
1959 float iter_angle_max, largest_diff, largest_progress;
1965 iter_angle_max = 90.0 * (angvel/1000.0) * iter_msec;
1968 largest_diff = largest_progress = 0.0;
1969 for (i = 0; i < NODE_COUNT; i++) {
1970 float curAngle = bp->node[i];
1971 float destAngle = model[bp->next_model].node[i];
1972 if (curAngle != destAngle) {
1974 if (fabs(curAngle-destAngle) <= iter_angle_max)
1975 bp->node[i] = destAngle;
1976 else if (fmod(curAngle-destAngle+360,360) > 180)
1977 bp->node[i] = fmod(curAngle + iter_angle_max, 360);
1979 bp->node[i] = fmod(curAngle+360 - iter_angle_max, 360);
1980 largest_diff = MAX(largest_diff, fabs(destAngle-bp->node[i]));
1981 largest_progress = MAX(largest_diff, fabs(bp->node[i] - model[bp->prev_model].node[i]));
1985 return MIN(largest_diff / largest_progress, 1.0);
1991 static void glsnake_idle();
1993 static restore_idle(int v __attribute__((__unused__)))
1995 glutIdleFunc(glsnake_idle);
1999 static void quick_sleep(void)
2002 /* By using glutTimerFunc we can keep responding to
2003 * mouse and keyboard events, unlike using something like
2006 glutTimerFunc(1, restore_idle, 0);
2012 static void glsnake_idle(
2014 struct glsnake_cfg * bp
2018 /* time since last iteration */
2020 /* time since the beginning of last morph */
2022 float iter_angle_max;
2023 snaketime current_time;
2024 /* morphFunc transition; */
2028 /* Do nothing to the model if we are paused */
2030 /* Avoid busy waiting when nothing is changing */
2034 glutPostRedisplay();
2039 /* <spiv> Well, ftime gives time with millisecond resolution.
2040 * <spiv> (or worse, perhaps... who knows what the OS will do)
2041 * <spiv> So if no discernable amount of time has passed:
2042 * <spiv> a) There's no point updating the screen, because
2043 * it would be the same
2044 * <spiv> b) The code will divide by zero
2046 gettime(¤t_time);
2048 iter_msec = (long) GETMSECS(current_time) - GETMSECS(bp->last_iteration) +
2049 ((long) GETSECS(current_time) - GETSECS(bp->last_iteration)) * 1000L;
2052 /* save the current time */
2053 memcpy(&bp->last_iteration, ¤t_time, sizeof(snaketime));
2055 /* work out if we have to switch models */
2056 morf_msec = GETMSECS(bp->last_iteration) - GETMSECS(bp->last_morph) +
2057 ((long) (GETSECS(bp->last_iteration)-GETSECS(bp->last_morph)) * 1000L);
2059 if ((morf_msec > statictime) && !interactive && !bp->morphing) {
2060 /*printf("starting morph\n");*/
2061 memcpy(&bp->last_morph, &(bp->last_iteration), sizeof(bp->last_morph));
2062 start_morph(bp, RAND(models), 0);
2065 if (interactive && !bp->morphing) {
2070 /* if (!bp->dragging && !bp->interactive) { */
2073 yspin += 360/((1000/yangvel)/iter_msec);
2074 zspin += 360/((1000/zangvel)/iter_msec);
2076 yspin += 360 * (yangvel/1000.0) * iter_msec;
2077 zspin += 360 * (zangvel/1000.0) * iter_msec;
2080 /*printf("yspin: %f, zspin: %f\n", yspin, zspin);*/
2084 /* work out the maximum angle we could turn this node in this
2085 * timeslice, iter_msec milliseconds long */
2086 iter_angle_max = 90.0 * (angvel/1000.0) * iter_msec;
2089 for (i = 0; i < NODE_COUNT; i++) {
2090 float cur_angle = bp->node[i];
2091 float dest_angle = model[bp->next_model].node[i];
2092 if (cur_angle != dest_angle) {
2094 if (fabs(cur_angle - dest_angle) <= iter_angle_max)
2095 bp->node[i] = dest_angle;
2096 else if (fmod(cur_angle - dest_angle + 360, 360) > 180)
2097 bp->node[i] = fmod(cur_angle + iter_angle_max, 360);
2099 bp->node[i] = fmod(cur_angle + 360 - iter_angle_max, 360);
2103 if (!still_morphing)
2106 /* colour cycling */
2111 glutPostRedisplay();
2114 /* We are going too fast, so we may as well let the
2115 * cpu relax a little by sleeping for a millisecond. */
2121 ENTRYPOINT void glsnake_display(
2128 struct glsnake_cfg * bp = &glc[MI_SCREEN(mi)];
2129 Display * dpy = MI_DISPLAY(mi);
2130 Window window = MI_WINDOW(mi);
2135 float positions[NODE_COUNT][4]; /* origin points for each node */
2136 float com[4]; /* it's the CENTRE of MASS */
2139 if (!bp->glx_context)
2142 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
2145 /* clear the buffer */
2146 glClear((GLbitfield) GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2148 /* go into the modelview stack */
2149 glMatrixMode(GL_MODELVIEW);
2152 /* get the centre of each node, by moving through the snake and
2153 * performing the rotations, then grabbing the matrix at each point
2154 * and applying it to the origin */
2158 /* apply the mouse drag rotation */
2162 /* apply the continuous rotation */
2163 glRotatef(yspin, 0.0, 1.0, 0.0);
2164 glRotatef(zspin, 0.0, 0.0, 1.0);
2170 for (i = 0; i < NODE_COUNT; i++) {
2175 /*printf("ang = %f\n", ang);*/
2177 glTranslatef(0.5, 0.5, 0.5); /* move to center */
2178 glRotatef(90.0, 0.0, 0.0, -1.0); /* reorient */
2179 glTranslatef(1.0 + explode, 0.0, 0.0); /* move to new pos. */
2180 glRotatef(180.0 + ang, 1.0, 0.0, 0.0); /* pivot to new angle */
2181 glTranslatef(-0.5, -0.5, -0.5); /* return from center */
2183 glGetFloatv(GL_MODELVIEW_MATRIX, rotmat);
2185 matmult_origin(rotmat, positions[i]);
2187 /*printf("positions %f %f %f %f\n", positions[i][0], positions[i][1], positions[i][2], positions[i][3]);*/
2189 com[0] += positions[i][0];
2190 com[1] += positions[i][1];
2191 com[2] += positions[i][2];
2192 com[3] += positions[i][3];
2195 com[0] /= NODE_COUNT;
2196 com[1] /= NODE_COUNT;
2197 com[2] /= NODE_COUNT;
2198 com[3] /= NODE_COUNT;
2204 /*printf("com: %f, %f, %f, %f\n", com[0], com[1], com[2], com[3]);*/
2206 #if MAGICAL_RED_STRING
2208 glTranslatef(-com[0], -com[1], -com[2]);
2210 glDisable(GL_LIGHTING);
2211 glColor4f(1.0, 0.0, 0.0, 1.0);
2212 glBegin(GL_LINE_STRIP);
2213 for (i = 0; i < NODE_COUNT - 1; i++) {
2214 glVertex3fv(positions[i]);
2217 glEnable(GL_LIGHTING);
2218 /*glTranslatef(com[0], com[1], com[2]);*/
2223 glTranslatef(-com[0], -com[1], -com[2]);
2226 /* apply the mouse drag rotation */
2230 /* apply the continuous rotation */
2231 glRotatef(yspin, 0.0, 1.0, 0.0);
2232 glRotatef(zspin, 0.0, 0.0, 1.0);
2234 /* now draw each node along the snake -- this is quite ugly :p */
2235 for (i = 0; i < NODE_COUNT; i++) {
2236 /* choose a colour for this node */
2237 if ((i == bp->selected || i == bp->selected+1) && interactive)
2239 glColor4f(1.0, 1.0, 0.0, 1.0);
2241 /*glColor4fv(bp->colour[(i+1)%2]);*/
2242 glMaterialfv(GL_FRONT, GL_AMBIENT, bp->colour[(i+1)%2]);
2243 glMaterialfv(GL_FRONT, GL_DIFFUSE, bp->colour[(i+1)%2]);
2244 /*glMaterialfv(GL_FRONT, GL_SPECULAR, bp->colour[(i+1)%2]);*/
2249 glCallList(bp->node_wire);
2251 glCallList(bp->node_solid);
2253 /* now work out where to draw the next one */
2255 /* Interpolate between models */
2258 glTranslatef(0.5, 0.5, 0.5); /* move to center */
2259 glRotatef(90.0, 0.0, 0.0, -1.0); /* reorient */
2260 glTranslatef(1.0 + explode, 0.0, 0.0); /* move to new pos. */
2261 glRotatef(180.0 + ang, 1.0, 0.0, 0.0); /* pivot to new angle */
2262 glTranslatef(-0.5, -0.5, -0.5); /* return from center */
2282 glXSwapBuffers(dpy, window);
2287 /* anything that needs to be cleaned up goes here */
2288 static void unmain()
2290 glutDestroyWindow(bp->window);
2294 static void ui_init(int *, char **);
2296 int main(int argc, char ** argv)
2298 bp = malloc(sizeof(struct glsnake_cfg));
2299 memset(bp, 0, sizeof(struct glsnake_cfg));
2304 ui_init(&argc, argv);
2306 gettime(&bp->last_iteration);
2307 memcpy(&bp->last_morph, &bp->last_iteration, sizeof(snaketime));
2308 srand((unsigned int)GETSECS(bp->last_iteration));
2310 bp->prev_colour = bp->next_colour = COLOUR_ACYCLIC;
2311 bp->next_model = RAND(models);
2313 start_morph(bp->prev_model, 1);
2331 /* trackball quaternions */
2332 static float cumquat[4] = {0.0,0.0,0.0,0.0}, oldquat[4] = {0.0,0.0,0.0,0.1};
2334 /* rotation matrix */
2335 static float rotation[16];
2337 /* mouse drag vectors: start and end */
2338 static float mouse_start[3], mouse_end[3];
2340 /* dragging boolean */
2341 static int dragging = 0;
2343 /* this function calculates the rotation matrix based on the quaternions
2344 * generated from the mouse drag vectors */
2345 static void calc_rotation()
2348 double xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
2350 /* this bit ripped from Shoemake's quaternion notes from SIGGRAPH */
2351 Nq = cumquat[0] * cumquat[0] + cumquat[1] * cumquat[1] +
2352 cumquat[2] * cumquat[2] + cumquat[3] * cumquat[3];
2353 s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
2354 xs = cumquat[0] * s; ys = cumquat[1] * s; zs = cumquat[2] * s;
2355 wx = cumquat[3] * xs; wy = cumquat[3] * ys; wz = cumquat[3] * zs;
2356 xx = cumquat[0] * xs; xy = cumquat[0] * ys; xz = cumquat[0] * zs;
2357 yy = cumquat[1] * ys; yz = cumquat[1] * zs; zz = cumquat[2] * zs;
2359 rotation[0] = 1.0 - (yy + zz);
2360 rotation[1] = xy + wz;
2361 rotation[2] = xz - wy;
2362 rotation[4] = xy - wz;
2363 rotation[5] = 1.0 - (xx + zz);
2364 rotation[6] = yz + wx;
2365 rotation[8] = xz + wy;
2366 rotation[9] = yz - wx;
2367 rotation[10] = 1.0 - (xx + yy);
2368 rotation[3] = rotation[7] = rotation[11] = 0.0;
2369 rotation[12] = rotation[13] = rotation[14] = 0.0;
2373 static inline void ui_mousedrag()
2375 glMultMatrixf(rotation);
2378 static void ui_keyboard(unsigned char c, int x__attribute__((__unused__)), int y __attribute__((__unused__)))
2388 explode += DEF_EXPLODE;
2389 glutPostRedisplay();
2392 explode -= DEF_EXPLODE;
2393 if (explode < 0.0) explode = 0.0;
2394 glutPostRedisplay();
2399 bp->next_model %= models;
2400 start_morph(bp->next_model, 0);
2402 /* Reset last_morph time */
2403 gettime(&bp->last_morph);
2406 /* previous model */
2407 bp->next_model = (bp->next_model + (int)models - 1) % (int)models;
2408 start_morph(bp->next_model, 0);
2410 /* Reset bp->last_morph time */
2411 gettime(&bp->last_morph);
2414 angvel += DEF_ANGVEL;
2417 if (angvel > DEF_ANGVEL)
2418 angvel -= DEF_ANGVEL;
2422 /* Reset last_iteration and last_morph time */
2423 gettime(&bp->last_iteration);
2424 gettime(&bp->last_morph);
2426 interactive = 1 - interactive;
2427 glutPostRedisplay();
2430 wireframe = 1 - wireframe;
2432 glDisable(GL_LIGHTING);
2434 glEnable(GL_LIGHTING);
2435 glutPostRedisplay();
2438 transparent = 1 - transparent;
2442 glDisable(GL_BLEND);
2447 /* unpausing, reset last_iteration and last_morph time */
2448 gettime(&bp->last_iteration);
2449 gettime(&bp->last_morph);
2451 bp->paused = 1 - bp->paused;
2454 /* dump the current model so we can add it! */
2455 printf("# %s\nnoname:\t", model[bp->next_model].name);
2459 for (i = 0; i < NODE_COUNT; i++) {
2460 if (bp->node[i] == ZERO)
2462 else if (bp->node[i] == LEFT)
2464 else if (bp->node[i] == PIN)
2466 else if (bp->node[i] == RIGHT)
2470 printf("%f", node[i].curAngle);
2472 if (i < NODE_COUNT - 1)
2479 bp->fullscreen = 1 - bp->fullscreen;
2480 if (bp->fullscreen) {
2481 bp->old_width = bp->width;
2482 bp->old_height = bp->height;
2485 glutReshapeWindow(bp->old_width, bp->old_height);
2486 glutPositionWindow(50,50);
2490 titles = 1 - titles;
2491 if (interactive || bp->paused)
2492 glutPostRedisplay();
2495 altcolour = 1 - altcolour;
2499 glsnake_reshape(bp->width, bp->height);
2503 glsnake_reshape(bp->width, bp->height);
2510 static void ui_special(int key, int x__attribute__((__unused__)), int y __attribute__((__unused__)))
2512 float *destAngle = &(model[bp->next_model].node[bp->selected]);
2513 int unknown_key = 0;
2518 bp->selected = (bp->selected + (NODE_COUNT - 2)) % (NODE_COUNT - 1);
2521 bp->selected = (bp->selected + 1) % (NODE_COUNT - 1);
2524 *destAngle = fmod(*destAngle+(LEFT), 360);
2525 bp->morphing = bp->new_morph = 1;
2527 case GLUT_KEY_RIGHT:
2528 *destAngle = fmod(*destAngle+(RIGHT), 360);
2529 bp->morphing = bp->new_morph = 1;
2532 start_morph(STRAIGHT_MODEL, 0);
2539 calc_snake_metrics();
2542 glutPostRedisplay();
2545 static void ui_mouse(int button, int state, int x, int y)
2551 mouse_start[0] = M_SQRT1_2 *
2552 (x - (bp->width / 2.0)) / (bp->width / 2.0);
2553 mouse_start[1] = M_SQRT1_2 *
2554 ((bp->height / 2.0) - y) / (bp->height / 2.0);
2555 mouse_start[2] = sqrt((double)(1-(mouse_start[0]*mouse_start[0]+mouse_start[1]*mouse_start[1])));
2559 oldquat[0] = cumquat[0];
2560 oldquat[1] = cumquat[1];
2561 oldquat[2] = cumquat[2];
2562 oldquat[3] = cumquat[3];
2568 glutPostRedisplay();
2571 static void ui_motion(int x, int y)
2577 /* construct the motion end vector from the x,y position on the
2579 mouse_end[0] = M_SQRT1_2 * (x - (bp->width/ 2.0)) / (bp->width / 2.0);
2580 mouse_end[1] = M_SQRT1_2 * ((bp->height / 2.0) - y) / (bp->height / 2.0);
2581 /* calculate the normal of the vector... */
2582 norm = mouse_end[0] * mouse_end[0] + mouse_end[1] * mouse_end[1];
2583 /* check if norm is outside the sphere and wraparound if necessary */
2585 mouse_end[0] = -mouse_end[0];
2586 mouse_end[1] = -mouse_end[1];
2587 mouse_end[2] = sqrt(norm - 1);
2589 /* the z value comes from projecting onto an elliptical spheroid */
2590 mouse_end[2] = sqrt(1 - norm);
2593 /* now here, build a quaternion from mouse_start and mouse_end */
2594 q[0] = mouse_start[1] * mouse_end[2] - mouse_start[2] * mouse_end[1];
2595 q[1] = mouse_start[2] * mouse_end[0] - mouse_start[0] * mouse_end[2];
2596 q[2] = mouse_start[0] * mouse_end[1] - mouse_start[1] * mouse_end[0];
2597 q[3] = mouse_start[0] * mouse_end[0] + mouse_start[1] * mouse_end[1] + mouse_start[2] * mouse_end[2];
2599 /* new rotation is the product of the new one and the old one */
2600 cumquat[0] = q[3] * oldquat[0] + q[0] * oldquat[3] +
2601 q[1] * oldquat[2] - q[2] * oldquat[1];
2602 cumquat[1] = q[3] * oldquat[1] + q[1] * oldquat[3] +
2603 q[2] * oldquat[0] - q[0] * oldquat[2];
2604 cumquat[2] = q[3] * oldquat[2] + q[2] * oldquat[3] +
2605 q[0] * oldquat[1] - q[1] * oldquat[0];
2606 cumquat[3] = q[3] * oldquat[3] - q[0] * oldquat[0] -
2607 q[1] * oldquat[1] - q[2] * oldquat[2];
2611 glutPostRedisplay();
2614 static void ui_init(int * argc, char ** argv)
2616 glutInit(argc, argv);
2617 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
2618 glutInitWindowSize(bp->width, bp->height);
2619 bp->window = glutCreateWindow("glsnake");
2621 glutDisplayFunc(glsnake_display);
2622 glutReshapeFunc(glsnake_reshape);
2623 glutIdleFunc(glsnake_idle);
2624 glutKeyboardFunc(ui_keyboard);
2625 glutSpecialFunc(ui_special);
2626 glutMouseFunc(ui_mouse);
2627 glutMotionFunc(ui_motion);
2629 yangvel = DEF_YANGVEL;
2630 zangvel = DEF_ZANGVEL;
2631 explode = DEF_EXPLODE;
2632 angvel = DEF_ANGVEL;
2633 statictime = DEF_STATICTIME;
2634 altcolour = DEF_ALTCOLOUR;
2635 titles = DEF_TITLES;
2636 interactive = DEF_INTERACTIVE;
2638 wireframe = DEF_WIREFRAME;
2639 transparent = DEF_TRANSPARENT;
2641 #endif /* HAVE_GLUT */
2643 XSCREENSAVER_MODULE ("GLSnake", glsnake)