rnd-20021228-1-src
[rocksndiamonds.git] / src / events.c
1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment                      *
5 *               Holger Schemel                             *
6 *               Detmolder Strasse 189                      *
7 *               33604 Bielefeld                            *
8 *               Germany                                    *
9 *               e-mail: info@artsoft.org                   *
10 *----------------------------------------------------------*
11 * events.c                                                 *
12 ***********************************************************/
13
14 #include "libgame/libgame.h"
15
16 #include "events.h"
17 #include "init.h"
18 #include "screens.h"
19 #include "tools.h"
20 #include "game.h"
21 #include "editor.h"
22 #include "files.h"
23 #include "tape.h"
24 #include "network.h"
25
26 /* values for key_status */
27 #define KEY_NOT_PRESSED         FALSE
28 #define KEY_RELEASED            FALSE
29 #define KEY_PRESSED             TRUE
30
31
32 /* event filter especially needed for SDL event filtering due to
33    delay problems with lots of mouse motion events when mouse
34    button not pressed */
35
36 int FilterMouseMotionEvents(const Event *event)
37 {
38   if (event->type != EVENT_MOTIONNOTIFY)
39     return 1;
40
41   /* get mouse motion events without pressed button only in level editor */
42   if (button_status == MB_RELEASED && game_status != LEVELED)
43     return 0;
44   else
45     return 1;
46 }
47
48 /* this is only really needed for non-SDL targets to filter unwanted events;
49    when using SDL with properly installed event filter, this function can be
50    replaced with a simple "NextEvent()" call, but it doesn't hurt either */
51
52 static boolean NextValidEvent(Event *event)
53 {
54   while (PendingEvent())
55   {
56     NextEvent(event);
57
58     if (FilterMouseMotionEvents(event))
59       return TRUE;
60   }
61
62   return FALSE;
63 }
64
65 void EventLoop(void)
66 {
67   while(1)
68   {
69     if (PendingEvent())         /* got event */
70     {
71       Event event;
72
73       if (NextValidEvent(&event))
74       {
75         switch(event.type)
76         {
77           case EVENT_BUTTONPRESS:
78           case EVENT_BUTTONRELEASE:
79             HandleButtonEvent((ButtonEvent *) &event);
80             break;
81   
82           case EVENT_MOTIONNOTIFY:
83             HandleMotionEvent((MotionEvent *) &event);
84             break;
85   
86           case EVENT_KEYPRESS:
87           case EVENT_KEYRELEASE:
88             HandleKeyEvent((KeyEvent *) &event);
89             break;
90   
91           default:
92             HandleOtherEvents(&event);
93             break;
94         }
95       }
96     }
97     else
98       HandleNoEvent();
99
100     /* don't use all CPU time when idle; the main loop while playing
101        has its own synchronization and is CPU friendly, too */
102
103     if (game_status == PLAYING)
104       HandleGameActions();
105     else
106     {
107       SyncDisplay();
108       if (!PendingEvent())      /* delay only if no pending events */
109         Delay(10);
110     }
111
112     /* refresh window contents from drawing buffer, if needed */
113     BackToFront();
114
115     if (game_status == EXITGAME)
116       return;
117   }
118 }
119
120 void HandleOtherEvents(Event *event)
121 {
122   switch(event->type)
123   {
124     case EVENT_EXPOSE:
125       HandleExposeEvent((ExposeEvent *) event);
126       break;
127
128     case EVENT_UNMAPNOTIFY:
129 #if 0
130       SleepWhileUnmapped();
131 #endif
132       break;
133
134     case EVENT_FOCUSIN:
135     case EVENT_FOCUSOUT:
136       HandleFocusEvent((FocusChangeEvent *) event);
137       break;
138
139     case EVENT_CLIENTMESSAGE:
140       HandleClientMessageEvent((ClientMessageEvent *) event);
141       break;
142
143 #if defined(TARGET_SDL)
144     case SDL_JOYAXISMOTION:
145     case SDL_JOYBUTTONDOWN:
146     case SDL_JOYBUTTONUP:
147       HandleJoystickEvent(event);
148       break;
149 #endif
150
151     default:
152       break;
153   }
154 }
155
156 void ClearEventQueue()
157 {
158   while (PendingEvent())
159   {
160     Event event;
161
162     NextEvent(&event);
163
164     switch(event.type)
165     {
166       case EVENT_BUTTONRELEASE:
167         button_status = MB_RELEASED;
168         break;
169
170       case EVENT_KEYRELEASE:
171         key_joystick_mapping = 0;
172         break;
173
174       default:
175         HandleOtherEvents(&event);
176         break;
177     }
178   }
179 }
180
181 void ClearPlayerAction()
182 {
183   int i;
184
185   /* simulate key release events for still pressed keys */
186   key_joystick_mapping = 0;
187   for (i=0; i<MAX_PLAYERS; i++)
188     stored_player[i].action = 0;
189 }
190
191 void SleepWhileUnmapped()
192 {
193   boolean window_unmapped = TRUE;
194
195   KeyboardAutoRepeatOn();
196
197   while(window_unmapped)
198   {
199     Event event;
200
201     NextEvent(&event);
202
203     switch(event.type)
204     {
205       case EVENT_BUTTONRELEASE:
206         button_status = MB_RELEASED;
207         break;
208
209       case EVENT_KEYRELEASE:
210         key_joystick_mapping = 0;
211         break;
212
213       case EVENT_MAPNOTIFY:
214         window_unmapped = FALSE;
215         break;
216
217       case EVENT_UNMAPNOTIFY:
218         /* this is only to surely prevent the 'should not happen' case
219          * of recursively looping between 'SleepWhileUnmapped()' and
220          * 'HandleOtherEvents()' which usually calls this funtion.
221          */
222         break;
223
224       default:
225         HandleOtherEvents(&event);
226         break;
227     }
228   }
229
230   if (game_status == PLAYING)
231     KeyboardAutoRepeatOff();
232 }
233
234 void HandleExposeEvent(ExposeEvent *event)
235 {
236 #ifndef TARGET_SDL
237   RedrawPlayfield(FALSE, event->x, event->y, event->width, event->height);
238   FlushDisplay();
239 #endif
240 }
241
242 void HandleButtonEvent(ButtonEvent *event)
243 {
244   motion_status = FALSE;
245
246   if (event->type == EVENT_BUTTONPRESS)
247     button_status = event->button;
248   else
249     button_status = MB_RELEASED;
250
251   HandleButton(event->x, event->y, button_status);
252 }
253
254 void HandleMotionEvent(MotionEvent *event)
255 {
256   if (!PointerInWindow(window))
257     return;     /* window and pointer are on different screens */
258
259 #if 1
260   if (button_status == MB_RELEASED && game_status != LEVELED)
261     return;
262 #endif
263
264   motion_status = TRUE;
265
266   HandleButton(event->x, event->y, button_status);
267 }
268
269 void HandleKeyEvent(KeyEvent *event)
270 {
271   int key_status = (event->type==EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
272   boolean with_modifiers = (game_status == PLAYING ? FALSE : TRUE);
273   Key key = GetEventKey(event, with_modifiers);
274
275   HandleKey(key, key_status);
276 }
277
278 void HandleFocusEvent(FocusChangeEvent *event)
279 {
280   static int old_joystick_status = -1;
281
282   if (event->type == EVENT_FOCUSOUT)
283   {
284     KeyboardAutoRepeatOn();
285     old_joystick_status = joystick.status;
286     joystick.status = JOYSTICK_NOT_AVAILABLE;
287
288     ClearPlayerAction();
289   }
290   else if (event->type == EVENT_FOCUSIN)
291   {
292     /* When there are two Rocks'n'Diamonds windows which overlap and
293        the player moves the pointer from one game window to the other,
294        a 'FocusOut' event is generated for the window the pointer is
295        leaving and a 'FocusIn' event is generated for the window the
296        pointer is entering. In some cases, it can happen that the
297        'FocusIn' event is handled by the one game process before the
298        'FocusOut' event by the other game process. In this case the
299        X11 environment would end up with activated keyboard auto repeat,
300        because unfortunately this is a global setting and not (which
301        would be far better) set for each X11 window individually.
302        The effect would be keyboard auto repeat while playing the game
303        (game_status == PLAYING), which is not desired.
304        To avoid this special case, we just wait 1/10 second before
305        processing the 'FocusIn' event.
306     */
307
308     if (game_status == PLAYING)
309     {
310       Delay(100);
311       KeyboardAutoRepeatOff();
312     }
313     if (old_joystick_status != -1)
314       joystick.status = old_joystick_status;
315   }
316 }
317
318 void HandleClientMessageEvent(ClientMessageEvent *event)
319 {
320   if (CheckCloseWindowEvent(event))
321     CloseAllAndExit(0);
322 }
323
324 void HandleButton(int mx, int my, int button)
325 {
326   static int old_mx = 0, old_my = 0;
327
328   if (button < 0)
329   {
330     mx = old_mx;
331     my = old_my;
332     button = -button;
333   }
334   else
335   {
336     old_mx = mx;
337     old_my = my;
338   }
339
340   HandleGadgets(mx, my, button);
341
342   switch(game_status)
343   {
344     case MAINMENU:
345       HandleMainMenu(mx,my, 0,0, button);
346       break;
347
348     case TYPENAME:
349       HandleTypeName(0, KSYM_Return);
350       break;
351
352     case CHOOSELEVEL:
353       HandleChooseLevel(mx,my, 0,0, button);
354       break;
355
356     case HALLOFFAME:
357       HandleHallOfFame(0,0, 0,0, button);
358       break;
359
360     case LEVELED:
361       break;
362
363     case HELPSCREEN:
364       HandleHelpScreen(button);
365       break;
366
367     case SETUP:
368       HandleSetupScreen(mx,my, 0,0, button);
369       break;
370
371     case PLAYING:
372 #ifdef DEBUG
373       if (button == MB_RELEASED)
374       {
375         int sx = (mx - SX) / TILEX;
376         int sy = (my - SY) / TILEY;
377
378         if (IN_VIS_FIELD(sx,sy))
379         {
380           int x = LEVELX(sx);
381           int y = LEVELY(sy);
382
383           printf("INFO: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
384
385           if (!IN_LEV_FIELD(x, y))
386             break;
387
388           printf("      Feld[%d][%d] == %d\n", x,y, Feld[x][y]);
389           printf("      Store[%d][%d] == %d\n", x,y, Store[x][y]);
390           printf("      Store2[%d][%d] == %d\n", x,y, Store2[x][y]);
391           printf("      StorePlayer[%d][%d] == %d\n", x,y, StorePlayer[x][y]);
392           printf("      MovPos[%d][%d] == %d\n", x,y, MovPos[x][y]);
393           printf("      MovDir[%d][%d] == %d\n", x,y, MovDir[x][y]);
394           printf("      MovDelay[%d][%d] == %d\n", x,y, MovDelay[x][y]);
395           printf("\n");
396         }
397       }
398 #endif
399       break;
400
401     default:
402       break;
403   }
404 }
405
406 void HandleKey(Key key, int key_status)
407 {
408   int joy = 0;
409   boolean anyTextGadgetActiveOrJustFinished = anyTextGadgetActive();
410   static struct SetupKeyboardInfo custom_key;
411   static struct
412   {
413     Key *key_custom;
414     Key key_default;
415     byte action;
416   } key_info[] =
417   {
418     { &custom_key.left,  DEFAULT_KEY_LEFT,  JOY_LEFT     },
419     { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT    },
420     { &custom_key.up,    DEFAULT_KEY_UP,    JOY_UP       },
421     { &custom_key.down,  DEFAULT_KEY_DOWN,  JOY_DOWN     },
422     { &custom_key.snap,  DEFAULT_KEY_SNAP,  JOY_BUTTON_1 },
423     { &custom_key.bomb,  DEFAULT_KEY_BOMB,  JOY_BUTTON_2 }
424   };
425
426   if (game_status == PLAYING)
427   {
428     /* only needed for single-step tape recording mode */
429     static boolean clear_button_2[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
430     static boolean bomb_placed[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
431     int pnr;
432
433     for (pnr=0; pnr<MAX_PLAYERS; pnr++)
434     {
435       int i;
436       byte key_action = 0;
437
438       if (setup.input[pnr].use_joystick)
439         continue;
440
441       custom_key = setup.input[pnr].key;
442
443       for (i=0; i<6; i++)
444         if (key == *key_info[i].key_custom)
445           key_action |= key_info[i].action;
446
447       if (tape.single_step && clear_button_2[pnr])
448       {
449         stored_player[pnr].action &= ~KEY_BUTTON_2;
450         clear_button_2[pnr] = FALSE;
451       }
452
453       if (key_status == KEY_PRESSED)
454         stored_player[pnr].action |= key_action;
455       else
456         stored_player[pnr].action &= ~key_action;
457
458       if (tape.single_step && tape.recording && tape.pausing)
459       {
460         if (key_status == KEY_PRESSED &&
461             (key_action & (KEY_MOTION | KEY_BUTTON_1)))
462         {
463           TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
464
465           if (key_action & KEY_MOTION)
466           {
467             if (stored_player[pnr].action & KEY_BUTTON_2)
468               bomb_placed[pnr] = TRUE;
469           }
470         }
471         else if (key_status == KEY_RELEASED &&
472                  (key_action & KEY_BUTTON_2))
473         {
474           if (!bomb_placed[pnr])
475           {
476             TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
477
478             stored_player[pnr].action |= KEY_BUTTON_2;
479             clear_button_2[pnr] = TRUE;
480           }
481
482           bomb_placed[pnr] = FALSE;
483         }
484       }
485       else if (tape.recording && tape.pausing && (key_action & KEY_ACTION))
486         TapeTogglePause(TAPE_TOGGLE_MANUAL);
487     }
488   }
489   else
490   {
491     int i;
492
493     for (i=0; i<6; i++)
494       if (key == key_info[i].key_default)
495         joy |= key_info[i].action;
496   }
497
498   if (joy)
499   {
500     if (key_status == KEY_PRESSED)
501       key_joystick_mapping |= joy;
502     else
503       key_joystick_mapping &= ~joy;
504
505     HandleJoystick();
506   }
507
508   if (game_status != PLAYING)
509     key_joystick_mapping = 0;
510
511   if (key_status == KEY_RELEASED)
512     return;
513
514   if ((key == KSYM_Return || key == setup.shortcut.toggle_pause) &&
515       game_status == PLAYING && AllPlayersGone)
516   {
517     CloseDoor(DOOR_CLOSE_1);
518     game_status = MAINMENU;
519     DrawMainMenu();
520     return;
521   }
522
523   /* allow quick escape to the main menu with the Escape key */
524   if (key == KSYM_Escape &&
525       game_status != MAINMENU &&
526       game_status != PLAYING &&
527       game_status != LEVELED &&
528       game_status != CHOOSELEVEL &&
529       game_status != SETUP)
530   {
531     game_status = MAINMENU;
532     DrawMainMenu();
533     return;
534   }
535
536   /* special key shortcuts */
537   if (game_status == MAINMENU || game_status == PLAYING)
538   {
539     if (key == setup.shortcut.save_game)
540       TapeQuickSave();
541     else if (key == setup.shortcut.load_game)
542       TapeQuickLoad();
543     else if (key == setup.shortcut.toggle_pause)
544       TapeTogglePause(TAPE_TOGGLE_MANUAL);
545   }
546
547
548 #ifndef DEBUG
549
550   if (game_status == PLAYING && (tape.playing || tape.pausing))
551     return;
552
553 #endif
554
555
556
557   HandleGadgetsKeyInput(key);
558
559   switch(game_status)
560   {
561     case TYPENAME:
562       HandleTypeName(0, key);
563       break;
564
565     case MAINMENU:
566     case CHOOSELEVEL:
567     case SETUP:
568       switch(key)
569       {
570         case KSYM_Return:
571           if (game_status == MAINMENU)
572             HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
573           else if (game_status == CHOOSELEVEL)
574             HandleChooseLevel(0,0, 0,0, MB_MENU_CHOICE);
575           else if (game_status == SETUP)
576             HandleSetupScreen(0,0, 0,0, MB_MENU_CHOICE);
577           break;
578
579         case KSYM_Escape:
580           if (game_status == CHOOSELEVEL)
581             HandleChooseLevel(0,0, 0,0, MB_MENU_LEAVE);
582           else if (game_status == SETUP)
583             HandleSetupScreen(0,0, 0,0, MB_MENU_LEAVE);
584           break;
585
586         case KSYM_Page_Up:
587           if (game_status == CHOOSELEVEL)
588             HandleChooseLevel(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
589           else if (game_status == SETUP)
590             HandleSetupScreen(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
591           break;
592
593         case KSYM_Page_Down:
594           if (game_status == CHOOSELEVEL)
595             HandleChooseLevel(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
596           else if (game_status == SETUP)
597             HandleSetupScreen(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
598           break;
599
600 #ifdef DEBUG
601         case KSYM_t:
602           DumpTape(&tape);
603           break;
604 #endif
605
606         default:
607           break;
608       }
609       break;
610
611     case HELPSCREEN:
612       HandleHelpScreen(MB_RELEASED);
613       break;
614
615     case HALLOFFAME:
616       switch(key)
617       {
618         case KSYM_Return:
619           game_status = MAINMENU;
620           DrawMainMenu();
621           BackToFront();
622           break;
623
624         case KSYM_Page_Up:
625           HandleHallOfFame(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
626           break;
627
628         case KSYM_Page_Down:
629           HandleHallOfFame(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
630           break;
631
632         default:
633           break;
634       }
635       break;
636
637     case LEVELED:
638       if (!anyTextGadgetActiveOrJustFinished || key == KSYM_Escape)
639         HandleLevelEditorKeyInput(key);
640       break;
641
642     case PLAYING:
643     {
644       switch(key)
645       {
646         case KSYM_Escape:
647           RequestQuitGame(setup.ask_on_escape);
648           break;
649
650 #ifdef DEBUG
651         case KSYM_0:
652         case KSYM_1:
653         case KSYM_2:
654         case KSYM_3:
655         case KSYM_4:
656         case KSYM_5:
657         case KSYM_6:
658         case KSYM_7:
659         case KSYM_8:
660         case KSYM_9:
661           if (key == KSYM_0)
662           {
663             if (GameFrameDelay == 500)
664               GameFrameDelay = GAME_FRAME_DELAY;
665             else
666               GameFrameDelay = 500;
667           }
668           else
669             GameFrameDelay = (key - KSYM_0) * 10;
670           printf("Game speed == %d%% (%d ms delay between two frames)\n",
671                  GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
672           break;
673
674         case KSYM_d:
675           if (options.debug)
676           {
677             options.debug = FALSE;
678             printf("debug mode disabled\n");
679           }
680           else
681           {
682             options.debug = TRUE;
683             printf("debug mode enabled\n");
684           }
685           break;
686
687         case KSYM_s:
688           if (!global.fps_slowdown)
689           {
690             global.fps_slowdown = TRUE;
691             global.fps_slowdown_factor = 2;
692             printf("fps slowdown enabled -- display only every 2nd frame\n");
693           }
694           else if (global.fps_slowdown_factor == 2)
695           {
696             global.fps_slowdown_factor = 4;
697             printf("fps slowdown enabled -- display only every 4th frame\n");
698           }
699           else
700           {
701             global.fps_slowdown = FALSE;
702             global.fps_slowdown_factor = 1;
703             printf("fps slowdown disabled\n");
704           }
705           break;
706
707 #if 0
708         case KSYM_a:
709           if (ScrollStepSize == TILEX/8)
710             ScrollStepSize = TILEX/4;
711           else
712             ScrollStepSize = TILEX/8;
713           printf("ScrollStepSize == %d\n", ScrollStepSize);
714           break;
715 #endif
716
717 #if 0
718         case KSYM_m:
719           if (MoveSpeed == 8)
720           {
721             MoveSpeed = 4;
722             ScrollStepSize = TILEX/4;
723           }
724           else
725           {
726             MoveSpeed = 8;
727             ScrollStepSize = TILEX/8;
728           }
729           printf("MoveSpeed == %d\n", MoveSpeed);
730           break;
731 #endif
732
733         case KSYM_f:
734           ScrollStepSize = TILEX/8;
735           printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
736           break;
737
738         case KSYM_g:
739           ScrollStepSize = TILEX/4;
740           printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
741           break;
742
743         case KSYM_h:
744           ScrollStepSize = TILEX/2;
745           printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
746           break;
747
748         case KSYM_l:
749           ScrollStepSize = TILEX;
750           printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
751           break;
752
753         case KSYM_Q:
754         case KSYM_q:
755           local_player->dynamite = 1000;
756           break;
757
758
759
760 #if 0
761
762         case KSYM_z:
763           {
764             int i;
765
766             for(i=0; i<MAX_PLAYERS; i++)
767             {
768               printf("Player %d:\n", i);
769               printf("  jx == %d, jy == %d\n",
770                      stored_player[i].jx, stored_player[i].jy);
771               printf("  last_jx == %d, last_jy == %d\n",
772                      stored_player[i].last_jx, stored_player[i].last_jy);
773             }
774             printf("\n");
775           }
776
777           break;
778 #endif
779 #endif
780
781         default:
782           break;
783       }
784       break;
785     }
786     default:
787       break;
788   }
789 }
790
791 void HandleNoEvent()
792 {
793   if (button_status && game_status != PLAYING)
794   {
795     HandleButton(0, 0, -button_status);
796     return;
797   }
798
799 #if defined(PLATFORM_UNIX)
800   if (options.network)
801     HandleNetworking();
802 #endif
803
804   HandleJoystick();
805 }
806
807 static int HandleJoystickForAllPlayers()
808 {
809   int i;
810   int result = 0;
811
812   for (i=0; i<MAX_PLAYERS; i++)
813   {
814     byte joy_action = 0;
815
816     /*
817     if (!setup.input[i].use_joystick)
818       continue;
819       */
820
821     joy_action = Joystick(i);
822     result |= joy_action;
823
824     if (!setup.input[i].use_joystick)
825       continue;
826
827     stored_player[i].action = joy_action;
828   }
829
830   return result;
831 }
832
833 void HandleJoystick()
834 {
835   int joystick  = HandleJoystickForAllPlayers();
836   int keyboard  = key_joystick_mapping;
837   int joy       = (joystick | keyboard);
838   int left      = joy & JOY_LEFT;
839   int right     = joy & JOY_RIGHT;
840   int up        = joy & JOY_UP;
841   int down      = joy & JOY_DOWN;
842   int button    = joy & JOY_BUTTON;
843   int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
844   int dx        = (left ? -1    : right ? 1     : 0);
845   int dy        = (up   ? -1    : down  ? 1     : 0);
846
847   switch(game_status)
848   {
849     case MAINMENU:
850     case CHOOSELEVEL:
851     case SETUP:
852     {
853       static unsigned long joystickmove_delay = 0;
854
855       if (joystick && !button &&
856           !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
857         newbutton = dx = dy = 0;
858
859       if (game_status == MAINMENU)
860         HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
861       else if (game_status == CHOOSELEVEL)
862         HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
863       else if (game_status == SETUP)
864         HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
865       break;
866     }
867
868     case HALLOFFAME:
869       HandleHallOfFame(0,0, dx,dy, !newbutton);
870       break;
871
872     case HELPSCREEN:
873       HandleHelpScreen(!newbutton);
874       break;
875
876     case LEVELED:
877       HandleLevelEditorIdle();
878       break;
879
880     case PLAYING:
881       if (tape.playing || keyboard)
882         newbutton = ((joy & JOY_BUTTON) != 0);
883
884       if (AllPlayersGone && newbutton)
885       {
886         CloseDoor(DOOR_CLOSE_1);
887         game_status = MAINMENU;
888         DrawMainMenu();
889         return;
890       }
891
892       break;
893
894     default:
895       break;
896   }
897 }