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
44 #endif /* HAVE_JWZGLES */
47 # include "xlockmoreI.h"
61 #ifdef HAVE_GETTIMEOFDAY
62 # ifdef GETTIMEOFDAY_TWO_ARGS
64 # include <sys/time.h>
66 typedef struct timeval snaketime;
67 # define GETSECS(t) ((t).tv_sec)
68 # define GETMSECS(t) ((t).tv_usec/1000)
70 # else /* !GETTIMEOFDAY_TWO_ARGS */
72 # include <sys/time.h>
74 typedef struct timeval snaketime;
75 # define GETSECS(t) ((t).tv_sec)
76 # define GETMSECS(t) ((t).tv_usec/1000)
78 # endif /* GETTIMEOFDAY_TWO_ARGS */
80 #else /* !HAVE_GETTIMEOFDAY */
83 # include <sys/timeb.h>
84 typedef struct timeb snaketime;
85 # define GETSECS(t) ((long)(t).time)
86 # define GETMSECS(t) ((t).millitm/1000)
88 # endif /* HAVE_FTIME */
89 #endif /* HAVE_GETTIMEOFDAY */
93 #ifndef M_SQRT1_2 /* Win32 doesn't have this constant */
94 #define M_SQRT1_2 0.70710678118654752440084436210485
100 #define DEF_YANGVEL 0.10
101 #define DEF_ZANGVEL 0.14
102 #define DEF_EXPLODE 0.03
103 #define DEF_ANGVEL 1.0
104 #define DEF_STATICTIME 5000
105 #define DEF_ALTCOLOUR 0
107 #define DEF_INTERACTIVE 0
108 #define DEF_ZOOM 25.0
109 #define DEF_WIREFRAME 0
110 #define DEF_TRANSPARENT 1
112 /* xscreensaver options doobies prefer strings */
113 #define DEF_YANGVEL "0.10"
114 #define DEF_ZANGVEL "0.14"
115 #define DEF_EXPLODE "0.03"
116 #define DEF_ANGVEL "1.0"
117 #define DEF_STATICTIME "5000"
118 #define DEF_ALTCOLOUR "False"
119 #define DEF_TITLES "False"
120 #define DEF_INTERACTIVE "False"
121 #define DEF_ZOOM "25.0"
122 #define DEF_WIREFRAME "False"
123 #define DEF_TRANSPARENT "True"
126 /* static variables */
128 static GLfloat explode;
129 static long statictime;
130 static GLfloat yspin = 60.0;
131 static GLfloat zspin = -45.0;
132 static GLfloat yangvel;
133 static GLfloat zangvel;
134 static Bool altcolour;
136 static Bool interactive;
137 static Bool wireframe;
138 static Bool transparent;
140 static GLfloat angvel;
144 #define glsnake_init init_glsnake
145 #define glsnake_display draw_glsnake
146 #define glsnake_reshape reshape_glsnake
147 #define refresh_glsnake 0
148 #define release_glsnake 0
149 #define glsnake_handle_event 0
151 /* xscreensaver defaults */
152 #define DEFAULTS "*delay: 30000 \n" \
154 "*showFPS: False \n" \
155 "*suppressRotationAnimation: True\n" \
156 "*labelfont: -*-helvetica-medium-r-normal-*-*-180-*-*-*-*-*-*\n" \
160 #define countof(x) (sizeof((x))/sizeof((*x)))
162 #include "xlockmore.h"
165 static XrmOptionDescRec opts[] = {
166 { "-explode", ".explode", XrmoptionSepArg, DEF_EXPLODE },
167 { "-angvel", ".angvel", XrmoptionSepArg, DEF_ANGVEL },
168 { "-statictime", ".statictime", XrmoptionSepArg, DEF_STATICTIME },
169 { "-yangvel", ".yangvel", XrmoptionSepArg, DEF_YANGVEL },
170 { "-zangvel", ".zangvel", XrmoptionSepArg, DEF_ZANGVEL },
171 { "-altcolour", ".altcolour", XrmoptionNoArg, "True" },
172 { "-no-altcolour", ".altcolour", XrmoptionNoArg, "False" },
173 { "-titles", ".titles", XrmoptionNoArg, "True" },
174 { "-no-titles", ".titles", XrmoptionNoArg, "False" },
175 { "-zoom", ".zoom", XrmoptionSepArg, DEF_ZOOM },
176 { "-wireframe", ".wireframe", XrmoptionNoArg, "true" },
177 { "-no-wireframe", ".wireframe", XrmoptionNoArg, "false" },
178 { "-transparent", ".transparent", XrmoptionNoArg, "true" },
179 { "-no-transparent", ".transparent", XrmoptionNoArg, "false" },
182 static argtype vars[] = {
183 {&explode, "explode", "Explode", DEF_EXPLODE, t_Float},
184 {&angvel, "angvel", "Angular Velocity", DEF_ANGVEL, t_Float},
185 {&statictime, "statictime", "Static Time", DEF_STATICTIME, t_Int},
186 {&yangvel, "yangvel", "Angular Velocity about Y axis", DEF_YANGVEL, t_Float},
187 {&zangvel, "zangvel", "Angular Velocity about X axis", DEF_ZANGVEL, t_Float},
188 {&interactive, "interactive", "Interactive", DEF_INTERACTIVE, t_Bool},
189 {&altcolour, "altcolour", "Alternate Colour Scheme", DEF_ALTCOLOUR, t_Bool},
190 {&titles, "titles", "Titles", DEF_TITLES, t_Bool},
191 {&zoom, "zoom", "Zoom", DEF_ZOOM, t_Float},
192 {&wireframe, "wireframe", "Wireframe", DEF_WIREFRAME, t_Bool},
193 {&transparent, "transparent", "Transparent!", DEF_TRANSPARENT, t_Bool},
196 ENTRYPOINT ModeSpecOpt glsnake_opts = {countof(opts), opts, countof(vars), vars, NULL};
201 float node[NODE_COUNT];
206 GLXContext * glx_context;
207 texture_font_data *font_data;
209 /* font list number */
216 /* is a morph in progress? */
219 /* has the model been paused? */
228 /* the shape of the model */
229 float node[NODE_COUNT];
231 /* currently selected node for interactive mode */
235 unsigned int prev_model;
236 unsigned int next_model;
246 /* timing variables */
247 snaketime last_iteration;
248 snaketime last_morph;
252 int old_width, old_height;
254 /* the id of the display lists for drawing a node */
255 GLuint node_solid, node_wire;
258 /* is the window fullscreen? */
262 #define COLOUR_CYCLIC 0
263 #define COLOUR_ACYCLIC 1
264 #define COLOUR_INVALID 2
265 #define COLOUR_AUTHENTIC 3
266 #define COLOUR_ORIGLOGO 4
268 static const float colour[][2][4] = {
270 { { 0.4, 0.8, 0.2, 0.6 },
271 { 1.0, 1.0, 1.0, 0.6 } },
273 { { 0.3, 0.1, 0.9, 0.6 },
274 { 1.0, 1.0, 1.0, 0.6 } },
276 { { 0.3, 0.1, 0.9, 0.6 },
277 { 1.0, 1.0, 1.0, 0.6 } },
278 /* authentic - purple and green */
279 { { 0.38, 0.0, 0.55, 0.7 },
280 { 0.0, 0.5, 0.34, 0.7 } },
281 /* old "authentic" colours from the logo */
282 { { 171/255.0, 0, 1.0, 1.0 },
283 { 46/255.0, 205/255.0, 227/255.0, 1.0 } }
286 static const struct model_s model[] = {
287 #define STRAIGHT_MODEL 0
289 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
290 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
293 /* the models in the Rubik's snake manual */
295 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT,
296 RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT,
297 RIGHT, LEFT, RIGHT, LEFT, ZERO }
299 #define START_MODEL 2
301 { RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT,
302 RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT,
303 RIGHT, LEFT, LEFT, LEFT, ZERO }
306 { ZERO, ZERO, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO, ZERO,
307 ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO, ZERO, ZERO, RIGHT,
308 LEFT, RIGHT, ZERO, LEFT }
311 { ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, RIGHT, PIN,
312 RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, ZERO, ZERO,
316 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN,
317 ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
321 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, LEFT, RIGHT, PIN, RIGHT,
322 ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, LEFT, ZERO,
325 /* These models were taken from Andrew and Peter's original snake.c
326 * as well as some newer ones made up by Jamie, Andrew and Peter. */
328 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT,
329 LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT,
330 RIGHT, LEFT, LEFT, LEFT, ZERO }
333 { RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT,
334 LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT,
335 RIGHT, RIGHT, LEFT, LEFT, ZERO }
338 { PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN,
339 ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN,
343 { PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN,
344 LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN,
348 { RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT,
349 LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN,
353 { RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT,
354 LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT,
355 RIGHT, RIGHT, LEFT, LEFT, ZERO }
358 { ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT,
359 LEFT, RIGHT, LEFT, LEFT, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT,
360 RIGHT, RIGHT, RIGHT, ZERO }
363 { RIGHT, PIN, ZERO, ZERO, PIN, LEFT, ZERO, LEFT, LEFT, ZERO,
364 LEFT, PIN, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO,
368 { PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT,
369 LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT,
370 RIGHT, LEFT, LEFT, ZERO }
373 { ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO,
374 ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO,
375 LEFT, ZERO, ZERO, RIGHT }
378 { ZERO, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO, RIGHT, ZERO, ZERO,
379 LEFT, RIGHT, ZERO, LEFT, ZERO, RIGHT, ZERO, ZERO, LEFT, RIGHT,
380 ZERO, LEFT, ZERO, RIGHT }
383 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO,
384 ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO,
385 ZERO, ZERO, LEFT, RIGHT }
388 { ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT,
389 RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN,
393 { ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN,
394 PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN }
397 { PIN, RIGHT, LEFT, PIN, LEFT, PIN, ZERO, ZERO, RIGHT, PIN, LEFT,
398 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
402 { ZERO, ZERO, ZERO, ZERO, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT,
403 ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT,
404 LEFT, ZERO, PIN, ZERO }
407 { RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO,
408 LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, PIN, RIGHT,
412 { ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN,
413 ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO }
416 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, LEFT, PIN,
417 RIGHT, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT,
418 RIGHT, LEFT, LEFT, ZERO }
421 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, ZERO, ZERO,
422 RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO, LEFT, LEFT,
423 RIGHT, LEFT, RIGHT, RIGHT, ZERO }
426 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, PIN, ZERO, ZERO,
427 LEFT, PIN, RIGHT, ZERO, ZERO, PIN, ZERO, LEFT, LEFT, RIGHT, LEFT,
431 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO,
432 RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT,
436 { LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT,
437 ZERO, ZERO, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN,
441 { RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN,
442 LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT,
446 { RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN,
447 LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT,
448 LEFT, PIN, LEFT, PIN }
451 { ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN,
452 ZERO, PIN, ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT,
456 { ZERO, PIN, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, PIN,
457 ZERO, PIN, ZERO, PIN, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO,
461 { ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN,
462 ZERO, PIN, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
466 { ZERO, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT,
467 ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
471 { ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO,
472 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
476 { ZERO, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, ZERO,
477 ZERO, PIN, ZERO, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO,
481 { RIGHT, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, ZERO,
482 LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT,
483 ZERO, ZERO, LEFT, PIN }
486 { RIGHT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT,
487 ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT,
488 LEFT, RIGHT, ZERO, LEFT, PIN }
491 { RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO,
492 LEFT, PIN, RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT,
496 { ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, ZERO,
497 ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT,
501 { ZERO, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN,
502 RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT,
506 { LEFT, PIN, LEFT, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, LEFT,
507 PIN, RIGHT, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN,
511 { RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, ZERO,
512 ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, RIGHT, RIGHT, LEFT,
513 RIGHT, LEFT, LEFT, LEFT, PIN }
516 { ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, RIGHT,
517 RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT,
518 PIN, LEFT, LEFT, LEFT }
521 { PIN, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, LEFT,
522 ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, LEFT, ZERO,
523 LEFT, RIGHT, ZERO, ZERO }
526 { PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, RIGHT,
527 RIGHT, PIN, RIGHT, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO,
528 ZERO, PIN, PIN, ZERO }
531 /* the following modesl were created during the slug/compsoc codefest
533 { "cool looking gegl",
534 { PIN, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT,
535 ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, ZERO,
539 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN,
540 PIN, ZERO, RIGHT, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO,
544 { RIGHT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT,
545 RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN,
546 RIGHT, LEFT, RIGHT, PIN, ZERO }
549 { ZERO, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO,
550 ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
554 { LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO,
555 RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT,
556 RIGHT, ZERO, LEFT, ZERO }
558 { "not very good (but accurate) gegl",
559 { ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO,
560 PIN, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO, PIN, PIN, ZERO,
564 { ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
565 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO,
569 { PIN, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
570 ZERO, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO,
573 { "erect penis", /* thanks benno */
574 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, PIN,
575 PIN, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
579 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, PIN,
580 PIN, ZERO, ZERO, ZERO, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
584 { RIGHT, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO,
585 LEFT, ZERO, ZERO, ZERO, LEFT, ZERO, LEFT, PIN, LEFT, PIN, RIGHT,
589 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN,
590 ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO,
593 { "poles or columns or something",
594 { LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
595 ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
599 { ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
600 ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
604 { ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO,
605 LEFT, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
609 { ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO,
610 LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO,
611 LEFT, PIN, ZERO, ZERO }
614 { ZERO, ZERO, PIN, RIGHT, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO,
615 LEFT, PIN, ZERO, ZERO, PIN, ZERO, LEFT, ZERO, RIGHT, LEFT, ZERO,
619 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
620 RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
624 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
625 ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
629 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
630 LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
634 { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
635 PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
639 { RIGHT, ZERO, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT,
640 RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT,
641 ZERO, ZERO, RIGHT, ZERO }
644 { RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT,
645 ZERO, RIGHT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, ZERO,
646 RIGHT, ZERO, RIGHT, ZERO, ZERO }
649 /* These models come from the website at
650 * http://www.geocities.com/stigeide/snake */
653 { RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO }
657 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, ZERO }
660 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, ZERO }
663 { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, ZERO }
666 { ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, ZERO, ZERO }
669 { RIGHT, LEFT, RIGHT, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO, PIN, PIN, ZERO }
672 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO }
675 { LEFT, PIN, RIGHT, ZERO, ZERO, PIN, RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO }
678 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT , ZERO }
681 { ZERO, RIGHT, RIGHT, ZERO, RIGHT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, ZERO, LEFT , ZERO }
684 { PIN, LEFT, RIGHT, ZERO, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, LEFT, RIGHT, PIN, RIGHT , ZERO }
687 { PIN, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, PIN , ZERO }
690 { LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT , ZERO }
693 { RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT , ZERO }
696 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, PIN , ZERO }
699 { PIN, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, ZERO , ZERO }
702 { RIGHT, ZERO, PIN, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, ZERO, ZERO, LEFT , ZERO }
705 { LEFT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT , ZERO }
708 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO , ZERO }
711 { RIGHT, ZERO, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO , ZERO }
714 { PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO , ZERO }
717 { RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, LEFT, RIGHT, LEFT, LEFT , ZERO }
720 { RIGHT, RIGHT, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, LEFT, LEFT , ZERO }
723 { RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT , ZERO }
726 { ZERO, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, LEFT, ZERO, LEFT, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT , ZERO }
730 { LEFT, ZERO, PIN, ZERO, PIN, LEFT, ZERO, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, PIN, ZERO, RIGHT , ZERO }
734 { ZERO, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, LEFT , ZERO }
737 { ZERO, ZERO, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN , ZERO }
740 { LEFT, PIN, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO , ZERO }
743 { ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN , ZERO }
746 { PIN, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO , ZERO }
749 { LEFT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT , ZERO }
752 { PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, RIGHT, PIN , ZERO }
755 { RIGHT, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, LEFT , ZERO }
758 { ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO, PIN , ZERO }
760 { "Counterclockwise",
761 { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT , ZERO }
764 { LEFT, LEFT, ZERO, PIN, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, RIGHT, LEFT, LEFT, ZERO, ZERO, RIGHT , ZERO }
767 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, PIN, RIGHT , ZERO }
770 { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN , ZERO }
773 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO , ZERO }
776 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, ZERO }
779 { PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, ZERO }
782 { RIGHT, LEFT, PIN, LEFT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, LEFT, PIN, LEFT, RIGHT, ZERO }
785 { LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, PIN, ZERO, ZERO }
788 { RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, ZERO }
791 { ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO }
794 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, LEFT, RIGHT, ZERO }
797 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, LEFT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, RIGHT, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
800 { ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, LEFT, ZERO, PIN, ZERO, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, ZERO }
803 { ZERO, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO }
806 { ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO }
809 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO }
812 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO, RIGHT, ZERO, RIGHT, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO }
815 { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, RIGHT, ZERO, RIGHT, LEFT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO }
818 { PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, ZERO }
821 { PIN, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO }
824 { ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO }
827 { LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, ZERO }
830 { LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, ZERO }
833 { RIGHT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, ZERO }
836 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, ZERO }
839 { ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO }
842 { LEFT, LEFT, RIGHT, PIN, ZERO, RIGHT, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, LEFT, ZERO, PIN, LEFT, RIGHT, RIGHT, RIGHT, PIN, ZERO }
845 { PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
848 { ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, RIGHT, ZERO, PIN, ZERO }
851 { ZERO, RIGHT, ZERO, PIN, LEFT, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, RIGHT, PIN, ZERO, LEFT, ZERO, ZERO }
854 { ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, ZERO, ZERO, ZERO, PIN, ZERO }
857 { ZERO, PIN, PIN, ZERO, PIN, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO }
860 { ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO }
863 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO }
866 { LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, RIGHT, LEFT, RIGHT, RIGHT, ZERO }
869 { LEFT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, ZERO, RIGHT, ZERO }
872 { PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO }
875 { ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO }
878 { LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO }
881 { RIGHT, LEFT, ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, LEFT, ZERO, ZERO }
884 { PIN, PIN, ZERO, LEFT, RIGHT, LEFT, ZERO, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO }
887 { PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO }
890 { PIN, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO }
893 { RIGHT, ZERO, ZERO, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, RIGHT, ZERO, PIN, ZERO, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO, ZERO, ZERO, LEFT, ZERO }
896 { ZERO, PIN, ZERO, ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO }
899 { ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO }
901 { "HoleInTheMiddle1",
902 { ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO }
904 { "HoleInTheMiddle2",
905 { ZERO, LEFT, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO }
908 { RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, ZERO }
911 { LEFT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, ZERO }
914 { LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO }
917 { RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
920 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO }
923 { RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, LEFT, ZERO }
926 { ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO }
929 { LEFT, LEFT, PIN, LEFT, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, RIGHT, PIN, RIGHT, RIGHT, LEFT, ZERO }
932 { ZERO, PIN, PIN, ZERO, ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO }
935 { RIGHT, PIN, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, PIN, LEFT, ZERO }
938 { PIN, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO }
941 { PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, ZERO }
943 { "magnifying glass",
944 { ZERO, ZERO, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, ZERO }
947 { ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, ZERO }
950 { PIN, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO }
953 { PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO }
956 { ZERO, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, LEFT, PIN, RIGHT, RIGHT, ZERO, RIGHT, ZERO }
959 { ZERO, RIGHT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, ZERO, RIGHT, RIGHT, PIN, LEFT, ZERO }
962 { LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
965 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, LEFT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO }
968 { ZERO, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO }
970 { "MouseWithoutTail",
971 { ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO }
974 { PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, ZERO }
977 { ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO }
980 { LEFT, ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, ZERO }
983 { ZERO, RIGHT, PIN, LEFT, LEFT, LEFT, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO }
986 { LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, ZERO }
989 { PIN, ZERO, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, ZERO, ZERO }
992 { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, ZERO }
995 { PIN, PIN, ZERO, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
998 { ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
1001 { ZERO, ZERO, ZERO, ZERO, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO }
1004 { PIN, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, PIN, ZERO }
1006 { "PictureComingSoon",
1007 { LEFT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, RIGHT, RIGHT, ZERO }
1010 { LEFT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, ZERO }
1013 { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, ZERO }
1016 { RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO }
1019 { ZERO, PIN, ZERO, PIN, RIGHT, PIN, ZERO, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, ZERO, PIN, LEFT, ZERO }
1023 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO }
1027 { RIGHT, PIN, ZERO, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, PIN, ZERO, PIN, LEFT, ZERO }
1030 { ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, ZERO }
1033 { ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, LEFT, ZERO }
1035 { "QuarterbackTiltedAndReadyToHut",
1036 { PIN, ZERO, RIGHT, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, LEFT, ZERO, PIN, ZERO }
1039 { PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1042 { LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, PIN, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, ZERO }
1045 { ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, ZERO }
1048 { LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, ZERO }
1051 { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1054 { RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, ZERO }
1057 { ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO }
1060 { PIN, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, PIN, ZERO }
1063 { RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1066 { RIGHT, LEFT, PIN, ZERO, ZERO, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO }
1069 { LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO }
1072 { RIGHT, PIN, ZERO, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO }
1075 { RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, ZERO }
1078 { LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO }
1081 { PIN, RIGHT, LEFT, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, LEFT, ZERO, PIN, PIN, ZERO }
1084 { LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO }
1087 { LEFT, RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, RIGHT, LEFT, ZERO }
1090 { ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO }
1092 { "SnakeReadyToStrike",
1093 { LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO }
1096 { RIGHT, RIGHT, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO }
1099 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO }
1102 { PIN, PIN, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
1105 { LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, ZERO }
1108 { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO }
1111 { PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, ZERO }
1114 { PIN, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, PIN, ZERO }
1117 { PIN, PIN, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, LEFT, LEFT, PIN, PIN, ZERO }
1120 { LEFT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, ZERO }
1123 { PIN, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, ZERO, RIGHT, PIN, LEFT, ZERO }
1126 { RIGHT, RIGHT, ZERO, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, RIGHT, LEFT, RIGHT, ZERO, ZERO, LEFT, ZERO }
1129 { PIN, LEFT, ZERO, RIGHT, RIGHT, LEFT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, LEFT, LEFT, ZERO, ZERO }
1132 { ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, ZERO }
1135 { PIN, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO }
1138 { RIGHT, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, ZERO }
1141 { ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO }
1144 { ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
1147 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO }
1150 { ZERO, PIN, ZERO, PIN, LEFT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, ZERO }
1153 { PIN, ZERO, PIN, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO }
1156 { PIN, PIN, ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO }
1159 { RIGHT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, RIGHT, ZERO }
1162 { RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO }
1165 { ZERO, PIN, LEFT, LEFT, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1168 { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, RIGHT, PIN, ZERO }
1171 { ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO }
1174 { ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO }
1177 { RIGHT, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, ZERO }
1180 { RIGHT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO }
1183 { RIGHT, LEFT, ZERO, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO }
1186 { PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO }
1189 { RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, PIN, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO }
1192 { RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, ZERO }
1195 { ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, LEFT, LEFT, PIN, ZERO, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, ZERO }
1198 { PIN, LEFT, LEFT, PIN, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO }
1201 { PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO }
1204 { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO }
1207 { PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, ZERO }
1211 { RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO }
1215 { ZERO, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO, ZERO }
1218 { ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, ZERO }
1221 { PIN, LEFT, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, ZERO, ZERO }
1224 { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1227 { LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO }
1230 { ZERO, PIN, ZERO, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, ZERO }
1233 { ZERO, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, ZERO }
1236 { PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO }
1239 { ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO }
1242 { PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, PIN, RIGHT, ZERO, RIGHT, RIGHT, ZERO, RIGHT, PIN, ZERO, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, ZERO }
1245 { ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1248 { LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO }
1251 { PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO }
1254 { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO }
1256 { "WindowToTheWorld",
1257 { PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
1260 { PIN, PIN, ZERO, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, PIN, ZERO }
1263 { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO }
1266 { RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO }
1269 { PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, ZERO }
1272 { ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO }
1275 { LEFT, ZERO, ZERO, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, ZERO, ZERO, ZERO }
1279 static size_t models = sizeof(model) / sizeof(struct model_s);
1281 #define VOFFSET 0.045
1287 /* the connecting string that holds the snake together */
1288 #define MAGICAL_RED_STRING 0
1290 #define GETSCALAR(vec,mask) ((vec)==(mask) ? 1 : ((vec)==-(mask) ? -1 : 0 ))
1293 # define MAX(x, y) ((x) > (y) ? (x) : (y))
1296 # define MIN(x, y) ((x) < (y) ? (x) : (y))
1299 #define RAND(n) ((random() & 0x7fffffff) % ((long) (n)))
1300 #define RANDSIGN() ((random() & 1) ? 1 : -1)
1302 /* the triangular prism what makes up the basic unit */
1303 static const float solid_prism_v[][3] = {
1304 /* first corner, bottom left front */
1305 { VOFFSET, VOFFSET, 1.0 },
1306 { VOFFSET, 0.00, 1.0 - VOFFSET },
1307 { 0.00, VOFFSET, 1.0 - VOFFSET },
1308 /* second corner, rear */
1309 { VOFFSET, VOFFSET, 0.00 },
1310 { VOFFSET, 0.00, VOFFSET },
1311 { 0.00, VOFFSET, VOFFSET },
1312 /* third, right front */
1313 { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 1.0 },
1314 { 1.0 - VOFFSET / M_SQRT1_2, 0.0, 1.0 - VOFFSET },
1315 { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, 1.0 - VOFFSET },
1316 /* fourth, right rear */
1317 { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 0.0 },
1318 { 1.0 - VOFFSET / M_SQRT1_2, 0.0, VOFFSET },
1319 { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, VOFFSET },
1320 /* fifth, upper front */
1321 { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 1.0 },
1322 { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, 1.0 - VOFFSET },
1323 { 0.0, 1.0 - VOFFSET / M_SQRT1_2, 1.0 - VOFFSET},
1324 /* sixth, upper rear */
1325 { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 0.0 },
1326 { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, VOFFSET },
1327 { 0.0, 1.0 - VOFFSET / M_SQRT1_2, VOFFSET }};
1329 static const float solid_prism_n[][3] = {/* corners */
1330 { -VOFFSET, -VOFFSET, VOFFSET },
1331 { VOFFSET, -VOFFSET, VOFFSET },
1332 { -VOFFSET, VOFFSET, VOFFSET },
1333 { -VOFFSET, -VOFFSET, -VOFFSET },
1334 { VOFFSET, -VOFFSET, -VOFFSET },
1335 { -VOFFSET, VOFFSET, -VOFFSET },
1337 { -VOFFSET, 0.0, VOFFSET },
1338 { 0.0, -VOFFSET, VOFFSET },
1339 { VOFFSET, VOFFSET, VOFFSET },
1340 { -VOFFSET, 0.0, -VOFFSET },
1341 { 0.0, -VOFFSET, -VOFFSET },
1342 { VOFFSET, VOFFSET, -VOFFSET },
1343 { -VOFFSET, -VOFFSET, 0.0 },
1344 { VOFFSET, -VOFFSET, 0.0 },
1345 { -VOFFSET, VOFFSET, 0.0 },
1349 { M_SQRT1_2, M_SQRT1_2, 0.0 },
1351 { 0.0, 0.0, -1.0 }};
1353 static const float wire_prism_v[][3] = {{ 0.0, 0.0, 1.0 },
1361 static const float wire_prism_n[][3] = {{ 0.0, 0.0, 1.0},
1363 { M_SQRT1_2, M_SQRT1_2, 0.0},
1368 static struct glsnake_cfg * glc = NULL;
1373 typedef float (*morphFunc)(long);
1376 /* forward definitions for GLUT functions */
1377 static void calc_rotation();
1378 static inline void ui_mousedrag();
1381 static const GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };
1382 static const GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
1383 static const GLfloat mat_specular[] = { 0.1, 0.1, 0.1, 1.0 };
1384 static const GLfloat mat_shininess[] = { 20.0 };
1386 static void gl_init(
1392 float light_pos[][3] = {{0.0, 10.0, 20.0}, {0.0, 20.0, -1.0}};
1393 float light_dir[][3] = {{0.0, -10.0,-20.0}, {0.0,-20.0, 1.0}};
1395 glEnable(GL_DEPTH_TEST);
1396 glShadeModel(GL_SMOOTH);
1397 glCullFace(GL_BACK);
1398 /*glEnable(GL_CULL_FACE);*/
1399 glEnable(GL_NORMALIZE);
1401 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1406 /*glColor4f(1.0, 1.0, 1.0, 1.0);*/
1407 glLightfv(GL_LIGHT0, GL_POSITION, light_pos[0]);
1408 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_dir[0]);
1409 glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
1410 /*glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);*/
1412 glLightfv(GL_LIGHT1, GL_POSITION, light_pos[1]);
1413 glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light_dir[1]);
1414 glLightfv(GL_LIGHT1, GL_DIFFUSE, white_light);
1415 glLightfv(GL_LIGHT1, GL_SPECULAR, white_light);
1417 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
1418 glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
1419 glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
1420 glEnable(GL_LIGHTING);
1421 glEnable(GL_LIGHT0);
1422 glEnable(GL_LIGHT1);
1423 /*glEnable(GL_COLOR_MATERIAL);*/
1427 static void gettime(snaketime *t)
1429 #ifdef HAVE_GETTIMEOFDAY
1430 #ifdef GETTIMEOFDAY_TWO_ARGS
1431 struct timezone tzp;
1432 gettimeofday(t, &tzp);
1433 #else /* !GETTIMEOFDAY_TWO_ARGS */
1435 #endif /* !GETTIMEOFDAY_TWO_ARGS */
1436 #else /* !HAVE_GETTIMEOFDAY */
1439 #endif /* HAVE_FTIME */
1440 #endif /* !HAVE_GETTIMEOFDAY */
1444 ENTRYPOINT void glsnake_reshape(
1450 static void start_morph(struct glsnake_cfg *,
1451 unsigned int model_index, int immediate);
1453 /* wot initialises it */
1454 ENTRYPOINT void glsnake_init(
1461 struct glsnake_cfg * bp;
1463 /* set up the conf struct and glx contexts */
1464 MI_INIT(mi, glc, NULL);
1465 bp = &glc[MI_SCREEN(mi)];
1467 if ((bp->glx_context = init_GL(mi)) != NULL) {
1469 glsnake_reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1475 /* initialise conf struct */
1476 memset(&bp->node, 0, sizeof(float) * NODE_COUNT);
1486 gettime(&bp->last_iteration);
1487 memcpy(&bp->last_morph, &bp->last_iteration, sizeof(bp->last_morph));
1489 bp->prev_colour = bp->next_colour = COLOUR_ACYCLIC;
1490 bp->next_model = RAND(models);
1491 bp->prev_model = START_MODEL;
1492 start_morph(bp, bp->prev_model, 1);
1494 /* set up a font for the labels */
1497 bp->font_data = load_texture_font (mi->dpy, "labelfont");
1500 /* build a solid display list */
1501 bp->node_solid = glGenLists(1);
1502 glNewList(bp->node_solid, GL_COMPILE);
1504 glBegin(GL_TRIANGLES);
1505 glNormal3fv(solid_prism_n[0]);
1506 glVertex3fv(solid_prism_v[0]);
1507 glVertex3fv(solid_prism_v[2]);
1508 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]);
1517 glNormal3fv(solid_prism_n[2]);
1518 glVertex3fv(solid_prism_v[12]);
1519 glVertex3fv(solid_prism_v[13]);
1520 glVertex3fv(solid_prism_v[14]);
1523 glNormal3fv(solid_prism_n[3]);
1524 glVertex3fv(solid_prism_v[3]);
1525 glVertex3fv(solid_prism_v[4]);
1526 glVertex3fv(solid_prism_v[5]);
1529 glNormal3fv(solid_prism_n[4]);
1530 glVertex3fv(solid_prism_v[9]);
1531 glVertex3fv(solid_prism_v[11]);
1532 glVertex3fv(solid_prism_v[10]);
1535 glNormal3fv(solid_prism_n[5]);
1536 glVertex3fv(solid_prism_v[16]);
1537 glVertex3fv(solid_prism_v[15]);
1538 glVertex3fv(solid_prism_v[17]);
1544 glNormal3fv(solid_prism_n[6]);
1545 glVertex3fv(solid_prism_v[0]);
1546 glVertex3fv(solid_prism_v[12]);
1547 glVertex3fv(solid_prism_v[14]);
1548 glVertex3fv(solid_prism_v[2]);
1551 glNormal3fv(solid_prism_n[7]);
1552 glVertex3fv(solid_prism_v[0]);
1553 glVertex3fv(solid_prism_v[1]);
1554 glVertex3fv(solid_prism_v[7]);
1555 glVertex3fv(solid_prism_v[6]);
1558 glNormal3fv(solid_prism_n[8]);
1559 glVertex3fv(solid_prism_v[6]);
1560 glVertex3fv(solid_prism_v[8]);
1561 glVertex3fv(solid_prism_v[13]);
1562 glVertex3fv(solid_prism_v[12]);
1565 glNormal3fv(solid_prism_n[9]);
1566 glVertex3fv(solid_prism_v[3]);
1567 glVertex3fv(solid_prism_v[5]);
1568 glVertex3fv(solid_prism_v[17]);
1569 glVertex3fv(solid_prism_v[15]);
1572 glNormal3fv(solid_prism_n[10]);
1573 glVertex3fv(solid_prism_v[3]);
1574 glVertex3fv(solid_prism_v[9]);
1575 glVertex3fv(solid_prism_v[10]);
1576 glVertex3fv(solid_prism_v[4]);
1579 glNormal3fv(solid_prism_n[11]);
1580 glVertex3fv(solid_prism_v[15]);
1581 glVertex3fv(solid_prism_v[16]);
1582 glVertex3fv(solid_prism_v[11]);
1583 glVertex3fv(solid_prism_v[9]);
1586 glNormal3fv(solid_prism_n[12]);
1587 glVertex3fv(solid_prism_v[1]);
1588 glVertex3fv(solid_prism_v[2]);
1589 glVertex3fv(solid_prism_v[5]);
1590 glVertex3fv(solid_prism_v[4]);
1593 glNormal3fv(solid_prism_n[13]);
1594 glVertex3fv(solid_prism_v[8]);
1595 glVertex3fv(solid_prism_v[7]);
1596 glVertex3fv(solid_prism_v[10]);
1597 glVertex3fv(solid_prism_v[11]);
1600 glNormal3fv(solid_prism_n[14]);
1601 glVertex3fv(solid_prism_v[13]);
1602 glVertex3fv(solid_prism_v[16]);
1603 glVertex3fv(solid_prism_v[17]);
1604 glVertex3fv(solid_prism_v[14]);
1609 glBegin(GL_TRIANGLES);
1610 glNormal3fv(solid_prism_n[15]);
1611 glVertex3fv(solid_prism_v[0]);
1612 glVertex3fv(solid_prism_v[6]);
1613 glVertex3fv(solid_prism_v[12]);
1616 glNormal3fv(solid_prism_n[19]);
1617 glVertex3fv(solid_prism_v[3]);
1618 glVertex3fv(solid_prism_v[15]);
1619 glVertex3fv(solid_prism_v[9]);
1624 glNormal3fv(solid_prism_n[16]);
1625 glVertex3fv(solid_prism_v[1]);
1626 glVertex3fv(solid_prism_v[4]);
1627 glVertex3fv(solid_prism_v[10]);
1628 glVertex3fv(solid_prism_v[7]);
1631 glNormal3fv(solid_prism_n[17]);
1632 glVertex3fv(solid_prism_v[8]);
1633 glVertex3fv(solid_prism_v[11]);
1634 glVertex3fv(solid_prism_v[16]);
1635 glVertex3fv(solid_prism_v[13]);
1638 glNormal3fv(solid_prism_n[18]);
1639 glVertex3fv(solid_prism_v[2]);
1640 glVertex3fv(solid_prism_v[14]);
1641 glVertex3fv(solid_prism_v[17]);
1642 glVertex3fv(solid_prism_v[5]);
1647 /* build wire display list */
1648 bp->node_wire = glGenLists(1);
1649 glNewList(bp->node_wire, GL_COMPILE);
1650 glBegin(GL_LINE_STRIP);
1651 glVertex3fv(wire_prism_v[0]);
1652 glVertex3fv(wire_prism_v[1]);
1654 glVertex3fv(wire_prism_v[2]);
1655 glVertex3fv(wire_prism_v[0]);
1657 glVertex3fv(wire_prism_v[3]);
1658 glVertex3fv(wire_prism_v[4]);
1660 glVertex3fv(wire_prism_v[5]);
1661 glVertex3fv(wire_prism_v[3]);
1665 glVertex3fv(wire_prism_v[1]);
1666 glVertex3fv(wire_prism_v[4]);
1668 glVertex3fv(wire_prism_v[2]);
1669 glVertex3fv(wire_prism_v[5]);
1675 /* initialise the rotation */
1680 static void draw_title(
1687 struct glsnake_cfg * bp = &glc[MI_SCREEN(mi)];
1690 /* draw some text */
1692 /* glPushAttrib((GLbitfield) GL_TRANSFORM_BIT | GL_ENABLE_BIT);*/
1693 glDisable(GL_LIGHTING);
1694 glDisable(GL_DEPTH_TEST);
1696 glDisable(GL_BLEND);
1698 glMatrixMode(GL_PROJECTION);
1701 glMatrixMode(GL_MODELVIEW);
1705 glOrtho((GLdouble) 0., (GLdouble) bp->width, (GLdouble) 0., (GLdouble) bp->height, -1, 1);
1707 glOrtho((GLdouble) 0., (GLdouble) mi->xgwa.width, (GLdouble) 0., (GLdouble) mi->xgwa.height, -1, 1);
1710 glColor4f(1.0, 1.0, 1.0, 1.0);
1712 char interactstr[] = "interactive";
1721 s = model[bp->next_model].name;
1727 w = glutBitmapLength(GLUT_BITMAP_HELVETICA_12, (const unsigned char *) s);
1728 glRasterPos2f((GLfloat) (bp->width - w - 3), 4.0);
1729 while (s[i] != '\0')
1730 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, s[i++]);
1733 print_texture_label (mi->dpy, bp->font_data,
1734 mi->xgwa.width, mi->xgwa.height,
1739 glMatrixMode(GL_PROJECTION);
1746 /* apply the matrix to the origin and stick it in vec */
1747 static void matmult_origin(float rotmat[16], float vec[4])
1750 vec[0] = 0.5 * rotmat[0] + 0.5 * rotmat[4] + 0.5 * rotmat [8] + 1 * rotmat[12];
1751 vec[1] = 0.5 * rotmat[1] + 0.5 * rotmat[5] + 0.5 * rotmat [9] + 1 * rotmat[13];
1752 vec[2] = 0.5 * rotmat[2] + 0.5 * rotmat[6] + 0.5 * rotmat[10] + 1 * rotmat[14];
1753 vec[3] = 0.5 * rotmat[3] + 0.5 * rotmat[7] + 0.5 * rotmat[11] + 1 * rotmat[15];
1755 vec[0] = 0 * rotmat [0] + 0 * rotmat [1] + 0 * rotmat [2] + 1 * rotmat [3];
1756 vec[1] = 0 * rotmat [4] + 0 * rotmat [5] + 0 * rotmat [6] + 1 * rotmat [7];
1757 vec[2] = 0 * rotmat [8] + 0 * rotmat [9] + 0 * rotmat[10] + 1 * rotmat[11];
1758 vec[3] = 0 * rotmat[12] + 0 * rotmat[13] + 0 * rotmat[14] + 1 * rotmat[15];
1766 /* wot gets called when the winder is resized */
1767 ENTRYPOINT void glsnake_reshape(
1773 glViewport(0, 0, (GLint) w, (GLint) h);
1774 glMatrixMode(GL_PROJECTION);
1776 /* jwz: 0.05 was too close (left black rectangles) */
1777 gluPerspective(zoom, (GLdouble) w / (GLdouble) h, 1.0, 100.0);
1778 gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
1779 glMatrixMode(GL_MODELVIEW);
1780 /*gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);*/
1788 /* Returns the new dst_dir for the given src_dir and dst_dir */
1789 static int cross_product(int src_dir, int dst_dir)
1791 return X_MASK*(GETSCALAR(src_dir,Y_MASK) * GETSCALAR(dst_dir,Z_MASK) -
1792 GETSCALAR(src_dir,Z_MASK) * GETSCALAR(dst_dir,Y_MASK))+
1793 Y_MASK*(GETSCALAR(src_dir,Z_MASK) * GETSCALAR(dst_dir,X_MASK) -
1794 GETSCALAR(src_dir,X_MASK) * GETSCALAR(dst_dir,Z_MASK))+
1795 Z_MASK*(GETSCALAR(src_dir,X_MASK) * GETSCALAR(dst_dir,Y_MASK) -
1796 GETSCALAR(src_dir,Y_MASK) * GETSCALAR(dst_dir,X_MASK));
1799 /* calculate orthogonal snake metrics
1800 * is_legal = true if model does not pass through itself
1801 * is_cyclic = true if last node connects back to first node
1802 * last_turn = for cyclic snakes, specifes what the 24th turn would be
1804 static void calc_snake_metrics(struct glsnake_cfg *bp)
1808 int prevSrcDir = -Y_MASK;
1809 int prevDstDir = Z_MASK;
1810 int grid[25][25][25];
1813 memset(&grid, 0, sizeof(int) * 25*25*25);
1818 /* trace path of snake - and keep record for is_legal */
1819 for (i = 0; i < NODE_COUNT - 1; i++) {
1820 /*int ang_card;*/ /* cardinal direction of node angle */
1821 /* establish new state vars */
1822 srcDir = -prevDstDir;
1823 x += GETSCALAR(prevDstDir, X_MASK);
1824 y += GETSCALAR(prevDstDir, Y_MASK);
1825 z += GETSCALAR(prevDstDir, Z_MASK);
1827 switch ((int) model[bp->next_model].node[i]) {
1829 dstDir = -prevSrcDir;
1832 dstDir = prevSrcDir;
1836 dstDir = cross_product(prevSrcDir, prevDstDir);
1837 if (model[bp->next_model].node[i] == (int) (RIGHT))
1841 /* Prevent spurious "might be used
1842 * uninitialised" warnings when compiling
1848 if (grid[x][y][z] == 0)
1849 grid[x][y][z] = srcDir + dstDir;
1850 else if (grid[x][y][z] + srcDir + dstDir == 0)
1855 prevSrcDir = srcDir;
1856 prevDstDir = dstDir;
1859 /* determine if the snake is cyclic */
1860 bp->is_cyclic = (dstDir == Y_MASK && x == 12 && y == 11 && z == 12);
1862 /* determine last_turn */
1866 case -Z_MASK: bp->last_turn = ZERO; break;
1867 case Z_MASK: bp->last_turn = PIN; break;
1868 case X_MASK: bp->last_turn = LEFT; break;
1869 case -X_MASK: bp->last_turn = RIGHT; break;
1873 /* work out how far through the current morph we are */
1874 static float morph_percent(struct glsnake_cfg *bp)
1879 /* extend this function later with a case statement for each of the
1882 /* when morphing all nodes at once, the longest morph will be the node
1883 * that needs to rotate 180 degrees. For each node, work out how far it
1884 * has to go, and store the maximum rotation and current largest angular
1885 * difference, returning the angular difference over the maximum. */
1887 float rot_max = 0.0, ang_diff_max = 0.0;
1889 for (i = 0; i < NODE_COUNT - 1; i++) {
1890 float rot, ang_diff;
1892 /* work out the maximum rotation this node has to go through
1893 * from the previous to the next model, taking into account that
1894 * the snake always morphs through the smaller angle */
1895 rot = fabs(model[bp->prev_model].node[i] -
1896 model[bp->next_model].node[i]);
1897 if (rot > 180.0) rot = 180.0 - rot;
1898 /* work out the difference between the current position and the
1900 ang_diff = fabs(bp->node[i] -
1901 model[bp->next_model].node[i]);
1902 if (ang_diff > 180.0) ang_diff = 180.0 - ang_diff;
1903 /* if it's the biggest so far, record it */
1904 if (rot > rot_max) rot_max = rot;
1905 if (ang_diff > ang_diff_max) ang_diff_max = ang_diff;
1908 /* ang_diff / rot approaches 0, we want the complement */
1909 retval = 1.0 - (ang_diff_max / rot_max);
1910 /* protect against naan */
1912 /* Apparently some systems (Solaris) don't have isinf() */
1914 #define isinf(x) (((x) > 999999999999.9) || ((x) < -999999999999.9))
1916 if (isnan(retval) || isinf(retval)) retval = 1.0;
1918 /*printf("morph_pct = %f\n", retval);*/
1922 static void morph_colour(struct glsnake_cfg *bp)
1924 float percent, compct; /* complement of percentage */
1926 percent = morph_percent(bp);
1927 compct = 1.0 - percent;
1929 bp->colour[0][0] = colour[bp->prev_colour][0][0] * compct + colour[bp->next_colour][0][0] * percent;
1930 bp->colour[0][1] = colour[bp->prev_colour][0][1] * compct + colour[bp->next_colour][0][1] * percent;
1931 bp->colour[0][2] = colour[bp->prev_colour][0][2] * compct + colour[bp->next_colour][0][2] * percent;
1932 bp->colour[0][3] = colour[bp->prev_colour][0][3] * compct + colour[bp->next_colour][0][3] * percent;
1934 bp->colour[1][0] = colour[bp->prev_colour][1][0] * compct + colour[bp->next_colour][1][0] * percent;
1935 bp->colour[1][1] = colour[bp->prev_colour][1][1] * compct + colour[bp->next_colour][1][1] * percent;
1936 bp->colour[1][2] = colour[bp->prev_colour][1][2] * compct + colour[bp->next_colour][1][2] * percent;
1937 bp->colour[1][3] = colour[bp->prev_colour][1][3] * compct + colour[bp->next_colour][1][3] * percent;
1940 /* Start morph process to this model */
1941 static void start_morph(struct glsnake_cfg *bp,
1942 unsigned int model_index, int immediate)
1944 /* if immediate, don't bother morphing, go straight to the next model */
1948 for (i = 0; i < NODE_COUNT; i++)
1949 bp->node[i] = model[model_index].node[i];
1952 bp->prev_model = bp->next_model;
1953 bp->next_model = model_index;
1954 bp->prev_colour = bp->next_colour;
1956 calc_snake_metrics(bp);
1958 bp->next_colour = COLOUR_INVALID;
1960 bp->next_colour = COLOUR_AUTHENTIC;
1961 else if (bp->is_cyclic)
1962 bp->next_colour = COLOUR_CYCLIC;
1964 bp->next_colour = COLOUR_ACYCLIC;
1967 bp->colour[0][0] = colour[bp->next_colour][0][0];
1968 bp->colour[0][1] = colour[bp->next_colour][0][1];
1969 bp->colour[0][2] = colour[bp->next_colour][0][2];
1970 bp->colour[0][3] = colour[bp->next_colour][0][3];
1971 bp->colour[1][0] = colour[bp->next_colour][1][0];
1972 bp->colour[1][1] = colour[bp->next_colour][1][1];
1973 bp->colour[1][2] = colour[bp->next_colour][1][2];
1974 bp->colour[1][3] = colour[bp->next_colour][1][3];
1982 /* Returns morph progress */
1983 static float morph(long iter_msec)
1985 /* work out the maximum angle for this iteration */
1987 float iter_angle_max, largest_diff, largest_progress;
1993 iter_angle_max = 90.0 * (angvel/1000.0) * iter_msec;
1996 largest_diff = largest_progress = 0.0;
1997 for (i = 0; i < NODE_COUNT; i++) {
1998 float curAngle = bp->node[i];
1999 float destAngle = model[bp->next_model].node[i];
2000 if (curAngle != destAngle) {
2002 if (fabs(curAngle-destAngle) <= iter_angle_max)
2003 bp->node[i] = destAngle;
2004 else if (fmod(curAngle-destAngle+360,360) > 180)
2005 bp->node[i] = fmod(curAngle + iter_angle_max, 360);
2007 bp->node[i] = fmod(curAngle+360 - iter_angle_max, 360);
2008 largest_diff = MAX(largest_diff, fabs(destAngle-bp->node[i]));
2009 largest_progress = MAX(largest_diff, fabs(bp->node[i] - model[bp->prev_model].node[i]));
2013 return MIN(largest_diff / largest_progress, 1.0);
2019 static void glsnake_idle();
2021 static restore_idle(int v __attribute__((__unused__)))
2023 glutIdleFunc(glsnake_idle);
2027 static void quick_sleep(void)
2030 /* By using glutTimerFunc we can keep responding to
2031 * mouse and keyboard events, unlike using something like
2034 glutTimerFunc(1, restore_idle, 0);
2040 static void glsnake_idle(
2042 struct glsnake_cfg * bp
2046 /* time since last iteration */
2048 /* time since the beginning of last morph */
2050 float iter_angle_max;
2051 snaketime current_time;
2052 /* morphFunc transition; */
2056 /* Do nothing to the model if we are paused */
2058 /* Avoid busy waiting when nothing is changing */
2062 glutPostRedisplay();
2067 /* <spiv> Well, ftime gives time with millisecond resolution.
2068 * <spiv> (or worse, perhaps... who knows what the OS will do)
2069 * <spiv> So if no discernable amount of time has passed:
2070 * <spiv> a) There's no point updating the screen, because
2071 * it would be the same
2072 * <spiv> b) The code will divide by zero
2074 gettime(¤t_time);
2076 iter_msec = (long) GETMSECS(current_time) - GETMSECS(bp->last_iteration) +
2077 ((long) GETSECS(current_time) - GETSECS(bp->last_iteration)) * 1000L;
2080 /* save the current time */
2081 memcpy(&bp->last_iteration, ¤t_time, sizeof(snaketime));
2083 /* work out if we have to switch models */
2084 morf_msec = GETMSECS(bp->last_iteration) - GETMSECS(bp->last_morph) +
2085 ((long) (GETSECS(bp->last_iteration)-GETSECS(bp->last_morph)) * 1000L);
2087 if ((morf_msec > statictime) && !interactive && !bp->morphing) {
2088 /*printf("starting morph\n");*/
2089 memcpy(&bp->last_morph, &(bp->last_iteration), sizeof(bp->last_morph));
2090 start_morph(bp, RAND(models), 0);
2093 if (interactive && !bp->morphing) {
2098 /* if (!bp->dragging && !bp->interactive) { */
2101 yspin += 360/((1000/yangvel)/iter_msec);
2102 zspin += 360/((1000/zangvel)/iter_msec);
2104 yspin += 360 * (yangvel/1000.0) * iter_msec;
2105 zspin += 360 * (zangvel/1000.0) * iter_msec;
2108 /*printf("yspin: %f, zspin: %f\n", yspin, zspin);*/
2112 /* work out the maximum angle we could turn this node in this
2113 * timeslice, iter_msec milliseconds long */
2114 iter_angle_max = 90.0 * (angvel/1000.0) * iter_msec;
2117 for (i = 0; i < NODE_COUNT; i++) {
2118 float cur_angle = bp->node[i];
2119 float dest_angle = model[bp->next_model].node[i];
2120 if (cur_angle != dest_angle) {
2122 if (fabs(cur_angle - dest_angle) <= iter_angle_max)
2123 bp->node[i] = dest_angle;
2124 else if (fmod(cur_angle - dest_angle + 360, 360) > 180)
2125 bp->node[i] = fmod(cur_angle + iter_angle_max, 360);
2127 bp->node[i] = fmod(cur_angle + 360 - iter_angle_max, 360);
2131 if (!still_morphing)
2134 /* colour cycling */
2139 glutPostRedisplay();
2142 /* We are going too fast, so we may as well let the
2143 * cpu relax a little by sleeping for a millisecond. */
2149 ENTRYPOINT void glsnake_display(
2156 struct glsnake_cfg * bp = &glc[MI_SCREEN(mi)];
2157 Display * dpy = MI_DISPLAY(mi);
2158 Window window = MI_WINDOW(mi);
2163 float positions[NODE_COUNT][4]; /* origin points for each node */
2164 float com[4]; /* it's the CENTRE of MASS */
2167 if (!bp->glx_context)
2170 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
2175 /* clear the buffer */
2176 glClear((GLbitfield) GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2178 /* go into the modelview stack */
2179 glMatrixMode(GL_MODELVIEW);
2182 /* get the centre of each node, by moving through the snake and
2183 * performing the rotations, then grabbing the matrix at each point
2184 * and applying it to the origin */
2188 /* apply the mouse drag rotation */
2192 /* apply the continuous rotation */
2193 glRotatef(yspin, 0.0, 1.0, 0.0);
2194 glRotatef(zspin, 0.0, 0.0, 1.0);
2200 for (i = 0; i < NODE_COUNT; i++) {
2205 /*printf("ang = %f\n", ang);*/
2207 glTranslatef(0.5, 0.5, 0.5); /* move to center */
2208 glRotatef(90.0, 0.0, 0.0, -1.0); /* reorient */
2209 glTranslatef(1.0 + explode, 0.0, 0.0); /* move to new pos. */
2210 glRotatef(180.0 + ang, 1.0, 0.0, 0.0); /* pivot to new angle */
2211 glTranslatef(-0.5, -0.5, -0.5); /* return from center */
2213 glGetFloatv(GL_MODELVIEW_MATRIX, rotmat);
2215 matmult_origin(rotmat, positions[i]);
2217 /*printf("positions %f %f %f %f\n", positions[i][0], positions[i][1], positions[i][2], positions[i][3]);*/
2219 com[0] += positions[i][0];
2220 com[1] += positions[i][1];
2221 com[2] += positions[i][2];
2222 com[3] += positions[i][3];
2225 com[0] /= NODE_COUNT;
2226 com[1] /= NODE_COUNT;
2227 com[2] /= NODE_COUNT;
2228 com[3] /= NODE_COUNT;
2234 /*printf("com: %f, %f, %f, %f\n", com[0], com[1], com[2], com[3]);*/
2236 #if MAGICAL_RED_STRING
2238 glTranslatef(-com[0], -com[1], -com[2]);
2240 glDisable(GL_LIGHTING);
2241 glColor4f(1.0, 0.0, 0.0, 1.0);
2242 glBegin(GL_LINE_STRIP);
2243 for (i = 0; i < NODE_COUNT - 1; i++) {
2244 glVertex3fv(positions[i]);
2247 glEnable(GL_LIGHTING);
2248 /*glTranslatef(com[0], com[1], com[2]);*/
2253 glTranslatef(-com[0], -com[1], -com[2]);
2256 /* apply the mouse drag rotation */
2260 /* apply the continuous rotation */
2261 glRotatef(yspin, 0.0, 1.0, 0.0);
2262 glRotatef(zspin, 0.0, 0.0, 1.0);
2264 # ifdef HAVE_MOBILE /* Keep it the same relative size when rotated. */
2266 GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
2267 int o = (int) current_device_rotation();
2268 if (o != 0 && o != 180 && o != -180)
2269 glScalef (1/h, 1/h, 1/h);
2273 /* now draw each node along the snake -- this is quite ugly :p */
2274 mi->polygon_count = 0;
2275 for (i = 0; i < NODE_COUNT; i++) {
2276 /* choose a colour for this node */
2277 if ((i == bp->selected || i == bp->selected+1) && interactive)
2279 glColor4f(1.0, 1.0, 0.0, 1.0);
2281 /*glColor4fv(bp->colour[(i+1)%2]);*/
2282 glMaterialfv(GL_FRONT, GL_AMBIENT, bp->colour[(i+1)%2]);
2283 glMaterialfv(GL_FRONT, GL_DIFFUSE, bp->colour[(i+1)%2]);
2284 /*glMaterialfv(GL_FRONT, GL_SPECULAR, bp->colour[(i+1)%2]);*/
2289 glCallList(bp->node_wire);
2291 glCallList(bp->node_solid);
2292 mi->polygon_count += bp->node_polys;
2294 /* now work out where to draw the next one */
2296 /* Interpolate between models */
2299 glTranslatef(0.5, 0.5, 0.5); /* move to center */
2300 glRotatef(90.0, 0.0, 0.0, -1.0); /* reorient */
2301 glTranslatef(1.0 + explode, 0.0, 0.0); /* move to new pos. */
2302 glRotatef(180.0 + ang, 1.0, 0.0, 0.0); /* pivot to new angle */
2303 glTranslatef(-0.5, -0.5, -0.5); /* return from center */
2317 if (mi->fps_p) do_fps(mi);
2324 glXSwapBuffers(dpy, window);
2329 /* anything that needs to be cleaned up goes here */
2330 static void unmain()
2332 glutDestroyWindow(bp->window);
2336 static void ui_init(int *, char **);
2338 int main(int argc, char ** argv)
2340 bp = malloc(sizeof(struct glsnake_cfg));
2341 memset(bp, 0, sizeof(struct glsnake_cfg));
2346 ui_init(&argc, argv);
2348 gettime(&bp->last_iteration);
2349 memcpy(&bp->last_morph, &bp->last_iteration, sizeof(snaketime));
2350 srand((unsigned int)GETSECS(bp->last_iteration));
2352 bp->prev_colour = bp->next_colour = COLOUR_ACYCLIC;
2353 bp->next_model = RAND(models);
2355 start_morph(bp->prev_model, 1);
2373 /* trackball quaternions */
2374 static float cumquat[4] = {0.0,0.0,0.0,0.0}, oldquat[4] = {0.0,0.0,0.0,0.1};
2376 /* rotation matrix */
2377 static float rotation[16];
2379 /* mouse drag vectors: start and end */
2380 static float mouse_start[3], mouse_end[3];
2382 /* dragging boolean */
2383 static int dragging = 0;
2385 /* this function calculates the rotation matrix based on the quaternions
2386 * generated from the mouse drag vectors */
2387 static void calc_rotation()
2390 double xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
2392 /* this bit ripped from Shoemake's quaternion notes from SIGGRAPH */
2393 Nq = cumquat[0] * cumquat[0] + cumquat[1] * cumquat[1] +
2394 cumquat[2] * cumquat[2] + cumquat[3] * cumquat[3];
2395 s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
2396 xs = cumquat[0] * s; ys = cumquat[1] * s; zs = cumquat[2] * s;
2397 wx = cumquat[3] * xs; wy = cumquat[3] * ys; wz = cumquat[3] * zs;
2398 xx = cumquat[0] * xs; xy = cumquat[0] * ys; xz = cumquat[0] * zs;
2399 yy = cumquat[1] * ys; yz = cumquat[1] * zs; zz = cumquat[2] * zs;
2401 rotation[0] = 1.0 - (yy + zz);
2402 rotation[1] = xy + wz;
2403 rotation[2] = xz - wy;
2404 rotation[4] = xy - wz;
2405 rotation[5] = 1.0 - (xx + zz);
2406 rotation[6] = yz + wx;
2407 rotation[8] = xz + wy;
2408 rotation[9] = yz - wx;
2409 rotation[10] = 1.0 - (xx + yy);
2410 rotation[3] = rotation[7] = rotation[11] = 0.0;
2411 rotation[12] = rotation[13] = rotation[14] = 0.0;
2415 static inline void ui_mousedrag()
2417 glMultMatrixf(rotation);
2420 static void ui_keyboard(unsigned char c, int x__attribute__((__unused__)), int y __attribute__((__unused__)))
2430 explode += DEF_EXPLODE;
2431 glutPostRedisplay();
2434 explode -= DEF_EXPLODE;
2435 if (explode < 0.0) explode = 0.0;
2436 glutPostRedisplay();
2441 bp->next_model %= models;
2442 start_morph(bp->next_model, 0);
2444 /* Reset last_morph time */
2445 gettime(&bp->last_morph);
2448 /* previous model */
2449 bp->next_model = (bp->next_model + (int)models - 1) % (int)models;
2450 start_morph(bp->next_model, 0);
2452 /* Reset bp->last_morph time */
2453 gettime(&bp->last_morph);
2456 angvel += DEF_ANGVEL;
2459 if (angvel > DEF_ANGVEL)
2460 angvel -= DEF_ANGVEL;
2464 /* Reset last_iteration and last_morph time */
2465 gettime(&bp->last_iteration);
2466 gettime(&bp->last_morph);
2468 interactive = 1 - interactive;
2469 glutPostRedisplay();
2472 wireframe = 1 - wireframe;
2474 glDisable(GL_LIGHTING);
2476 glEnable(GL_LIGHTING);
2477 glutPostRedisplay();
2480 transparent = 1 - transparent;
2484 glDisable(GL_BLEND);
2489 /* unpausing, reset last_iteration and last_morph time */
2490 gettime(&bp->last_iteration);
2491 gettime(&bp->last_morph);
2493 bp->paused = 1 - bp->paused;
2496 /* dump the current model so we can add it! */
2497 printf("# %s\nnoname:\t", model[bp->next_model].name);
2501 for (i = 0; i < NODE_COUNT; i++) {
2502 if (bp->node[i] == ZERO)
2504 else if (bp->node[i] == LEFT)
2506 else if (bp->node[i] == PIN)
2508 else if (bp->node[i] == RIGHT)
2512 printf("%f", node[i].curAngle);
2514 if (i < NODE_COUNT - 1)
2521 bp->fullscreen = 1 - bp->fullscreen;
2522 if (bp->fullscreen) {
2523 bp->old_width = bp->width;
2524 bp->old_height = bp->height;
2527 glutReshapeWindow(bp->old_width, bp->old_height);
2528 glutPositionWindow(50,50);
2532 titles = 1 - titles;
2533 if (interactive || bp->paused)
2534 glutPostRedisplay();
2537 altcolour = 1 - altcolour;
2541 glsnake_reshape(bp->width, bp->height);
2545 glsnake_reshape(bp->width, bp->height);
2552 static void ui_special(int key, int x__attribute__((__unused__)), int y __attribute__((__unused__)))
2554 float *destAngle = &(model[bp->next_model].node[bp->selected]);
2555 int unknown_key = 0;
2560 bp->selected = (bp->selected + (NODE_COUNT - 2)) % (NODE_COUNT - 1);
2563 bp->selected = (bp->selected + 1) % (NODE_COUNT - 1);
2566 *destAngle = fmod(*destAngle+(LEFT), 360);
2567 bp->morphing = bp->new_morph = 1;
2569 case GLUT_KEY_RIGHT:
2570 *destAngle = fmod(*destAngle+(RIGHT), 360);
2571 bp->morphing = bp->new_morph = 1;
2574 start_morph(STRAIGHT_MODEL, 0);
2581 calc_snake_metrics();
2584 glutPostRedisplay();
2587 static void ui_mouse(int button, int state, int x, int y)
2593 mouse_start[0] = M_SQRT1_2 *
2594 (x - (bp->width / 2.0)) / (bp->width / 2.0);
2595 mouse_start[1] = M_SQRT1_2 *
2596 ((bp->height / 2.0) - y) / (bp->height / 2.0);
2597 mouse_start[2] = sqrt((double)(1-(mouse_start[0]*mouse_start[0]+mouse_start[1]*mouse_start[1])));
2601 oldquat[0] = cumquat[0];
2602 oldquat[1] = cumquat[1];
2603 oldquat[2] = cumquat[2];
2604 oldquat[3] = cumquat[3];
2610 glutPostRedisplay();
2613 static void ui_motion(int x, int y)
2619 /* construct the motion end vector from the x,y position on the
2621 mouse_end[0] = M_SQRT1_2 * (x - (bp->width/ 2.0)) / (bp->width / 2.0);
2622 mouse_end[1] = M_SQRT1_2 * ((bp->height / 2.0) - y) / (bp->height / 2.0);
2623 /* calculate the normal of the vector... */
2624 norm = mouse_end[0] * mouse_end[0] + mouse_end[1] * mouse_end[1];
2625 /* check if norm is outside the sphere and wraparound if necessary */
2627 mouse_end[0] = -mouse_end[0];
2628 mouse_end[1] = -mouse_end[1];
2629 mouse_end[2] = sqrt(norm - 1);
2631 /* the z value comes from projecting onto an elliptical spheroid */
2632 mouse_end[2] = sqrt(1 - norm);
2635 /* now here, build a quaternion from mouse_start and mouse_end */
2636 q[0] = mouse_start[1] * mouse_end[2] - mouse_start[2] * mouse_end[1];
2637 q[1] = mouse_start[2] * mouse_end[0] - mouse_start[0] * mouse_end[2];
2638 q[2] = mouse_start[0] * mouse_end[1] - mouse_start[1] * mouse_end[0];
2639 q[3] = mouse_start[0] * mouse_end[0] + mouse_start[1] * mouse_end[1] + mouse_start[2] * mouse_end[2];
2641 /* new rotation is the product of the new one and the old one */
2642 cumquat[0] = q[3] * oldquat[0] + q[0] * oldquat[3] +
2643 q[1] * oldquat[2] - q[2] * oldquat[1];
2644 cumquat[1] = q[3] * oldquat[1] + q[1] * oldquat[3] +
2645 q[2] * oldquat[0] - q[0] * oldquat[2];
2646 cumquat[2] = q[3] * oldquat[2] + q[2] * oldquat[3] +
2647 q[0] * oldquat[1] - q[1] * oldquat[0];
2648 cumquat[3] = q[3] * oldquat[3] - q[0] * oldquat[0] -
2649 q[1] * oldquat[1] - q[2] * oldquat[2];
2653 glutPostRedisplay();
2656 static void ui_init(int * argc, char ** argv)
2658 glutInit(argc, argv);
2659 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
2660 glutInitWindowSize(bp->width, bp->height);
2661 bp->window = glutCreateWindow("glsnake");
2663 glutDisplayFunc(glsnake_display);
2664 glutReshapeFunc(glsnake_reshape);
2665 glutIdleFunc(glsnake_idle);
2666 glutKeyboardFunc(ui_keyboard);
2667 glutSpecialFunc(ui_special);
2668 glutMouseFunc(ui_mouse);
2669 glutMotionFunc(ui_motion);
2671 yangvel = DEF_YANGVEL;
2672 zangvel = DEF_ZANGVEL;
2673 explode = DEF_EXPLODE;
2674 angvel = DEF_ANGVEL;
2675 statictime = DEF_STATICTIME;
2676 altcolour = DEF_ALTCOLOUR;
2677 titles = DEF_TITLES;
2678 interactive = DEF_INTERACTIVE;
2680 wireframe = DEF_WIREFRAME;
2681 transparent = DEF_TRANSPARENT;
2683 #endif /* HAVE_GLUT */
2685 XSCREENSAVER_MODULE ("GLSnake", glsnake)