ftp://ftp.krokus.ru/pub/OpenBSD/distfiles/xscreensaver-4.21.tar.gz
[xscreensaver] / hacks / glx / glsnake.c
1 /* glsnake.c - OpenGL imitation of Rubik's Snake
2  * 
3  * (c) 2001-2003 Jamie Wilkinson <jaq@spacepants.org>
4  * (c) 2001-2003 Andrew Bennetts <andrew@puzzling.org> 
5  * (c) 2001-2003 Peter Aylett <peter@ylett.com>
6  * 
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.
11  *
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.
16  *
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.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 /* HAVE_GLUT defined if we're building a standalone glsnake,
27  * and not defined if we're building as an xscreensaver hack */
28 #ifdef HAVE_GLUT
29 # include <GL/glut.h>
30 #else
31 # include <GL/gl.h>
32 # include <GL/glu.h>
33 #endif
34
35 #include <stdio.h>
36 #include <stddef.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 /* angles */
41 #define ZERO      0.0
42 #define LEFT     90.0
43 #define PIN     180.0
44 #define RIGHT   270.0
45
46 #ifdef HAVE_GETTIMEOFDAY
47 #ifdef GETTIMEOFDAY_TWO_ARGS
48 # include <sys/time.h>
49 # include <time.h>
50   typedef struct timeval snaketime;
51 # define GETSECS(t) ((t).tv_sec)
52 # define GETMSECS(t) ((t).tv_usec/1000)
53 #else /* GETTIMEOFDAY_TWO_ARGS */
54 # include <sys/time.h>
55 # include <time.h>
56   typedef struct timeval snaketime;
57 # define GETSECS(t) ((t).tv_sec)
58 # define GETMSECS(t) ((t).tv_usec/1000)
59 #endif
60 #else /* HAVE_GETTIMEOFDAY */
61 #ifdef HAVE_FTIME
62 # include <sys/timeb.h>
63   typedef struct timeb snaketime;
64 # define GETSECS(t) ((long)(t).time)
65 # define GETMSECS(t) ((t).millitm/1000)
66 #endif /* HAVE_FTIME */
67 #endif /* HAVE_GETTIMEOFDAY */
68
69 #include <math.h>
70
71 #ifndef M_SQRT1_2       /* Win32 doesn't have this constant  */
72 #define M_SQRT1_2 0.70710678118654752440084436210485
73 #endif
74
75 #define NODE_COUNT 24
76
77 #ifdef HAVE_GLUT
78 #define DEF_YANGVEL     0.10
79 #define DEF_ZANGVEL     0.14
80 #define DEF_EXPLODE     0.03
81 #define DEF_ANGVEL      1.0
82 #define DEF_ACCEL       0.1
83 #define DEF_STATICTIME  5000
84 #define DEF_ALTCOLOUR   0
85 #define DEF_TITLES      1
86 #define DEF_INTERACTIVE 0
87 #define DEF_ZOOM        25.0
88 #define DEF_WIREFRAME   0
89 #else
90 /* xscreensaver options doobies prefer strings */
91 #define DEF_YANGVEL     "0.10"
92 #define DEF_ZANGVEL     "0.14"
93 #define DEF_EXPLODE     "0.03"
94 #define DEF_ANGVEL      "1.0"
95 #define DEF_ACCEL       "0.1"
96 #define DEF_STATICTIME  "5000"
97 #define DEF_ALTCOLOUR   "False"
98 #define DEF_TITLES      "True"
99 #define DEF_INTERACTIVE "False"
100 #define DEF_ZOOM        "25.0"
101 #define DEF_WIREFRAME   "False"
102 #endif
103
104 /* static variables */
105 #ifndef HAVE_GLUT
106 # include <X11/Intrinsic.h>
107 #else
108 /* xscreensaver boolean type */
109 # define Bool int
110 #endif
111
112 static GLfloat explode;
113 static GLfloat accel;
114 static long statictime;
115 static GLfloat yspin = 0;
116 static GLfloat zspin = 0;
117 static GLfloat yangvel;
118 static GLfloat zangvel;
119 static Bool altcolour;
120 static Bool titles;
121 static Bool interactive;
122 static Bool wireframe;
123 static GLfloat zoom;
124 static GLfloat angvel;
125
126 #ifndef HAVE_GLUT
127 /* xscreensaver setup */
128 extern XtAppContext app;
129
130 #define PROGCLASS "glsnake"
131 #define HACK_INIT glsnake_init
132 #define HACK_DRAW glsnake_display
133 #define HACK_RESHAPE glsnake_reshape
134 #define sws_opts xlockmore_opts
135
136
137 /* xscreensaver defaults */
138 #define DEFAULTS "*delay:          30000                      \n" \
139                  "*count:          30                         \n" \
140                  "*showFPS:        False                      \n" \
141                  "*labelfont:   -*-times-bold-r-normal-*-180-*\n" \
142
143 #undef countof
144 #define countof(x) (sizeof((x))/sizeof((*x)))
145
146 #include "xlockmore.h"
147 #include "glxfonts.h"
148
149 static XrmOptionDescRec opts[] = {
150     { "-explode", ".explode", XrmoptionSepArg, DEF_EXPLODE },
151     { "-angvel", ".angvel", XrmoptionSepArg, DEF_ANGVEL },
152     { "-accel", ".accel", XrmoptionSepArg, DEF_ACCEL },
153     { "-statictime", ".statictime", XrmoptionSepArg, DEF_STATICTIME },
154     { "-yangvel", ".yangvel", XrmoptionSepArg, DEF_YANGVEL },
155     { "-zangvel", ".zangvel", XrmoptionSepArg, DEF_ZANGVEL },
156     { "-altcolour", ".altcolour", XrmoptionNoArg, "True" },
157     { "-no-altcolour", ".altcolour", XrmoptionNoArg, "False" },
158     { "-titles", ".titles", XrmoptionNoArg, "True" },
159     { "-no-titles", ".titles", XrmoptionNoArg, "False" },
160     { "-zoom", ".zoom", XrmoptionSepArg, DEF_ZOOM },
161     { "-wireframe", ".wireframe", XrmoptionNoArg, "true" },
162     { "-no-wireframe", ".wireframe", XrmoptionNoArg, "false" },
163 };
164
165 static argtype vars[] = {
166     {&explode, "explode", "Explode", DEF_EXPLODE, t_Float},
167     {&angvel, "angvel", "Angular Velocity", DEF_ANGVEL, t_Float},
168     {&accel, "accel", "Acceleration", DEF_ACCEL, t_Float},
169     {&statictime, "statictime", "Static Time", DEF_STATICTIME, t_Int},
170     {&yangvel, "yangvel", "Angular Velocity about Y axis", DEF_YANGVEL, t_Float},
171     {&zangvel, "zangvel", "Angular Velocity about X axis", DEF_ZANGVEL, t_Float},
172     {&interactive, "interactive", "Interactive", DEF_INTERACTIVE, t_Bool},
173     {&altcolour, "altcolour", "Alternate Colour Scheme", DEF_ALTCOLOUR, t_Bool},
174     {&titles, "titles", "Titles", DEF_TITLES, t_Bool},
175     {&zoom, "zoom", "Zoom", DEF_ZOOM, t_Float},
176     {&wireframe, "wireframe", "Wireframe", DEF_WIREFRAME, t_Bool},
177 };
178
179 ModeSpecOpt sws_opts = {countof(opts), opts, countof(vars), vars, NULL};
180 #endif
181
182 struct model_s {
183     char * name;
184     float node[NODE_COUNT];
185 };
186
187 struct glsnake_cfg {
188 #ifndef HAVE_GLUT
189     GLXContext * glx_context;
190     XFontStruct * font;
191     GLuint font_list;
192 #else
193     /* font list number */
194     int font;
195 #endif
196
197     /* window id */
198     int window;
199
200     /* is a morph in progress? */
201     int morphing;
202
203     /* has the model been paused? */
204     int paused;
205
206     /* snake metrics */
207     int is_cyclic;
208     int is_legal;
209     int last_turn;
210     int debug;
211
212     /* the shape of the model */
213     float node[NODE_COUNT];
214
215     /* currently selected node for interactive mode */
216     int selected;
217
218     /* models */
219     int prev_model;
220     int next_model;
221
222     /* model morphing */
223     int new_morph;
224
225     /* colours */
226     float colour[2][3];
227     int next_colour;
228     int prev_colour;
229
230     /* timing variables */
231     snaketime last_iteration;
232     snaketime last_morph;
233
234     /* window size */
235     int width, height;
236     int old_width, old_height;
237
238     /* the id of the display lists for drawing a node */
239     int node_solid, node_wire;
240
241     /* is the window fullscreen? */
242     int fullscreen;
243 };
244
245 #define COLOUR_CYCLIC 0
246 #define COLOUR_ACYCLIC 1
247 #define COLOUR_INVALID 2
248 #define COLOUR_AUTHENTIC 3
249
250 float colour[][2][3] = {
251     /* cyclic - green */
252     { { 0.4, 0.8, 0.2 },
253       { 1.0, 1.0, 1.0 } },
254     /* acyclic - blue */
255     { { 0.3, 0.1, 0.9 },
256       { 1.0, 1.0, 1.0 } },
257     /* invalid - grey */
258     { { 0.3, 0.1, 0.9 },
259       { 1.0, 1.0, 1.0 } },
260     /* authentic - purple and green */
261     { { 0.38, 0.0, 0.55 },
262       { 0.0,  0.5, 0.34 } }
263 };
264
265 struct model_s model[] = {
266 #define STRAIGHT_MODEL 0
267     { "straight",
268       { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
269         ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
270         ZERO, ZERO }
271     },
272     /* the models in the Rubik's snake manual */
273 #define START_MODEL 1
274     { "ball",
275       { RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT,
276         RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT,
277         RIGHT, LEFT, RIGHT, LEFT }
278     },
279     { "snow",
280       { RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT,
281         RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT,
282         RIGHT, LEFT, LEFT, LEFT }
283     },
284     { "propellor",
285       { ZERO, ZERO, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO, ZERO,
286         ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO, ZERO, ZERO, RIGHT,
287         LEFT, RIGHT, ZERO, LEFT }
288     },
289     { "flamingo",
290       { ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, RIGHT, PIN,
291         RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, ZERO, ZERO,
292         ZERO, PIN }
293     },
294     { "cat",
295       { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN,
296         ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
297         ZERO }
298     },
299     { "rooster",
300       { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, LEFT, RIGHT, PIN, RIGHT,
301         ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, LEFT, ZERO,
302         PIN }
303     },
304     /* These models were taken from Andrew and Peter's original snake.c
305      * as well as some newer ones made up by Jamie, Andrew and Peter. */
306     { "half balls",
307       { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT,
308         LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT,
309         RIGHT, LEFT, LEFT, LEFT }
310     },
311     { "zigzag1",
312       { RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT,
313         LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT,
314         RIGHT, RIGHT, LEFT, LEFT }
315     },
316     { "zigzag2",
317       { PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN,
318         ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN }
319     },
320     { "zigzag3",
321       { PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN,
322         LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN }
323     },
324     { "caterpillar",
325       { RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT,
326         LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN,
327         LEFT, LEFT }
328     },
329     { "bow",
330       { RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT,
331         LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT,
332         RIGHT, RIGHT, LEFT, LEFT }
333     },
334     { "turtle",
335       { ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT,
336         LEFT, RIGHT, LEFT, LEFT, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT,
337         RIGHT, RIGHT, RIGHT }
338     },
339     { "basket",
340       { RIGHT, PIN, ZERO, ZERO, PIN, LEFT, ZERO, LEFT, LEFT, ZERO,
341         LEFT, PIN, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO,
342         PIN, LEFT }
343     },
344     { "thing",
345       { PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT,
346         LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT,
347         RIGHT, LEFT, LEFT }
348     },
349     { "hexagon",
350       { ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO,
351         ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO,
352         LEFT, ZERO, ZERO, RIGHT }
353     },
354     { "tri1",
355       { ZERO, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO, RIGHT, ZERO, ZERO,
356         LEFT, RIGHT, ZERO, LEFT, ZERO, RIGHT, ZERO, ZERO, LEFT, RIGHT,
357         ZERO, LEFT, ZERO, RIGHT }
358     },
359     { "triangle",
360       { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO,
361         ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO,
362         ZERO, ZERO, LEFT, RIGHT }
363     },
364     { "flower",
365       { ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT,
366         RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN,
367         RIGHT, RIGHT, PIN }
368     },
369     { "crucifix",
370       { ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN,
371         PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN }
372     },
373     { "kayak",
374       { PIN, RIGHT, LEFT, PIN, LEFT, PIN, ZERO, ZERO, RIGHT, PIN, LEFT,
375         ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
376         PIN, RIGHT }
377     },
378     { "bird",
379       { ZERO, ZERO, ZERO, ZERO, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT,
380         ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT,
381         LEFT, ZERO, PIN }
382     },
383     { "seal",
384       { RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO,
385         LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, PIN, RIGHT,
386         RIGHT, LEFT }
387     },
388     { "dog",
389       { ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN,
390         ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN }
391     },
392     { "frog",
393       { RIGHT, RIGHT, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, LEFT, PIN,
394         RIGHT, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT,
395         RIGHT, LEFT, LEFT }
396     },
397     { "quavers",
398       { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, ZERO, ZERO,
399         RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO, LEFT, LEFT,
400         RIGHT, LEFT, RIGHT, RIGHT }
401     },
402     { "fly",
403       { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, PIN, ZERO, ZERO,
404         LEFT, PIN, RIGHT, ZERO, ZERO, PIN, ZERO, LEFT, LEFT, RIGHT, LEFT,
405         RIGHT, RIGHT }
406     },
407     { "puppy",
408       { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO,
409         RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT,
410         LEFT }
411     },
412     { "stars",
413       { LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT,
414         ZERO, ZERO, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN,
415         RIGHT, LEFT }
416     },
417     { "mountains",
418       { RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN,
419         LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT,
420         PIN, LEFT, PIN }
421     },
422     { "quad1",
423       { RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN,
424         LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT,
425         LEFT, PIN, LEFT, PIN }
426     },
427     { "quad2",
428       { ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN,
429         ZERO, PIN, ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT,
430         PIN, ZERO, PIN }
431     },
432     { "glasses",
433       { ZERO, PIN, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, PIN,
434         ZERO, PIN, ZERO, PIN, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO,
435         PIN, ZERO, PIN }
436     },
437     { "em",
438       { ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN,
439         ZERO, PIN, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
440         PIN, ZERO, PIN }
441     },
442     { "quad3",
443       { ZERO, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT,
444         ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
445         LEFT, ZERO, PIN }
446     },
447     { "vee",
448       { ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO,
449         ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO,
450         ZERO, ZERO, PIN }
451     },
452     { "square",
453       { ZERO, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, ZERO,
454         ZERO, PIN, ZERO, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO,
455         ZERO, ZERO, PIN }
456     },
457     { "eagle",
458       { RIGHT, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, ZERO,
459         LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT,
460         ZERO, ZERO, LEFT, PIN }
461     },
462     { "volcano",
463       { RIGHT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT,
464         ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT,
465         LEFT, RIGHT, ZERO, LEFT, PIN }
466     },
467     { "saddle",
468       { RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO,
469         LEFT, PIN, RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT,
470         ZERO, LEFT, PIN }
471     },
472     { "c3d",
473       { ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, ZERO,
474         ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT,
475         ZERO, ZERO, PIN }
476     },
477     { "block",
478       { ZERO, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN,
479         RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT,
480         PIN, RIGHT }
481     },
482     { "duck",
483       { LEFT, PIN, LEFT, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, LEFT,
484         PIN, RIGHT, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN,
485         LEFT }
486     },
487     { "prayer",
488       { RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, ZERO,
489         ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, RIGHT, RIGHT, LEFT,
490         RIGHT, LEFT, LEFT, LEFT, PIN }
491     },
492     { "giraffe",
493       { ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, RIGHT,
494         RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT,
495         PIN, LEFT, LEFT, LEFT }
496     },
497     { "tie fighter",
498       { PIN, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, LEFT,
499         ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, LEFT, ZERO,
500         LEFT, RIGHT, ZERO }
501     },
502     { "Strong Arms",
503       { PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, RIGHT,
504         RIGHT, PIN, RIGHT, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO,
505         ZERO, PIN, PIN, ZERO }
506     },
507
508     /* the following modesl were created during the slug/compsoc codefest
509      * febrray 2003 */
510     { "cool gegl",
511       { PIN, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT,
512         ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, ZERO,
513         ZERO, ZERO }
514     },
515     { "knuckledusters",
516       { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN,
517         PIN, ZERO, RIGHT, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO,
518         RIGHT, ZERO }
519     },
520     { "k's turd",
521       { RIGHT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT,
522         RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN,
523         RIGHT, LEFT, RIGHT, PIN, ZERO }
524     },
525     { "lightsabre",
526       { ZERO, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO,
527         ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
528         ZERO, ZERO }
529     },
530     { "not a stairway",
531       { LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO,
532         RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT,
533         RIGHT, ZERO, LEFT, ZERO }
534     },
535     { "arse gegl",
536       { ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO,
537         PIN, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO, PIN, PIN, ZERO,
538         PIN, ZERO }
539     },
540     { "box",
541       { ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
542         ZERO, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO,
543         ZERO, ZERO, ZERO }
544     },
545     { "kissy box",
546       { PIN, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
547         ZERO, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO,
548         ZERO, PIN, ZERO }
549     },
550     { "erect penis",     /* thanks benno */
551       { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, PIN,
552         PIN, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
553         ZERO, ZERO }
554     },
555     { "flaccid penis",
556       { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, PIN,
557         PIN, ZERO, ZERO, ZERO, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO,
558         ZERO, ZERO }
559     },
560     { "vagina",
561       { RIGHT, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO,
562         LEFT, ZERO, ZERO, ZERO, LEFT, ZERO, LEFT, PIN, LEFT, PIN, RIGHT,
563         PIN, RIGHT, ZERO }
564     },
565     { "mask",
566       { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN,
567         ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO,
568         ZERO, ZERO, ZERO }
569     },
570     { "poles or columns or something",
571       { LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
572         ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
573         ZERO, LEFT, ZERO }
574     },
575     { "crooked v",
576       { ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
577         ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
578         ZERO, ZERO, ZERO }
579     },
580     { "dog leg",
581       { ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO,
582         LEFT, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO,
583         ZERO, ZERO }
584     },
585     { "scrubby",
586       { ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO,
587         LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO,
588         LEFT, PIN, ZERO, ZERO }
589     },
590     { "voltron's eyes",
591       { ZERO, ZERO, PIN, RIGHT, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO,
592         LEFT, PIN, ZERO, ZERO, PIN, ZERO, LEFT, ZERO, RIGHT, LEFT, ZERO,
593         RIGHT, ZERO, ZERO }
594     },
595     { "flying toaster",
596       { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
597         RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
598         PIN, ZERO }
599     },
600     { "dubbya",
601       { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
602         ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
603         PIN, ZERO }
604     },
605     { "tap handle",
606       { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
607         LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
608         PIN, ZERO }
609     },
610     { "wingnut",
611       { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO,
612         PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO,
613         PIN, ZERO }
614     },
615     { "tight twist",
616       { RIGHT, ZERO, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT,
617         RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT,
618         ZERO, ZERO, RIGHT, ZERO }
619     },
620     { "double helix",
621       { RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT,
622         ZERO, RIGHT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, ZERO,
623         RIGHT, ZERO, RIGHT, ZERO, ZERO }
624     },
625
626     /* These models come from the website at 
627      * http://www.geocities.com/stigeide/snake */
628     { "Abstract",
629         { RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO }
630     },
631     { "AlanH1",
632         { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN }
633     },
634     { "AlanH2",
635         { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT }
636     },
637     { "AlanH3",
638         { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN }
639     },
640     { "AlanH4",
641         { ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, ZERO }
642     },
643     { "Alien",
644         { RIGHT, LEFT, RIGHT, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO, PIN, PIN }
645     },
646     { "Angel",
647         { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT }
648     },
649     { "AnotherFigure",
650         { LEFT, PIN, RIGHT, ZERO, ZERO, PIN, RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, ZERO }
651     },
652     { "Ball",
653         { LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT }
654     },
655     { "Basket",
656         { ZERO, RIGHT, RIGHT, ZERO, RIGHT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, ZERO, LEFT }
657     },
658     { "Beetle",
659         { PIN, LEFT, RIGHT, ZERO, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, LEFT, RIGHT, PIN, RIGHT }
660     },
661     { "Bone",
662         { PIN, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, PIN }
663     },
664     { "Bow",
665         { LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT }
666     },
667     { "Bra",
668         { RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT }
669     },
670     { "BronchoSaurian",
671         { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, PIN }
672     },
673     { "Cactus",
674         { PIN, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, ZERO }
675     },
676     { "Camel",
677         { RIGHT, ZERO, PIN, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, ZERO, ZERO, LEFT }
678     },
679     { "Candlestick",
680         { LEFT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT }
681     },
682     { "Cat",
683         { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO }
684     },
685     { "Cave",
686         { RIGHT, ZERO, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO }
687     },
688     { "Chains",
689         { PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO }
690     },
691     { "Chair",
692         { RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, LEFT, RIGHT, LEFT, LEFT }
693     },
694     { "Chick",
695         { RIGHT, RIGHT, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, LEFT, LEFT }
696     },
697     { "Clockwise",
698         { RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT }
699     },
700     { "Cobra",
701         { ZERO, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, LEFT, ZERO, LEFT, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT }
702     },
703     { "Cobra2",
704         { LEFT, ZERO, PIN, ZERO, PIN, LEFT, ZERO, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, PIN, ZERO, RIGHT }
705     },
706     { "Cobra3",
707         { ZERO, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, LEFT }
708     },
709     { "Compact1",
710         { ZERO, ZERO, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN }
711     },
712     { "Compact2",
713         { LEFT, PIN, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO }
714     },
715     { "Compact3",
716         { ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN }
717     },
718     { "Compact4",
719         { PIN, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO }
720     },
721     { "Compact5",
722         { LEFT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT }
723     },
724     { "Contact",
725         { PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, RIGHT, PIN }
726     },
727     { "Contact2",
728         { RIGHT, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, LEFT }
729     },
730     { "Cook",
731         { ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO, PIN }
732     },
733     { "Counterclockwise",
734         { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT }
735     },
736     { "Cradle",
737         { LEFT, LEFT, ZERO, PIN, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, RIGHT, LEFT, LEFT, ZERO, ZERO, RIGHT }
738     },
739     { "Crankshaft",
740         { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, PIN, RIGHT }
741     },
742     { "Cross",
743         { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN }
744     },
745     { "Cross2",
746         { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO }
747     },
748     { "Cross3",
749         { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO }
750     },
751     { "CrossVersion1",
752         { PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN }
753     },
754     { "CrossVersion2",
755         { RIGHT, LEFT, PIN, LEFT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, LEFT, PIN, LEFT, RIGHT }
756     },
757     { "Crown",
758         { LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, PIN, ZERO }
759     },
760     { "DNAStrand",
761         { RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT }
762     },
763     { "Diamond",
764         { ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, LEFT }
765     },
766     { "Dog",
767         { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, LEFT, RIGHT }
768     },
769     { "DogFace",
770         { ZERO, ZERO, PIN, PIN, ZERO, LEFT, LEFT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, RIGHT, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, PIN }
771     },
772     { "DoublePeak",
773         { ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, LEFT, ZERO, PIN, ZERO, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT }
774     },
775     { "DoubleRoof",
776         { ZERO, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT }
777     },
778     { "DoubleToboggan",
779         { ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN }
780     },
781     { "Doubled",
782         { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT }
783     },
784     { "Doubled1",
785         { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO, RIGHT, ZERO, RIGHT, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT }
786     },
787     { "Doubled2",
788         { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, RIGHT, ZERO, RIGHT, LEFT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT }
789     },
790     { "DumblingSpoon",
791         { PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO }
792     },
793     { "Embrace",
794         { PIN, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO }
795     },
796     { "EndlessBelt",
797         { ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, RIGHT }
798     },
799     { "Entrance",
800         { LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT }
801     },
802     { "Esthetic",
803         { LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT }
804     },
805     { "Explotion",
806         { RIGHT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT }
807     },
808     { "F-ZeroXCar",
809         { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT }
810     },
811     { "Face",
812         { ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT }
813     },
814     { "Fantasy",
815         { LEFT, LEFT, RIGHT, PIN, ZERO, RIGHT, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, LEFT, ZERO, PIN, LEFT, RIGHT, RIGHT, RIGHT, PIN }
816     },
817     { "Fantasy1",
818         { PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN }
819     },
820     { "FaserGun",
821         { ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, RIGHT, ZERO, PIN }
822     },
823     { "FelixW",
824         { ZERO, RIGHT, ZERO, PIN, LEFT, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, RIGHT, PIN, ZERO, LEFT, ZERO }
825     },
826     { "Flamingo",
827         { ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, ZERO, ZERO, ZERO, PIN }
828     },
829     { "FlatOnTheTop",
830         { ZERO, PIN, PIN, ZERO, PIN, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, PIN }
831     },
832     { "Fly",
833         { ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT }
834     },
835     { "Fountain",
836         { LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN }
837     },
838     { "Frog",
839         { LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, RIGHT, LEFT, RIGHT, RIGHT }
840     },
841     { "Frog2",
842         { LEFT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, ZERO, RIGHT }
843     },
844     { "Furby",
845         { PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN }
846     },
847     { "Gate",
848         { ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, ZERO, PIN, PIN, ZERO }
849     },
850     { "Ghost",
851         { LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT }
852     },
853     { "Globus",
854         { RIGHT, LEFT, ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, LEFT, ZERO }
855     },
856     { "Grotto",
857         { PIN, PIN, ZERO, LEFT, RIGHT, LEFT, ZERO, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, RIGHT, LEFT, RIGHT }
858     },
859     { "H",
860         { PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO }
861     },
862     { "HeadOfDevil",
863         { PIN, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO }
864     },
865     { "Heart",
866         { RIGHT, ZERO, ZERO, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, RIGHT, ZERO, PIN, ZERO, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO, ZERO, ZERO, LEFT }
867     },
868     { "Heart2",
869         { ZERO, PIN, ZERO, ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO }
870     },
871     { "Hexagon",
872         { ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO }
873     },
874     { "HoleInTheMiddle1",
875         { ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT }
876     },
877     { "HoleInTheMiddle2",
878         { ZERO, LEFT, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT }
879     },
880     { "HouseBoat",
881         { RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, PIN }
882     },
883     { "HouseByHouse",
884         { LEFT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT }
885     },
886     { "Infinity",
887         { LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT }
888     },
889     { "Integral",
890         { RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT }
891     },
892     { "Iron",
893         { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, RIGHT }
894     },
895     { "JustSquares",
896         { RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, LEFT }
897     },
898     { "Kink",
899         { ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO }
900     },
901     { "Knot",
902         { LEFT, LEFT, PIN, LEFT, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, RIGHT, PIN, RIGHT, RIGHT, LEFT }
903     },
904     { "Leaf",
905         { ZERO, PIN, PIN, ZERO, ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO }
906     },
907     { "LeftAsRight",
908         { RIGHT, PIN, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, PIN, LEFT }
909     },
910     { "Long-necked",
911         { PIN, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO }
912     },
913     { "LunaModule",
914         { PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT }
915     },
916     { "MagnifyingGlass",
917         { ZERO, ZERO, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO }
918     },
919     { "Mask",
920         { ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT }
921     },
922     { "Microscope",
923         { PIN, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN }
924     },
925     { "Mirror",
926         { PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, PIN, ZERO }
927     },
928     { "MissPiggy",
929         { ZERO, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, LEFT, PIN, RIGHT, RIGHT, ZERO, RIGHT }
930     },
931     { "Mole",
932         { ZERO, RIGHT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, ZERO, RIGHT, RIGHT, PIN, LEFT }
933     },
934     { "Monk",
935         { LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT }
936     },
937     { "Mountain",
938         { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, LEFT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO }
939     },
940     { "Mountains",
941         { ZERO, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO }
942     },
943     { "MouseWithoutTail",
944         { ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO }
945     },
946     { "Mushroom",
947         { PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN }
948     },
949     { "Necklace",
950         { ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO }
951     },
952     { "NestledAgainst",
953         { LEFT, ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT }
954     },
955     { "NoClue",
956         { ZERO, RIGHT, PIN, LEFT, LEFT, LEFT, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, RIGHT, RIGHT, PIN, LEFT, ZERO }
957     },
958     { "Noname",
959         { LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT }
960     },
961     { "Obelisk",
962         { PIN, ZERO, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, ZERO }
963     },
964     { "Ostrich",
965         { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN }
966     },
967     { "Ostrich2",
968         { PIN, PIN, ZERO, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO }
969     },
970     { "PairOfGlasses",
971         { ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO }
972     },
973     { "Parrot",
974         { ZERO, ZERO, ZERO, ZERO, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, ZERO, PIN }
975     },
976     { "Penis",
977         { PIN, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, PIN }
978     },
979     { "PictureCommingSoon",
980         { LEFT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, RIGHT, RIGHT }
981     },
982     { "Pitti",
983         { LEFT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT }
984     },
985     { "Plait",
986         { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT }
987     },
988     { "Platform",
989         { RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT }
990     },
991     { "PodRacer",
992         { ZERO, PIN, ZERO, PIN, RIGHT, PIN, ZERO, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, ZERO, PIN, LEFT }
993     },
994     { "Pokemon",
995         { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT }
996     },
997     { "Prawn",
998         { RIGHT, PIN, ZERO, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, PIN, ZERO, PIN, LEFT }
999     },
1000     { "Propeller",
1001         { ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT }
1002     },
1003     { "Pyramid",
1004         { ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, LEFT }
1005     },
1006     { "QuarterbackTiltedAndReadyToHut",
1007         { PIN, ZERO, RIGHT, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, LEFT, ZERO, PIN }
1008     },
1009     { "Ra",
1010         { PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT }
1011     },
1012     { "Rattlesnake",
1013         { LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, PIN, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT }
1014     },
1015     { "Revelation",
1016         { ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN }
1017     },
1018     { "Revolution1",
1019         { LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT }
1020     },
1021     { "Ribbon",
1022         { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT }
1023     },
1024     { "Rocket",
1025         { RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT }
1026     },
1027     { "Roofed",
1028         { ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, ZERO, PIN, ZERO, RIGHT }
1029     },
1030     { "Roofs",
1031         { PIN, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, PIN }
1032     },
1033     { "RowHouses",
1034         { RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT }
1035     },
1036     { "Sculpture",
1037         { RIGHT, LEFT, PIN, ZERO, ZERO, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT }
1038     },
1039     { "Seal",
1040         { LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, LEFT }
1041     },
1042     { "Seal2",
1043         { RIGHT, PIN, ZERO, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO }
1044     },
1045     { "Sheep",
1046         { RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT }
1047     },
1048     { "Shelter",
1049         { LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT }
1050     },
1051     { "Ship",
1052         { PIN, RIGHT, LEFT, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, LEFT, ZERO, PIN, PIN }
1053     },
1054     { "Shpongle",
1055         { LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO }
1056     },
1057     { "Slide",
1058         { LEFT, RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, RIGHT, LEFT }
1059     },
1060     { "SmallShip",
1061         { ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, LEFT }
1062     },
1063     { "SnakeReadyToStrike",
1064         { LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, LEFT }
1065     },
1066     { "Snakes14",
1067         { RIGHT, RIGHT, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, LEFT, RIGHT }
1068     },
1069     { "Snakes15",
1070         { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, PIN, RIGHT }
1071     },
1072     { "Snakes18",
1073         { PIN, PIN, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, PIN }
1074     },
1075     { "Snowflake",
1076         { LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT }
1077     },
1078     { "Snowman",
1079         { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO }
1080     },
1081     { "Source",
1082         { PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN }
1083     },
1084     { "Spaceship",
1085         { PIN, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, PIN }
1086     },
1087     { "Spaceship2",
1088         { PIN, PIN, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, LEFT, LEFT, PIN, PIN }
1089     },
1090     { "Speedboat",
1091         { LEFT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT }
1092     },
1093     { "Speedboat2",
1094         { PIN, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, ZERO, RIGHT, PIN, LEFT }
1095     },
1096     { "Spider",
1097         { RIGHT, RIGHT, ZERO, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, RIGHT, LEFT, RIGHT, ZERO, ZERO, LEFT }
1098     },
1099     { "Spitzbergen",
1100         { PIN, LEFT, ZERO, RIGHT, RIGHT, LEFT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, LEFT, LEFT, ZERO }
1101     },
1102     { "Square",
1103         { ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO }
1104     },
1105     { "SquareHole",
1106         { PIN, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN }
1107     },
1108     { "Stage",
1109         { RIGHT, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO }
1110     },
1111     { "Stairs",
1112         { ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO }
1113     },
1114     { "Stairs2",
1115         { ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO }
1116     },
1117     { "Straight",
1118         { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO }
1119     },
1120     { "Swan",
1121         { ZERO, PIN, ZERO, PIN, LEFT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT }
1122     },
1123     { "Swan2",
1124         { PIN, ZERO, PIN, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, PIN }
1125     },
1126     { "Swan3",
1127         { PIN, PIN, ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, RIGHT }
1128     },
1129     { "Symbol",
1130         { RIGHT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, RIGHT }
1131     },
1132     { "Symmetry",
1133         { RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT }
1134     },
1135     { "Symmetry2",
1136         { ZERO, PIN, LEFT, LEFT, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, PIN, LEFT }
1137     },
1138     { "TableFireworks",
1139         { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, RIGHT, PIN }
1140     },
1141     { "Tapering",
1142         { ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO }
1143     },
1144     { "TaperingTurned",
1145         { ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO }
1146     },
1147     { "TeaLightStick",
1148         { RIGHT, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN }
1149     },
1150     { "Tent",
1151         { RIGHT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO }
1152     },
1153     { "Terraces",
1154         { RIGHT, LEFT, ZERO, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT }
1155     },
1156     { "Terrier",
1157         { PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO }
1158     },
1159     { "Three-Legged",
1160         { RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, PIN, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT }
1161     },
1162     { "ThreePeaks",
1163         { RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT }
1164     },
1165     { "ToTheFront",
1166         { ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, LEFT, LEFT, PIN, ZERO, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT }
1167     },
1168     { "Top",
1169         { PIN, LEFT, LEFT, PIN, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, ZERO }
1170     },
1171     { "Transport",
1172         { PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO }
1173     },
1174     { "Triangle",
1175         { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT }
1176     },
1177     { "Tripple",
1178         { PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN }
1179     },
1180     { "Turtle",
1181         { RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO }
1182     },
1183     { "Twins",
1184         { ZERO, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO }
1185     },
1186     { "TwoSlants",
1187         { ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN }
1188     },
1189     { "TwoWings",
1190         { PIN, LEFT, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, ZERO }
1191     },
1192     { "UFO",
1193         { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT }
1194     },
1195     { "USSEnterprice",
1196         { LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, ZERO }
1197     },
1198     { "UpAndDown",
1199         { ZERO, PIN, ZERO, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO }
1200     },
1201     { "Upright",
1202         { ZERO, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO }
1203     },
1204     { "Upside-down",
1205         { PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN }
1206     },
1207     { "Valley",
1208         { ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO }
1209     },
1210     { "Viaduct",
1211         { PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, PIN, RIGHT, ZERO, RIGHT, RIGHT, ZERO, RIGHT, PIN, ZERO, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO }
1212     },
1213     { "View",
1214         { ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT }
1215     },
1216     { "Waterfall",
1217         { LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT }
1218     },
1219     { "WindWheel",
1220         { PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO }
1221     },
1222     { "Window",
1223         { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO }
1224     },
1225     { "WindowToTheWorld",
1226         { PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO }
1227     },
1228     { "Windshield",
1229         { PIN, PIN, ZERO, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, PIN }
1230     },
1231     { "WingNut",
1232         { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO }
1233     },
1234     { "Wings2",
1235         { RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, ZERO }
1236     },
1237     { "WithoutName",
1238         { PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN }
1239     },
1240     { "Wolf",
1241         { ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN }
1242     },
1243     { "X",
1244         { LEFT, ZERO, ZERO, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, ZERO, ZERO }
1245     },
1246 };
1247
1248 int models = (sizeof(model) / sizeof(struct model_s));
1249
1250 #define VOFFSET 0.045
1251
1252 #define X_MASK  1
1253 #define Y_MASK  2
1254 #define Z_MASK  4
1255
1256 /* the connecting string that holds the snake together */
1257 #define MAGICAL_RED_STRING 0
1258
1259 #define GETSCALAR(vec,mask) ((vec)==(mask) ? 1 : ((vec)==-(mask) ? -1 : 0 ))
1260
1261 #ifndef MAX
1262 # define MAX(x, y) ((x) > (y) ? (x) : (y))
1263 #endif
1264 #ifndef MIN
1265 # define MIN(x, y) ((x) < (y) ? (x) : (y))
1266 #endif
1267
1268 #define RAND(n) ((random() & 0x7fffffff) % ((long) (n)))
1269 #define RANDSIGN() ((random() & 1) ? 1 : -1)
1270
1271 /* the triangular prism what makes up the basic unit */
1272 float solid_prism_v[][3] = {
1273     /* first corner, bottom left front */
1274     { VOFFSET, VOFFSET, 1.0 },
1275     { VOFFSET, 0.00, 1.0 - VOFFSET },
1276     { 0.00, VOFFSET, 1.0 - VOFFSET },
1277     /* second corner, rear */
1278     { VOFFSET, VOFFSET, 0.00 },
1279     { VOFFSET, 0.00, VOFFSET },
1280     { 0.00, VOFFSET, VOFFSET },
1281     /* third, right front */
1282     { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 1.0 },
1283     { 1.0 - VOFFSET / M_SQRT1_2, 0.0, 1.0 - VOFFSET },
1284     { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, 1.0 - VOFFSET },
1285     /* fourth, right rear */
1286     { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 0.0 },
1287     { 1.0 - VOFFSET / M_SQRT1_2, 0.0, VOFFSET },
1288     { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, VOFFSET },
1289     /* fifth, upper front */
1290     { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 1.0 },
1291     { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, 1.0 - VOFFSET },
1292     { 0.0, 1.0 - VOFFSET / M_SQRT1_2, 1.0 - VOFFSET},
1293     /* sixth, upper rear */
1294     { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 0.0 },
1295     { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, VOFFSET },
1296     { 0.0, 1.0 - VOFFSET / M_SQRT1_2, VOFFSET }};
1297
1298 float solid_prism_n[][3] = {/* corners */
1299     { -VOFFSET, -VOFFSET, VOFFSET },
1300     { VOFFSET, -VOFFSET, VOFFSET },
1301     { -VOFFSET, VOFFSET, VOFFSET },
1302     { -VOFFSET, -VOFFSET, -VOFFSET },
1303     { VOFFSET, -VOFFSET, -VOFFSET },
1304     { -VOFFSET, VOFFSET, -VOFFSET },
1305     /* edges */
1306     { -VOFFSET, 0.0, VOFFSET },
1307     { 0.0, -VOFFSET, VOFFSET },
1308     { VOFFSET, VOFFSET, VOFFSET },
1309     { -VOFFSET, 0.0, -VOFFSET },
1310     { 0.0, -VOFFSET, -VOFFSET },
1311     { VOFFSET, VOFFSET, -VOFFSET },
1312     { -VOFFSET, -VOFFSET, 0.0 },
1313     { VOFFSET, -VOFFSET, 0.0 },
1314     { -VOFFSET, VOFFSET, 0.0 },
1315     /* faces */
1316     { 0.0, 0.0, 1.0 },
1317     { 0.0, -1.0, 0.0 },
1318     { M_SQRT1_2, M_SQRT1_2, 0.0 },
1319     { -1.0, 0.0, 0.0 },
1320     { 0.0, 0.0, -1.0 }};
1321
1322 float wire_prism_v[][3] = {{ 0.0, 0.0, 1.0 },
1323                            { 1.0, 0.0, 1.0 },
1324                            { 0.0, 1.0, 1.0 },
1325                            { 0.0, 0.0, 0.0 },
1326                            { 1.0, 0.0, 0.0 },
1327                            { 0.0, 1.0, 0.0 }};
1328
1329 float wire_prism_n[][3] = {{ 0.0, 0.0, 1.0},
1330                            { 0.0,-1.0, 0.0},
1331                            { M_SQRT1_2, M_SQRT1_2, 0.0},
1332                            {-1.0, 0.0, 0.0},
1333                            { 0.0, 0.0,-1.0}};
1334
1335 static struct glsnake_cfg * glc = NULL;
1336 #ifdef HAVE_GLUT
1337 # define bp glc
1338 #endif
1339
1340 typedef float (*morphFunc)(long);
1341
1342 #ifdef HAVE_GLUT
1343 /* forward definitions for GLUT functions */
1344 void calc_rotation();
1345 inline void ui_mousedrag();
1346 #endif
1347
1348 void gl_init(
1349 #ifndef HAVE_GLUT
1350              ModeInfo * mi
1351 #endif
1352              ) {
1353     float light_pos[][3] = {{0.0, 0.0, 20.0}, {0.0, 20.0, 0.0}};
1354     float light_dir[][3] = {{0.0, 0.0,-20.0}, {0.0,-20.0, 0.0}};
1355
1356     glClearColor(0.0, 0.0, 0.0, 0.0);
1357     glEnable(GL_DEPTH_TEST);
1358     glShadeModel(GL_SMOOTH);
1359     glCullFace(GL_BACK);
1360     glEnable(GL_CULL_FACE);
1361     glEnable(GL_NORMALIZE);
1362
1363     if (!wireframe) {
1364         glColor3f(1.0, 1.0, 1.0);
1365         glLightfv(GL_LIGHT0, GL_POSITION, light_pos[0]);
1366         glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_dir[0]);
1367         glLightfv(GL_LIGHT1, GL_POSITION, light_pos[1]);
1368         glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light_dir[1]);
1369         glEnable(GL_LIGHTING);
1370         glEnable(GL_LIGHT0);
1371         glEnable(GL_LIGHT1);
1372         glEnable(GL_COLOR_MATERIAL);
1373     }
1374 }
1375
1376 void gettime(snaketime *t)
1377 {
1378 #ifdef HAVE_GETTIMEOFDAY
1379 #ifdef GETTIMEOFDAY_TWO_ARGS
1380         struct timezone tzp;
1381         gettimeofday(t, &tzp);
1382 #else /* !GETTIMEOFDAY_TWO_ARGS */
1383         gettimeofday(t);
1384 #endif /* !GETTIMEOFDAY_TWO_ARGS */
1385 #else /* !HAVE_GETTIMEOFDAY */
1386 #ifdef HAVE_FTIME
1387         ftime(t);
1388 #endif /* HAVE_FTIME */
1389 #endif /* !HAVE_GETTIMEOFDAY */
1390 }
1391
1392
1393 void start_morph(int model_index, int immediate);
1394
1395 /* wot initialises it */
1396 void glsnake_init(
1397 #ifndef HAVE_GLUT
1398 ModeInfo * mi
1399 #endif
1400 ) {
1401 #ifndef HAVE_GLUT
1402     struct glsnake_cfg * bp;
1403
1404     /* set up the conf struct and glx contexts */
1405     if (!glc) {
1406         glc = (struct glsnake_cfg *) calloc(MI_NUM_SCREENS(mi), sizeof(struct glsnake_cfg));
1407         if (!glc) {
1408             fprintf(stderr, "%s: out of memory\n", progname);
1409             exit(1);
1410         }
1411     }
1412     bp = &glc[MI_SCREEN(mi)];
1413
1414     if ((bp->glx_context = init_GL(mi)) != NULL) {
1415         gl_init(mi);
1416         glsnake_reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1417     }
1418 #else
1419     gl_init();
1420 #endif
1421
1422     /* initialise conf struct */
1423     memset(&bp->node, 0, sizeof(float) * NODE_COUNT);
1424
1425     bp->selected = 11;
1426     bp->is_cyclic = 0;
1427     bp->is_legal = 1;
1428     bp->last_turn = -1;
1429     bp->morphing = 0;
1430     bp->paused = 0;
1431     bp->new_morph = 0;
1432
1433     gettime(&bp->last_iteration);
1434     memcpy(&bp->last_morph, &bp->last_iteration, sizeof(bp->last_morph));
1435
1436     bp->prev_colour = bp->next_colour = COLOUR_ACYCLIC;
1437     bp->next_model = RAND(models);
1438     bp->prev_model = START_MODEL;
1439     start_morph(bp->prev_model, 1);
1440
1441     /* set up a font for the labels */
1442 #ifndef HAVE_GLUT
1443     if (titles)
1444         load_font(mi->dpy, "labelfont", &bp->font, &bp->font_list);
1445 #endif
1446     
1447     /* build a solid display list */
1448     glc->node_solid = glGenLists(1);
1449     glNewList(glc->node_solid, GL_COMPILE);
1450     /* corners */
1451     glBegin(GL_TRIANGLES);
1452     glNormal3fv(solid_prism_n[0]);
1453     glVertex3fv(solid_prism_v[0]);
1454     glVertex3fv(solid_prism_v[2]);
1455     glVertex3fv(solid_prism_v[1]);
1456     
1457     glNormal3fv(solid_prism_n[1]);
1458     glVertex3fv(solid_prism_v[6]);
1459     glVertex3fv(solid_prism_v[7]);
1460     glVertex3fv(solid_prism_v[8]);
1461     
1462     glNormal3fv(solid_prism_n[2]);
1463     glVertex3fv(solid_prism_v[12]);
1464     glVertex3fv(solid_prism_v[13]);
1465     glVertex3fv(solid_prism_v[14]);
1466     
1467     glNormal3fv(solid_prism_n[3]);
1468     glVertex3fv(solid_prism_v[3]);
1469     glVertex3fv(solid_prism_v[4]);
1470     glVertex3fv(solid_prism_v[5]);
1471     
1472     glNormal3fv(solid_prism_n[4]);
1473     glVertex3fv(solid_prism_v[9]);
1474     glVertex3fv(solid_prism_v[11]);
1475     glVertex3fv(solid_prism_v[10]);
1476     
1477     glNormal3fv(solid_prism_n[5]);
1478     glVertex3fv(solid_prism_v[16]);
1479     glVertex3fv(solid_prism_v[15]);
1480     glVertex3fv(solid_prism_v[17]);
1481     glEnd();
1482     /* edges */
1483     glBegin(GL_QUADS);
1484     glNormal3fv(solid_prism_n[6]);
1485     glVertex3fv(solid_prism_v[0]);
1486     glVertex3fv(solid_prism_v[12]);
1487     glVertex3fv(solid_prism_v[14]);
1488     glVertex3fv(solid_prism_v[2]);
1489     
1490     glNormal3fv(solid_prism_n[7]);
1491     glVertex3fv(solid_prism_v[0]);
1492     glVertex3fv(solid_prism_v[1]);
1493     glVertex3fv(solid_prism_v[7]);
1494     glVertex3fv(solid_prism_v[6]);
1495     
1496     glNormal3fv(solid_prism_n[8]);
1497     glVertex3fv(solid_prism_v[6]);
1498     glVertex3fv(solid_prism_v[8]);
1499     glVertex3fv(solid_prism_v[13]);
1500     glVertex3fv(solid_prism_v[12]);
1501     
1502     glNormal3fv(solid_prism_n[9]);
1503     glVertex3fv(solid_prism_v[3]);
1504     glVertex3fv(solid_prism_v[5]);
1505     glVertex3fv(solid_prism_v[17]);
1506     glVertex3fv(solid_prism_v[15]);
1507     
1508     glNormal3fv(solid_prism_n[10]);
1509     glVertex3fv(solid_prism_v[3]);
1510     glVertex3fv(solid_prism_v[9]);
1511     glVertex3fv(solid_prism_v[10]);
1512     glVertex3fv(solid_prism_v[4]);
1513     
1514     glNormal3fv(solid_prism_n[11]);
1515     glVertex3fv(solid_prism_v[15]);
1516     glVertex3fv(solid_prism_v[16]);
1517     glVertex3fv(solid_prism_v[11]);
1518     glVertex3fv(solid_prism_v[9]);
1519     
1520     glNormal3fv(solid_prism_n[12]);
1521     glVertex3fv(solid_prism_v[1]);
1522     glVertex3fv(solid_prism_v[2]);
1523     glVertex3fv(solid_prism_v[5]);
1524     glVertex3fv(solid_prism_v[4]);
1525     
1526     glNormal3fv(solid_prism_n[13]);
1527     glVertex3fv(solid_prism_v[8]);
1528     glVertex3fv(solid_prism_v[7]);
1529     glVertex3fv(solid_prism_v[10]);
1530     glVertex3fv(solid_prism_v[11]);
1531     
1532     glNormal3fv(solid_prism_n[14]);
1533     glVertex3fv(solid_prism_v[13]);
1534     glVertex3fv(solid_prism_v[16]);
1535     glVertex3fv(solid_prism_v[17]);
1536     glVertex3fv(solid_prism_v[14]);
1537     glEnd();
1538     
1539     /* faces */
1540     glBegin(GL_TRIANGLES);
1541     glNormal3fv(solid_prism_n[15]);
1542     glVertex3fv(solid_prism_v[0]);
1543     glVertex3fv(solid_prism_v[6]);
1544     glVertex3fv(solid_prism_v[12]);
1545     
1546     glNormal3fv(solid_prism_n[19]);
1547     glVertex3fv(solid_prism_v[3]);
1548     glVertex3fv(solid_prism_v[15]);
1549     glVertex3fv(solid_prism_v[9]);
1550     glEnd();
1551     
1552     glBegin(GL_QUADS);
1553     glNormal3fv(solid_prism_n[16]);
1554     glVertex3fv(solid_prism_v[1]);
1555     glVertex3fv(solid_prism_v[4]);
1556     glVertex3fv(solid_prism_v[10]);
1557     glVertex3fv(solid_prism_v[7]);
1558     
1559     glNormal3fv(solid_prism_n[17]);
1560     glVertex3fv(solid_prism_v[8]);
1561     glVertex3fv(solid_prism_v[11]);
1562     glVertex3fv(solid_prism_v[16]);
1563     glVertex3fv(solid_prism_v[13]);
1564     
1565     glNormal3fv(solid_prism_n[18]);
1566     glVertex3fv(solid_prism_v[2]);
1567     glVertex3fv(solid_prism_v[14]);
1568     glVertex3fv(solid_prism_v[17]);
1569     glVertex3fv(solid_prism_v[5]);
1570     glEnd();
1571     glEndList();
1572     
1573     /* build wire display list */
1574     glc->node_wire = glGenLists(1);
1575     glNewList(glc->node_wire, GL_COMPILE);
1576     glBegin(GL_LINE_STRIP);
1577     glVertex3fv(wire_prism_v[0]);
1578     glVertex3fv(wire_prism_v[1]);
1579     glVertex3fv(wire_prism_v[2]);
1580     glVertex3fv(wire_prism_v[0]);
1581     glVertex3fv(wire_prism_v[3]);
1582     glVertex3fv(wire_prism_v[4]);
1583     glVertex3fv(wire_prism_v[5]);
1584     glVertex3fv(wire_prism_v[3]);
1585     glEnd();
1586     glBegin(GL_LINES);
1587     glVertex3fv(wire_prism_v[1]);
1588     glVertex3fv(wire_prism_v[4]);
1589     glVertex3fv(wire_prism_v[2]);
1590     glVertex3fv(wire_prism_v[5]);
1591     glEnd();
1592     glEndList();
1593     
1594 #ifdef HAVE_GLUT
1595     /* initialise the rotation */
1596     calc_rotation();
1597 #endif
1598 }
1599
1600 void draw_title(
1601 #ifndef HAVE_GLUT
1602                 ModeInfo * mi
1603 #endif
1604                 ) {
1605 #ifndef HAVE_GLUT
1606     struct glsnake_cfg * bp = &glc[MI_SCREEN(mi)];
1607 #endif
1608
1609     /* draw some text */
1610     glPushAttrib(GL_TRANSFORM_BIT | GL_ENABLE_BIT);
1611     glDisable(GL_LIGHTING);
1612     glDisable(GL_DEPTH_TEST);
1613     glMatrixMode(GL_PROJECTION);
1614     glPushMatrix();
1615     glLoadIdentity();
1616     glMatrixMode(GL_MODELVIEW);
1617     glPushMatrix();
1618     glLoadIdentity();
1619 #ifdef HAVE_GLUT
1620     gluOrtho2D(0, glc->width, 0, glc->height);
1621 #else
1622     gluOrtho2D(0, mi->xgwa.width, 0, mi->xgwa.height);
1623 #endif
1624     glColor3f(1.0, 1.0, 1.0);
1625     {
1626         char interactstr[] = "interactive";
1627         char * s;
1628         if (interactive)
1629             s = interactstr;
1630         else
1631             s = model[glc->next_model].name;
1632
1633         print_gl_string (mi->dpy, bp->font, bp->font_list,
1634                          mi->xgwa.width, mi->xgwa.height,
1635                          10, mi->xgwa.height - 10,
1636                          s);
1637     }
1638     glPopMatrix();
1639     glMatrixMode(GL_PROJECTION);
1640     glPopMatrix();
1641     glPopAttrib();
1642 }
1643
1644 /* apply the matrix to the origin and stick it in vec */
1645 void matmult_origin(float rotmat[16], float vec[4]) {
1646 #if 1
1647     vec[0] = 0.5 * rotmat[0] + 0.5 * rotmat[4] + 0.5 * rotmat [8] + 1 * rotmat[12];
1648     vec[1] = 0.5 * rotmat[1] + 0.5 * rotmat[5] + 0.5 * rotmat [9] + 1 * rotmat[13];
1649     vec[2] = 0.5 * rotmat[2] + 0.5 * rotmat[6] + 0.5 * rotmat[10] + 1 * rotmat[14];
1650     vec[3] = 0.5 * rotmat[3] + 0.5 * rotmat[7] + 0.5 * rotmat[11] + 1 * rotmat[15];
1651 #else
1652     vec[0] = 0 * rotmat [0] + 0 * rotmat [1] + 0 * rotmat [2] + 1 * rotmat [3];
1653     vec[1] = 0 * rotmat [4] + 0 * rotmat [5] + 0 * rotmat [6] + 1 * rotmat [7];
1654     vec[2] = 0 * rotmat [8] + 0 * rotmat [9] + 0 * rotmat[10] + 1 * rotmat[11];
1655     vec[3] = 0 * rotmat[12] + 0 * rotmat[13] + 0 * rotmat[14] + 1 * rotmat[15];
1656 #endif
1657     vec[0] /= vec[3];
1658     vec[1] /= vec[3];
1659     vec[2] /= vec[3];
1660     vec[3] = 1.0;
1661 }
1662
1663 /* wot gets called when the winder is resized */
1664 void glsnake_reshape(
1665 #ifndef HAVE_GLUT
1666                      ModeInfo * mi,
1667 #endif
1668                      int w, int h) {
1669     glViewport(0, 0, (GLint) w, (GLint) h);
1670     glMatrixMode(GL_PROJECTION);
1671     glLoadIdentity();
1672     gluPerspective(zoom, w/(GLfloat)h, 0.05, 100.0);
1673     gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
1674     glMatrixMode(GL_MODELVIEW);
1675     /*gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);*/
1676     glLoadIdentity();
1677 #ifdef HAVE_GLUT
1678     glc->width = w;
1679     glc->height = h;
1680 #endif
1681 }
1682
1683 /* Returns the new dst_dir for the given src_dir and dst_dir */
1684 int cross_product(int src_dir, int dst_dir) {
1685     return X_MASK*(GETSCALAR(src_dir,Y_MASK) * GETSCALAR(dst_dir,Z_MASK) -
1686                    GETSCALAR(src_dir,Z_MASK) * GETSCALAR(dst_dir,Y_MASK))+ 
1687         Y_MASK*(GETSCALAR(src_dir,Z_MASK) * GETSCALAR(dst_dir,X_MASK) -
1688                 GETSCALAR(src_dir,X_MASK) * GETSCALAR(dst_dir,Z_MASK))+ 
1689         Z_MASK*(GETSCALAR(src_dir,X_MASK) * GETSCALAR(dst_dir,Y_MASK) -
1690                 GETSCALAR(src_dir,Y_MASK) * GETSCALAR(dst_dir,X_MASK));
1691 }
1692
1693 /* calculate orthogonal snake metrics
1694  *  is_legal  = true if model does not pass through itself
1695  *  is_cyclic = true if last node connects back to first node
1696  *  last_turn = for cyclic snakes, specifes what the 24th turn would be
1697  */
1698 void calc_snake_metrics(void) {
1699     int srcDir, dstDir;
1700     int i, x, y, z;
1701     int prevSrcDir = -Y_MASK;
1702     int prevDstDir = Z_MASK;
1703     int grid[25][25][25];
1704     
1705     /* zero the grid */
1706     memset(&grid, 0, sizeof(int) * 25*25*25);
1707     
1708     glc->is_legal = 1;
1709     x = y = z = 12;
1710     
1711     /* trace path of snake - and keep record for is_legal */
1712     for (i = 0; i < NODE_COUNT - 1; i++) {
1713         /*int ang_card;*/ /* cardinal direction of node angle */
1714         /* establish new state vars */
1715         srcDir = -prevDstDir;
1716         x += GETSCALAR(prevDstDir, X_MASK);
1717         y += GETSCALAR(prevDstDir, Y_MASK);
1718         z += GETSCALAR(prevDstDir, Z_MASK);
1719
1720         switch ((int) model[glc->next_model].node[i]) {
1721           case (int) (ZERO):
1722             dstDir = -prevSrcDir;
1723             break;
1724           case (int) (PIN):
1725             dstDir = prevSrcDir;
1726             break;
1727           case (int) (RIGHT):
1728           case (int) (LEFT):
1729             dstDir = cross_product(prevSrcDir, prevDstDir);
1730             if (model[glc->next_model].node[i] == (int) (RIGHT))
1731                 dstDir = -dstDir;
1732             break;
1733           default:
1734             /* Prevent spurious "might be used 
1735              * uninitialised" warnings when compiling
1736              * with -O2 */
1737             dstDir = 0;
1738             break;
1739         }
1740         
1741         if (grid[x][y][z] == 0)
1742             grid[x][y][z] = srcDir + dstDir;
1743         else if (grid[x][y][z] + srcDir + dstDir == 0)
1744             grid[x][y][z] = 8;
1745         else
1746             glc->is_legal = 0;
1747         
1748         prevSrcDir = srcDir;
1749         prevDstDir = dstDir;
1750     }   
1751     
1752     /* determine if the snake is cyclic */
1753     glc->is_cyclic = (dstDir == Y_MASK && x == 12 && y == 11 && z == 12);
1754     
1755     /* determine last_turn */
1756     glc->last_turn = -1;
1757     if (glc->is_cyclic)
1758         switch (srcDir) {
1759           case -Z_MASK: glc->last_turn = ZERO; break;
1760           case Z_MASK:  glc->last_turn = PIN; break;
1761           case X_MASK:  glc->last_turn = LEFT; break;
1762           case -X_MASK: glc->last_turn = RIGHT; break;
1763         }
1764 }
1765
1766 /* work out how far through the current morph we are */
1767 float morph_percent(void) {
1768     float retval;
1769     int i;
1770
1771     /* extend this function later with a case statement for each of the
1772      * morph schemes */
1773
1774     /* when morphing all nodes at once, the longest morph will be the node
1775      * that needs to rotate 180 degrees.  For each node, work out how far it
1776      * has to go, and store the maximum rotation and current largest angular
1777      * difference, returning the angular difference over the maximum. */
1778     {
1779         float rot_max = 0.0, ang_diff_max = 0.0;
1780
1781         for (i = 0; i < NODE_COUNT - 1; i++) {
1782             float rot, ang_diff;
1783
1784             /* work out the maximum rotation this node has to go through
1785              * from the previous to the next model, taking into account that
1786              * the snake always morphs through the smaller angle */
1787             rot = fabs(model[glc->prev_model].node[i] -
1788                        model[glc->next_model].node[i]);
1789             if (rot > 180.0) rot = 180.0 - rot;
1790             /* work out the difference between the current position and the
1791              * target */
1792             ang_diff = fabs(glc->node[i] -
1793                             model[glc->next_model].node[i]);
1794             if (ang_diff > 180.0) ang_diff = 180 - ang_diff;
1795             /* if it's the biggest so far, record it */
1796             if (rot > rot_max) rot_max = rot;
1797             if (ang_diff > ang_diff_max) ang_diff_max = ang_diff;
1798         }
1799         
1800         /* ang_diff / rot approaches 0, we want the complement */
1801         retval = 1.0 - (ang_diff_max / rot_max);
1802         /* protect against naan */
1803
1804 /* Apparently some systems (Solaris) don't have isinf() */
1805 #undef isinf
1806 #define isinf(x) (((x) > 999999999999.9) || ((x) < -999999999999.9))
1807
1808         if (isnan(retval) || isinf(retval)) retval = 1.0;
1809     }
1810     /*printf("morph_pct = %f\n", retval);*/
1811     return retval;
1812 }
1813
1814 void morph_colour(void) {
1815     float percent, compct; /* complement of percentage */
1816
1817     percent = morph_percent();
1818     compct = 1.0 - percent;
1819
1820     glc->colour[0][0] = colour[glc->prev_colour][0][0] * compct + colour[glc->next_colour][0][0] * percent;
1821     glc->colour[0][1] = colour[glc->prev_colour][0][1] * compct + colour[glc->next_colour][0][1] * percent;
1822     glc->colour[0][2] = colour[glc->prev_colour][0][2] * compct + colour[glc->next_colour][0][2] * percent;
1823
1824     glc->colour[1][0] = colour[glc->prev_colour][1][0] * compct + colour[glc->next_colour][1][0] * percent;
1825     glc->colour[1][1] = colour[glc->prev_colour][1][1] * compct + colour[glc->next_colour][1][1] * percent;
1826     glc->colour[1][2] = colour[glc->prev_colour][1][2] * compct + colour[glc->next_colour][1][2] * percent;
1827 }
1828
1829 /* Start morph process to this model */
1830 void start_morph(int model_index, int immediate) {
1831     /* if immediate, don't bother morphing, go straight to the next model */
1832     if (immediate) {
1833         int i;
1834
1835         for (i = 0; i < NODE_COUNT; i++)
1836             glc->node[i] = model[model_index].node[i];
1837     }
1838
1839     glc->prev_model = glc->next_model;
1840     glc->next_model = model_index;
1841     glc->prev_colour = glc->next_colour;
1842
1843     calc_snake_metrics();
1844     if (!glc->is_legal)
1845         glc->next_colour = COLOUR_INVALID;
1846     else if (altcolour)
1847         glc->next_colour = COLOUR_AUTHENTIC;
1848     else if (glc->is_cyclic)
1849         glc->next_colour = COLOUR_CYCLIC;
1850     else
1851         glc->next_colour = COLOUR_ACYCLIC;
1852
1853     if (immediate) {
1854         glc->colour[0][0] = colour[glc->next_colour][0][0];
1855         glc->colour[0][1] = colour[glc->next_colour][0][1];
1856         glc->colour[0][2] = colour[glc->next_colour][0][2];
1857         glc->colour[1][0] = colour[glc->next_colour][1][0];
1858         glc->colour[1][1] = colour[glc->next_colour][1][1];
1859         glc->colour[1][2] = colour[glc->next_colour][1][2];
1860     }
1861     glc->morphing = 1;
1862
1863     morph_colour();
1864 }
1865
1866 /* Returns morph progress */
1867 float morph(long iter_msec) {
1868     /* work out the maximum angle for this iteration */
1869     int still_morphing;
1870     float iter_angle_max, largest_diff, largest_progress;
1871     int i;
1872
1873     if (glc->new_morph)
1874         glc->new_morph = 0;
1875         
1876     iter_angle_max = 90.0 * (angvel/1000.0) * iter_msec;
1877         
1878     still_morphing = 0;
1879     largest_diff = largest_progress = 0.0;
1880     for (i = 0; i < NODE_COUNT; i++) {
1881         float curAngle = glc->node[i];
1882         float destAngle = model[glc->next_model].node[i];
1883         if (curAngle != destAngle) {
1884             still_morphing = 1;
1885             if (fabs(curAngle-destAngle) <= iter_angle_max)
1886                 glc->node[i] = destAngle;
1887             else if (fmod(curAngle-destAngle+360,360) > 180)
1888                 glc->node[i] = fmod(curAngle + iter_angle_max, 360);
1889             else
1890                 glc->node[i] = fmod(curAngle+360 - iter_angle_max, 360);
1891             largest_diff = MAX(largest_diff, fabs(destAngle-glc->node[i]));
1892             largest_progress = MAX(largest_diff, fabs(glc->node[i] - model[glc->prev_model].node[i]));
1893         }
1894     }
1895         
1896     return MIN(largest_diff / largest_progress, 1.0);
1897 }
1898
1899 #ifdef HAVE_GLUT
1900 void glsnake_idle();
1901
1902 void restore_idle(int value)
1903 {
1904     glutIdleFunc(glsnake_idle);
1905 }
1906 #endif
1907
1908 void quick_sleep(void)
1909 {
1910 #ifdef HAVE_GLUT
1911     /* By using glutTimerFunc we can keep responding to 
1912      * mouse and keyboard events, unlike using something like
1913      * usleep. */
1914     glutIdleFunc(NULL);
1915     glutTimerFunc(1, restore_idle, 0);
1916 #else
1917     usleep(1);
1918 #endif
1919 }
1920
1921 void glsnake_idle(
1922 #ifndef HAVE_GLUT
1923                   struct glsnake_cfg * bp
1924 #endif
1925                   ) {
1926     /* time since last iteration */
1927     long iter_msec;
1928     /* time since the beginning of last morph */
1929     long morf_msec;
1930     float iter_angle_max;
1931     snaketime current_time;
1932     /*    morphFunc transition; */
1933     int still_morphing;
1934     int i;
1935     
1936     /* Do nothing to the model if we are paused */
1937     if (glc->paused) {
1938         /* Avoid busy waiting when nothing is changing */
1939         quick_sleep();
1940 #ifdef HAVE_GLUT
1941         glutSwapBuffers();
1942         glutPostRedisplay();
1943 #endif
1944         return;
1945     }
1946
1947     /* <spiv> Well, ftime gives time with millisecond resolution.
1948      * <spiv> (or worse, perhaps... who knows what the OS will do)
1949      * <spiv> So if no discernable amount of time has passed:
1950      * <spiv>   a) There's no point updating the screen, because
1951      *             it would be the same
1952      * <spiv>   b) The code will divide by zero
1953      */
1954     gettime(&current_time);
1955     
1956     iter_msec = (long) GETMSECS(current_time) - GETMSECS(glc->last_iteration) + 
1957         ((long) GETSECS(current_time) - GETSECS(glc->last_iteration)) * 1000L;
1958
1959     if (iter_msec) {
1960         /* save the current time */
1961         memcpy(&glc->last_iteration, &current_time, sizeof(snaketime));
1962         
1963         /* work out if we have to switch models */
1964         morf_msec = GETMSECS(glc->last_iteration) - GETMSECS(glc->last_morph) +
1965             ((long) (GETSECS(glc->last_iteration)-GETSECS(glc->last_morph)) * 1000L);
1966
1967         if ((morf_msec > statictime) && !interactive && !glc->morphing) {
1968             /*printf("starting morph\n");*/
1969             memcpy(&glc->last_morph, &(glc->last_iteration), sizeof(glc->last_morph));
1970             start_morph(RAND(models), 0);
1971         }
1972         
1973         if (interactive && !glc->morphing) {
1974             quick_sleep();
1975             return;
1976         }
1977         
1978         /*      if (!glc->dragging && !glc->interactive) { */
1979         if (!interactive) {
1980             
1981             yspin += 360/((1000/yangvel)/iter_msec);
1982             zspin += 360/((1000/zangvel)/iter_msec);
1983             /*
1984             yspin += 360 * (yangvel/1000.0) * iter_msec;
1985             zspin += 360 * (zangvel/1000.0) * iter_msec;
1986             */
1987             
1988             /*printf("yspin: %f, zspin: %f\n", yspin, zspin);*/
1989
1990         }
1991
1992         /* work out the maximum angle we could turn this node in this
1993          * timeslice, iter_msec milliseconds long */
1994         iter_angle_max = 90.0 * (angvel/1000.0) * iter_msec;
1995
1996         still_morphing = 0;
1997         for (i = 0; i < NODE_COUNT; i++) {
1998             float cur_angle = glc->node[i];
1999             float dest_angle = model[glc->next_model].node[i];
2000             if (cur_angle != dest_angle) {
2001                 still_morphing = 1;
2002                 if (fabs(cur_angle - dest_angle) <= iter_angle_max)
2003                     glc->node[i] = dest_angle;
2004                 else if (fmod(cur_angle - dest_angle + 360, 360) > 180)
2005                     glc->node[i] = fmod(cur_angle + iter_angle_max, 360);
2006                 else
2007                     glc->node[i] = fmod(cur_angle + 360 - iter_angle_max, 360);
2008             }
2009         }
2010
2011         if (!still_morphing)
2012             glc->morphing = 0;
2013
2014         /* colour cycling */
2015         morph_colour();
2016         
2017 #ifdef HAVE_GLUT
2018         glutSwapBuffers();
2019         glutPostRedisplay();
2020 #endif
2021     } else {
2022         /* We are going too fast, so we may as well let the 
2023          * cpu relax a little by sleeping for a millisecond. */
2024         quick_sleep();
2025     }
2026 }
2027
2028 /* wot draws it */
2029 void glsnake_display(
2030 #ifndef HAVE_GLUT
2031                      ModeInfo * mi
2032 #endif
2033                      ) {
2034 #ifndef HAVE_GLUT
2035     struct glsnake_cfg * bp = &glc[MI_SCREEN(mi)];
2036     Display * dpy = MI_DISPLAY(mi);
2037     Window window = MI_WINDOW(mi);
2038 #endif
2039
2040     int i;
2041     float ang;
2042     float positions[NODE_COUNT][4]; /* origin points for each node */
2043     float com[4]; /* it's the CENTRE of MASS */
2044
2045 #ifndef HAVE_GLUT
2046     if (!bp->glx_context)
2047         return;
2048 #endif
2049     
2050     /* clear the buffer */
2051     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2052     
2053     /* go into the modelview stack */
2054     glMatrixMode(GL_MODELVIEW);
2055     glLoadIdentity();
2056     
2057     /* get the centre of each node, by moving through the snake and
2058      * performing the rotations, then grabbing the matrix at each point
2059      * and applying it to the origin */
2060     glPushMatrix();
2061
2062 #ifdef HAVE_GLUT
2063     /* apply the mouse drag rotation */
2064     ui_mousedrag();
2065 #endif
2066     
2067     /* apply the continuous rotation */
2068     glRotatef(yspin, 0.0, 1.0, 0.0); 
2069     glRotatef(zspin, 0.0, 0.0, 1.0); 
2070     
2071     com[0] = 0.0;
2072     com[1] = 0.0;
2073     com[2] = 0.0;
2074     com[3] = 0.0;
2075     for (i = 0; i < NODE_COUNT; i++) {
2076         float rotmat[16];
2077
2078         ang = glc->node[i];
2079
2080         /*printf("ang = %f\n", ang);*/
2081         
2082         glTranslatef(0.5, 0.5, 0.5);            /* move to center */
2083         glRotatef(90, 0.0, 0.0, -1.0);          /* reorient  */
2084         glTranslatef(1.0 + explode, 0.0, 0.0);  /* move to new pos. */
2085         glRotatef(180 + ang, 1.0, 0.0, 0.0);    /* pivot to new angle */
2086         glTranslatef(-0.5, -0.5, -0.5);         /* return from center */
2087
2088         glGetFloatv(GL_MODELVIEW_MATRIX, rotmat);
2089
2090         matmult_origin(rotmat, positions[i]);
2091
2092         /*printf("positions %f %f %f %f\n", positions[i][0], positions[i][1], positions[i][2], positions[i][3]);*/
2093
2094         com[0] += positions[i][0];
2095         com[1] += positions[i][1];
2096         com[2] += positions[i][2];
2097         com[3] += positions[i][3];
2098     }
2099     glPopMatrix();
2100     com[0] /= NODE_COUNT;
2101     com[1] /= NODE_COUNT;
2102     com[2] /= NODE_COUNT;
2103     com[3] /= NODE_COUNT;
2104
2105     com[0] /= com[3];
2106     com[1] /= com[3];
2107     com[2] /= com[3];
2108
2109     /*printf("com: %f, %f, %f, %f\n", com[0], com[1], com[2], com[3]);*/
2110
2111 #if MAGICAL_RED_STRING
2112     glPushMatrix();
2113     glTranslatef(-com[0], -com[1], -com[2]);
2114
2115     glDisable(GL_LIGHTING);
2116     glColor3f(1.0, 0.0, 0.0);
2117     glBegin(GL_LINE_STRIP);
2118     for (i = 0; i < NODE_COUNT - 1; i++) {
2119         glVertex3fv(positions[i]);
2120     }
2121     glEnd();
2122     glEnable(GL_LIGHTING);
2123     /*glTranslatef(com[0], com[1], com[2]);*/
2124     glPopMatrix();
2125 #endif
2126
2127     glPushMatrix();
2128     glTranslatef(-com[0], -com[1], -com[2]);
2129
2130 #ifdef HAVE_GLUT
2131     /* apply the mouse drag rotation */
2132     ui_mousedrag();
2133 #endif
2134     
2135     /* apply the continuous rotation */
2136     glRotatef(yspin, 0.0, 1.0, 0.0); 
2137     glRotatef(zspin, 0.0, 0.0, 1.0); 
2138
2139     /* now draw each node along the snake -- this is quite ugly :p */
2140     for (i = 0; i < NODE_COUNT; i++) {
2141         /* choose a colour for this node */
2142         if ((i == glc->selected || i == glc->selected+1) && interactive)
2143             /* yellow */
2144             glColor3f(1.0, 1.0, 0.0);
2145         else
2146             glColor3fv(glc->colour[(i+1)%2]);
2147
2148         /* draw the node */
2149         if (wireframe)
2150             glCallList(glc->node_wire);
2151         else
2152             glCallList(glc->node_solid);
2153
2154         /* now work out where to draw the next one */
2155         
2156         /* Interpolate between models */
2157         ang = glc->node[i];
2158         
2159         glTranslatef(0.5, 0.5, 0.5);            /* move to center */
2160         glRotatef(90, 0.0, 0.0, -1.0);          /* reorient  */
2161         glTranslatef(1.0 + explode, 0.0, 0.0);  /* move to new pos. */
2162         glRotatef(180 + ang, 1.0, 0.0, 0.0);    /* pivot to new angle */
2163         glTranslatef(-0.5, -0.5, -0.5);         /* return from center */
2164     }
2165
2166     glPopMatrix();
2167     
2168     if (titles)
2169 #ifdef HAVE_GLUT
2170         draw_title();
2171 #else
2172         draw_title(mi);
2173 #endif
2174
2175 #ifndef HAVE_GLUT
2176         glsnake_idle(bp);
2177 #endif
2178     
2179     glFlush();
2180 #ifdef HAVE_GLUT
2181     glutSwapBuffers();
2182 #else
2183     glXSwapBuffers(dpy, window);
2184 #endif
2185 }
2186
2187 #ifdef HAVE_GLUT
2188 /* anything that needs to be cleaned up goes here */
2189 void unmain() {
2190     glutDestroyWindow(glc->window);
2191     free(glc);
2192 }
2193
2194 void ui_init(int *, char **);
2195
2196 int main(int argc, char ** argv) {
2197     glc = malloc(sizeof(struct glsnake_cfg));
2198     memset(glc, 0, sizeof(struct glsnake_cfg));
2199
2200     glc->width = 320;
2201     glc->height = 240;
2202     
2203     ui_init(&argc, argv);
2204
2205     gettime(&glc->last_iteration);
2206     memcpy(&glc->last_morph, &glc->last_iteration, sizeof(snaketime));
2207     srand((unsigned int)GETSECS(glc->last_iteration));
2208
2209     glc->prev_colour = glc->next_colour = COLOUR_ACYCLIC;
2210     glc->next_model = RAND(models);
2211     glc->prev_model = 0;
2212     start_morph(glc->prev_model, 1);    
2213
2214     glsnake_init();
2215     
2216     atexit(unmain);
2217     glutSwapBuffers();
2218     glutMainLoop();
2219     
2220     return 0;
2221 }
2222 #endif
2223
2224 /*
2225  * GLUT FUNCTIONS
2226  */
2227
2228 #ifdef HAVE_GLUT
2229
2230 /* trackball quaternions */
2231 float cumquat[4] = {0.0,0.0,0.0,0.0}, oldquat[4] = {0.0,0.0,0.0,0.1};
2232
2233 /* rotation matrix */
2234 float rotation[16];
2235
2236 /* mouse drag vectors: start and end */
2237 float m_s[3], m_e[3];
2238
2239 /* dragging boolean */
2240 int dragging = 0;
2241
2242 /* this function calculates the rotation matrix based on the quaternions
2243  * generated from the mouse drag vectors */
2244 void calc_rotation() {
2245     double Nq, s;
2246     double xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
2247
2248     /* this bit ripped from Shoemake's quaternion notes from SIGGRAPH */
2249     Nq = cumquat[0] * cumquat[0] + cumquat[1] * cumquat[1] +
2250         cumquat[2] * cumquat[2] + cumquat[3] * cumquat[3];
2251     s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
2252     xs = cumquat[0] *  s; ys = cumquat[1] *  s; zs = cumquat[2] * s;
2253     wx = cumquat[3] * xs; wy = cumquat[3] * ys; wz = cumquat[3] * zs;
2254     xx = cumquat[0] * xs; xy = cumquat[0] * ys; xz = cumquat[0] * zs;
2255     yy = cumquat[1] * ys; yz = cumquat[1] * zs; zz = cumquat[2] * zs;
2256
2257     rotation[0] = 1.0 - (yy + zz);
2258     rotation[1] = xy + wz;
2259     rotation[2] = xz - wy;
2260     rotation[4] = xy - wz;
2261     rotation[5] = 1.0 - (xx + zz);
2262     rotation[6] = yz + wx;
2263     rotation[8] = xz + wy;
2264     rotation[9] = yz - wx;
2265     rotation[10] = 1.0 - (xx + yy);
2266     rotation[3] = rotation[7] = rotation[11] = 0.0;
2267     rotation[12] = rotation[13] = rotation[14] = 0.0;
2268     rotation[15] = 1.0;
2269 }
2270
2271 inline void ui_mousedrag() {
2272     glMultMatrixf(rotation);
2273 }
2274
2275 void ui_keyboard(unsigned char c, int x, int y) {
2276     int i;
2277     
2278     switch (c) {
2279       case 27:  /* ESC */
2280       case 'q':
2281         exit(0);
2282         break;
2283       case 'e':
2284         explode += DEF_EXPLODE;
2285         glutPostRedisplay();
2286         break;
2287       case 'E':
2288         explode -= DEF_EXPLODE;
2289         if (explode < 0.0) explode = 0.0;
2290         glutPostRedisplay();
2291         break;
2292       case '.':
2293         /* next model */
2294         glc->next_model++;
2295         glc->next_model %= models;
2296         start_morph(glc->next_model, 0);
2297         
2298         /* Reset last_morph time */
2299         gettime(&glc->last_morph);                      
2300         break;
2301       case ',':
2302         /* previous model */
2303         glc->next_model = (glc->next_model + models - 1) % models;
2304         start_morph(glc->next_model, 0);
2305         
2306         /* Reset glc->last_morph time */
2307         gettime(&glc->last_morph);                      
2308         break;
2309       case '+':
2310         angvel += DEF_ACCEL;
2311         break;
2312       case '-':
2313         if (angvel > DEF_ACCEL)
2314             angvel -= DEF_ACCEL;
2315         break;
2316       case 'i':
2317         if (interactive) {
2318             /* Reset last_iteration and last_morph time */
2319             gettime(&glc->last_iteration);
2320             gettime(&glc->last_morph);
2321         }
2322         interactive = 1 - interactive;
2323         glutPostRedisplay();
2324         break;
2325       case 'w':
2326         wireframe = 1 - wireframe;
2327         if (wireframe)
2328             glDisable(GL_LIGHTING);
2329         else
2330             glEnable(GL_LIGHTING);
2331         glutPostRedisplay();
2332         break;
2333       case 'p':
2334         if (glc->paused) {
2335             /* unpausing, reset last_iteration and last_morph time */
2336             gettime(&glc->last_iteration);
2337             gettime(&glc->last_morph);
2338         }
2339         glc->paused = 1 - glc->paused;
2340         break;
2341       case 'd':
2342         /* dump the current model so we can add it! */
2343         printf("# %s\nnoname:\t", model[glc->next_model].name);
2344         for (i = 0; i < NODE_COUNT; i++) {
2345             if (glc->node[i] == ZERO)
2346                 printf("Z");
2347             else if (glc->node[i] == LEFT)
2348                 printf("L");
2349             else if (glc->node[i] == PIN)
2350                 printf("P");
2351             else if (glc->node[i] == RIGHT)
2352                 printf("R");
2353             /*
2354               else
2355               printf("%f", node[i].curAngle);
2356             */
2357             if (i < NODE_COUNT - 1)
2358                 printf(" ");
2359         }
2360         printf("\n");
2361         break;
2362       case 'f':
2363         glc->fullscreen = 1 - glc->fullscreen;
2364         if (glc->fullscreen) {
2365             glc->old_width = glc->width;
2366             glc->old_height = glc->height;
2367             glutFullScreen();
2368         } else {
2369             glutReshapeWindow(glc->old_width, glc->old_height);
2370             glutPositionWindow(50,50);
2371         }
2372         break;
2373       case 't':
2374         titles = 1 - titles;
2375         if (interactive || glc->paused)
2376             glutPostRedisplay();
2377         break;
2378       case 'a':
2379         altcolour = 1 - altcolour;
2380         break;
2381       case 'z':
2382         zoom += 1.0;
2383         glsnake_reshape(glc->width, glc->height);
2384         break;
2385       case 'Z':
2386         zoom -= 1.0;
2387         glsnake_reshape(glc->width, glc->height);
2388         break;
2389       default:
2390         break;
2391     }
2392 }
2393
2394 void ui_special(int key, int x, int y) {
2395     int i;
2396     float *destAngle = &(model[glc->next_model].node[glc->selected]);
2397     int unknown_key = 0;
2398
2399     if (interactive) {
2400         switch (key) {
2401           case GLUT_KEY_UP:
2402             glc->selected = (glc->selected + (NODE_COUNT - 2)) % (NODE_COUNT - 1);
2403             break;
2404           case GLUT_KEY_DOWN:
2405             glc->selected = (glc->selected + 1) % (NODE_COUNT - 1);
2406             break;
2407           case GLUT_KEY_LEFT:
2408             *destAngle = fmod(*destAngle+(LEFT), 360);
2409             glc->morphing = glc->new_morph = 1;
2410             break;
2411           case GLUT_KEY_RIGHT:
2412             *destAngle = fmod(*destAngle+(RIGHT), 360);
2413             glc->morphing = glc->new_morph = 1;
2414             break;
2415           case GLUT_KEY_HOME:
2416             start_morph(STRAIGHT_MODEL, 0);
2417             break;
2418           default:
2419             unknown_key = 1;
2420             break;
2421         }
2422     }
2423     calc_snake_metrics();
2424
2425     if (!unknown_key)
2426         glutPostRedisplay();
2427 }
2428
2429 void ui_mouse(int button, int state, int x, int y) {
2430     if (button==0) {
2431         switch (state) {
2432           case GLUT_DOWN:
2433             dragging = 1;
2434             m_s[0] = M_SQRT1_2 * 
2435                 (x - (glc->width / 2.0)) / (glc->width / 2.0);
2436             m_s[1] = M_SQRT1_2 * 
2437                 ((glc->height / 2.0) - y) / (glc->height / 2.0);
2438             m_s[2] = sqrt(1-(m_s[0]*m_s[0]+m_s[1]*m_s[1]));
2439             break;
2440           case GLUT_UP:
2441             dragging = 0;
2442             oldquat[0] = cumquat[0];
2443             oldquat[1] = cumquat[1];
2444             oldquat[2] = cumquat[2];
2445             oldquat[3] = cumquat[3];
2446             break;
2447           default:
2448             break;
2449         }
2450     }
2451     glutPostRedisplay();
2452 }
2453
2454 void ui_motion(int x, int y) {
2455     double norm;
2456     float q[4];
2457     
2458     if (dragging) {
2459         /* construct the motion end vector from the x,y position on the
2460          * window */
2461         m_e[0] = (x - (glc->width/ 2.0)) / (glc->width / 2.0);
2462         m_e[1] = ((glc->height / 2.0) - y) / (glc->height / 2.0);
2463         /* calculate the normal of the vector... */
2464         norm = m_e[0] * m_e[0] + m_e[1] * m_e[1];
2465         /* check if norm is outside the sphere and wraparound if necessary */
2466         if (norm > 1.0) {
2467             m_e[0] = -m_e[0];
2468             m_e[1] = -m_e[1];
2469             m_e[2] = sqrt(norm - 1);
2470         } else {
2471             /* the z value comes from projecting onto an elliptical spheroid */
2472             m_e[2] = sqrt(1 - norm);
2473         }
2474
2475         /* now here, build a quaternion from m_s and m_e */
2476         q[0] = m_s[1] * m_e[2] - m_s[2] * m_e[1];
2477         q[1] = m_s[2] * m_e[0] - m_s[0] * m_e[2];
2478         q[2] = m_s[0] * m_e[1] - m_s[1] * m_e[0];
2479         q[3] = m_s[0] * m_e[0] + m_s[1] * m_e[1] + m_s[2] * m_e[2];
2480
2481         /* new rotation is the product of the new one and the old one */
2482         cumquat[0] = q[3] * oldquat[0] + q[0] * oldquat[3] + 
2483             q[1] * oldquat[2] - q[2] * oldquat[1];
2484         cumquat[1] = q[3] * oldquat[1] + q[1] * oldquat[3] + 
2485             q[2] * oldquat[0] - q[0] * oldquat[2];
2486         cumquat[2] = q[3] * oldquat[2] + q[2] * oldquat[3] + 
2487             q[0] * oldquat[1] - q[1] * oldquat[0];
2488         cumquat[3] = q[3] * oldquat[3] - q[0] * oldquat[0] - 
2489             q[1] * oldquat[1] - q[2] * oldquat[2];
2490         
2491         calc_rotation();
2492     }
2493     glutPostRedisplay();
2494 }
2495
2496 void ui_init(int * argc, char ** argv) {
2497     glutInit(argc, argv);
2498     glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
2499     glutInitWindowSize(glc->width, glc->height);
2500     glc->window = glutCreateWindow("glsnake");
2501
2502     glutDisplayFunc(glsnake_display);
2503     glutReshapeFunc(glsnake_reshape);
2504     glutIdleFunc(glsnake_idle);
2505     glutKeyboardFunc(ui_keyboard);
2506     glutSpecialFunc(ui_special);
2507     glutMouseFunc(ui_mouse);
2508     glutMotionFunc(ui_motion);
2509
2510     yangvel = DEF_YANGVEL;
2511     zangvel = DEF_ZANGVEL;
2512     explode = DEF_EXPLODE;
2513     angvel = DEF_ANGVEL;
2514     statictime = DEF_STATICTIME;
2515     altcolour = DEF_ALTCOLOUR;
2516     titles = DEF_TITLES;
2517     interactive = DEF_INTERACTIVE;
2518     zoom = DEF_ZOOM;
2519     wireframe = DEF_WIREFRAME;
2520 }
2521 #endif /* HAVE_GLUT */