http://ftp.ksu.edu.tw/FTP/FreeBSD/distfiles/xscreensaver-4.23.tar.gz
[xscreensaver] / hacks / glx / tangram.c
1 /* tangram, Copyright (c) 2005 Jeremy English <jhe@jeremyenglish.org>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software
4  * and its documentation for any purpose is hereby granted without
5  * fee, provided that the above copyright notice appear in all copies
6  * and that both that copyright notice and this permission notice
7  * appear in supporting documentation.  No representations are made
8  * about the suitability of this software for any purpose.  It is
9  * provided "as is" without express or implied warranty.
10  *
11  * Sun 10 July 2005 Changed the code that solves the puzzles.
12  *                  Also, limited the palette and added names. 
13  *
14  * Wed 13 July 2005 Added option to turn off rotation.
15  *                  Changed color and materials
16  */
17
18
19 #include <X11/Intrinsic.h>
20
21 extern XtAppContext app;
22
23 #define PROGCLASS         "Tangram"
24 #define HACK_INIT         init_tangram
25 #define HACK_DRAW         draw_tangram
26 #define HACK_RESHAPE  reshape_tangram
27 #define sws_opts          xlockmore_opts
28
29
30 #define DEFAULTS        "*delay:        10000            \n" \
31   "*wireframe:  False            \n" \
32
33 #undef countof
34 #define countof(x) (sizeof((x))/sizeof((*x)))
35
36 #include "xlockmore.h"
37
38 #include <ctype.h>
39
40
41 #ifdef USE_GL                   /* whole file */
42
43
44 #include <GL/glu.h>
45 #include <time.h>
46 #include <math.h>
47 #include "tangram_shapes.h"
48 #include "glxfonts.h"
49
50 typedef struct {
51     GLubyte r;
52     GLubyte g;
53     GLubyte b;
54 } color;
55
56 typedef struct {
57     GLfloat x;
58     GLfloat y;
59     GLfloat z;
60 } coord;
61
62 typedef struct {
63     coord crd;                  /* coordinates */
64     GLint r;                    /* rotation */
65     GLint fr;                   /* flip Rotate. Used to keep track during animation */
66     GLint dl;                   /* display List */
67     GLfloat dz;                 /* velocity */
68     GLfloat ddz;                /* Acceleration */
69     GLfloat solved;             /* shapes state */
70     Bool up;                    /* Move up the z axis? */
71 } tangram_shape;
72
73 typedef struct {
74     char *name;
75     tangram_shape ts[7];
76 } puzzle;
77
78 typedef enum {
79     no_shape = -1,
80     small_triangle1 = 0,
81     small_triangle2 = 1,
82     medium_triangle = 2,
83     large_triangle1 = 3,
84     large_triangle2 = 4,
85     square = 5,
86     rhomboid = 6
87 } shape_type;
88
89 #define SPEED 0.03
90 enum {
91     BOTTOM = 0,
92     DEF_WAIT = 500,
93     INIT_DZ = 2,
94     NUM_SHAPES = 7
95 };
96
97 typedef struct {
98     GLXContext *glx_context;
99     tangram_shape tsm1, tsm2, tm, tlg1, tlg2, sq, rh;
100     tangram_shape n_tsm1, n_tsm2, n_tm, n_tlg1, n_tlg2, n_sq, n_rh;
101     char *puzzle_name;
102     int csi;
103
104     int ncolors;
105     XColor *colors;
106     int ccolor;
107
108     XFontStruct *xfont1;
109     XFontStruct *xfont2;
110     XFontStruct *xfont3;
111     GLuint font1_dlist, font2_dlist, font3_dlist;
112     GLuint name_list;
113 } tangram_configuration;
114
115 static tangram_configuration *tps = NULL;
116
117 #define DEF_VIEWING_TIME "5"
118 #define DEF_ROTATE_CAMERA "True"
119 #define DEF_X_CAMERA_ROTATE "0.2"
120 #define DEF_Y_CAMERA_ROTATE "0.5"
121 #define DEF_Z_CAMERA_ROTATE "0"
122
123
124 static GLuint viewing_time = 0;
125 static Bool do_rotate = True;
126 static GLfloat x_camera_rotate = 0.3;
127 static GLfloat y_camera_rotate = 0.75;
128 static GLfloat z_camera_rotate = 0;
129 static int wire;
130
131 static XrmOptionDescRec opts[] = {
132     {"-viewing_time", ".viewing_time", XrmoptionSepArg, 0},
133     {"-rotate", ".rotate", XrmoptionNoArg, "True"},
134     {"+rotate", ".rotate", XrmoptionNoArg, "False"},
135     {"-x_camera_rotate", ".x_camera_rotate", XrmoptionSepArg, 0},
136     {"-y_camera_rotate", ".y_camera_rotate", XrmoptionSepArg, 0},
137     {"-z_camera_rotate", ".z_camera_rotate", XrmoptionSepArg, 0}
138 };
139
140 static argtype vars[] = {
141     {&viewing_time, "viewing_time", "Viewing Time", DEF_VIEWING_TIME, t_Int},
142     {&do_rotate, "rotate", "Rotate", DEF_ROTATE_CAMERA, t_Bool},
143     {&x_camera_rotate, "x_camera_rotate", "X Camera Rotate", DEF_X_CAMERA_ROTATE, t_Float},
144     {&y_camera_rotate, "y_camera_rotate", "Y Camera Rotate", DEF_Y_CAMERA_ROTATE, t_Float},
145     {&z_camera_rotate, "z_camera_rotate", "Z Camera Rotate", DEF_Z_CAMERA_ROTATE, t_Float}
146 };
147
148 ModeSpecOpt sws_opts = { countof(opts), opts, countof(vars), vars, NULL };
149
150 static puzzle solved[] = {
151   {"Teapot", {
152       {{-1.664000, -1.552000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
153       {{-1.696000, 0.944000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0,  False},
154       {{0.064000, -2.128000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0,  True},
155       {{-0.960000, -1.056000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, False},
156       {{1.104000, 0.960000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True},
157       {{-1.376000, -0.800000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
158       {{1.152000, 0.736000, 0}, 360, 0, 0, INIT_DZ, -SPEED, 0, True},
159     },
160   },
161   {"Candle", {
162       {{-0.016000, 2.176001, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, False},
163       {{0.016000, 2.960001, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True},
164       {{0.000000, 0.400000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, False},
165       {{-2.015998, 2.208001, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, True},
166       {{2.000001, 2.208001, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False},
167       {{0.496000, 0.432000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True},
168       {{-0.016000, -0.672000, 0}, 335, 0, 0, INIT_DZ, -SPEED, 0, False},
169     },
170   },
171   {"Square", {
172       {{-0.048000, -0.016000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True},
173       {{0.704000, 0.736000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False},
174       {{-1.488000, 1.424001, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True},
175       {{-0.016000, -0.016000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False},
176       {{0.000000, 0.000000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True},
177       {{0.688000, 0.720000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False},
178       {{-0.784000, 0.672000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True},
179     },
180   },
181   {"Crane", {
182       {{1.248001, 1.759999, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False},
183       {{1.024000, 3.071999, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True},
184       {{-0.975999, -2.096001, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False},
185       {{0.480000, -1.968001, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
186       {{1.056000, -0.496000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
187       {{-0.239999, -1.312001, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True},
188       {{-0.223999, -1.360001, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False},
189     },
190   },
191   {"Crane", {
192       {{0.320000, 1.360000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True},
193       {{0.704000, 3.072000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False},
194       {{-1.200000, -3.392000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
195       {{0.688000, -1.184000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False},
196       {{-0.768000, 0.192000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True},
197       {{-1.168000, -2.304000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
198       {{1.312000, 1.296000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True},
199     },
200   },
201   {"Duck", {
202       {{-1.391999, 1.424000, 0}, 65, 0, 0, INIT_DZ, -SPEED, 0, False},
203       {{0.768000, 2.000000, 0}, 99, 180, 0, INIT_DZ, -SPEED, 0, True},
204       {{2.688001, -1.872000, 0}, 270, 180, 0, INIT_DZ, -SPEED, 0, False},
205       {{-1.343999, 0.944000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True},
206       {{0.112000, -0.464000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False},
207       {{1.984001, -1.120000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True},
208       {{1.536001, 0.912000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, False},
209     },
210   },
211   {"Pelican", {
212       {{1.088000, 0.064001, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
213       {{0.864000, -1.279999, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, False},
214       {{-1.807999, 1.520000, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, True},
215       {{1.824001, -1.231998, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
216       {{-0.368000, 1.472000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, True},
217       {{0.832000, -2.271998, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
218       {{1.776001, 0.816000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True},
219     },
220   },
221   {"Cat", {
222       {{0.416000, -2.432000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False},
223       {{0.352000, -2.432000, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, True},
224       {{0.832000, -0.480000, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, False},
225       {{-1.632000, 3.056000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True},
226       {{-1.616000, 1.040000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False},
227       {{1.088000, -1.696000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True},
228       {{0.832000, -0.432000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
229     },
230   },
231   {"Coi", {
232       {{1.264000, -1.232000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True},
233       {{1.216000, 0.816000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, False},
234       {{-1.631999, 1.872000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, True},
235       {{0.832000, 2.287999, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False},
236       {{-0.608000, 0.912000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, True},
237       {{2.240001, -0.176000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
238       {{0.256000, -1.200000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True},
239     },
240   },
241   {"Man Skipping", {
242       {{1.727998, 2.303998, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
243       {{-1.120000, 3.376001, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True},
244       {{0.879998, -3.008001, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
245       {{-1.072000, 2.559999, 0}, 360, 0, 0, INIT_DZ, -SPEED, 0, True},
246       {{-1.440000, 0.144000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False},
247       {{-0.192001, -2.592001, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
248       {{0.015999, 0.176000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False},
249     },
250   },
251   {"Old Man", {
252       {{-0.400000, 1.744000, 0}, 58, 180, 0, INIT_DZ, -SPEED, 0, True},
253       {{0.704000, 0.128000, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, False},
254       {{0.656000, 0.320000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True},
255       {{-0.112000, -0.384000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False},
256       {{-0.096000, -0.399999, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, True},
257       {{-0.736000, 0.352000, 0}, 123, 0, 0, INIT_DZ, -SPEED, 0, False},
258       {{-0.336000, 0.352000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True},
259     },
260   },
261   {"Spear Head", {
262       {{0.688000, -0.144000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False},
263       {{-0.080000, 0.592000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True},
264       {{-0.048000, 0.592000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, False},
265       {{-1.488000, -0.848000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True},
266       {{1.376000, -0.864000, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, False},
267       {{0.688000, -0.128000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
268       {{-1.504000, -0.832000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False},
269     },
270   },
271   {"Diamond", {
272       {{0.624000, -1.776000, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, True},
273       {{-0.144000, 0.432000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False},
274       {{-0.800000, -0.272000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, True},
275       {{-2.320000, -0.304000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False},
276       {{2.048000, -0.320000, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, True},
277       {{-0.112000, 0.480000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False},
278       {{-0.832000, -0.320000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, True},
279     },
280   },
281   {"Arrow", {
282       {{-2.048001, -1.232000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False},
283       {{0.112000, 0.943999, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True},
284       {{-1.312001, -0.560000, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, False},
285       {{0.496000, 0.656000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
286       {{0.528000, 0.608000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False},
287       {{-2.048001, -2.704000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
288       {{-1.312001, -0.512000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False},
289     },
290   },
291   {"Lady", {
292       {{-0.720000, 3.440000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True},
293       {{0.912000, -1.072000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False},
294       {{0.736000, 3.440000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True},
295       {{0.720000, 1.984000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False},
296       {{-0.672000, 0.544000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, True},
297       {{-0.192000, -3.840000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False},
298       {{-0.528000, -2.480000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
299     },
300   },
301   {"Running Man", {
302       {{1.136000, 2.720000, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, False},
303       {{-2.304001, 1.776000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True},
304       {{-0.256000, 0.288000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False},
305       {{-0.304000, 0.304000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
306       {{0.096000, -0.128000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, False},
307       {{-0.656000, -2.832000, 0}, 105, 0, 0, INIT_DZ, -SPEED, 0, True},
308       {{0.784000, -0.096000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False},
309     },
310   },
311   {"Parallelogram", {
312       {{-1.104000, -1.455999, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True},
313       {{0.912000, -0.447999, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
314       {{-0.048000, -1.471999, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
315       {{-1.136000, -1.439999, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
316       {{0.944000, 1.552000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True},
317       {{0.912000, 0.560000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
318       {{-0.112000, 1.568000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True},
319     },
320   },
321   {"N", {
322       {{-1.615999, 0.064000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False},
323       {{-0.592000, 0.112000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True},
324       {{0.432000, 0.096000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False},
325       {{-1.679999, -0.880000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True},
326       {{1.488001, 1.103999, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False},
327       {{-0.640000, 0.112000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True},
328       {{1.392001, -0.928000, 0}, 270, 180, 0, INIT_DZ, -SPEED, 0, False},
329     },
330   },
331   {"Farm House", {
332       {{2.112000, 1.504000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True},
333       {{-1.040000, 1.472000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, False},
334       {{0.032000, -1.600000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
335       {{1.056000, 1.504000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False},
336       {{-0.992000, -0.528000, 0}, 0, 180, 0, INIT_DZ, -SPEED, 0, True},
337       {{2.080000, 0.512000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
338       {{-1.104000, 0.480000, 0}, 270, 180, 0, INIT_DZ, -SPEED, 0, True},
339     },
340   },
341   {"Vulture", {
342       {{0.912000, 1.728000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False},
343       {{-2.623998, -1.040000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
344       {{0.992000, 1.104000, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, False},
345       {{0.944000, -0.288000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True},
346       {{-0.448000, -1.760000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, False},
347       {{-1.887998, -0.368000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True},
348       {{3.008002, 2.160000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False},
349     },
350   },
351   {"Swan", {
352       {{0.720000, 0.352000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True},
353       {{0.672000, -1.568000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False},
354       {{1.376000, 1.104000, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, True},
355       {{-1.151999, 1.488000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False},
356       {{0.320000, 2.096000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True},
357       {{0.656000, 0.304000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False},
358       {{0.624000, -2.559999, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, True},
359     },
360   },
361   {"High Karate", {
362       {{-0.144000, 2.576000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False},
363       {{1.696001, -2.432000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True},
364       {{2.176001, -0.400000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, False},
365       {{-0.624000, -0.512000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True},
366       {{-0.576000, -1.152000, 0}, 0, 180, 0, INIT_DZ, -SPEED, 0, False},
367       {{-1.919999, -1.376000, 0}, 303, 0, 0, INIT_DZ, -SPEED, 0, True},
368       {{0.448000, -0.096001, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
369     },
370   },
371   {"Lazy", {
372       {{-2.416000, 1.120000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True},
373       {{-1.952000, -2.016000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False},
374       {{-1.552000, -0.640000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, True},
375       {{-0.016000, 1.840000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False},
376       {{1.456000, -1.072000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, True},
377       {{0.848000, -0.816000, 0}, 332, 0, 0, INIT_DZ, -SPEED, 0, False},
378       {{-1.200000, -1.792000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
379     },
380   },
381   {"Bat", {
382       {{-0.304000, -0.352000, 0}, 259, 0, 0, INIT_DZ, -SPEED, 0, False},
383       {{0.304000, -1.344000, 0}, 105, 0, 0, INIT_DZ, -SPEED, 0, True},
384       {{1.312000, -1.024000, 0}, 300, 180, 0, INIT_DZ, -SPEED, 0, False},
385       {{1.952000, 0.240000, 0}, 195, 0, 0, INIT_DZ, -SPEED, 0, True},
386       {{-2.272000, 0.096000, 0}, 11, 180, 0, INIT_DZ, -SPEED, 0, False},
387       {{-0.112000, -1.056000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True},
388       {{-0.560000, -1.344000, 0}, 281, 180, 0, INIT_DZ, -SPEED, 0, False},
389     },
390   },
391   {"Sail Boat", {
392       {{0.544000, 2.000000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True},
393       {{0.880000, 0.160000, 0}, 360, 0, 0, INIT_DZ, -SPEED, 0, False},
394       {{0.656000, -1.503999, 0}, 220, 180, 0, INIT_DZ, -SPEED, 0, True},
395       {{-0.656000, -0.336000, 0}, 50, 0, 0, INIT_DZ, -SPEED, 0, False},
396       {{-0.688000, -0.288000, 0}, 310, 180, 0, INIT_DZ, -SPEED, 0, True},
397       {{0.864000, 1.232000, 0}, 360, 0, 0, INIT_DZ, -SPEED, 0, False},
398       {{0.496000, 2.016001, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, True},
399     },
400   },
401   {"Glenda", {
402       {{-2.016000, 2.080000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False},
403       {{0.240001, 1.824000, 0}, 360, 0, 0, INIT_DZ, -SPEED, 0, True},
404       {{2.239999, -0.752000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, False},
405       {{-1.264000, 2.784000, 0}, 360, 0, 0, INIT_DZ, -SPEED, 0, True},
406       {{-1.248000, 0.736000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False},
407       {{0.240001, 0.304000, 0}, 360, 0, 0, INIT_DZ, -SPEED, 0, True},
408       {{0.544000, -2.976001, 0}, 149, 0, 0, INIT_DZ, -SPEED, 0, False},
409     },
410   },
411   {"Cat", {
412       {{1.376000, -1.536001, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True},
413       {{1.488000, -1.552001, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False},
414       {{0.352000, -0.048000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True},
415       {{-2.144000, 2.415999, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False},
416       {{-2.096000, 0.368000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True},
417       {{2.144000, -0.800000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False},
418       {{1.392000, -0.064000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True},
419     },
420   },
421   {"Lying Cat", {
422       {{2.480000, -0.912000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False},
423       {{2.592000, -0.928000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True},
424       {{0.352000, 1.280000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False},
425       {{-0.688000, 0.336000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
426       {{1.808000, -0.112000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False},
427       {{3.248000, -0.176000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True},
428       {{-1.472000, 1.024000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False},
429     },
430   },
431   {"Witch", {
432       {{-0.943999, -0.304000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True},
433       {{-0.144000, 0.288000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False},
434       {{1.360000, -2.304000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True},
435       {{1.328000, -0.848000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False},
436       {{1.008000, 1.584000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True},
437       {{0.512000, 2.688000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False},
438       {{-0.863999, -0.096000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, True},
439     },
440   },
441   {"Laugh", {
442       {{0.703999, -0.160000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False},
443       {{-0.064000, -0.400000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True},
444       {{0.767999, -1.408000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False},
445       {{-1.232000, -1.328000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True},
446       {{-1.040000, 2.624000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False},
447       {{-0.288000, 1.264000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True},
448       {{-1.760001, -1.408000, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, False},
449     },
450   },
451   {"Standing Man", {
452       {{0.272000, 3.392000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True},
453       {{-0.144000, -1.328000, 0}, 331, 0, 0, INIT_DZ, -SPEED, 0, False},
454       {{1.216001, 0.272000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True},
455       {{0.736000, 0.208000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False},
456       {{0.432000, -3.440000, 0}, 151, 0, 0, INIT_DZ, -SPEED, 0, True},
457       {{0.720000, 2.320000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False},
458       {{-1.263998, 0.272000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True},
459     },
460   },
461   {"Walking Man", {
462       {{-1.056000, -3.456000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, False},
463       {{0.736000, 2.000000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
464       {{-1.488000, 1.760000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False},
465       {{-0.432000, 0.016000, 0}, 0, 180, 0, INIT_DZ, -SPEED, 0, True},
466       {{-0.432000, -0.064000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False},
467       {{0.560000, -2.576000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True},
468       {{0.032000, 2.656000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False},
469     },
470   },
471   {"Repose", {
472       {{-2.800000, -2.304000, 0}, 101, 0, 0, INIT_DZ, -SPEED, 0, True},
473       {{1.888000, 2.032000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, False},
474       {{-1.856000, 2.016000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True},
475       {{0.352000, -0.144000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, False},
476       {{-2.848000, 0.976000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True},
477       {{-1.424000, -1.104000, 0}, 236, 0, 0, INIT_DZ, -SPEED, 0, False},
478       {{-1.792000, 2.016000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True},
479     },
480   },
481   {"Shape", {
482       {{1.263999, 1.600001, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
483       {{1.311999, -1.568000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True},
484       {{-0.736000, 0.576000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False},
485       {{-0.736000, -2.591999, 0}, 360, 180, 0, INIT_DZ, -SPEED, 0, True},
486       {{-0.768000, 2.640001, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False},
487       {{-0.784000, -0.528000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True},
488       {{-0.736000, 0.496000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False},
489     },
490   },
491   {"Shape", {
492       {{-0.816000, 1.392000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True},
493       {{-0.832000, -1.807999, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, False},
494       {{1.216000, -0.752000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True},
495       {{1.232000, -2.815999, 0}, 270, 180, 0, INIT_DZ, -SPEED, 0, False},
496       {{1.248000, 2.400000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True},
497       {{-0.864000, 1.392000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
498       {{0.240000, 1.328000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True},
499     },
500   },
501   {"Lightning", {
502       {{0.176000, -2.448000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, False},
503       {{-1.888000, 2.880000, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, True},
504       {{-1.856000, 1.824000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False},
505       {{-1.872000, -1.392000, 0}, 0, 180, 0, INIT_DZ, -SPEED, 0, True},
506       {{1.264000, -0.432000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False},
507       {{2.320001, -2.432000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True},
508       {{-1.872000, 1.728000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False},
509     },
510   },
511   {"E", {
512       {{0.928000, 1.664000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True},
513       {{0.896000, -1.519998, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, False},
514       {{-1.136000, 0.608000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True},
515       {{-1.152000, -2.559998, 0}, 0, 180, 0, INIT_DZ, -SPEED, 0, False},
516       {{-1.152000, 2.672002, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True},
517       {{0.960000, -0.384000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
518       {{-1.136000, 0.528000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True},
519     },
520   },
521   {"Dagger", {
522       {{-0.096000, 0.448000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False},
523       {{0.640000, 2.656000, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, True},
524       {{-0.064000, -3.104000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False},
525       {{-0.767999, 1.184000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, True},
526       {{-0.080000, 0.416000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False},
527       {{0.416000, -2.064000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True},
528       {{-0.112000, 3.328001, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False},
529     },
530   },
531   {"Knight", {
532       {{-0.368000, 0.400000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True},
533       {{1.871998, -1.808000, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, False},
534       {{-1.056000, -0.368000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True},
535       {{-1.056000, -1.840000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False},
536       {{-0.352000, 1.440000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, True},
537       {{0.128000, 0.432000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
538       {{1.119999, -1.120000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True},
539     },
540   },
541   {"Candy", {
542       {{-1.039999, 1.136000, 0}, 360, 0, 0, INIT_DZ, -SPEED, 0, False},
543       {{1.024000, 0.096000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True},
544       {{-0.016000, 0.048000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False},
545       {{-0.016000, -1.008000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, True},
546       {{-0.016000, 1.216000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, False},
547       {{1.024000, 0.144000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True},
548       {{-0.032000, 1.088000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, False},
549     },
550   },
551   {"King", {
552       {{-0.688000, 1.904000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
553       {{0.800000, 1.904000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False},
554       {{0.512000, -1.392000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True},
555       {{1.488000, 1.120000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False},
556       {{-1.392000, 1.120000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True},
557       {{0.496000, -1.312000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
558       {{0.480000, -1.376000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True},
559     },
560   },
561   {"Top", {
562       {{-1.055999, -0.800000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, False},
563       {{-1.103999, 0.208000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True},
564       {{0.000000, -0.784000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False},
565       {{0.016000, 0.272000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True},
566       {{-0.032000, 0.288000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
567       {{0.480000, -1.855999, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True},
568       {{2.096001, 0.224000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False},
569     },
570   },
571   {"Dog", {
572       {{-2.896000, -0.128000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True},
573       {{-0.800000, 0.992000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False},
574       {{-1.152000, -0.416000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True},
575       {{-0.016000, 0.656000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False},
576       {{1.456000, -0.736000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
577       {{2.864000, 0.736000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
578       {{-0.048000, 1.664000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True},
579     },
580   },
581   {"Moose Head", {
582       {{2.944000, -0.288000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False},
583       {{1.936000, -0.224000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True},
584       {{-0.112000, 1.808000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False},
585       {{-2.128000, 0.768000, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, True},
586       {{1.888000, 0.768000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, False},
587       {{-0.112000, -0.688000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True},
588       {{-3.184000, -1.216000, 0}, 360, 180, 0, INIT_DZ, -SPEED, 0, False},
589     },
590   },
591   {"Negative Square", {
592       {{-1.520000, -0.624000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True},
593       {{-1.520000, 0.480000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False},
594       {{2.352000, 0.480000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True},
595       {{-0.080000, -3.040000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, False},
596       {{-0.096000, 2.944000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, True},
597       {{-2.528000, -0.576000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, False},
598       {{1.360000, -1.600000, 0}, 360, 180, INIT_DZ, -SPEED, 0, True},
599     }}
600 };
601 \f
602
603 static void get_solved_puzzle(ModeInfo * mi,
604                               tangram_shape * tsm1, tangram_shape * tsm2,
605                               tangram_shape * tm, tangram_shape * tlg1,
606                               tangram_shape * tlg2, tangram_shape * sq,
607                               tangram_shape * rh)
608 {
609     tangram_configuration *tp = &tps[MI_SCREEN(mi)];
610     int sz = sizeof(solved) / sizeof(solved[0]);
611     int r;
612
613     /* we don't want to see the same puzzle twice */
614     do {
615         r = random() % sz;
616     } while (r == tp->csi);
617     tp->csi = r;
618
619     *tsm1 = solved[r].ts[small_triangle1];
620     *tsm2 = solved[r].ts[small_triangle2];
621     *tm = solved[r].ts[medium_triangle];
622     *tlg1 = solved[r].ts[large_triangle1];
623     *tlg2 = solved[r].ts[large_triangle2];
624     *sq = solved[r].ts[square];
625     *rh = solved[r].ts[rhomboid];
626
627     tp->puzzle_name = solved[r].name;
628 }
629
630 static int approach_number(int goal, int current, int step)
631 {
632
633     int i = 0;
634
635     if (goal > current) {
636         while (i < step) {
637             current++;
638             if (goal <= current)
639                 break;
640             i++;
641         }
642     } else if (goal < current) {
643         while (i < step) {
644             current--;
645             if (goal >= current)
646                 break;
647             i++;
648         }
649     }
650
651     return current;
652 }
653
654 /* gt - floating point greater than comparison */
655 static Bool gt(GLfloat x1, GLfloat x2, GLfloat per)
656 {
657     if ((x1 > x2) && (fabs(x1 - x2) > per))
658         return True;
659     else
660         return False;
661 }
662
663 /* lt - floating point less than comparison */
664 static Bool lt(GLfloat x1, GLfloat x2, GLfloat per)
665 {
666     if ((x1 < x2) && (fabs(x1 - x2) > per))
667         return True;
668     else
669         return False;
670 }
671
672 static GLfloat approach_float(GLfloat goal, GLfloat current,
673                               Bool * changed, GLfloat per)
674 {
675     *changed = False;
676     if (gt(goal, current, per)) {
677         current += per;
678         *changed = True;
679     } else if (lt(goal, current, per)) {
680         current -= per;
681         *changed = True;
682     }
683     return current;
684 }
685
686 #if 0
687 static void print_shape(char *s, tangram_shape sh)
688 {
689     fprintf(stderr, "%s\n", s);
690     fprintf(stderr, "(%f, %f, %f)\n", sh.crd.x, sh.crd.y, sh.crd.z);
691     fprintf(stderr, "%d\n", sh.r);
692     fprintf(stderr, "%d\n", sh.fr);
693     fprintf(stderr, "\n");
694 }
695 #endif
696 \f
697
698 void reset_shape(tangram_shape * ts)
699 {
700     GLfloat r = random() % 10;
701     GLfloat f = r / 10;
702     ts->crd.z = BOTTOM;
703     ts->dz = INIT_DZ + f;
704     ts->ddz = -SPEED;
705 }
706
707 void bounce(tangram_shape * ts)
708 {
709     ts->crd.z *= -1;            /* ignore this */
710     ts->dz += ts->ddz;
711     ts->crd.z += ts->dz * SPEED;
712     if (ts->crd.z < BOTTOM) {
713         reset_shape(ts);
714     }
715
716     ts->crd.z *= -1;            /* ignore this */
717 }
718
719 static void draw_tangram_shape(tangram_shape ts)
720 {
721     glPushMatrix();
722
723     if (!do_rotate) {
724         ts.up = True;
725     }
726
727     glTranslatef(ts.crd.x, ts.crd.y, ts.up ? ts.crd.z : -ts.crd.z);
728     glRotated(90, 1, 0, 0);
729     glRotated(ts.fr, 1, 0, 0);
730     glRotated(ts.r, 0, 1, 0);
731     glCallList(ts.dl);
732     glPopMatrix();
733 }
734
735 static void load_fonts(ModeInfo * mi)
736 {
737     tangram_configuration *tp = &tps[MI_SCREEN(mi)];
738     load_font(mi->dpy, "titleFont", &tp->xfont1, &tp->font1_dlist);
739     load_font(mi->dpy, "titleFont2", &tp->xfont2, &tp->font2_dlist);
740     load_font(mi->dpy, "titleFont3", &tp->xfont3, &tp->font3_dlist);
741 }
742
743 static void draw_shapes(ModeInfo * mi)
744 {
745     tangram_configuration *tp = &tps[MI_SCREEN(mi)];
746
747     draw_tangram_shape(tp->tsm1);
748
749     draw_tangram_shape(tp->tsm2);
750     draw_tangram_shape(tp->tm);
751     draw_tangram_shape(tp->tlg1);
752     draw_tangram_shape(tp->tlg2);
753     draw_tangram_shape(tp->sq);
754     draw_tangram_shape(tp->rh);
755     glCallList(tp->name_list);
756 }
757
758 static void set_perspective(void)
759 {
760     glPushMatrix();
761     glMatrixMode(GL_PROJECTION);
762     glLoadIdentity();
763     gluPerspective(60, -1, 0.1, 50);
764     gluLookAt(0, 5, -5, 0, 0, 0, 0, -1, 0);
765     glMatrixMode(GL_MODELVIEW);
766     glPopMatrix();
767
768 }
769
770 void reshape_tangram(ModeInfo * mi, int w, int h)
771 {
772     glViewport(0, 0, w, h);
773     set_perspective();
774     glLoadIdentity();
775 }
776
777 static void set_camera(void)
778 {
779     static GLfloat theta[3] = { 1, 1, 1 };
780     static Bool going_down[3] = { False, False, False };
781
782     glPushMatrix();
783     glMatrixMode(GL_PROJECTION);
784     glLoadIdentity();
785     gluPerspective(60, -1, 0.1, 50);
786
787
788     gluLookAt(0, 5, -5, 0, 0, 0, 0, -1, 0);
789
790     if (do_rotate) {
791         glRotatef(theta[0], 1, 0, 0);
792         glRotatef(theta[1], 0, 1, 0);
793         glRotatef(theta[2], 0, 0, 1);
794     }
795
796     glMatrixMode(GL_MODELVIEW);
797     glPopMatrix();
798
799
800     if (going_down[0] && theta[0] < 0) {
801
802         going_down[0] = False;
803     } else if ((!going_down[0]) && theta[0] > 90) {
804
805         going_down[0] = True;
806     }
807
808     if (theta[1] > 360.0)
809         theta[1] -= 360.0;
810
811     if (theta[2] > 360.0)
812         theta[2] -= 360.0;
813
814     if (going_down[0])
815       theta[0] -= x_camera_rotate;
816     else
817       theta[0] += x_camera_rotate;
818
819     theta[1] += y_camera_rotate;
820     theta[2] += z_camera_rotate;
821 }
822
823 static void init_shapes(ModeInfo * mi)
824 {
825     int wire = MI_IS_WIREFRAME(mi);
826     tangram_configuration *tp = &tps[MI_SCREEN(mi)];
827     get_solved_puzzle(mi, &tp->tsm1, &tp->tsm2, &tp->tm, &tp->tlg1,
828                       &tp->tlg2, &tp->sq, &tp->rh);
829     get_solved_puzzle(mi, &tp->n_tsm1, &tp->n_tsm2, &tp->n_tm, &tp->n_tlg1,
830                       &tp->n_tlg2, &tp->n_sq, &tp->n_rh);
831     tp->tsm1.dl = get_sm_tri_dl(wire);
832     tp->tsm2.dl = get_sm_tri_dl(wire);
833     tp->tm.dl = get_md_tri_dl(wire);
834     tp->tlg1.dl = get_lg_tri_dl(wire);
835     tp->tlg2.dl = get_lg_tri_dl(wire);
836     tp->sq.dl = get_square_dl(wire);
837     tp->rh.dl = get_rhomboid_dl(wire);
838 }
839
840 static void gl_init(ModeInfo * mi)
841 {
842
843     int wire = MI_IS_WIREFRAME(mi);
844
845     GLfloat y = do_rotate ? -10 : 3;
846     GLfloat x = do_rotate ? 5 : 10;
847     GLfloat pos[4] = { 0, 0, -5, 1.00 };
848     GLfloat pos2[4] = { 0, 0, 5, 1.00 };
849     GLfloat dif2[4] = { 1, 1, 1, 1 };
850
851     pos[0] = -x;
852     pos[1] = y;
853
854     pos2[1] = x;
855     pos2[1] = y;
856
857     if (!wire) {
858         glEnable(GL_LIGHTING);
859         glLightfv(GL_LIGHT0, GL_POSITION, pos);
860         glEnable(GL_LIGHT0);
861         if (do_rotate) {
862             glLightfv(GL_LIGHT1, GL_POSITION, pos2);
863             glLightfv(GL_LIGHT1, GL_DIFFUSE, dif2);
864             glEnable(GL_LIGHT1);
865         }
866         glEnable(GL_DEPTH_TEST);
867     }
868
869 }
870
871 void init_tangram(ModeInfo * mi)
872 {
873     tangram_configuration *tp;
874
875     if (!tps) {
876         tps = (tangram_configuration *)
877             calloc(MI_NUM_SCREENS(mi), sizeof(tangram_configuration));
878         if (!tps) {
879             fprintf(stderr, "%s: out of memory\n", progname);
880             exit(1);
881         }
882
883         tp = &tps[MI_SCREEN(mi)];
884     }
885
886     tp = &tps[MI_SCREEN(mi)];
887
888     if ((tp->glx_context = init_GL(mi)) != NULL) {
889         gl_init(mi);
890     }
891
892     wire = MI_IS_WIREFRAME(mi);
893
894     load_fonts(mi);
895     init_shapes(mi);
896 }
897
898 static Bool all_solved(tangram_shape * ls[])
899 {
900     int i;
901     Bool b = True;
902     for (i = 0; i < NUM_SHAPES; i++) {
903         b = (b && ls[i]->solved);
904     }
905     return b;
906 }
907
908 static void solve(tangram_shape * new_s, tangram_shape * old_s)
909 {
910     Bool moved_x, moved_y, moved_r, moved_fr, z_ok;
911
912     old_s->fr = approach_number(new_s->fr, old_s->fr, 2);
913     moved_fr = (old_s->fr != new_s->fr);
914
915     old_s->r = approach_number(new_s->r, old_s->r, 2);
916     moved_r = (old_s->r != new_s->r);
917
918     old_s->crd.x =
919         approach_float(new_s->crd.x, old_s->crd.x, &moved_x, 0.1);
920     if (!moved_x)
921         old_s->crd.x = new_s->crd.x;
922
923     old_s->crd.y =
924         approach_float(new_s->crd.y, old_s->crd.y, &moved_y, 0.1);
925     if (!moved_y)
926         old_s->crd.y = new_s->crd.y;
927
928     z_ok = (-old_s->crd.z <= BOTTOM);
929
930     old_s->solved = (moved_x == False && moved_y == False &&
931                      moved_r == False && moved_fr == False &&
932                      z_ok == True);
933 }
934
935 static void set_not_solved(tangram_shape * ls[])
936 {
937     int i;
938     for (i = 0; i < NUM_SHAPES; i++)
939         ls[i]->solved = False;
940 }
941 \f
942
943 void draw_tangram(ModeInfo * mi)
944 {
945     Display *dpy = MI_DISPLAY(mi);
946     Window window = MI_WINDOW(mi);
947     tangram_configuration *tp = &tps[MI_SCREEN(mi)];
948
949     tangram_shape *ls[NUM_SHAPES];
950     tangram_shape *nls[NUM_SHAPES];
951
952
953     int i;
954     int MAX_DISPLAY;
955     static char *pn = "";
956     static int display_counter = 0;
957
958     static GLfloat color[4] = { 0.0, 0.0, 0.0, 1.0 };
959     static GLfloat white[4] = { 1.0, 1.0, 1.0, 1.0 };
960     MAX_DISPLAY = viewing_time * 100;
961
962     ls[small_triangle1] = &tp->tsm1;
963     ls[small_triangle2] = &tp->tsm2;
964     ls[medium_triangle] = &tp->tm;
965     ls[large_triangle1] = &tp->tlg1;
966     ls[large_triangle2] = &tp->tlg2;
967     ls[square] = &tp->sq;
968     ls[rhomboid] = &tp->rh;
969
970     nls[small_triangle1] = &tp->n_tsm1;
971     nls[small_triangle2] = &tp->n_tsm2;
972     nls[medium_triangle] = &tp->n_tm;
973     nls[large_triangle1] = &tp->n_tlg1;
974     nls[large_triangle2] = &tp->n_tlg2;
975     nls[square] = &tp->n_sq;
976     nls[rhomboid] = &tp->n_rh;
977
978     set_camera();
979
980     if (display_counter <= 0) {
981         for (i = 0; i < NUM_SHAPES; i++) {
982             if (ls[i]->solved) {
983                 if (all_solved(ls)) {
984                     display_counter = MAX_DISPLAY;
985                     pn = tp->puzzle_name;
986                     get_solved_puzzle(mi, nls[small_triangle1],
987                                       nls[small_triangle2],
988                                       nls[medium_triangle],
989                                       nls[large_triangle1],
990                                       nls[large_triangle2], nls[square],
991                                       nls[rhomboid]);
992                     tp->ncolors = 128;
993                     tp->colors =
994                         (XColor *) calloc(tp->ncolors, sizeof(XColor));
995
996                     make_random_colormap(0, 0, 0,
997                                          tp->colors, &tp->ncolors,
998                                          True, False, 0, False);
999
1000
1001                     color[0] = tp->colors[0].red / 65536.0;
1002                     color[1] = tp->colors[1].green / 65536.0;
1003                     color[2] = tp->colors[2].blue / 65536.0;
1004
1005
1006                     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
1007                                  color);
1008
1009                     set_not_solved(ls);
1010                     break;
1011                 }
1012             } else {
1013                 pn = "";
1014                 bounce(ls[i]);
1015                 solve(nls[i], ls[i]);
1016             }
1017         }
1018     } else {
1019         display_counter--;
1020     }
1021
1022     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1023     glPushMatrix();
1024
1025     glLoadIdentity();
1026     glNewList(tp->name_list, GL_COMPILE);
1027     {
1028         XFontStruct *f;
1029         GLuint fl;
1030         if (MI_WIDTH(mi) >= 500 && MI_HEIGHT(mi) >= 375)
1031             f = tp->xfont1, fl = tp->font1_dlist;
1032         else if (MI_WIDTH(mi) >= 350 && MI_HEIGHT(mi) >= 260)
1033             f = tp->xfont2, fl = tp->font2_dlist;
1034         else
1035             f = tp->xfont3, fl = tp->font3_dlist;
1036
1037         glColor3f(0.8, 0.8, 0);
1038         print_gl_string(mi->dpy, f, fl,
1039                         mi->xgwa.width, mi->xgwa.height,
1040                         10, mi->xgwa.height - 10, pn);
1041     }
1042     glEndList();
1043
1044     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
1045     glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 128);
1046
1047     draw_shapes(mi);
1048
1049     glFlush();
1050     glPopMatrix();
1051     glXSwapBuffers(dpy, window);
1052 }
1053
1054 #endif                          /* USE_GL */