1 /* game.c - play the game
2  *
3  * Copyright 1999, 2000  Jochen Voss  */
4 
5 static const  char  rcsid[] = "$Id: game.c 4839 2003-04-13 16:50:02Z voss $";
6 
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #include <signal.h>
12 
13 #include "moon-buggy.h"
14 
15 
16 struct mode *game_mode;
17 struct mode *crash_mode;
18 
19 
20 int  crash_detected;		/* a crash is in progress */
21 static  int  level;		/* the current level (crash_mode only) */
22 static  int  lives;		/* cars left (including the current one) */
23 static  int  score;		/* points we already got */
24 int  stakes;			/* points to get, when we reach the ground */
25 
26 
27 void
adjust_score(int val)28 adjust_score (int val)
29 /* Add VAL to the score and display the result.  */
30 {
31   if (crash_detected)  return;
32   score += val;
33   mvwprintw (status, 0, car_base-7, "score: %-8d", score);
34   wnoutrefresh (status);
35 }
36 
37 void
print_lives(void)38 print_lives (void)
39 {
40   mvwprintw (status, 0, car_base-20, "lives: %d", lives);
41   wnoutrefresh (status);
42 }
43 
44 /**********************************************************************
45  * game mode
46  */
47 
48 void
print_game_over(int blink)49 print_game_over (int blink)
50 {
51 #ifdef A_BLINK
52   if (blink)  wattron (moon, A_BLINK);
53 #endif
54   mvwaddstr (moon, LINES-11, car_base-1, "GAME OVER");
55 #ifdef A_BLINK
56   if (blink)  wattroff (moon, A_BLINK);
57 #endif
58   wnoutrefresh (moon);
59 }
60 
61 static void
game_enter(int seed)62 game_enter (int seed)
63 {
64   clock_reset ();
65 
66   if (seed == 0) {
67     level = 0;
68     score = 0;
69     lives = 3;
70     werase (status);
71     wnoutrefresh (status);
72   }
73 
74   resize_ground (1);
75   level_start (level);
76 
77   crash_detected = 0;
78   stakes = 0;
79   initialise_buggy ();
80   start_scrolling (1);
81 }
82 
83 static void
game_leave(void)84 game_leave (void)
85 {
86   --lives;
87   level = current_level ();
88   extinguish_laser ();
89   remove_meteors ();
90 }
91 
92 static void
game_redraw(void)93 game_redraw (void)
94 {
95   resize_meteors ();
96   resize_laser ();
97   resize_ground (0);
98 
99   print_ground ();
100   adjust_score (0);
101   print_lives ();
102   print_buggy ();
103 }
104 
105 static void
key_handler(game_time t,int val)106 key_handler (game_time t, int val)
107 {
108   switch (val) {
109   case 1:
110     if (! crash_detected && can_jump())  jump (t);
111     break;
112   case 2:
113     if (! crash_detected)  fire_laser (t);
114     break;
115   case 3:
116     lives = 1;
117     print_message ("aborted at user's request");
118     mode_change (crash_mode, 0);
119     break;
120   }
121 }
122 
123 static void
signal_handler(int signum)124 signal_handler (int signum)
125 {
126   switch (signum) {
127   case SIGTSTP:
128     if (lives > 1)  lives = 1;
129     if (! crash_detected)  crash_detected = 1;
130     print_message ("GAME OVER (suspended)");
131     break;
132   case SIGCONT:
133     print_message ("GAME OVER (suspended)");
134     break;
135   }
136 }
137 
138 /**********************************************************************
139  * crash mode
140  */
141 
142 static  int  lives_flag;
143 
144 static void
leave_crash_mode(game_time t,void * client_data)145 leave_crash_mode (game_time t, void *client_data)
146 /* This function is a possible callback argument to `add_event'.
147  * It switch control back to either `game_mode' or `highscore_mode'.
148  * The arguments T and CLIENT_DATA are ignored.  */
149 {
150   if (lives > 0) {
151     mode_change (game_mode, 1);
152   } else {
153     score_set (score, level+1);
154     mode_change (highscore_mode, 0);
155   }
156 }
157 
158 static void
print_lives_h(game_time t,void * client_data)159 print_lives_h (game_time t, void *client_data)
160 /* This function is a callback argument to `add_event'.
161  * It updates the number of lives display.  */
162 {
163   print_lives ();
164   lives_flag = 1;
165 }
166 
167 static void
crash_enter(int seed)168 crash_enter (int seed)
169 {
170   clock_reset ();
171   lives_flag = 0;
172   add_event (1.2, print_lives_h, NULL);
173   add_event (2.0, leave_crash_mode, NULL);
174   print_buggy ();
175   if (lives <= 0)  print_game_over (1);
176 }
177 
178 static void
crash_redraw(void)179 crash_redraw (void)
180 {
181   resize_ground (0);
182 
183   print_ground ();
184   print_buggy ();
185   adjust_score (0);
186   if (lives_flag)  print_lives ();
187 }
188 
189 static void
crash_key_handler(game_time t,int val)190 crash_key_handler (game_time t, int val)
191 {
192   if (t < 0.5)  return;
193 
194   switch (val) {
195   case 1:
196     leave_crash_mode (0, NULL);
197     break;
198   case 3:
199     lives = 0;
200     leave_crash_mode (0, NULL);
201     break;
202   }
203 }
204 
205 void
setup_game_mode(void)206 setup_game_mode (void)
207 {
208   game_mode = new_mode ();
209   game_mode->enter = game_enter;
210   game_mode->leave = game_leave;
211   game_mode->redraw = game_redraw;
212   game_mode->keypress = key_handler;
213   game_mode->signal = signal_handler;
214   mode_add_key (game_mode, mbk_jump, "jump", 1);
215   mode_add_key (game_mode, mbk_fire, "fire", 2);
216   mode_add_key (game_mode, mbk_end, "abort game", 3);
217   mode_complete (game_mode);
218 
219   crash_mode = new_mode ();
220   crash_mode->enter = crash_enter;
221   crash_mode->redraw = crash_redraw;
222   crash_mode->keypress = crash_key_handler;
223   mode_add_key (crash_mode, mbk_start, "continue", 1);
224   mode_add_key (crash_mode, mbk_end, "abort game", 3);
225   mode_complete (crash_mode);
226 }
227