1 /* buggy.c - implement the moon buggy
2  *
3  * Copyright 1999, 2004  Jochen Voss  */
4 
5 static const  char  rcsid[] = "$Id: buggy.c 6093 2004-12-27 15:58:57Z voss $";
6 
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #include <assert.h>
12 
13 #include "moon-buggy.h"
14 #include "buggy.h"
15 
16 
17 int  car_x, car_y;
18 
19 /**********************************************************************
20  * display the car
21  */
22 
23 typedef  struct scene {
24   enum car_state  n;		/* image number (index to array `image') */
25   int  y;			/* vertical position */
26   double  dt;			/* time to next state */
27   int  has_ground;		/* flag, true iff we may crash or jump */
28 }  scenario [];
29 
30 static  scenario  sz_empty = {
31   { car_NORMAL, 5, TICK(1), 1 },
32   { car_NORMAL1, 5, TICK(2.5), 1 },
33   { car_NORMAL2, 5, TICK(4), 1 },
34   { car_NORMAL3, 5, TICK(5.5), 1 }
35 };
36 
37 static scenario sz_jump = {
38   { car_START, 5, TICK(1), 0 },
39   { car_UP1, 6, TICK(2.5), 0 },
40   { car_UP2, 7, TICK(5), 0 },
41   { car_UP1, 6, TICK(2.5), 0 },
42   { car_LAND, 5, TICK(2.5), 1 },
43   { car_NORMAL, 5, -1, 1 }
44 };
45 
46 static  scenario  sz_crash = {
47   { car_BROKEN, 5, -1, 0 }
48 };
49 
50 static  scenario  sz_ram = {
51   { car_RAM1, 5, TICK(1), 0 },
52   { car_RAM2, 5, TICK(0.5), 0 },
53   { car_RAM3, 5, -1, 0 }
54 };
55 
56 static  scenario  sz_sit = {
57   { car_SIT, 5, -1, 0 }
58 };
59 
60 static  struct scene *state;
61 
62 static  int  nextG;
63 
64 
65 void
initialise_buggy(void)66 initialise_buggy (void)
67 /* Reset the buggy to its initial state.  */
68 {
69   int  y;
70 
71   state = sz_empty;
72   for (y=5; y<9; ++y)  mvwaddstr (moon, LINES-y, car_x, "       ");
73   car_x = car_base;
74   car_y = state->y;
75   wnoutrefresh (moon);
76 }
77 
78 void
print_buggy(void)79 print_buggy (void)
80 {
81   enum car_state  n = state->n;
82   int  y = state->y;
83 
84   if (y < car_y) {
85     mvwaddstr (moon, LINES-car_y-1, car_x, "       ");
86   } else if (y > car_y) {
87     mvwaddstr (moon, LINES-car_y, car_x, "       ");
88   }
89   car_y = y;
90 
91 /* ++pg the changing of the 4 normal states is realized
92         in the following lines.
93 */
94   if (n==car_NORMAL)  {
95     mvwaddstr (moon, LINES-y-1, car_x, image[n+nextG][0]);
96     mvwaddstr (moon, LINES-y, car_x, image[n+nextG][1]);
97   } else {
98     mvwaddstr (moon, LINES-y-1, car_x, image[n][0]);
99     mvwaddstr (moon, LINES-y, car_x, image[n][1]);
100   }
101   nextG++; if (nextG>3) nextG=0;
102 
103 
104   if (n == car_BROKEN) {
105     if (ground2[car_x+1] == ' ')  mvwaddch (moon, LINES-4, car_x+1, 'o');
106     if (ground2[car_x+5] == ' ')  mvwaddch (moon, LINES-4, car_x+5, 'o');
107   }
108   wnoutrefresh (moon);
109 }
110 
111 void
shift_buggy(int dx)112 shift_buggy (int dx)
113 /* Horizontally shift the buggy by the amount DX.
114  * Positive values of dx indicate a shift to the right.  */
115 {
116   mvwaddstr (moon, LINES-car_y-1, car_x, "       ");
117   mvwaddstr (moon, LINES-car_y, car_x, "       ");
118   car_x += dx;
119   print_buggy ();
120 }
121 
122 /**********************************************************************
123  * display a rolling wheel after a crash
124  */
125 
126 static int wheel_x, wheel_y;
127 
128 static void
wheel_handler(game_time t,void * client_data)129 wheel_handler (game_time t, void *client_data)
130 {
131   int  wheel_crash;
132 
133   wheel_crash = (wheel_x<car_x && wheel_y==LINES-5 && ground2[wheel_x]==' ');
134   if (wheel_x < car_x)  mvwaddch (moon, wheel_y, wheel_x, ' ');
135   wheel_x -= 1;
136   switch (car_x - wheel_x) {
137   case 1:
138   case 5:
139   case 7:
140   case 8:
141   case 9:
142     wheel_y = LINES - 6;
143     break;
144   case 2:
145   case 3:
146   case 4:
147     wheel_y = LINES - 7;
148     break;
149   default:
150     wheel_y = LINES - 5;
151     break;
152   }
153   if (wheel_x >= 0 && ! wheel_crash) {
154     mvwaddch (moon, wheel_y, wheel_x, 'o');
155     add_event (t+TICK(2.3), wheel_handler, NULL);
156   } else {
157     crash_detected = 1000;
158   }
159   wnoutrefresh (moon);
160 }
161 
162 static void
start_wheel(void)163 start_wheel (void)
164 {
165   wheel_x = car_x;
166   add_event (current_time()+TICK(0.5), wheel_handler, NULL);
167 }
168 
169 /**********************************************************************
170  * handle the jumps
171  */
172 
173 static void
jump_handler(game_time t,void * client_data)174 jump_handler (game_time t, void *client_data)
175 {
176   state = client_data;
177   if (car_y > 5 && state->y == 5) {
178     if (meteor_car_hit (car_x, car_x+7)) {
179       state = sz_sit;
180       start_wheel ();
181       crash_detected = 1;
182     }
183   }
184   print_buggy ();
185   if (state->dt >= -0.5) {
186     add_event (t+state->dt, jump_handler, state+1);
187   }
188 }
189 
190 void
jump(game_time t)191 jump (game_time t)
192 {
193   assert (state->has_ground);
194   remove_event (jump_handler);	/* only one jump at a time */
195   add_event (t, jump_handler, sz_jump);
196 }
197 
198 int
can_jump(void)199 can_jump (void)
200 {
201   return  state->has_ground;
202 }
203 
204 /**********************************************************************
205  * check for crashes
206  */
207 
208 int
crash_check(void)209 crash_check (void)
210 /* Return true, if the car crashed.  */
211 {
212   if (! state->has_ground)  return 0;
213   if (ground2[car_x+1] == ' ' || ground2[car_x+5] == ' ') {
214     remove_event (jump_handler);
215     state = sz_crash;
216     print_buggy ();
217     start_wheel ();
218     return 1;
219   }
220 
221   return  0;
222 }
223 
224 int
car_meteor_hit(int x)225 car_meteor_hit (int x)
226 /* Return true, if the car is down and occupies position X.
227  * Then the car crashes immediately.  */
228 {
229   if (car_y == 5 && x >= car_x && x < car_x+7) {
230     remove_event (jump_handler);
231     add_event (current_time (), jump_handler, sz_ram);
232     print_buggy ();
233     start_wheel ();
234     crash_detected = 1;
235     return 1;
236   }
237 
238   return  0;
239 }
240