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" \
156 #define countof(x) (sizeof((x))/sizeof((*x)))
158 #include "xlockmore.h"
161 static XrmOptionDescRec opts[] = {
162 { "-explode", ".explode", XrmoptionSepArg, DEF_EXPLODE },
163 { "-angvel", ".angvel", XrmoptionSepArg, DEF_ANGVEL },
164 { "-statictime", ".statictime", XrmoptionSepArg, DEF_STATICTIME },
165 { "-yangvel", ".yangvel", XrmoptionSepArg, DEF_YANGVEL },
166 { "-zangvel", ".zangvel", XrmoptionSepArg, DEF_ZANGVEL },
167 { "-altcolour", ".altcolour", XrmoptionNoArg, "True" },
168 { "-no-altcolour", ".altcolour", XrmoptionNoArg, "False" },
169 { "-titles", ".titles", XrmoptionNoArg, "True" },
170 { "-no-titles", ".titles", XrmoptionNoArg, "False" },
171 { "-zoom", ".zoom", XrmoptionSepArg, DEF_ZOOM },
172 { "-wireframe", ".wireframe", XrmoptionNoArg, "true" },
173 { "-no-wireframe", ".wireframe", XrmoptionNoArg, "false" },
174 { "-transparent", ".transparent", XrmoptionNoArg, "true" },
175 { "-no-transparent", ".transparent", XrmoptionNoArg, "false" },
178 static argtype vars[] = {
179 {&explode, "explode", "Explode", DEF_EXPLODE, t_Float},
180 {&angvel, "angvel", "Angular Velocity", DEF_ANGVEL, t_Float},
181 {&statictime, "statictime", "Static Time", DEF_STATICTIME, t_Int},
182 {&yangvel, "yangvel", "Angular Velocity about Y axis", DEF_YANGVEL, t_Float},
183 {&zangvel, "zangvel", "Angular Velocity about X axis", DEF_ZANGVEL, t_Float},
184 {&interactive, "interactive", "Interactive", DEF_INTERACTIVE, t_Bool},
185 {&altcolour, "altcolour", "Alternate Colour Scheme", DEF_ALTCOLOUR, t_Bool},
186 {&titles, "titles", "Titles", DEF_TITLES, t_Bool},
187 {&zoom, "zoom", "Zoom", DEF_ZOOM, t_Float},
188 {&wireframe, "wireframe", "Wireframe", DEF_WIREFRAME, t_Bool},
189 {&transparent, "transparent", "Transparent!", DEF_TRANSPARENT, t_Bool},
192 ENTRYPOINT ModeSpecOpt glsnake_opts = {countof(opts), opts, countof(vars), vars, NULL};
197 float node[NODE_COUNT];
202 GLXContext * glx_context;
203 texture_font_data *font_data;
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;
254 /* is the window fullscreen? */
258 #define COLOUR_CYCLIC 0
259 #define COLOUR_ACYCLIC 1
260 #define COLOUR_INVALID 2
261 #define COLOUR_AUTHENTIC 3
262 #define COLOUR_ORIGLOGO 4
264 static const float colour[][2][4] = {
266 { { 0.4, 0.8, 0.2, 0.6 },
267 { 1.0, 1.0, 1.0, 0.6 } },
269 { { 0.3, 0.1, 0.9, 0.6 },
270 { 1.0, 1.0, 1.0, 0.6 } },
272 { { 0.3, 0.1, 0.9, 0.6 },
273 { 1.0, 1.0, 1.0, 0.6 } },
274 /* authentic - purple and green */
275 { { 0.38, 0.0, 0.55, 0.7 },
276 { 0.0, 0.5, 0.34, 0.7 } },
277 /* old "authentic" colours from the logo */
278 { { 171/255.0, 0, 1.0, 1.0 },
279 { 46/255.0, 205/255.0, 227/255.0, 1.0 } }
282 static const struct model_s model[] = {
283 #define STRAIGHT_MODEL 0
285 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
286 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
289 /* the models in the Rubik's snake manual */
291 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT,
292 RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT,
293 RIGHT, LEFT, RIGHT, LEFT, ZERO }
295 #define START_MODEL 2
297 { RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT,
298 RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT,
299 RIGHT, LEFT, LEFT, LEFT, ZERO }
302 { ZERO, ZERO, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO, ZERO,
303 ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO, ZERO, ZERO, RIGHT,
304 LEFT, RIGHT, ZERO, LEFT }
307 { ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, RIGHT, PIN,
308 RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, ZERO, ZERO,
312 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN,
313 ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
317 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, LEFT, RIGHT, PIN, RIGHT,
318 ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, LEFT, ZERO,
321 /* These models were taken from Andrew and Peter's original snake.c
322 * as well as some newer ones made up by Jamie, Andrew and Peter. */
324 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT,
325 LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT,
326 RIGHT, LEFT, LEFT, LEFT, ZERO }
329 { RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT,
330 LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT,
331 RIGHT, RIGHT, LEFT, LEFT, ZERO }
334 { PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN,
335 ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN,
339 { PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN,
340 LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN,
344 { RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT,
345 LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN,
349 { RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT,
350 LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT,
351 RIGHT, RIGHT, LEFT, LEFT, ZERO }
354 { ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT,
355 LEFT, RIGHT, LEFT, LEFT, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT,
356 RIGHT, RIGHT, RIGHT, ZERO }
359 { RIGHT, PIN, ZERO, ZERO, PIN, LEFT, ZERO, LEFT, LEFT, ZERO,
360 LEFT, PIN, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO,
364 { PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT,
365 LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT,
366 RIGHT, LEFT, LEFT, ZERO }
369 { ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO,
370 ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO,
371 LEFT, ZERO, ZERO, RIGHT }
374 { ZERO, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO, RIGHT, ZERO, ZERO,
375 LEFT, RIGHT, ZERO, LEFT, ZERO, RIGHT, ZERO, ZERO, LEFT, RIGHT,
376 ZERO, LEFT, ZERO, RIGHT }
379 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO,
380 ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO,
381 ZERO, ZERO, LEFT, RIGHT }
384 { ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT,
385 RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN,
389 { ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN,
390 PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN }
393 { PIN, RIGHT, LEFT, PIN, LEFT, PIN, ZERO, ZERO, RIGHT, PIN, LEFT,
394 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
398 { ZERO, ZERO, ZERO, ZERO, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT,
399 ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT,
400 LEFT, ZERO, PIN, ZERO }
403 { RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO,
404 LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, PIN, RIGHT,
408 { ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN,
409 ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO }
412 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, LEFT, PIN,
413 RIGHT, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT,
414 RIGHT, LEFT, LEFT, ZERO }
417 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, ZERO, ZERO,
418 RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO, LEFT, LEFT,
419 RIGHT, LEFT, RIGHT, RIGHT, ZERO }
422 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, PIN, ZERO, ZERO,
423 LEFT, PIN, RIGHT, ZERO, ZERO, PIN, ZERO, LEFT, LEFT, RIGHT, LEFT,
427 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO,
428 RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT,
432 { LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT,
433 ZERO, ZERO, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN,
437 { RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN,
438 LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT,
442 { RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN,
443 LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT,
444 LEFT, PIN, LEFT, PIN }
447 { ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN,
448 ZERO, PIN, ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT,
452 { ZERO, PIN, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, PIN,
453 ZERO, PIN, ZERO, PIN, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO,
457 { ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN,
458 ZERO, PIN, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
462 { ZERO, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT,
463 ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
467 { ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO,
468 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
472 { ZERO, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, ZERO,
473 ZERO, PIN, ZERO, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO,
477 { RIGHT, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, ZERO,
478 LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT,
479 ZERO, ZERO, LEFT, PIN }
482 { RIGHT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT,
483 ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT,
484 LEFT, RIGHT, ZERO, LEFT, PIN }
487 { RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO,
488 LEFT, PIN, RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT,
492 { ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, ZERO,
493 ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT,
497 { ZERO, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN,
498 RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT,
502 { LEFT, PIN, LEFT, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, LEFT,
503 PIN, RIGHT, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN,
507 { RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, ZERO,
508 ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, RIGHT, RIGHT, LEFT,
509 RIGHT, LEFT, LEFT, LEFT, PIN }
512 { ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, RIGHT,
513 RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT,
514 PIN, LEFT, LEFT, LEFT }
517 { PIN, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, LEFT,
518 ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, LEFT, ZERO,
519 LEFT, RIGHT, ZERO, ZERO }
522 { PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, RIGHT,
523 RIGHT, PIN, RIGHT, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO,
524 ZERO, PIN, PIN, ZERO }
527 /* the following modesl were created during the slug/compsoc codefest
529 { "cool looking gegl",
530 { PIN, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT,
531 ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, ZERO,
535 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN,
536 PIN, ZERO, RIGHT, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO,
540 { RIGHT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT,
541 RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN,
542 RIGHT, LEFT, RIGHT, PIN, ZERO }
545 { ZERO, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO,
546 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
550 { LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO,
551 RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT,
552 RIGHT, ZERO, LEFT, ZERO }
554 { "not very good (but accurate) gegl",
555 { ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO,
556 PIN, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO, PIN, PIN, ZERO,
560 { ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
561 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO,
565 { PIN, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
566 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO,
569 { "erect penis", /* thanks benno */
570 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, PIN,
571 PIN, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
575 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, PIN,
576 PIN, ZERO, ZERO, ZERO, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
580 { RIGHT, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO,
581 LEFT, ZERO, ZERO, ZERO, LEFT, ZERO, LEFT, PIN, LEFT, PIN, RIGHT,
585 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN,
586 ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO,
589 { "poles or columns or something",
590 { LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
591 ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
595 { ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
596 ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
600 { ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO,
601 LEFT, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
605 { ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO,
606 LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO,
607 LEFT, PIN, ZERO, ZERO }
610 { ZERO, ZERO, PIN, RIGHT, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO,
611 LEFT, PIN, ZERO, ZERO, PIN, ZERO, LEFT, ZERO, RIGHT, LEFT, ZERO,
615 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
616 RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
620 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
621 ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
625 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
626 LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
630 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
631 PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
635 { RIGHT, ZERO, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT,
636 RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT,
637 ZERO, ZERO, RIGHT, ZERO }
640 { RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT,
641 ZERO, RIGHT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, ZERO,
642 RIGHT, ZERO, RIGHT, ZERO, ZERO }
645 /* These models come from the website at
646 * http://www.geocities.com/stigeide/snake */
649 { RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO }
653 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, ZERO }
656 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, ZERO }
659 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, ZERO }
662 { ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, ZERO, ZERO }
665 { RIGHT, LEFT, RIGHT, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO, PIN, PIN, ZERO }
668 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO }
671 { LEFT, PIN, RIGHT, ZERO, ZERO, PIN, RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO }
674 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT , ZERO }
677 { ZERO, RIGHT, RIGHT, ZERO, RIGHT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, ZERO, LEFT , ZERO }
680 { PIN, LEFT, RIGHT, ZERO, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, LEFT, RIGHT, PIN, RIGHT , ZERO }
683 { PIN, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, PIN , ZERO }
686 { LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT , ZERO }
689 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT , ZERO }
692 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, PIN , ZERO }
695 { PIN, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, ZERO , ZERO }
698 { RIGHT, ZERO, PIN, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, ZERO, ZERO, LEFT , ZERO }
701 { LEFT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT , ZERO }
704 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO , ZERO }
707 { RIGHT, ZERO, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO , ZERO }
710 { PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO , ZERO }
713 { RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, LEFT, RIGHT, LEFT, LEFT , ZERO }
716 { RIGHT, RIGHT, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, LEFT, LEFT , ZERO }
719 { RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT , ZERO }
722 { ZERO, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, LEFT, ZERO, LEFT, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT , ZERO }
726 { LEFT, ZERO, PIN, ZERO, PIN, LEFT, ZERO, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, PIN, ZERO, RIGHT , ZERO }
730 { ZERO, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, LEFT , ZERO }
733 { ZERO, ZERO, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN , ZERO }
736 { LEFT, PIN, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO , ZERO }
739 { ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN , ZERO }
742 { PIN, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO , ZERO }
745 { LEFT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT , ZERO }
748 { PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, RIGHT, PIN , ZERO }
751 { RIGHT, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, LEFT , ZERO }
754 { ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO, PIN , ZERO }
756 { "Counterclockwise",
757 { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT , ZERO }
760 { LEFT, LEFT, ZERO, PIN, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, RIGHT, LEFT, LEFT, ZERO, ZERO, RIGHT , ZERO }
763 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, PIN, RIGHT , ZERO }
766 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN , ZERO }
769 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO , ZERO }
772 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, ZERO }
775 { PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, ZERO }
778 { RIGHT, LEFT, PIN, LEFT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, LEFT, PIN, LEFT, RIGHT, ZERO }
781 { LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, PIN, ZERO, ZERO }
784 { RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, ZERO }
787 { ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO }
790 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, LEFT, RIGHT, ZERO }
793 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, LEFT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, RIGHT, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
796 { ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, LEFT, ZERO, PIN, ZERO, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, ZERO }
799 { ZERO, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO }
802 { ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO }
805 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO }
808 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO, RIGHT, ZERO, RIGHT, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO }
811 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, RIGHT, ZERO, RIGHT, LEFT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO }
814 { PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, ZERO }
817 { PIN, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO }
820 { ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO }
823 { LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, ZERO }
826 { LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, ZERO }
829 { RIGHT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, ZERO }
832 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, ZERO }
835 { ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO }
838 { LEFT, LEFT, RIGHT, PIN, ZERO, RIGHT, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, LEFT, ZERO, PIN, LEFT, RIGHT, RIGHT, RIGHT, PIN, ZERO }
841 { PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
844 { ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, RIGHT, ZERO, PIN, ZERO }
847 { ZERO, RIGHT, ZERO, PIN, LEFT, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, RIGHT, PIN, ZERO, LEFT, ZERO, ZERO }
850 { ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, ZERO, ZERO, ZERO, PIN, ZERO }
853 { ZERO, PIN, PIN, ZERO, PIN, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO }
856 { ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO }
859 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO }
862 { LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, RIGHT, LEFT, RIGHT, RIGHT, ZERO }
865 { LEFT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, ZERO, RIGHT, ZERO }
868 { PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO }
871 { ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO }
874 { LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO }
877 { RIGHT, LEFT, ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, LEFT, ZERO, ZERO }
880 { PIN, PIN, ZERO, LEFT, RIGHT, LEFT, ZERO, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO }
883 { PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO }
886 { PIN, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO }
889 { RIGHT, ZERO, ZERO, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, RIGHT, ZERO, PIN, ZERO, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO, ZERO, ZERO, LEFT, ZERO }
892 { ZERO, PIN, ZERO, ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO }
895 { ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO }
897 { "HoleInTheMiddle1",
898 { ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO }
900 { "HoleInTheMiddle2",
901 { ZERO, LEFT, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO }
904 { RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, ZERO }
907 { LEFT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, ZERO }
910 { LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO }
913 { RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
916 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO }
919 { RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, LEFT, ZERO }
922 { ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO }
925 { LEFT, LEFT, PIN, LEFT, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, RIGHT, PIN, RIGHT, RIGHT, LEFT, ZERO }
928 { ZERO, PIN, PIN, ZERO, ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO }
931 { RIGHT, PIN, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, PIN, LEFT, ZERO }
934 { PIN, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO }
937 { PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, ZERO }
939 { "magnifying glass",
940 { ZERO, ZERO, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, ZERO }
943 { ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, ZERO }
946 { PIN, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO }
949 { PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO }
952 { ZERO, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, LEFT, PIN, RIGHT, RIGHT, ZERO, RIGHT, ZERO }
955 { ZERO, RIGHT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, ZERO, RIGHT, RIGHT, PIN, LEFT, ZERO }
958 { LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
961 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, LEFT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO }
964 { ZERO, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO }
966 { "MouseWithoutTail",
967 { ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO }
970 { PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, ZERO }
973 { ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO }
976 { LEFT, ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, ZERO }
979 { ZERO, RIGHT, PIN, LEFT, LEFT, LEFT, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO }
982 { LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, ZERO }
985 { PIN, ZERO, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, ZERO, ZERO }
988 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, ZERO }
991 { PIN, PIN, ZERO, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
994 { ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
997 { ZERO, ZERO, ZERO, ZERO, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO }
1000 { PIN, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, PIN, ZERO }
1002 { "PictureComingSoon",
1003 { LEFT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, RIGHT, RIGHT, ZERO }
1006 { LEFT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, ZERO }
1009 { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, ZERO }
1012 { RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO }
1015 { ZERO, PIN, ZERO, PIN, RIGHT, PIN, ZERO, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, ZERO, PIN, LEFT, ZERO }
1019 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO }
1023 { RIGHT, PIN, ZERO, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, PIN, ZERO, PIN, LEFT, ZERO }
1026 { ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, ZERO }
1029 { ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, LEFT, ZERO }
1031 { "QuarterbackTiltedAndReadyToHut",
1032 { PIN, ZERO, RIGHT, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, LEFT, ZERO, PIN, ZERO }
1035 { PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1038 { LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, PIN, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, ZERO }
1041 { ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, ZERO }
1044 { LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, ZERO }
1047 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1050 { RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, ZERO }
1053 { ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO }
1056 { PIN, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, PIN, ZERO }
1059 { RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1062 { RIGHT, LEFT, PIN, ZERO, ZERO, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO }
1065 { LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO }
1068 { RIGHT, PIN, ZERO, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO }
1071 { RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, ZERO }
1074 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO }
1077 { PIN, RIGHT, LEFT, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, LEFT, ZERO, PIN, PIN, ZERO }
1080 { LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO }
1083 { LEFT, RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, RIGHT, LEFT, ZERO }
1086 { ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO }
1088 { "SnakeReadyToStrike",
1089 { LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO }
1092 { RIGHT, RIGHT, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO }
1095 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO }
1098 { PIN, PIN, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
1101 { LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, ZERO }
1104 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO }
1107 { PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, ZERO }
1110 { PIN, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, PIN, ZERO }
1113 { PIN, PIN, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, LEFT, LEFT, PIN, PIN, ZERO }
1116 { LEFT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, ZERO }
1119 { PIN, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, ZERO, RIGHT, PIN, LEFT, ZERO }
1122 { RIGHT, RIGHT, ZERO, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, RIGHT, LEFT, RIGHT, ZERO, ZERO, LEFT, ZERO }
1125 { PIN, LEFT, ZERO, RIGHT, RIGHT, LEFT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, LEFT, LEFT, ZERO, ZERO }
1128 { ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, ZERO }
1131 { PIN, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO }
1134 { RIGHT, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, ZERO }
1137 { ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO }
1140 { ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
1143 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO }
1146 { ZERO, PIN, ZERO, PIN, LEFT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, ZERO }
1149 { PIN, ZERO, PIN, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO }
1152 { PIN, PIN, ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO }
1155 { RIGHT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, RIGHT, ZERO }
1158 { RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO }
1161 { ZERO, PIN, LEFT, LEFT, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1164 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, RIGHT, PIN, ZERO }
1167 { ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO }
1170 { ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO }
1173 { RIGHT, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, ZERO }
1176 { RIGHT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO }
1179 { RIGHT, LEFT, ZERO, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO }
1182 { PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO }
1185 { RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, PIN, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO }
1188 { RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, ZERO }
1191 { ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, LEFT, LEFT, PIN, ZERO, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, ZERO }
1194 { PIN, LEFT, LEFT, PIN, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO }
1197 { PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO }
1200 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO }
1203 { PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, ZERO }
1207 { RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO }
1211 { ZERO, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO, ZERO }
1214 { ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, ZERO }
1217 { PIN, LEFT, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, ZERO, ZERO }
1220 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1223 { LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO }
1226 { ZERO, PIN, ZERO, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, ZERO }
1229 { ZERO, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, ZERO }
1232 { PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO }
1235 { ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO }
1238 { PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, PIN, RIGHT, ZERO, RIGHT, RIGHT, ZERO, RIGHT, PIN, ZERO, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, ZERO }
1241 { ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1244 { LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO }
1247 { PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO }
1250 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO }
1252 { "WindowToTheWorld",
1253 { PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
1256 { PIN, PIN, ZERO, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, PIN, ZERO }
1259 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO }
1262 { RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO }
1265 { PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, ZERO }
1268 { ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO }
1271 { LEFT, ZERO, ZERO, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, ZERO, ZERO, ZERO }
1275 static size_t models = sizeof(model) / sizeof(struct model_s);
1277 #define VOFFSET 0.045
1283 /* the connecting string that holds the snake together */
1284 #define MAGICAL_RED_STRING 0
1286 #define GETSCALAR(vec,mask) ((vec)==(mask) ? 1 : ((vec)==-(mask) ? -1 : 0 ))
1289 # define MAX(x, y) ((x) > (y) ? (x) : (y))
1292 # define MIN(x, y) ((x) < (y) ? (x) : (y))
1295 #define RAND(n) ((random() & 0x7fffffff) % ((long) (n)))
1296 #define RANDSIGN() ((random() & 1) ? 1 : -1)
1298 /* the triangular prism what makes up the basic unit */
1299 static const float solid_prism_v[][3] = {
1300 /* first corner, bottom left front */
1301 { VOFFSET, VOFFSET, 1.0 },
1302 { VOFFSET, 0.00, 1.0 - VOFFSET },
1303 { 0.00, VOFFSET, 1.0 - VOFFSET },
1304 /* second corner, rear */
1305 { VOFFSET, VOFFSET, 0.00 },
1306 { VOFFSET, 0.00, VOFFSET },
1307 { 0.00, VOFFSET, VOFFSET },
1308 /* third, right front */
1309 { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 1.0 },
1310 { 1.0 - VOFFSET / M_SQRT1_2, 0.0, 1.0 - VOFFSET },
1311 { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, 1.0 - VOFFSET },
1312 /* fourth, right rear */
1313 { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 0.0 },
1314 { 1.0 - VOFFSET / M_SQRT1_2, 0.0, VOFFSET },
1315 { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, VOFFSET },
1316 /* fifth, upper front */
1317 { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 1.0 },
1318 { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, 1.0 - VOFFSET },
1319 { 0.0, 1.0 - VOFFSET / M_SQRT1_2, 1.0 - VOFFSET},
1320 /* sixth, upper rear */
1321 { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 0.0 },
1322 { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, VOFFSET },
1323 { 0.0, 1.0 - VOFFSET / M_SQRT1_2, VOFFSET }};
1325 static const float solid_prism_n[][3] = {/* corners */
1326 { -VOFFSET, -VOFFSET, VOFFSET },
1327 { VOFFSET, -VOFFSET, VOFFSET },
1328 { -VOFFSET, VOFFSET, VOFFSET },
1329 { -VOFFSET, -VOFFSET, -VOFFSET },
1330 { VOFFSET, -VOFFSET, -VOFFSET },
1331 { -VOFFSET, VOFFSET, -VOFFSET },
1333 { -VOFFSET, 0.0, VOFFSET },
1334 { 0.0, -VOFFSET, VOFFSET },
1335 { VOFFSET, VOFFSET, VOFFSET },
1336 { -VOFFSET, 0.0, -VOFFSET },
1337 { 0.0, -VOFFSET, -VOFFSET },
1338 { VOFFSET, VOFFSET, -VOFFSET },
1339 { -VOFFSET, -VOFFSET, 0.0 },
1340 { VOFFSET, -VOFFSET, 0.0 },
1341 { -VOFFSET, VOFFSET, 0.0 },
1345 { M_SQRT1_2, M_SQRT1_2, 0.0 },
1347 { 0.0, 0.0, -1.0 }};
1349 static const float wire_prism_v[][3] = {{ 0.0, 0.0, 1.0 },
1357 static const float wire_prism_n[][3] = {{ 0.0, 0.0, 1.0},
1359 { M_SQRT1_2, M_SQRT1_2, 0.0},
1364 static struct glsnake_cfg * glc = NULL;
1369 typedef float (*morphFunc)(long);
1372 /* forward definitions for GLUT functions */
1373 static void calc_rotation();
1374 static inline void ui_mousedrag();
1377 static const GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };
1378 static const GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
1379 static const GLfloat mat_specular[] = { 0.1, 0.1, 0.1, 1.0 };
1380 static const GLfloat mat_shininess[] = { 20.0 };
1382 static void gl_init(
1388 float light_pos[][3] = {{0.0, 10.0, 20.0}, {0.0, 20.0, -1.0}};
1389 float light_dir[][3] = {{0.0, -10.0,-20.0}, {0.0,-20.0, 1.0}};
1391 glEnable(GL_DEPTH_TEST);
1392 glShadeModel(GL_SMOOTH);
1393 glCullFace(GL_BACK);
1394 /*glEnable(GL_CULL_FACE);*/
1395 glEnable(GL_NORMALIZE);
1397 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1402 /*glColor4f(1.0, 1.0, 1.0, 1.0);*/
1403 glLightfv(GL_LIGHT0, GL_POSITION, light_pos[0]);
1404 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_dir[0]);
1405 glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
1406 /*glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);*/
1408 glLightfv(GL_LIGHT1, GL_POSITION, light_pos[1]);
1409 glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light_dir[1]);
1410 glLightfv(GL_LIGHT1, GL_DIFFUSE, white_light);
1411 glLightfv(GL_LIGHT1, GL_SPECULAR, white_light);
1413 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
1414 glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
1415 glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
1416 glEnable(GL_LIGHTING);
1417 glEnable(GL_LIGHT0);
1418 glEnable(GL_LIGHT1);
1419 /*glEnable(GL_COLOR_MATERIAL);*/
1423 static void gettime(snaketime *t)
1425 #ifdef HAVE_GETTIMEOFDAY
1426 #ifdef GETTIMEOFDAY_TWO_ARGS
1427 struct timezone tzp;
1428 gettimeofday(t, &tzp);
1429 #else /* !GETTIMEOFDAY_TWO_ARGS */
1431 #endif /* !GETTIMEOFDAY_TWO_ARGS */
1432 #else /* !HAVE_GETTIMEOFDAY */
1435 #endif /* HAVE_FTIME */
1436 #endif /* !HAVE_GETTIMEOFDAY */
1440 ENTRYPOINT void glsnake_reshape(
1446 static void start_morph(struct glsnake_cfg *,
1447 unsigned int model_index, int immediate);
1449 /* wot initialises it */
1450 ENTRYPOINT void glsnake_init(
1457 struct glsnake_cfg * bp;
1459 /* set up the conf struct and glx contexts */
1461 glc = (struct glsnake_cfg *) calloc(MI_NUM_SCREENS(mi), sizeof(struct glsnake_cfg));
1463 fprintf(stderr, "%s: out of memory\n", progname);
1467 bp = &glc[MI_SCREEN(mi)];
1469 if ((bp->glx_context = init_GL(mi)) != NULL) {
1471 glsnake_reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1477 /* initialise conf struct */
1478 memset(&bp->node, 0, sizeof(float) * NODE_COUNT);
1488 gettime(&bp->last_iteration);
1489 memcpy(&bp->last_morph, &bp->last_iteration, sizeof(bp->last_morph));
1491 bp->prev_colour = bp->next_colour = COLOUR_ACYCLIC;
1492 bp->next_model = RAND(models);
1493 bp->prev_model = START_MODEL;
1494 start_morph(bp, bp->prev_model, 1);
1496 /* set up a font for the labels */
1499 bp->font_data = load_texture_font (mi->dpy, "labelfont");
1502 /* build a solid display list */
1503 bp->node_solid = glGenLists(1);
1504 glNewList(bp->node_solid, GL_COMPILE);
1506 glBegin(GL_TRIANGLES);
1507 glNormal3fv(solid_prism_n[0]);
1508 glVertex3fv(solid_prism_v[0]);
1509 glVertex3fv(solid_prism_v[2]);
1510 glVertex3fv(solid_prism_v[1]);
1513 glNormal3fv(solid_prism_n[1]);
1514 glVertex3fv(solid_prism_v[6]);
1515 glVertex3fv(solid_prism_v[7]);
1516 glVertex3fv(solid_prism_v[8]);
1519 glNormal3fv(solid_prism_n[2]);
1520 glVertex3fv(solid_prism_v[12]);
1521 glVertex3fv(solid_prism_v[13]);
1522 glVertex3fv(solid_prism_v[14]);
1525 glNormal3fv(solid_prism_n[3]);
1526 glVertex3fv(solid_prism_v[3]);
1527 glVertex3fv(solid_prism_v[4]);
1528 glVertex3fv(solid_prism_v[5]);
1531 glNormal3fv(solid_prism_n[4]);
1532 glVertex3fv(solid_prism_v[9]);
1533 glVertex3fv(solid_prism_v[11]);
1534 glVertex3fv(solid_prism_v[10]);
1537 glNormal3fv(solid_prism_n[5]);
1538 glVertex3fv(solid_prism_v[16]);
1539 glVertex3fv(solid_prism_v[15]);
1540 glVertex3fv(solid_prism_v[17]);
1546 glNormal3fv(solid_prism_n[6]);
1547 glVertex3fv(solid_prism_v[0]);
1548 glVertex3fv(solid_prism_v[12]);
1549 glVertex3fv(solid_prism_v[14]);
1550 glVertex3fv(solid_prism_v[2]);
1553 glNormal3fv(solid_prism_n[7]);
1554 glVertex3fv(solid_prism_v[0]);
1555 glVertex3fv(solid_prism_v[1]);
1556 glVertex3fv(solid_prism_v[7]);
1557 glVertex3fv(solid_prism_v[6]);
1560 glNormal3fv(solid_prism_n[8]);
1561 glVertex3fv(solid_prism_v[6]);
1562 glVertex3fv(solid_prism_v[8]);
1563 glVertex3fv(solid_prism_v[13]);
1564 glVertex3fv(solid_prism_v[12]);
1567 glNormal3fv(solid_prism_n[9]);
1568 glVertex3fv(solid_prism_v[3]);
1569 glVertex3fv(solid_prism_v[5]);
1570 glVertex3fv(solid_prism_v[17]);
1571 glVertex3fv(solid_prism_v[15]);
1574 glNormal3fv(solid_prism_n[10]);
1575 glVertex3fv(solid_prism_v[3]);
1576 glVertex3fv(solid_prism_v[9]);
1577 glVertex3fv(solid_prism_v[10]);
1578 glVertex3fv(solid_prism_v[4]);
1581 glNormal3fv(solid_prism_n[11]);
1582 glVertex3fv(solid_prism_v[15]);
1583 glVertex3fv(solid_prism_v[16]);
1584 glVertex3fv(solid_prism_v[11]);
1585 glVertex3fv(solid_prism_v[9]);
1588 glNormal3fv(solid_prism_n[12]);
1589 glVertex3fv(solid_prism_v[1]);
1590 glVertex3fv(solid_prism_v[2]);
1591 glVertex3fv(solid_prism_v[5]);
1592 glVertex3fv(solid_prism_v[4]);
1595 glNormal3fv(solid_prism_n[13]);
1596 glVertex3fv(solid_prism_v[8]);
1597 glVertex3fv(solid_prism_v[7]);
1598 glVertex3fv(solid_prism_v[10]);
1599 glVertex3fv(solid_prism_v[11]);
1602 glNormal3fv(solid_prism_n[14]);
1603 glVertex3fv(solid_prism_v[13]);
1604 glVertex3fv(solid_prism_v[16]);
1605 glVertex3fv(solid_prism_v[17]);
1606 glVertex3fv(solid_prism_v[14]);
1611 glBegin(GL_TRIANGLES);
1612 glNormal3fv(solid_prism_n[15]);
1613 glVertex3fv(solid_prism_v[0]);
1614 glVertex3fv(solid_prism_v[6]);
1615 glVertex3fv(solid_prism_v[12]);
1618 glNormal3fv(solid_prism_n[19]);
1619 glVertex3fv(solid_prism_v[3]);
1620 glVertex3fv(solid_prism_v[15]);
1621 glVertex3fv(solid_prism_v[9]);
1626 glNormal3fv(solid_prism_n[16]);
1627 glVertex3fv(solid_prism_v[1]);
1628 glVertex3fv(solid_prism_v[4]);
1629 glVertex3fv(solid_prism_v[10]);
1630 glVertex3fv(solid_prism_v[7]);
1633 glNormal3fv(solid_prism_n[17]);
1634 glVertex3fv(solid_prism_v[8]);
1635 glVertex3fv(solid_prism_v[11]);
1636 glVertex3fv(solid_prism_v[16]);
1637 glVertex3fv(solid_prism_v[13]);
1640 glNormal3fv(solid_prism_n[18]);
1641 glVertex3fv(solid_prism_v[2]);
1642 glVertex3fv(solid_prism_v[14]);
1643 glVertex3fv(solid_prism_v[17]);
1644 glVertex3fv(solid_prism_v[5]);
1649 /* build wire display list */
1650 bp->node_wire = glGenLists(1);
1651 glNewList(bp->node_wire, GL_COMPILE);
1652 glBegin(GL_LINE_STRIP);
1653 glVertex3fv(wire_prism_v[0]);
1654 glVertex3fv(wire_prism_v[1]);
1656 glVertex3fv(wire_prism_v[2]);
1657 glVertex3fv(wire_prism_v[0]);
1659 glVertex3fv(wire_prism_v[3]);
1660 glVertex3fv(wire_prism_v[4]);
1662 glVertex3fv(wire_prism_v[5]);
1663 glVertex3fv(wire_prism_v[3]);
1667 glVertex3fv(wire_prism_v[1]);
1668 glVertex3fv(wire_prism_v[4]);
1670 glVertex3fv(wire_prism_v[2]);
1671 glVertex3fv(wire_prism_v[5]);
1677 /* initialise the rotation */
1682 static void draw_title(
1689 struct glsnake_cfg * bp = &glc[MI_SCREEN(mi)];
1692 /* draw some text */
1694 /* glPushAttrib((GLbitfield) GL_TRANSFORM_BIT | GL_ENABLE_BIT);*/
1695 glDisable(GL_LIGHTING);
1696 glDisable(GL_DEPTH_TEST);
1698 glDisable(GL_BLEND);
1700 glMatrixMode(GL_PROJECTION);
1703 glMatrixMode(GL_MODELVIEW);
1707 glOrtho((GLdouble) 0., (GLdouble) bp->width, (GLdouble) 0., (GLdouble) bp->height, -1, 1);
1709 glOrtho((GLdouble) 0., (GLdouble) mi->xgwa.width, (GLdouble) 0., (GLdouble) mi->xgwa.height, -1, 1);
1712 glColor4f(1.0, 1.0, 1.0, 1.0);
1714 char interactstr[] = "interactive";
1723 s = model[bp->next_model].name;
1729 w = glutBitmapLength(GLUT_BITMAP_HELVETICA_12, (const unsigned char *) s);
1730 glRasterPos2f((GLfloat) (bp->width - w - 3), 4.0);
1731 while (s[i] != '\0')
1732 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, s[i++]);
1735 print_texture_label (mi->dpy, bp->font_data,
1736 mi->xgwa.width, mi->xgwa.height,
1741 glMatrixMode(GL_PROJECTION);
1748 /* apply the matrix to the origin and stick it in vec */
1749 static void matmult_origin(float rotmat[16], float vec[4])
1752 vec[0] = 0.5 * rotmat[0] + 0.5 * rotmat[4] + 0.5 * rotmat [8] + 1 * rotmat[12];
1753 vec[1] = 0.5 * rotmat[1] + 0.5 * rotmat[5] + 0.5 * rotmat [9] + 1 * rotmat[13];
1754 vec[2] = 0.5 * rotmat[2] + 0.5 * rotmat[6] + 0.5 * rotmat[10] + 1 * rotmat[14];
1755 vec[3] = 0.5 * rotmat[3] + 0.5 * rotmat[7] + 0.5 * rotmat[11] + 1 * rotmat[15];
1757 vec[0] = 0 * rotmat [0] + 0 * rotmat [1] + 0 * rotmat [2] + 1 * rotmat [3];
1758 vec[1] = 0 * rotmat [4] + 0 * rotmat [5] + 0 * rotmat [6] + 1 * rotmat [7];
1759 vec[2] = 0 * rotmat [8] + 0 * rotmat [9] + 0 * rotmat[10] + 1 * rotmat[11];
1760 vec[3] = 0 * rotmat[12] + 0 * rotmat[13] + 0 * rotmat[14] + 1 * rotmat[15];
1768 /* wot gets called when the winder is resized */
1769 ENTRYPOINT void glsnake_reshape(
1775 glViewport(0, 0, (GLint) w, (GLint) h);
1776 glMatrixMode(GL_PROJECTION);
1778 /* jwz: 0.05 was too close (left black rectangles) */
1779 gluPerspective(zoom, (GLdouble) w / (GLdouble) h, 1.0, 100.0);
1780 gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
1781 glMatrixMode(GL_MODELVIEW);
1782 /*gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);*/
1790 /* Returns the new dst_dir for the given src_dir and dst_dir */
1791 static int cross_product(int src_dir, int dst_dir)
1793 return X_MASK*(GETSCALAR(src_dir,Y_MASK) * GETSCALAR(dst_dir,Z_MASK) -
1794 GETSCALAR(src_dir,Z_MASK) * GETSCALAR(dst_dir,Y_MASK))+
1795 Y_MASK*(GETSCALAR(src_dir,Z_MASK) * GETSCALAR(dst_dir,X_MASK) -
1796 GETSCALAR(src_dir,X_MASK) * GETSCALAR(dst_dir,Z_MASK))+
1797 Z_MASK*(GETSCALAR(src_dir,X_MASK) * GETSCALAR(dst_dir,Y_MASK) -
1798 GETSCALAR(src_dir,Y_MASK) * GETSCALAR(dst_dir,X_MASK));
1801 /* calculate orthogonal snake metrics
1802 * is_legal = true if model does not pass through itself
1803 * is_cyclic = true if last node connects back to first node
1804 * last_turn = for cyclic snakes, specifes what the 24th turn would be
1806 static void calc_snake_metrics(struct glsnake_cfg *bp)
1810 int prevSrcDir = -Y_MASK;
1811 int prevDstDir = Z_MASK;
1812 int grid[25][25][25];
1815 memset(&grid, 0, sizeof(int) * 25*25*25);
1820 /* trace path of snake - and keep record for is_legal */
1821 for (i = 0; i < NODE_COUNT - 1; i++) {
1822 /*int ang_card;*/ /* cardinal direction of node angle */
1823 /* establish new state vars */
1824 srcDir = -prevDstDir;
1825 x += GETSCALAR(prevDstDir, X_MASK);
1826 y += GETSCALAR(prevDstDir, Y_MASK);
1827 z += GETSCALAR(prevDstDir, Z_MASK);
1829 switch ((int) model[bp->next_model].node[i]) {
1831 dstDir = -prevSrcDir;
1834 dstDir = prevSrcDir;
1838 dstDir = cross_product(prevSrcDir, prevDstDir);
1839 if (model[bp->next_model].node[i] == (int) (RIGHT))
1843 /* Prevent spurious "might be used
1844 * uninitialised" warnings when compiling
1850 if (grid[x][y][z] == 0)
1851 grid[x][y][z] = srcDir + dstDir;
1852 else if (grid[x][y][z] + srcDir + dstDir == 0)
1857 prevSrcDir = srcDir;
1858 prevDstDir = dstDir;
1861 /* determine if the snake is cyclic */
1862 bp->is_cyclic = (dstDir == Y_MASK && x == 12 && y == 11 && z == 12);
1864 /* determine last_turn */
1868 case -Z_MASK: bp->last_turn = ZERO; break;
1869 case Z_MASK: bp->last_turn = PIN; break;
1870 case X_MASK: bp->last_turn = LEFT; break;
1871 case -X_MASK: bp->last_turn = RIGHT; break;
1875 /* work out how far through the current morph we are */
1876 static float morph_percent(struct glsnake_cfg *bp)
1881 /* extend this function later with a case statement for each of the
1884 /* when morphing all nodes at once, the longest morph will be the node
1885 * that needs to rotate 180 degrees. For each node, work out how far it
1886 * has to go, and store the maximum rotation and current largest angular
1887 * difference, returning the angular difference over the maximum. */
1889 float rot_max = 0.0, ang_diff_max = 0.0;
1891 for (i = 0; i < NODE_COUNT - 1; i++) {
1892 float rot, ang_diff;
1894 /* work out the maximum rotation this node has to go through
1895 * from the previous to the next model, taking into account that
1896 * the snake always morphs through the smaller angle */
1897 rot = fabs(model[bp->prev_model].node[i] -
1898 model[bp->next_model].node[i]);
1899 if (rot > 180.0) rot = 180.0 - rot;
1900 /* work out the difference between the current position and the
1902 ang_diff = fabs(bp->node[i] -
1903 model[bp->next_model].node[i]);
1904 if (ang_diff > 180.0) ang_diff = 180.0 - ang_diff;
1905 /* if it's the biggest so far, record it */
1906 if (rot > rot_max) rot_max = rot;
1907 if (ang_diff > ang_diff_max) ang_diff_max = ang_diff;
1910 /* ang_diff / rot approaches 0, we want the complement */
1911 retval = 1.0 - (ang_diff_max / rot_max);
1912 /* protect against naan */
1914 /* Apparently some systems (Solaris) don't have isinf() */
1916 #define isinf(x) (((x) > 999999999999.9) || ((x) < -999999999999.9))
1918 if (isnan(retval) || isinf(retval)) retval = 1.0;
1920 /*printf("morph_pct = %f\n", retval);*/
1924 static void morph_colour(struct glsnake_cfg *bp)
1926 float percent, compct; /* complement of percentage */
1928 percent = morph_percent(bp);
1929 compct = 1.0 - percent;
1931 bp->colour[0][0] = colour[bp->prev_colour][0][0] * compct + colour[bp->next_colour][0][0] * percent;
1932 bp->colour[0][1] = colour[bp->prev_colour][0][1] * compct + colour[bp->next_colour][0][1] * percent;
1933 bp->colour[0][2] = colour[bp->prev_colour][0][2] * compct + colour[bp->next_colour][0][2] * percent;
1934 bp->colour[0][3] = colour[bp->prev_colour][0][3] * compct + colour[bp->next_colour][0][3] * percent;
1936 bp->colour[1][0] = colour[bp->prev_colour][1][0] * compct + colour[bp->next_colour][1][0] * percent;
1937 bp->colour[1][1] = colour[bp->prev_colour][1][1] * compct + colour[bp->next_colour][1][1] * percent;
1938 bp->colour[1][2] = colour[bp->prev_colour][1][2] * compct + colour[bp->next_colour][1][2] * percent;
1939 bp->colour[1][3] = colour[bp->prev_colour][1][3] * compct + colour[bp->next_colour][1][3] * percent;
1942 /* Start morph process to this model */
1943 static void start_morph(struct glsnake_cfg *bp,
1944 unsigned int model_index, int immediate)
1946 /* if immediate, don't bother morphing, go straight to the next model */
1950 for (i = 0; i < NODE_COUNT; i++)
1951 bp->node[i] = model[model_index].node[i];
1954 bp->prev_model = bp->next_model;
1955 bp->next_model = model_index;
1956 bp->prev_colour = bp->next_colour;
1958 calc_snake_metrics(bp);
1960 bp->next_colour = COLOUR_INVALID;
1962 bp->next_colour = COLOUR_AUTHENTIC;
1963 else if (bp->is_cyclic)
1964 bp->next_colour = COLOUR_CYCLIC;
1966 bp->next_colour = COLOUR_ACYCLIC;
1969 bp->colour[0][0] = colour[bp->next_colour][0][0];
1970 bp->colour[0][1] = colour[bp->next_colour][0][1];
1971 bp->colour[0][2] = colour[bp->next_colour][0][2];
1972 bp->colour[0][3] = colour[bp->next_colour][0][3];
1973 bp->colour[1][0] = colour[bp->next_colour][1][0];
1974 bp->colour[1][1] = colour[bp->next_colour][1][1];
1975 bp->colour[1][2] = colour[bp->next_colour][1][2];
1976 bp->colour[1][3] = colour[bp->next_colour][1][3];
1984 /* Returns morph progress */
1985 static float morph(long iter_msec)
1987 /* work out the maximum angle for this iteration */
1989 float iter_angle_max, largest_diff, largest_progress;
1995 iter_angle_max = 90.0 * (angvel/1000.0) * iter_msec;
1998 largest_diff = largest_progress = 0.0;
1999 for (i = 0; i < NODE_COUNT; i++) {
2000 float curAngle = bp->node[i];
2001 float destAngle = model[bp->next_model].node[i];
2002 if (curAngle != destAngle) {
2004 if (fabs(curAngle-destAngle) <= iter_angle_max)
2005 bp->node[i] = destAngle;
2006 else if (fmod(curAngle-destAngle+360,360) > 180)
2007 bp->node[i] = fmod(curAngle + iter_angle_max, 360);
2009 bp->node[i] = fmod(curAngle+360 - iter_angle_max, 360);
2010 largest_diff = MAX(largest_diff, fabs(destAngle-bp->node[i]));
2011 largest_progress = MAX(largest_diff, fabs(bp->node[i] - model[bp->prev_model].node[i]));
2015 return MIN(largest_diff / largest_progress, 1.0);
2021 static void glsnake_idle();
2023 static restore_idle(int v __attribute__((__unused__)))
2025 glutIdleFunc(glsnake_idle);
2029 static void quick_sleep(void)
2032 /* By using glutTimerFunc we can keep responding to
2033 * mouse and keyboard events, unlike using something like
2036 glutTimerFunc(1, restore_idle, 0);
2042 static void glsnake_idle(
2044 struct glsnake_cfg * bp
2048 /* time since last iteration */
2050 /* time since the beginning of last morph */
2052 float iter_angle_max;
2053 snaketime current_time;
2054 /* morphFunc transition; */
2058 /* Do nothing to the model if we are paused */
2060 /* Avoid busy waiting when nothing is changing */
2064 glutPostRedisplay();
2069 /* <spiv> Well, ftime gives time with millisecond resolution.
2070 * <spiv> (or worse, perhaps... who knows what the OS will do)
2071 * <spiv> So if no discernable amount of time has passed:
2072 * <spiv> a) There's no point updating the screen, because
2073 * it would be the same
2074 * <spiv> b) The code will divide by zero
2076 gettime(¤t_time);
2078 iter_msec = (long) GETMSECS(current_time) - GETMSECS(bp->last_iteration) +
2079 ((long) GETSECS(current_time) - GETSECS(bp->last_iteration)) * 1000L;
2082 /* save the current time */
2083 memcpy(&bp->last_iteration, ¤t_time, sizeof(snaketime));
2085 /* work out if we have to switch models */
2086 morf_msec = GETMSECS(bp->last_iteration) - GETMSECS(bp->last_morph) +
2087 ((long) (GETSECS(bp->last_iteration)-GETSECS(bp->last_morph)) * 1000L);
2089 if ((morf_msec > statictime) && !interactive && !bp->morphing) {
2090 /*printf("starting morph\n");*/
2091 memcpy(&bp->last_morph, &(bp->last_iteration), sizeof(bp->last_morph));
2092 start_morph(bp, RAND(models), 0);
2095 if (interactive && !bp->morphing) {
2100 /* if (!bp->dragging && !bp->interactive) { */
2103 yspin += 360/((1000/yangvel)/iter_msec);
2104 zspin += 360/((1000/zangvel)/iter_msec);
2106 yspin += 360 * (yangvel/1000.0) * iter_msec;
2107 zspin += 360 * (zangvel/1000.0) * iter_msec;
2110 /*printf("yspin: %f, zspin: %f\n", yspin, zspin);*/
2114 /* work out the maximum angle we could turn this node in this
2115 * timeslice, iter_msec milliseconds long */
2116 iter_angle_max = 90.0 * (angvel/1000.0) * iter_msec;
2119 for (i = 0; i < NODE_COUNT; i++) {
2120 float cur_angle = bp->node[i];
2121 float dest_angle = model[bp->next_model].node[i];
2122 if (cur_angle != dest_angle) {
2124 if (fabs(cur_angle - dest_angle) <= iter_angle_max)
2125 bp->node[i] = dest_angle;
2126 else if (fmod(cur_angle - dest_angle + 360, 360) > 180)
2127 bp->node[i] = fmod(cur_angle + iter_angle_max, 360);
2129 bp->node[i] = fmod(cur_angle + 360 - iter_angle_max, 360);
2133 if (!still_morphing)
2136 /* colour cycling */
2141 glutPostRedisplay();
2144 /* We are going too fast, so we may as well let the
2145 * cpu relax a little by sleeping for a millisecond. */
2151 ENTRYPOINT void glsnake_display(
2158 struct glsnake_cfg * bp = &glc[MI_SCREEN(mi)];
2159 Display * dpy = MI_DISPLAY(mi);
2160 Window window = MI_WINDOW(mi);
2165 float positions[NODE_COUNT][4]; /* origin points for each node */
2166 float com[4]; /* it's the CENTRE of MASS */
2169 if (!bp->glx_context)
2172 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
2177 /* clear the buffer */
2178 glClear((GLbitfield) GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2180 /* go into the modelview stack */
2181 glMatrixMode(GL_MODELVIEW);
2184 /* get the centre of each node, by moving through the snake and
2185 * performing the rotations, then grabbing the matrix at each point
2186 * and applying it to the origin */
2190 /* apply the mouse drag rotation */
2194 /* apply the continuous rotation */
2195 glRotatef(yspin, 0.0, 1.0, 0.0);
2196 glRotatef(zspin, 0.0, 0.0, 1.0);
2202 for (i = 0; i < NODE_COUNT; i++) {
2207 /*printf("ang = %f\n", ang);*/
2209 glTranslatef(0.5, 0.5, 0.5); /* move to center */
2210 glRotatef(90.0, 0.0, 0.0, -1.0); /* reorient */
2211 glTranslatef(1.0 + explode, 0.0, 0.0); /* move to new pos. */
2212 glRotatef(180.0 + ang, 1.0, 0.0, 0.0); /* pivot to new angle */
2213 glTranslatef(-0.5, -0.5, -0.5); /* return from center */
2215 glGetFloatv(GL_MODELVIEW_MATRIX, rotmat);
2217 matmult_origin(rotmat, positions[i]);
2219 /*printf("positions %f %f %f %f\n", positions[i][0], positions[i][1], positions[i][2], positions[i][3]);*/
2221 com[0] += positions[i][0];
2222 com[1] += positions[i][1];
2223 com[2] += positions[i][2];
2224 com[3] += positions[i][3];
2227 com[0] /= NODE_COUNT;
2228 com[1] /= NODE_COUNT;
2229 com[2] /= NODE_COUNT;
2230 com[3] /= NODE_COUNT;
2236 /*printf("com: %f, %f, %f, %f\n", com[0], com[1], com[2], com[3]);*/
2238 #if MAGICAL_RED_STRING
2240 glTranslatef(-com[0], -com[1], -com[2]);
2242 glDisable(GL_LIGHTING);
2243 glColor4f(1.0, 0.0, 0.0, 1.0);
2244 glBegin(GL_LINE_STRIP);
2245 for (i = 0; i < NODE_COUNT - 1; i++) {
2246 glVertex3fv(positions[i]);
2249 glEnable(GL_LIGHTING);
2250 /*glTranslatef(com[0], com[1], com[2]);*/
2255 glTranslatef(-com[0], -com[1], -com[2]);
2258 /* apply the mouse drag rotation */
2262 /* apply the continuous rotation */
2263 glRotatef(yspin, 0.0, 1.0, 0.0);
2264 glRotatef(zspin, 0.0, 0.0, 1.0);
2266 /* now draw each node along the snake -- this is quite ugly :p */
2267 mi->polygon_count = 0;
2268 for (i = 0; i < NODE_COUNT; i++) {
2269 /* choose a colour for this node */
2270 if ((i == bp->selected || i == bp->selected+1) && interactive)
2272 glColor4f(1.0, 1.0, 0.0, 1.0);
2274 /*glColor4fv(bp->colour[(i+1)%2]);*/
2275 glMaterialfv(GL_FRONT, GL_AMBIENT, bp->colour[(i+1)%2]);
2276 glMaterialfv(GL_FRONT, GL_DIFFUSE, bp->colour[(i+1)%2]);
2277 /*glMaterialfv(GL_FRONT, GL_SPECULAR, bp->colour[(i+1)%2]);*/
2282 glCallList(bp->node_wire);
2284 glCallList(bp->node_solid);
2285 mi->polygon_count += bp->node_polys;
2287 /* now work out where to draw the next one */
2289 /* Interpolate between models */
2292 glTranslatef(0.5, 0.5, 0.5); /* move to center */
2293 glRotatef(90.0, 0.0, 0.0, -1.0); /* reorient */
2294 glTranslatef(1.0 + explode, 0.0, 0.0); /* move to new pos. */
2295 glRotatef(180.0 + ang, 1.0, 0.0, 0.0); /* pivot to new angle */
2296 glTranslatef(-0.5, -0.5, -0.5); /* return from center */
2310 if (mi->fps_p) do_fps(mi);
2317 glXSwapBuffers(dpy, window);
2322 /* anything that needs to be cleaned up goes here */
2323 static void unmain()
2325 glutDestroyWindow(bp->window);
2329 static void ui_init(int *, char **);
2331 int main(int argc, char ** argv)
2333 bp = malloc(sizeof(struct glsnake_cfg));
2334 memset(bp, 0, sizeof(struct glsnake_cfg));
2339 ui_init(&argc, argv);
2341 gettime(&bp->last_iteration);
2342 memcpy(&bp->last_morph, &bp->last_iteration, sizeof(snaketime));
2343 srand((unsigned int)GETSECS(bp->last_iteration));
2345 bp->prev_colour = bp->next_colour = COLOUR_ACYCLIC;
2346 bp->next_model = RAND(models);
2348 start_morph(bp->prev_model, 1);
2366 /* trackball quaternions */
2367 static float cumquat[4] = {0.0,0.0,0.0,0.0}, oldquat[4] = {0.0,0.0,0.0,0.1};
2369 /* rotation matrix */
2370 static float rotation[16];
2372 /* mouse drag vectors: start and end */
2373 static float mouse_start[3], mouse_end[3];
2375 /* dragging boolean */
2376 static int dragging = 0;
2378 /* this function calculates the rotation matrix based on the quaternions
2379 * generated from the mouse drag vectors */
2380 static void calc_rotation()
2383 double xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
2385 /* this bit ripped from Shoemake's quaternion notes from SIGGRAPH */
2386 Nq = cumquat[0] * cumquat[0] + cumquat[1] * cumquat[1] +
2387 cumquat[2] * cumquat[2] + cumquat[3] * cumquat[3];
2388 s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
2389 xs = cumquat[0] * s; ys = cumquat[1] * s; zs = cumquat[2] * s;
2390 wx = cumquat[3] * xs; wy = cumquat[3] * ys; wz = cumquat[3] * zs;
2391 xx = cumquat[0] * xs; xy = cumquat[0] * ys; xz = cumquat[0] * zs;
2392 yy = cumquat[1] * ys; yz = cumquat[1] * zs; zz = cumquat[2] * zs;
2394 rotation[0] = 1.0 - (yy + zz);
2395 rotation[1] = xy + wz;
2396 rotation[2] = xz - wy;
2397 rotation[4] = xy - wz;
2398 rotation[5] = 1.0 - (xx + zz);
2399 rotation[6] = yz + wx;
2400 rotation[8] = xz + wy;
2401 rotation[9] = yz - wx;
2402 rotation[10] = 1.0 - (xx + yy);
2403 rotation[3] = rotation[7] = rotation[11] = 0.0;
2404 rotation[12] = rotation[13] = rotation[14] = 0.0;
2408 static inline void ui_mousedrag()
2410 glMultMatrixf(rotation);
2413 static void ui_keyboard(unsigned char c, int x__attribute__((__unused__)), int y __attribute__((__unused__)))
2423 explode += DEF_EXPLODE;
2424 glutPostRedisplay();
2427 explode -= DEF_EXPLODE;
2428 if (explode < 0.0) explode = 0.0;
2429 glutPostRedisplay();
2434 bp->next_model %= models;
2435 start_morph(bp->next_model, 0);
2437 /* Reset last_morph time */
2438 gettime(&bp->last_morph);
2441 /* previous model */
2442 bp->next_model = (bp->next_model + (int)models - 1) % (int)models;
2443 start_morph(bp->next_model, 0);
2445 /* Reset bp->last_morph time */
2446 gettime(&bp->last_morph);
2449 angvel += DEF_ANGVEL;
2452 if (angvel > DEF_ANGVEL)
2453 angvel -= DEF_ANGVEL;
2457 /* Reset last_iteration and last_morph time */
2458 gettime(&bp->last_iteration);
2459 gettime(&bp->last_morph);
2461 interactive = 1 - interactive;
2462 glutPostRedisplay();
2465 wireframe = 1 - wireframe;
2467 glDisable(GL_LIGHTING);
2469 glEnable(GL_LIGHTING);
2470 glutPostRedisplay();
2473 transparent = 1 - transparent;
2477 glDisable(GL_BLEND);
2482 /* unpausing, reset last_iteration and last_morph time */
2483 gettime(&bp->last_iteration);
2484 gettime(&bp->last_morph);
2486 bp->paused = 1 - bp->paused;
2489 /* dump the current model so we can add it! */
2490 printf("# %s\nnoname:\t", model[bp->next_model].name);
2494 for (i = 0; i < NODE_COUNT; i++) {
2495 if (bp->node[i] == ZERO)
2497 else if (bp->node[i] == LEFT)
2499 else if (bp->node[i] == PIN)
2501 else if (bp->node[i] == RIGHT)
2505 printf("%f", node[i].curAngle);
2507 if (i < NODE_COUNT - 1)
2514 bp->fullscreen = 1 - bp->fullscreen;
2515 if (bp->fullscreen) {
2516 bp->old_width = bp->width;
2517 bp->old_height = bp->height;
2520 glutReshapeWindow(bp->old_width, bp->old_height);
2521 glutPositionWindow(50,50);
2525 titles = 1 - titles;
2526 if (interactive || bp->paused)
2527 glutPostRedisplay();
2530 altcolour = 1 - altcolour;
2534 glsnake_reshape(bp->width, bp->height);
2538 glsnake_reshape(bp->width, bp->height);
2545 static void ui_special(int key, int x__attribute__((__unused__)), int y __attribute__((__unused__)))
2547 float *destAngle = &(model[bp->next_model].node[bp->selected]);
2548 int unknown_key = 0;
2553 bp->selected = (bp->selected + (NODE_COUNT - 2)) % (NODE_COUNT - 1);
2556 bp->selected = (bp->selected + 1) % (NODE_COUNT - 1);
2559 *destAngle = fmod(*destAngle+(LEFT), 360);
2560 bp->morphing = bp->new_morph = 1;
2562 case GLUT_KEY_RIGHT:
2563 *destAngle = fmod(*destAngle+(RIGHT), 360);
2564 bp->morphing = bp->new_morph = 1;
2567 start_morph(STRAIGHT_MODEL, 0);
2574 calc_snake_metrics();
2577 glutPostRedisplay();
2580 static void ui_mouse(int button, int state, int x, int y)
2586 mouse_start[0] = M_SQRT1_2 *
2587 (x - (bp->width / 2.0)) / (bp->width / 2.0);
2588 mouse_start[1] = M_SQRT1_2 *
2589 ((bp->height / 2.0) - y) / (bp->height / 2.0);
2590 mouse_start[2] = sqrt((double)(1-(mouse_start[0]*mouse_start[0]+mouse_start[1]*mouse_start[1])));
2594 oldquat[0] = cumquat[0];
2595 oldquat[1] = cumquat[1];
2596 oldquat[2] = cumquat[2];
2597 oldquat[3] = cumquat[3];
2603 glutPostRedisplay();
2606 static void ui_motion(int x, int y)
2612 /* construct the motion end vector from the x,y position on the
2614 mouse_end[0] = M_SQRT1_2 * (x - (bp->width/ 2.0)) / (bp->width / 2.0);
2615 mouse_end[1] = M_SQRT1_2 * ((bp->height / 2.0) - y) / (bp->height / 2.0);
2616 /* calculate the normal of the vector... */
2617 norm = mouse_end[0] * mouse_end[0] + mouse_end[1] * mouse_end[1];
2618 /* check if norm is outside the sphere and wraparound if necessary */
2620 mouse_end[0] = -mouse_end[0];
2621 mouse_end[1] = -mouse_end[1];
2622 mouse_end[2] = sqrt(norm - 1);
2624 /* the z value comes from projecting onto an elliptical spheroid */
2625 mouse_end[2] = sqrt(1 - norm);
2628 /* now here, build a quaternion from mouse_start and mouse_end */
2629 q[0] = mouse_start[1] * mouse_end[2] - mouse_start[2] * mouse_end[1];
2630 q[1] = mouse_start[2] * mouse_end[0] - mouse_start[0] * mouse_end[2];
2631 q[2] = mouse_start[0] * mouse_end[1] - mouse_start[1] * mouse_end[0];
2632 q[3] = mouse_start[0] * mouse_end[0] + mouse_start[1] * mouse_end[1] + mouse_start[2] * mouse_end[2];
2634 /* new rotation is the product of the new one and the old one */
2635 cumquat[0] = q[3] * oldquat[0] + q[0] * oldquat[3] +
2636 q[1] * oldquat[2] - q[2] * oldquat[1];
2637 cumquat[1] = q[3] * oldquat[1] + q[1] * oldquat[3] +
2638 q[2] * oldquat[0] - q[0] * oldquat[2];
2639 cumquat[2] = q[3] * oldquat[2] + q[2] * oldquat[3] +
2640 q[0] * oldquat[1] - q[1] * oldquat[0];
2641 cumquat[3] = q[3] * oldquat[3] - q[0] * oldquat[0] -
2642 q[1] * oldquat[1] - q[2] * oldquat[2];
2646 glutPostRedisplay();
2649 static void ui_init(int * argc, char ** argv)
2651 glutInit(argc, argv);
2652 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
2653 glutInitWindowSize(bp->width, bp->height);
2654 bp->window = glutCreateWindow("glsnake");
2656 glutDisplayFunc(glsnake_display);
2657 glutReshapeFunc(glsnake_reshape);
2658 glutIdleFunc(glsnake_idle);
2659 glutKeyboardFunc(ui_keyboard);
2660 glutSpecialFunc(ui_special);
2661 glutMouseFunc(ui_mouse);
2662 glutMotionFunc(ui_motion);
2664 yangvel = DEF_YANGVEL;
2665 zangvel = DEF_ZANGVEL;
2666 explode = DEF_EXPLODE;
2667 angvel = DEF_ANGVEL;
2668 statictime = DEF_STATICTIME;
2669 altcolour = DEF_ALTCOLOUR;
2670 titles = DEF_TITLES;
2671 interactive = DEF_INTERACTIVE;
2673 wireframe = DEF_WIREFRAME;
2674 transparent = DEF_TRANSPARENT;
2676 #endif /* HAVE_GLUT */
2678 XSCREENSAVER_MODULE ("GLSnake", glsnake)