]> icculus.org git repositories - taylor/freespace2.git/blob - src/gamesequence/gamesequence.cpp
warnings (clang): various
[taylor/freespace2.git] / src / gamesequence / gamesequence.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/GameSequence/GameSequence.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * File to control Game Sequencing
16  *
17  * $Log$
18  * Revision 1.2  2002/06/09 04:41:17  relnev
19  * added copyright header
20  *
21  * Revision 1.1.1.1  2002/05/03 03:28:09  root
22  * Initial import.
23  *
24  * 
25  * 3     2/23/99 2:29p Dave
26  * First run of oldschool dogfight mode. 
27  * 
28  * 2     10/07/98 10:52a Dave
29  * Initial checkin.
30  * 
31  * 1     10/07/98 10:48a Dave
32  * 
33  * 65    5/15/98 12:09a Dave
34  * New tracker api code. New game tracker code. Finished up first run of
35  * the PXO screen. Fixed a few game server list exceptions.
36  * 
37  * 64    5/12/98 2:46a Dave
38  * Rudimentary communication between Parallax Online and freespace. Can
39  * get and store channel lists.
40  * 
41  * 63    5/06/98 1:12a Allender
42  * fix sequencing names, added nprintf to help respawn debugging
43  * 
44  * 62    4/25/98 7:39p Allender
45  * fixd some small hotkey stuff.  Worked on turret orientation being
46  * correct for multiplayer.  new sexpression called end-campaign will will
47  * end the main campaign
48  * 
49  * 61    4/23/98 7:08p John
50  * Removed some obsoleted states.
51  * 
52  * 60    4/16/98 4:31p Hoffoss
53  * Changed demo screen referenced to view cutscenes screen, which is now
54  * what it's called.
55  * 
56  * 59    4/02/98 5:40p Hoffoss
57  * Added the Load Mission screen to FreeSpace.
58  * 
59  * 58    3/11/98 5:32p Lawrance
60  * Fix up text arrays for events/states
61  * 
62  * 57    3/09/98 12:13a Lawrance
63  * Add support for Red Alert missions
64  * 
65  * 56    3/05/98 4:12p John
66  * Made Debug+F4 switch Glide and windowed.
67  * 
68  * 55    3/03/98 1:00p Hoffoss
69  * Added new command briefing event and state.
70  * 
71  * 54    3/02/98 4:23p Hoffoss
72  * Forgot to add state label.
73  * 
74  * 53    3/02/98 3:44p Hoffoss
75  * Added new Campaign Room state and event.
76  * 
77  * 52    2/21/98 11:58a John
78  * Put in some stuff to externalize strings
79  * 
80  * 51    2/19/98 6:26p Dave
81  * Fixed a few file xfer bugs. Tweaked mp team select screen. Put in
82  * initial support for player data uploading.
83  * 
84  * 50    2/18/98 10:21p Dave
85  * Ripped out old file xfer system. Put in brand new xfer system.
86  * 
87  * 49    2/08/98 5:07p Dave
88  * Put in support for multiplayer furball mode.
89  * 
90  * 48    1/28/98 6:21p Dave
91  * Made the standalone use ~8 megs less memory. Fixed multiplayer submenu
92  * endgame problem.
93  * 
94  * 47    1/23/98 5:43p Dave
95  * Finished bringing standalone up to speed. Coded in new host options
96  * screen.
97  * 
98  * 46    1/22/98 5:25p Dave
99  * Modified some pregame sequencing packets. Starting to repair broken
100  * standalone stuff.
101  * 
102  * 45    1/22/98 4:15p Hoffoss
103  * Added code to allow popup to tell player he needs to bind a key for the
104  * training mission.
105  * 
106  * 44    1/20/98 5:42p Dave
107  * Moved ingame join to its own module. Improved it a bit.
108  * 
109  * 43    1/19/98 12:57p Allender
110  * removed confusing comment
111  * 
112  * 42    1/19/98 12:56p Allender
113  * fix problem of freespace_start_misison possibly failing due to mission
114  * not properly loading (for single player only right now).
115  * 
116  * 41    1/15/98 6:12p Dave
117  * Fixed weapons loadout bugs with multiplayer respawning. Added
118  * multiplayer start screen. Fixed a few chatbox bugs.
119  * 
120  * 40    1/15/98 6:00p Hoffoss
121  * Added option to quit menu (in game) to restart the mission.  Doesn't
122  * seem to quite work, though.  Checking code in so someone else can look
123  * into it.
124  * 
125  * 39    1/05/98 10:05a Dave
126  * Big re-sequencing of server transfer. Centralized _all_ server transfer
127  * code to one module.
128  * 
129  * 38    12/30/97 4:28p Lawrance
130  * Give text descriptions for events, change debug output to give text
131  * desciption of event/state
132  * 
133  * 37    12/24/97 8:56p Lawrance
134  * took out obsolete state used for non-existant sound config screen
135  * 
136  * 36    11/19/97 8:28p Dave
137  * Hooked in Main Hall screen. Put in Anim support for ping ponging
138  * animations as well as general reversal of anim direction.
139  * 
140  * 35    11/15/97 2:36p Dave
141  * Added more multiplayer campaign support.
142  * 
143  * 34    11/13/97 7:01p Hoffoss
144  * Fixed GS_state_text[], which didn't match the current states we have
145  * available.
146  * 
147  * 33    11/10/97 6:02p Hoffoss
148  * Added new debug paused state.
149  * 
150  * 32    11/03/97 10:12p Hoffoss
151  * Finished up work on the hud message/mission log scrollback screen.
152  * 
153  * 31    10/22/97 11:00p Lawrance
154  * modify pop_and_discard() to allow discarding of all states on the stack
155  * 
156  * 30    10/22/97 5:08p John
157  * fixed a whole slew of bugs and clean up a bunch of stuff dealing with
158  * end of mission stuff.
159  * 
160  * 29    10/02/97 9:49p Hoffoss
161  * Added event evaluation analysis debug screen so we can determine the
162  * state of events and their sexp trees to track down logic problems and
163  * such.
164  * 
165  * 28    9/23/97 11:53p Lawrance
166  * add state do perform multiplayer on-line help
167  * 
168  * 27    9/22/97 4:55p Hoffoss
169  * Added a training message window display thingy.
170  * 
171  * 26    9/19/97 4:24p Allender
172  * added team selection state -- initialze player* variable in
173  * player_level_init
174  * 
175  * 25    9/18/97 10:17p Lawrance
176  * add help state for briefing
177  * 
178  * 24    9/18/97 10:15p Lawrance
179  * add help state for briefing
180  * 
181  * 23    7/14/97 12:03a Lawrance
182  * added navmap state
183  * 
184  * 22    6/13/97 2:30p Lawrance
185  * Added debriefings
186  * 
187  * 21    5/20/97 10:02a Lawrance
188  * added view medals screen
189  * 
190  * 20    4/28/97 2:17p Lawrance
191  * added help state for hotkey assignment screen
192  * 
193  * 19    4/25/97 3:41p Lawrance
194  * added support for hotkey assignment screen
195  * 
196  * 18    4/23/97 9:54a Lawrance
197  * made show goals screen a separate state
198  * 
199  * 17    4/22/97 11:06a Lawrance
200  * added credits state
201  * 
202  * 16    4/17/97 9:01p Allender
203  * start of campaign stuff.  Campaigns now stored in external file (no
204  * filenames in code).  Continuing campaign won't work at this point
205  * 
206  * 15    4/03/97 8:40p Lawrance
207  * add new player death states to GS_state_text[]
208  * 
209  * 14    3/05/97 5:04p Lawrance
210  * added new states for different context help
211  * 
212  * 13    1/09/97 12:41a Lawrance
213  * added function to pop a state without restoring that state
214  * 
215  * 12    12/22/96 3:41p Lawrance
216  * integrating energy transfer system
217  * 
218  * 11    12/09/96 2:35p Allender
219  * modifed game sequencing so that game_leave_state and game_enter_state
220  * are *always* called.
221  * 
222  * 10    12/08/96 1:54a Lawrance
223  * put check in to see if a state change request is invalid (ie already in
224  * that state)
225  * 
226  * 9     11/18/96 5:07p John
227  * Changed sequencing code to call entry,leave functions for each state
228  * change.   Added Shift+Pause debug pause thing.
229  * 
230  * 8     11/13/96 4:02p Lawrance
231  * complete over-haul of the menu system and the states associated with
232  * them
233  * 
234  * 7     10/23/96 9:08a Allender
235  * Removed primary and secondary goal complete states -- to be implemented
236  * later.
237  *
238 */
239
240 /*
241  *  All states for game sequencing are defined in GameSequence.h.
242  *  States should always be referred to using the macros.
243 */
244
245 #include "freespace.h"
246 #include "gamesequence.h"
247
248 // local defines
249 #define MAX_GAMESEQ_EVENTS              20              // maximum number of events on the game sequencing queue
250 #define GS_STACK_SIZE                   10              // maximum number of stacked states
251
252 // local variables
253 typedef struct state_stack {
254         int     current_state;
255         int     event_queue[MAX_GAMESEQ_EVENTS];
256         int     queue_tail, queue_head;
257 } state_stack;
258
259 // DO NOT MAKE THIS NON-STATIC!!!!
260 LOCAL state_stack gs[GS_STACK_SIZE];
261 LOCAL int gs_current_stack = -1;                                                // index of top state on stack.
262
263 static int state_reentry = 0;  // set if we are already in state processing
264 static int state_processing_event_post = 0;  // set if we are already processing an event to switch states
265 static int state_in_event_processer = 0;
266
267 // Text of state, corresponding to #define values for GS_STATE_*
268 //XSTR:OFF
269 const char *GS_event_text[] =
270 {
271         "GS_EVENT_MAIN_MENU",
272         "GS_EVENT_START_GAME",
273         "GS_EVENT_ENTER_GAME",
274         "GS_EVENT_START_GAME_QUICK",
275         "GS_EVENT_END_GAME",                                                                    
276         "GS_EVENT_QUIT_GAME",                                                           // 5
277         "GS_EVENT_PAUSE_GAME",
278         "GS_EVENT_PREVIOUS_STATE",
279         "GS_EVENT_OPTIONS_MENU",
280         "GS_EVENT_BARRACKS_MENU",                                                       
281         "GS_EVENT_TRAINING_MENU",                                                       // 10
282         "GS_EVENT_TECH_MENU",
283         "GS_EVENT_LOAD_MISSION_MENU",
284         "GS_EVENT_SHIP_SELECTION",
285         "GS_EVENT_TOGGLE_FULLSCREEN",                                           
286         "GS_EVENT_WEAPON_SELECT_HELP",                                  // 15
287         "GS_EVENT_START_BRIEFING",
288         "GS_EVENT_DEBUG_PAUSE_GAME",
289         "GS_EVENT_HUD_CONFIG",
290         "GS_EVENT_MULTI_SETUP",                                                         
291         "GS_EVENT_MULTI_JOIN_GAME",                                             // 20
292         "GS_EVENT_CONTROL_CONFIG",
293         "GS_EVENT_EVENT_DEBUG",
294         "GS_EVENT_MULTI_PROTO_CHOICE",
295         "GS_EVENT_SAVE_RESTORE",                                                        
296         "GS_EVENT_CHOOSE_SAVE_OR_RESTORE",                              // 25
297         "GS_EVENT_WEAPON_SELECTION",
298         "GS_EVENT_MISSION_LOG_SCROLLBACK",
299         "GS_EVENT_MAIN_MENU_HELP",                                                      
300         "GS_EVENT_GAMEPLAY_HELP",
301         "GS_EVENT_SHIP_SELECT_HELP",                                            // 30
302         "GS_EVENT_DEATH_DIED",
303         "GS_EVENT_DEATH_BLEW_UP",
304         "GS_EVENT_NEW_CAMPAIGN",
305         "GS_EVENT_CREDITS",
306         "GS_EVENT_SHOW_GOALS",                                                          // 35
307         "GS_EVENT_HOTKEY_SCREEN",
308         "GS_EVENT_HOTKEY_SCREEN_HELP",                                  
309         "GS_EVENT_VIEW_MEDALS",
310         "GS_EVENT_MULTI_HOST_SETUP",
311         "GS_EVENT_MULTI_CLIENT_SETUP",                                  // 40
312         "GS_EVENT_DEBRIEF",
313         "GS_EVENT_NAVMAP",                                                                      
314         "GS_EVENT_MULTI_JOIN_TRACKER",
315         "GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN",
316         "GS_EVENT_MULTI_STD_WAIT",                                                      // 45
317         "GS_EVENT_STANDALONE_MAIN",
318         "GS_EVENT_MULTI_PAUSE",
319         "GS_EVENT_BRIEFING_HELP",
320         "GS_EVENT_TEAM_SELECT",
321         "GS_EVENT_TRAINING_PAUSE",                                                      // 50   
322         "GS_EVENT_MULTI_HELP",                                                          
323         "GS_EVENT_INGAME_PRE_JOIN",
324         "GS_EVENT_PLAYER_WARPOUT_START",
325         "GS_EVENT_PLAYER_WARPOUT_START_FORCED",
326         "GS_EVENT_PLAYER_WARPOUT_STOP",                                 // 55
327         "GS_EVENT_PLAYER_WARPOUT_DONE_STAGE1",                  
328         "GS_EVENT_PLAYER_WARPOUT_DONE_STAGE2",
329         "GS_EVENT_PLAYER_WARPOUT_DONE",
330         "GS_EVENT_STANDALONE_POSTGAME",
331         "GS_EVENT_INITIAL_PLAYER_SELECT",                               // 60
332         "GS_EVENT_GAME_INIT",                                                           
333         "GS_EVENT_MULTI_MISSION_SYNC",
334         "GS_EVENT_MULTI_CAMPAIGN_SELECT",
335         "GS_EVENT_MULTI_SERVER_TRANSFER",
336         "GS_EVENT_MULTI_START_GAME",                                            // 65
337         "GS_EVENT_MULTI_HOST_OPTIONS",                                  
338         "GS_EVENT_MULTI_DOGFIGHT_DEBRIEF",
339         "GS_EVENT_CAMPAIGN_ROOM",
340         "GS_EVENT_CMD_BRIEF",
341         "GS_EVENT_TOGGLE_GLIDE",                                                        // 70
342         "GS_EVENT_RED_ALERT",                                                           
343         "GS_EVENT_SIMULATOR_ROOM",
344         "GS_EVENT_EMD_CAMPAIGN",        
345 };
346 //XSTR:ON
347
348 // Text of state, corresponding to #define values for GS_STATE_*
349 //XSTR:OFF
350 const char *GS_state_text[] =
351 {
352         "NOT A VALID STATE",
353         "GS_STATE_MAIN_MENU",                                                           // 1
354         "GS_STATE_GAME_PLAY",
355         "GS_STATE_GAME_PAUSED",
356         "GS_STATE_QUIT_GAME",
357         "GS_STATE_OPTIONS_MENU",                                                        // 5
358         "GS_EVENT_WEAPON_SELECT_HELP",
359         "GS_STATE_BARRACKS_MENU",
360         "GS_STATE_TECH_MENU",
361         "GS_STATE_TRAINING_MENU",
362         "GS_STATE_LOAD_MISSION_MENU",                                           // 10
363         "GS_STATE_BRIEFING",
364         "GS_STATE_SHIP_SELECT",
365         "GS_STATE_DEBUG_PAUSED",
366         "GS_STATE_HUD_CONFIG",
367         "GS_STATE_MULTI_SETUP",                                                         // 15
368         "GS_STATE_MULTI_JOIN_GAME",
369         "GS_STATE_CONTROL_CONFIG",
370         "GS_STATE_MULTI_PROTO_CHOICE",
371         "GS_STATE_SAVE_RESTORE",
372         "GS_STATE_WEAPON_SELECT",                                                       // 20
373         "GS_STATE_MISSION_LOG_SCROLLBACK",
374         "GS_STATE_MAIN_MENU_HELP",
375         "GS_STATE_GAMEPLAY_HELP",
376         "GS_STATE_SHIP_SELECT_HELP",
377         "GS_STATE_DEATH_DIED",                                                          // 25
378         "GS_STATE_DEATH_BLEW_UP",
379         "GS_STATE_SIMULATOR_ROOM",
380         "GS_STATE_CREDITS",
381         "GS_STATE_SHOW_GOALS",
382         "GS_STATE_HOTKEY_SCREEN",                                                       // 30
383         "GS_STATE_HOTKEY_SCREEN_HELP",
384         "GS_STATE_VIEW_MEDALS",
385         "GS_STATE_MULTI_HOST_SETUP",
386         "GS_STATE_MULTI_CLIENT_SETUP",
387         "GS_STATE_DEBRIEF",                                                                     // 35
388         "GS_STATE_NAVMAP",
389         "GS_STATE_MULTI_JOIN_TRACKER",  
390         "GS_STATE_VIEW_CUTSCENES",
391         "GS_STATE_MULTI_STD_WAIT",
392         "GS_STATE_STANDALONE_MAIN",                                             // 40
393         "GS_STATE_MULTI_PAUSED",        
394         "GS_STATE_BRIEFING_HELP",
395         "GS_STATE_TEAM_SELECT",
396         "GS_STATE_TRAINING_PAUSED",
397         "GS_STATE_MULTI_HELP",                                                          // 45
398         "GS_STATE_INGAME_PRE_JOIN",                                             
399         "GS_STATE_EVENT_DEBUG",
400         "GS_STATE_STANDALONE_POSTGAME",
401         "GS_STATE_INITIAL_PLAYER_SELECT",
402         "GS_STATE_MULTI_MISSION_SYNC",                                  // 50
403         "GS_STATE_MULTI_SERVER_TRANSFER",                               
404         "GS_STATE_MULTI_START_GAME",
405         "GS_STATE_MULTI_HOST_OPTIONS",
406         "GS_STATE_MULTI_DOGFIGHT_DEBRIEF",                              
407         "GS_STATE_CAMPAIGN_ROOM",                                                       // 55
408         "GS_STATE_CMD_BRIEF",
409         "GS_STATE_RED_ALERT",
410         "GS_STATE_END_OF_CAMPAIGN",
411 };
412 //XSTR:ON
413
414 void gameseq_init()
415 {
416         int i;
417
418         for (i=0; i<GS_STACK_SIZE; i++ )        {
419                 // gs[i].current_state = GS_STATE_MAIN_MENU;
420                 gs[i].current_state = 0;
421                 gs[i].queue_tail=0;
422                 gs[i].queue_head=0;
423         }
424
425         gs_current_stack = 0;
426         state_reentry = 0;
427         state_processing_event_post = 0;
428         state_in_event_processer = 0;
429 }
430
431 // gameseq_post_event posts a new game sequencing event onto the gameseq
432 // event queue
433
434 void gameseq_post_event( int event )
435 {
436         if (state_processing_event_post) {
437                 nprintf(("Warning", "Received post for event %s during state transtition. Find Allender if you are unsure if this is bad.\n", GS_event_text[event] ));
438         }
439
440         SDL_assert(gs[gs_current_stack].queue_tail < MAX_GAMESEQ_EVENTS);
441         gs[gs_current_stack].event_queue[gs[gs_current_stack].queue_tail++] = event;
442         if ( gs[gs_current_stack].queue_tail == MAX_GAMESEQ_EVENTS )
443                 gs[gs_current_stack].queue_tail = 0;
444 }
445
446 // returns one of the GS_EVENT_ id's on the game sequencing queue
447
448 int gameseq_get_event()
449 {
450         int event;
451
452         if ( gs[gs_current_stack].queue_head == gs[gs_current_stack].queue_tail )
453                 return -1;
454         event = gs[gs_current_stack].event_queue[gs[gs_current_stack].queue_head++];
455         if ( gs[gs_current_stack].queue_head == MAX_GAMESEQ_EVENTS )
456                 gs[gs_current_stack].queue_head = 0;
457
458         return event;
459 }          
460
461 // returns one of the GS_STATE_ macros
462 int gameseq_get_state(int depth)
463 {       
464         SDL_assert(depth <= gs_current_stack);
465                         
466         return gs[gs_current_stack - depth].current_state;
467 }
468
469 int gameseq_get_depth()
470 {
471         return gs_current_stack;
472 }
473
474 void gameseq_set_state(int new_state, int override)
475 {
476         int event, old_state;
477
478         if ( (new_state == gs[gs_current_stack].current_state) && !override )
479                 return;
480
481         old_state = gs[gs_current_stack].current_state;
482
483         // Flush all events!!
484         while ( (event = gameseq_get_event()) != -1 ) {
485                 mprintf(( "Throwing out event %d because of state set from %d to %d\n", event, old_state, new_state ));
486         }
487
488         SDL_assert( state_reentry == 1 );               // Get John! (Invalid state sequencing!)
489         SDL_assert( state_in_event_processer == 1 );            // can only call from game_process_event
490
491         state_processing_event_post++;
492         state_reentry++;
493         game_leave_state(gs[gs_current_stack].current_state,new_state);
494
495         gs[gs_current_stack].current_state = new_state;
496
497         game_enter_state(old_state,gs[gs_current_stack].current_state);
498         state_reentry--;
499         state_processing_event_post--;
500 }
501         
502 void gameseq_push_state( int new_state )
503 {
504         if ( new_state == gs[gs_current_stack].current_state )
505                 return;
506
507         int old_state = gs[gs_current_stack].current_state;
508
509         // Flush all events!!
510 // I commented out because I'm not sure if we should throw out events when pushing or not.
511 //      int event;
512 //      while( (event = gameseq_get_event()) != -1 )    {
513 //              mprintf(( "Throwing out event %d because of state push from %d to %d\n", event, old_state, new_state ));
514 //      }
515
516         SDL_assert( state_reentry == 1 );               // Get John! (Invalid state sequencing!)
517         SDL_assert( state_in_event_processer == 1 );            // can only call from game_process_event
518
519         gs_current_stack++;
520         SDL_assert(gs_current_stack < GS_STACK_SIZE);
521
522         state_processing_event_post++;
523         state_reentry++;
524         game_leave_state(old_state,new_state);
525
526         gs[gs_current_stack].current_state = new_state;
527         gs[gs_current_stack].queue_tail = 0;
528         gs[gs_current_stack].queue_head = 0;
529
530         game_enter_state(old_state,gs[gs_current_stack].current_state);
531         state_reentry--;
532         state_processing_event_post--;
533 }
534
535 void gameseq_pop_state()
536 {
537         int popped_state = 0;
538
539         SDL_assert(state_reentry == 1);         // Get John! (Invalid state sequencing!)
540
541         if (gs_current_stack >= 1) {
542                 int old_state;
543
544                 // set the old state to be the state which is about to be popped off the queue
545                 old_state = gs[gs_current_stack].current_state;
546
547                 // set the popped_state to be the state which is going to be moved into
548                 popped_state = gs[gs_current_stack-1].current_state;
549
550                 // leave the current state
551                 state_reentry++;
552                 game_leave_state(gs[gs_current_stack].current_state,popped_state);
553
554                 // set the popped_state to be the one we moved into
555                 gs_current_stack--;
556
557                 // swap all remaining events from the state which just got popped to this new state
558                 while(gs[gs_current_stack+1].queue_head != gs[gs_current_stack+1].queue_tail){
559                         gameseq_post_event(gs[gs_current_stack+1].event_queue[gs[gs_current_stack+1].queue_head++]);
560                 }
561
562                 game_enter_state(old_state, gs[gs_current_stack].current_state);
563                 state_reentry--;
564
565         }
566
567 }
568
569 // gameseq_pop_and_discard_state() is used to remove a state that was pushed onto the stack, but
570 // will never need to be popped.  An example of this is entering a state that may require returning
571 // to the previous state (then you would call gameseq_pop_state).  Or you may simply continue to
572 // another part of the game, to avoid filling up the stack with states that may never be popped, you
573 // call this function to discard the top of the gs.
574 //
575
576 void gameseq_pop_and_discard_state()
577 {
578         if (gs_current_stack > 0 ) {
579                 gs_current_stack--;
580         }
581 }
582
583 // Returns the last state pushed on stack
584 int gameseq_get_pushed_state()
585 {
586         if (gs_current_stack >= 1) {
587                 return gs[gs_current_stack-1].current_state;
588         } else  
589                 return -1;
590 }
591
592 // gameseq_process_events gets called every time through high level loops
593 // (i.e. game loops, main menu loop).  Function is responsible for pulling
594 // game sequence events off the queue and changing the state when necessary.
595 // Returns the current state.
596                 // pull events game sequence events off of the queue.  Process one at a time
597                 // based on the current state and the new event.
598
599 int gameseq_process_events()    
600 {
601         int event, old_state;
602         old_state = gs[gs_current_stack].current_state;
603
604         SDL_assert(state_reentry == 0);         // Get John! (Invalid state sequencing!)
605
606         while ( (event = gameseq_get_event()) != -1 ) {
607                 state_reentry++;
608                 state_in_event_processer++;
609                 game_process_event(gs[gs_current_stack].current_state, event);
610                 state_in_event_processer--;
611                 state_reentry--;
612                 // break when state changes so that code will get called at
613                 // least one frame for each state.
614                 if (old_state != gs[gs_current_stack].current_state)
615                         break;  
616         }
617
618         state_reentry++;
619         game_do_state(gs[gs_current_stack].current_state);
620         state_reentry--;
621
622         return gs[gs_current_stack].current_state;
623
624