rnd-19981105-1
[rocksndiamonds.git] / src / events.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  (c) 1995-98 Artsoft Entertainment                       *
5 *              Holger Schemel                              *
6 *              Oststrasse 11a                              *
7 *              33604 Bielefeld                             *
8 *              phone: ++49 +521 290471                     *
9 *              email: aeglos@valinor.owl.de                *
10 *----------------------------------------------------------*
11 *  events.c                                                *
12 ***********************************************************/
13
14 #include "events.h"
15 #include "init.h"
16 #include "screens.h"
17 #include "tools.h"
18 #include "game.h"
19 #include "editor.h"
20 #include "misc.h"
21 #include "tape.h"
22 #include "joystick.h"
23 #include "network.h"
24
25 void EventLoop(void)
26 {
27   while(1)
28   {
29     if (XPending(display))      /* got event from X server */
30     {
31       XEvent event;
32
33       XNextEvent(display, &event);
34
35       switch(event.type)
36       {
37         case ButtonPress:
38         case ButtonRelease:
39           HandleButtonEvent((XButtonEvent *) &event);
40           break;
41
42         case MotionNotify:
43           HandleMotionEvent((XMotionEvent *) &event);
44           break;
45
46         case KeyPress:
47         case KeyRelease:
48           HandleKeyEvent((XKeyEvent *) &event);
49           break;
50
51         default:
52           HandleOtherEvents(&event);
53           break;
54       }
55     }
56
57     HandleNoXEvent();
58
59     /* don't use all CPU time when idle; the main loop while playing
60        has its own synchronization and is CPU friendly, too */
61
62     if (game_status != PLAYING)
63     {
64       XSync(display, FALSE);
65       Delay(10);
66     }
67
68
69
70 #if 0
71     else                        /* got no event, but don't be lazy... */
72     {
73       HandleNoXEvent();
74
75       /* don't use all CPU time when idle; the main loop while playing
76          has its own synchronization and is CPU friendly, too */
77
78       if (game_status != PLAYING)
79       {
80         XSync(display, FALSE);
81         Delay(10);
82       }
83     }
84 #endif
85
86
87
88     if (game_status == EXITGAME)
89       return;
90   }
91 }
92
93 void HandleOtherEvents(XEvent *event)
94 {
95   switch(event->type)
96   {
97     case Expose:
98       HandleExposeEvent((XExposeEvent *) event);
99       break;
100
101     case UnmapNotify:
102       SleepWhileUnmapped();
103       break;
104
105     case FocusIn:
106     case FocusOut:
107       HandleFocusEvent((XFocusChangeEvent *) event);
108       break;
109
110     case ClientMessage:
111       HandleClientMessageEvent((XClientMessageEvent *) event);
112       break;
113
114     default:
115       break;
116   }
117 }
118
119 void ClearEventQueue()
120 {
121   while(XPending(display))
122   {
123     XEvent event;
124
125     XNextEvent(display, &event);
126
127     switch(event.type)
128     {
129       case ButtonRelease:
130         button_status = MB_RELEASED;
131         break;
132
133       case KeyRelease:
134         key_joystick_mapping = 0;
135         break;
136
137       default:
138         HandleOtherEvents(&event);
139         break;
140     }
141   }
142 }
143
144 void SleepWhileUnmapped()
145 {
146   boolean window_unmapped = TRUE;
147
148   XAutoRepeatOn(display);
149
150   while(window_unmapped)
151   {
152     XEvent event;
153
154     XNextEvent(display, &event);
155
156     switch(event.type)
157     {
158       case ButtonRelease:
159         button_status = MB_RELEASED;
160         break;
161
162       case KeyRelease:
163         key_joystick_mapping = 0;
164         break;
165
166       case MapNotify:
167         window_unmapped = FALSE;
168         break;
169
170       case UnmapNotify:
171         /* this is only to surely prevent the 'should not happen' case
172          * of recursively looping between 'SleepWhileUnmapped()' and
173          * 'HandleOtherEvents()' which usually calls this funtion.
174          */
175         break;
176
177       default:
178         HandleOtherEvents(&event);
179         break;
180     }
181   }
182
183   if (game_status==PLAYING)
184     XAutoRepeatOff(display);
185 }
186
187 void HandleExposeEvent(XExposeEvent *event)
188 {
189   int x = event->x, y = event->y;
190   int width = event->width, height = event->height;
191
192   if (setup.direct_draw && game_status==PLAYING)
193   {
194     int xx,yy;
195     int x1 = (x-SX)/TILEX, y1 = (y-SY)/TILEY;
196     int x2 = (x-SX+width)/TILEX, y2 = (y-SY+height)/TILEY;
197
198     SetDrawtoField(DRAW_BACKBUFFER);
199
200     for(xx=0; xx<SCR_FIELDX; xx++)
201       for(yy=0; yy<SCR_FIELDY; yy++)
202         if (xx>=x1 && xx<=x2 && yy>=y1 && yy<=y2)
203           DrawScreenField(xx,yy);
204     DrawAllPlayers();
205
206     SetDrawtoField(DRAW_DIRECT);
207   }
208
209   if (setup.soft_scrolling && game_status == PLAYING)
210   {
211     int fx = FX, fy = FY;
212
213     fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
214     fy += (ScreenMovDir & (MV_UP|MV_DOWN)    ? ScreenGfxPos : 0);
215
216     XCopyArea(display,fieldbuffer,backbuffer,gc,
217               fx,fy, SXSIZE,SYSIZE,
218               SX,SY);
219   }
220
221   XCopyArea(display,drawto,window,gc, x,y, width,height, x,y);
222
223   XFlush(display);
224 }
225
226 void HandleButtonEvent(XButtonEvent *event)
227 {
228   motion_status = FALSE;
229
230   if (event->type==ButtonPress)
231     button_status = event->button;
232   else
233     button_status = MB_RELEASED;
234
235   HandleButton(event->x, event->y, button_status);
236 }
237
238 void HandleMotionEvent(XMotionEvent *event)
239 {
240   motion_status = TRUE;
241
242   HandleButton(event->x, event->y, button_status);
243 }
244
245 void HandleKeyEvent(XKeyEvent *event)
246 {
247   int key_status = (event->type == KeyPress ? KEY_PRESSED : KEY_RELEASED);
248   unsigned int event_state = (game_status != PLAYING ? event->state : 0);
249   KeySym key = XLookupKeysym(event, event_state);
250
251   HandleKey(key, key_status);
252 }
253
254 void HandleFocusEvent(XFocusChangeEvent *event)
255 {
256   static int old_joystick_status = -1;
257
258   if (event->type == FocusOut)
259   {
260     XAutoRepeatOn(display);
261     old_joystick_status = joystick_status;
262     joystick_status = JOYSTICK_OFF;
263     key_joystick_mapping = 0;
264   }
265   else if (event->type == FocusIn)
266   {
267     if (game_status == PLAYING)
268       XAutoRepeatOff(display);
269     if (old_joystick_status != -1)
270       joystick_status = old_joystick_status;
271   }
272 }
273
274 void HandleClientMessageEvent(XClientMessageEvent *event)
275 {
276   if ((event->window == window) &&
277       (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
278     CloseAllAndExit(0);
279 }
280
281 void HandleButton(int mx, int my, int button)
282 {
283   static int old_mx = 0, old_my = 0;
284
285   if (mx<0 || my<0)
286   {
287     mx = old_mx;
288     my = old_my;
289   }
290   else
291   {
292     old_mx = mx;
293     old_my = my;
294
295     HandleVideoButtons(mx,my,button);
296     HandleSoundButtons(mx,my,button);
297     HandleGameButtons(mx,my,button);
298   }
299
300 #ifdef DEBUG
301   if (game_status == PLAYING && !button)
302   {
303     int sx = (mx - SX) / TILEX;
304     int sy = (my - SY) / TILEY;
305
306     if (IN_VIS_FIELD(sx,sy))
307     {
308       int x = LEVELX(sx);
309       int y = LEVELY(sy);
310
311       printf("INFO: Feld[%d][%d] == %d\n", x,y, Feld[x][y]);
312       printf("      Store[%d][%d] == %d\n", x,y, Store[x][y]);
313       printf("      Store2[%d][%d] == %d\n", x,y, Store2[x][y]);
314       printf("      StorePlayer[%d][%d] == %d\n", x,y, StorePlayer[x][y]);
315       printf("      MovPos[%d][%d] == %d\n", x,y, MovPos[x][y]);
316       printf("      MovDir[%d][%d] == %d\n", x,y, MovDir[x][y]);
317       printf("      MovDelay[%d][%d] == %d\n", x,y, MovDelay[x][y]);
318       printf("\n");
319     }
320   }
321 #endif
322
323   switch(game_status)
324   {
325     case MAINMENU:
326       HandleMainMenu(mx,my,0,0,button);
327       break;
328
329     case TYPENAME:
330       HandleTypeName(0,XK_Return);
331       break;
332
333     case CHOOSELEVEL:
334       HandleChooseLevel(mx,my,0,0,button);
335       break;
336
337     case HALLOFFAME:
338       HandleHallOfFame(button);
339       break;
340
341     case LEVELED:
342       LevelEd(mx,my,button);
343       break;
344
345     case HELPSCREEN:
346       HandleHelpScreen(button);
347       break;
348
349     case SETUP:
350       HandleSetupScreen(mx,my,0,0,button);
351       break;
352
353     case SETUPINPUT:
354       HandleSetupInputScreen(mx,my,0,0,button);
355       break;
356
357     case PLAYING:
358
359       /* --> NoXEvent() will follow */
360
361       /*
362       HandleGameActions(0);
363       */
364
365       break;
366
367     default:
368       break;
369   }
370 }
371
372 void HandleKey(KeySym key, int key_status)
373 {
374   int joy = 0;
375   static struct SetupKeyboardInfo custom_key;
376   static struct
377   {
378     KeySym *keysym_custom;
379     KeySym keysym_default;
380     byte action;
381   } key_info[] =
382   {
383     { &custom_key.left,  DEFAULT_KEY_LEFT,  JOY_LEFT     },
384     { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT    },
385     { &custom_key.up,    DEFAULT_KEY_UP,    JOY_UP       },
386     { &custom_key.down,  DEFAULT_KEY_DOWN,  JOY_DOWN     },
387     { &custom_key.snap,  DEFAULT_KEY_SNAP,  JOY_BUTTON_1 },
388     { &custom_key.bomb,  DEFAULT_KEY_BOMB,  JOY_BUTTON_2 }
389   };
390
391   if (game_status == PLAYING)
392   {
393     int pnr;
394
395     for (pnr=0; pnr<MAX_PLAYERS; pnr++)
396     {
397       int i;
398       byte key_action = 0;
399
400       if (setup.input[pnr].use_joystick)
401         continue;
402
403       custom_key = setup.input[pnr].key;
404
405       for (i=0; i<6; i++)
406         if (key == *key_info[i].keysym_custom)
407           key_action |= key_info[i].action;
408
409       if (key_status == KEY_PRESSED)
410         stored_player[pnr].action |= key_action;
411       else
412         stored_player[pnr].action &= ~key_action;
413     }
414   }
415   else
416   {
417     int i;
418
419     for (i=0; i<6; i++)
420       if (key == key_info[i].keysym_default)
421         joy |= key_info[i].action;
422   }
423
424
425 #if 0
426
427
428   /* Map cursor keys to joystick directions */
429
430   switch(key)
431   {
432     case XK_Left:               /* normale Richtungen */
433 #ifdef XK_KP_Left
434     case XK_KP_Left:
435 #endif
436     case XK_KP_4:
437 #ifndef MSDOS
438     case XK_J:
439 #endif
440     case XK_j:
441       joy |= JOY_LEFT;
442       break;
443
444     case XK_Right:
445 #ifdef XK_KP_Right
446     case XK_KP_Right:
447 #endif
448     case XK_KP_6:
449 #ifndef MSDOS
450     case XK_K:
451 #endif
452     case XK_k:
453       joy |= JOY_RIGHT;
454       break;
455
456     case XK_Up:
457 #ifdef XK_KP_Up
458     case XK_KP_Up:
459 #endif
460     case XK_KP_8:
461 #ifndef MSDOS
462     case XK_I:
463 #endif
464     case XK_i:
465       joy |= JOY_UP;
466       break;
467
468     case XK_Down:
469 #ifdef XK_KP_Down
470     case XK_KP_Down:
471 #endif
472     case XK_KP_2:
473 #ifndef MSDOS
474     case XK_M:
475 #endif
476     case XK_m:
477       joy |= JOY_DOWN;
478       break;
479
480 #ifdef XK_KP_Home
481     case XK_KP_Home:            /* Diagonalrichtungen */
482 #endif
483     case XK_KP_7:
484       joy |= JOY_UP | JOY_LEFT;
485       break;
486
487 #ifdef XK_KP_Page_Up
488     case XK_KP_Page_Up:
489 #endif
490     case XK_KP_9:
491       joy = JOY_UP | JOY_RIGHT;
492       break;
493
494 #ifdef XK_KP_End
495     case XK_KP_End:
496 #endif
497     case XK_KP_1:
498       joy |= JOY_DOWN | JOY_LEFT;
499       break;
500
501 #ifdef XK_KP_Page_Down
502     case XK_KP_Page_Down:
503 #endif
504     case XK_KP_3:
505       joy |= JOY_DOWN | JOY_RIGHT;
506       break;
507
508 #ifndef MSDOS
509     case XK_S:                  /* Feld entfernen */
510 #endif
511     case XK_s:
512       joy |= JOY_BUTTON_1 | JOY_LEFT;
513       break;
514
515 #ifndef MSDOS
516     case XK_D:
517 #endif
518     case XK_d:
519       joy |= JOY_BUTTON_1 | JOY_RIGHT;
520       break;
521
522 #ifndef MSDOS
523     case XK_E:
524 #endif
525     case XK_e:
526       joy |= JOY_BUTTON_1 | JOY_UP;
527       break;
528
529 #ifndef MSDOS
530     case XK_X:
531 #endif
532     case XK_x:
533       joy |= JOY_BUTTON_1 | JOY_DOWN;
534       break;
535
536     case XK_Shift_L:            /* Linker Feuerknopf */
537 #ifndef MSDOS
538     case XK_Control_L:
539     case XK_Alt_L:
540     case XK_Meta_L:
541 #endif
542       joy |= JOY_BUTTON_1;
543       break;
544
545     case XK_Shift_R:            /* Rechter Feuerknopf */
546 #ifndef MSDOS
547     case XK_Control_R:
548     case XK_Alt_R:
549     case XK_Meta_R:
550     case XK_Mode_switch:
551     case XK_Multi_key:
552     case XK_B:                  /* (Bombe legen) */
553 #endif
554     case XK_b:
555       joy |= JOY_BUTTON_2;
556       break;
557
558     default:
559       break;
560   }
561
562
563 #endif
564
565
566   if (joy)
567   {
568     if (key_status == KEY_PRESSED)
569       key_joystick_mapping |= joy;
570     else
571       key_joystick_mapping &= ~joy;
572
573     HandleJoystick();
574   }
575
576   if (game_status != PLAYING)
577     key_joystick_mapping = 0;
578
579   if (key_status == KEY_RELEASED)
580     return;
581
582   if (key==XK_Return && game_status==PLAYING && AllPlayersGone)
583   {
584     CloseDoor(DOOR_CLOSE_1);
585     game_status = MAINMENU;
586     DrawMainMenu();
587     return;
588   }
589
590   if (key==XK_Escape && game_status!=MAINMENU)  /* quick quit to MAINMENU */
591   {
592     CloseDoor(DOOR_CLOSE_1 | DOOR_NO_DELAY);
593     game_status = MAINMENU;
594     DrawMainMenu();
595     return;
596   }
597
598   if (game_status==PLAYING && (tape.playing || tape.pausing))
599     return;
600
601   switch(game_status)
602   {
603     case TYPENAME:
604       HandleTypeName(0,key);
605       break;
606
607     case MAINMENU:
608     case CHOOSELEVEL:
609     case SETUP:
610     case SETUPINPUT:
611       switch(key)
612       {
613         case XK_Return:
614           if (game_status==MAINMENU)
615             HandleMainMenu(0,0,0,0,MB_MENU_CHOICE);
616           else if (game_status==CHOOSELEVEL)
617             HandleChooseLevel(0,0,0,0,MB_MENU_CHOICE);
618           else if (game_status==SETUP)
619             HandleSetupScreen(0,0,0,0,MB_MENU_CHOICE);
620           else if (game_status==SETUPINPUT)
621             HandleSetupInputScreen(0,0,0,0,MB_MENU_CHOICE);
622           break;
623
624         default:
625           break;
626       }
627       break;
628
629     case HELPSCREEN:
630       HandleHelpScreen(MB_RELEASED);
631       break;
632
633     case HALLOFFAME:
634       switch(key)
635       {
636         case XK_Return:
637           game_status = MAINMENU;
638           DrawMainMenu();
639           BackToFront();
640           break;
641
642         default:
643           break;
644       }
645       break;
646
647     case LEVELED:
648       LevelNameTyping(key);
649       break;
650
651     case PLAYING:
652     {
653       switch(key)
654       {
655
656 #ifdef DEBUG
657         case XK_0:
658         case XK_1:
659         case XK_2:
660         case XK_3:
661         case XK_4:
662         case XK_5:
663         case XK_6:
664         case XK_7:
665         case XK_8:
666         case XK_9:
667           if (key == XK_0)
668             GameFrameDelay = 500;
669           else
670             GameFrameDelay = (key - XK_0) * 10;
671           printf("Game speed == %d%% (%d ms delay between two frames)\n",
672                  GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
673           break;
674
675
676 #if 0
677         case XK_a:
678           if (ScrollStepSize == TILEX/8)
679             ScrollStepSize = TILEX/4;
680           else
681             ScrollStepSize = TILEX/8;
682           printf("ScrollStepSize == %d\n", ScrollStepSize);
683           break;
684 #endif
685
686         case XK_f:
687           ScrollStepSize = TILEX/8;
688           printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
689           break;
690
691         case XK_g:
692           ScrollStepSize = TILEX/4;
693           printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
694           break;
695
696         case XK_h:
697           ScrollStepSize = TILEX/2;
698           printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
699           break;
700
701         case XK_l:
702           ScrollStepSize = TILEX;
703           printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
704           break;
705
706 #ifndef MSDOS
707         case XK_Q:
708 #endif
709         case XK_q:
710           local_player->dynamite = 1000;
711           break;
712
713
714
715 #if 0
716
717         case XK_x:
718
719           {
720             int i,j,k, num_steps = 8, step_size = TILEX / num_steps;
721             static long scroll_delay=0;
722             long scroll_delay_value = 4*4 / num_steps;
723
724             printf("Scroll test\n");
725
726             for(i=0;i<3;i++)
727             {
728               for(j=0;j<SCR_FIELDX;j++)
729               {
730                 for(k=0;k<num_steps;k++)
731                 {
732                   int xxx = j*TILEX+k*step_size;
733                   int done = 0;
734
735                   while(!done)
736                   {
737                     if (DelayReached(&scroll_delay, scroll_delay_value))
738                     {
739                       XCopyArea(display,fieldbuffer,window,gc,
740                                 SX+xxx,SY,
741                                 SXSIZE-xxx,SYSIZE,
742                                 SX,SY);
743                       XCopyArea(display,fieldbuffer,window,gc,
744                                 SX,SY,
745                                 xxx,SYSIZE,
746                                 SX+SXSIZE-xxx,SY);
747   
748                       XFlush(display);
749                       XSync(display,FALSE);
750
751                       done = 1;
752                     }
753                     else
754                     {
755                       Delay(1);
756                     }
757                   }
758   
759                   /*
760                   Delay(160 / num_steps);
761                   */
762                   /*
763                   Delay(120 / num_steps);
764                   */
765                 }
766               }
767             }
768           }
769
770           break;
771
772         case XK_y:
773           /*
774           {
775             printf("FX = %d, FY = %d\n", FX,FY);
776
777             XCopyArea(display,fieldbuffer,window,gc,
778                       0,0,
779                       MIN(WIN_XSIZE,FXSIZE),MIN(WIN_YSIZE,FYSIZE),
780                       0,0);
781             XFlush(display);
782             XSync(display,FALSE);
783             Delay(1000);
784           }
785           */
786
787           printf("direct_draw == %d\n", setup.direct_draw);
788
789           break;
790
791         case XK_z:
792           {
793             int i;
794
795             for(i=0; i<MAX_PLAYERS; i++)
796             {
797               printf("Player %d:\n", i);
798               printf("  jx == %d, jy == %d\n",
799                      stored_player[i].jx, stored_player[i].jy);
800               printf("  last_jx == %d, last_jy == %d\n",
801                      stored_player[i].last_jx, stored_player[i].last_jy);
802             }
803             printf("\n");
804           }
805
806           break;
807
808         case XK_t:
809           {
810             char *color[] = { "yellow", "red", "green", "blue" };
811
812             do
813               TestPlayer = (TestPlayer + 1) % MAX_PLAYERS;
814             while(!stored_player[TestPlayer].active);
815
816             printf("TestPlayer = %d (%s player)\n",
817                    TestPlayer, color[TestPlayer]);
818           }
819
820           break;
821 #endif
822 #endif
823
824         default:
825           break;
826       }
827       break;
828     }
829     default:
830       break;
831   }
832 }
833
834 void HandleNoXEvent()
835 {
836   if (button_status && game_status != PLAYING)
837   {
838     HandleButton(-1,-1,button_status);
839     return;
840   }
841
842   if (options.network)
843     HandleNetworking();
844
845   switch(game_status)
846   {
847     case MAINMENU:
848     case CHOOSELEVEL:
849     case HALLOFFAME:
850     case HELPSCREEN:
851     case SETUP:
852     case SETUPINPUT:
853       HandleJoystick();
854       break;
855
856     case PLAYING:
857       HandleJoystick();
858
859       /*
860       HandleGameActions(0);
861       */
862
863       break;
864
865     default:
866       break;
867   }
868 }
869
870 static int HandleJoystickForAllPlayers()
871 {
872   int i;
873   int result = 0;
874
875   for (i=0; i<MAX_PLAYERS; i++)
876   {
877     byte joy_action = 0;
878
879     if (!setup.input[i].use_joystick)
880       continue;
881
882     joy_action = Joystick(i);
883     result |= joy_action;
884
885     stored_player[i].action = joy_action;
886   }
887
888   return result;
889 }
890
891 void HandleJoystick()
892 {
893   int joystick  = HandleJoystickForAllPlayers();
894   int keyboard  = key_joystick_mapping;
895   int joy       = (joystick | keyboard);
896   int left      = joy & JOY_LEFT;
897   int right     = joy & JOY_RIGHT;
898   int up        = joy & JOY_UP;
899   int down      = joy & JOY_DOWN;
900   int button    = joy & JOY_BUTTON;
901   int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
902   int dx        = (left ? -1    : right ? 1     : 0);
903   int dy        = (up   ? -1    : down  ? 1     : 0);
904
905   switch(game_status)
906   {
907     case MAINMENU:
908     case CHOOSELEVEL:
909     case SETUP:
910     case SETUPINPUT:
911     {
912       static long joystickmove_delay = 0;
913
914       if (joystick && !button && !DelayReached(&joystickmove_delay,150))
915         newbutton = dx = dy = 0;
916
917       if (game_status==MAINMENU)
918         HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
919       else if (game_status==CHOOSELEVEL)
920         HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
921       else if (game_status==SETUP)
922         HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
923       else if (game_status==SETUPINPUT)
924         HandleSetupInputScreen(0,0,dx,dy,
925                                newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
926       break;
927     }
928
929     case HALLOFFAME:
930       HandleHallOfFame(!newbutton);
931       break;
932
933     case HELPSCREEN:
934       HandleHelpScreen(!newbutton);
935       break;
936
937     case PLAYING:
938       if (tape.playing || keyboard)
939         newbutton = ((joy & JOY_BUTTON) != 0);
940
941       if (AllPlayersGone && newbutton)
942       {
943         CloseDoor(DOOR_CLOSE_1);
944         game_status = MAINMENU;
945         DrawMainMenu();
946         return;
947       }
948
949       HandleGameActions();
950       break;
951
952     default:
953       break;
954   }
955 }