1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
27 static boolean cursor_inside_playfield = FALSE;
28 static boolean playfield_cursor_set = FALSE;
29 static unsigned long playfield_cursor_delay = 0;
32 /* event filter especially needed for SDL event filtering due to
33 delay problems with lots of mouse motion events when mouse button
34 not pressed (X11 can handle this with 'PointerMotionHintMask') */
36 int FilterMouseMotionEvents(const Event *event)
40 /* non-motion events are directly passed to event handler functions */
41 if (event->type != EVENT_MOTIONNOTIFY)
44 motion = (MotionEvent *)event;
45 cursor_inside_playfield = (motion->x >= SX && motion->x < SX + SXSIZE &&
46 motion->y >= SY && motion->y < SY + SYSIZE);
48 if (game_status == GAME_MODE_PLAYING && playfield_cursor_set)
50 SetMouseCursor(CURSOR_DEFAULT);
51 playfield_cursor_set = FALSE;
52 DelayReached(&playfield_cursor_delay, 0);
55 /* skip mouse motion events without pressed button outside level editor */
56 if (button_status == MB_RELEASED &&
57 game_status != GAME_MODE_EDITOR && game_status != GAME_MODE_PLAYING)
63 /* to prevent delay problems, skip mouse motion events if the very next
64 event is also a mouse motion event (and therefore effectively only
65 handling the last of a row of mouse motion events in the event queue) */
67 boolean SkipPressedMouseMotionEvent(const Event *event)
69 /* nothing to do if the current event is not a mouse motion event */
70 if (event->type != EVENT_MOTIONNOTIFY)
73 /* only skip motion events with pressed button outside level editor */
74 if (button_status == MB_RELEASED ||
75 game_status == GAME_MODE_EDITOR || game_status == GAME_MODE_PLAYING)
82 PeekEvent(&next_event);
84 /* if next event is also a mouse motion event, skip the current one */
85 if (next_event.type == EVENT_MOTIONNOTIFY)
92 /* this is only really needed for non-SDL targets to filter unwanted events;
93 when using SDL with properly installed event filter, this function can be
94 replaced with a simple "NextEvent()" call, but it doesn't hurt either */
96 static boolean NextValidEvent(Event *event)
98 while (PendingEvent())
100 boolean handle_this_event = FALSE;
104 if (FilterMouseMotionEvents(event))
105 handle_this_event = TRUE;
108 if (SkipPressedMouseMotionEvent(event))
109 handle_this_event = FALSE;
112 if (handle_this_event)
123 if (PendingEvent()) /* got event */
127 while (NextValidEvent(&event))
131 case EVENT_BUTTONPRESS:
132 case EVENT_BUTTONRELEASE:
133 HandleButtonEvent((ButtonEvent *) &event);
136 case EVENT_MOTIONNOTIFY:
137 HandleMotionEvent((MotionEvent *) &event);
141 case EVENT_KEYRELEASE:
142 HandleKeyEvent((KeyEvent *) &event);
146 HandleOtherEvents(&event);
153 /* when playing, display a special mouse pointer inside the playfield */
154 if (game_status == GAME_MODE_PLAYING && !tape.pausing)
156 if (!playfield_cursor_set && cursor_inside_playfield &&
157 DelayReached(&playfield_cursor_delay, 1000))
159 SetMouseCursor(CURSOR_PLAYFIELD);
160 playfield_cursor_set = TRUE;
163 else if (playfield_cursor_set)
165 SetMouseCursor(CURSOR_DEFAULT);
166 playfield_cursor_set = FALSE;
172 /* don't use all CPU time when idle; the main loop while playing
173 has its own synchronization and is CPU friendly, too */
175 if (game_status == GAME_MODE_PLAYING)
180 if (!PendingEvent()) /* delay only if no pending events */
184 /* refresh window contents from drawing buffer, if needed */
187 if (game_status == GAME_MODE_QUIT)
192 void HandleOtherEvents(Event *event)
197 HandleExposeEvent((ExposeEvent *) event);
200 case EVENT_UNMAPNOTIFY:
202 /* This causes the game to stop not only when iconified, but also
203 when on another virtual desktop, which might be not desired. */
204 SleepWhileUnmapped();
210 HandleFocusEvent((FocusChangeEvent *) event);
213 case EVENT_CLIENTMESSAGE:
214 HandleClientMessageEvent((ClientMessageEvent *) event);
217 #if defined(TARGET_SDL)
218 case SDL_JOYAXISMOTION:
219 case SDL_JOYBUTTONDOWN:
220 case SDL_JOYBUTTONUP:
221 HandleJoystickEvent(event);
230 void ClearEventQueue()
232 while (PendingEvent())
240 case EVENT_BUTTONRELEASE:
241 button_status = MB_RELEASED;
244 case EVENT_KEYRELEASE:
245 key_joystick_mapping = 0;
249 HandleOtherEvents(&event);
255 void ClearPlayerAction()
259 /* simulate key release events for still pressed keys */
260 key_joystick_mapping = 0;
261 for (i = 0; i < MAX_PLAYERS; i++)
262 stored_player[i].action = 0;
265 void SleepWhileUnmapped()
267 boolean window_unmapped = TRUE;
269 KeyboardAutoRepeatOn();
271 while (window_unmapped)
279 case EVENT_BUTTONRELEASE:
280 button_status = MB_RELEASED;
283 case EVENT_KEYRELEASE:
284 key_joystick_mapping = 0;
287 case EVENT_MAPNOTIFY:
288 window_unmapped = FALSE;
291 case EVENT_UNMAPNOTIFY:
292 /* this is only to surely prevent the 'should not happen' case
293 * of recursively looping between 'SleepWhileUnmapped()' and
294 * 'HandleOtherEvents()' which usually calls this funtion.
299 HandleOtherEvents(&event);
304 if (game_status == GAME_MODE_PLAYING)
305 KeyboardAutoRepeatOffUnlessAutoplay();
308 void HandleExposeEvent(ExposeEvent *event)
311 RedrawPlayfield(FALSE, event->x, event->y, event->width, event->height);
316 void HandleButtonEvent(ButtonEvent *event)
318 motion_status = FALSE;
320 if (event->type == EVENT_BUTTONPRESS)
321 button_status = event->button;
323 button_status = MB_RELEASED;
326 printf("::: button %s\n", event->type == EVENT_BUTTONPRESS ?
327 "pressed" : "released");
330 HandleButton(event->x, event->y, button_status);
333 void HandleMotionEvent(MotionEvent *event)
335 if (!PointerInWindow(window))
336 return; /* window and pointer are on different screens */
339 if (button_status == MB_RELEASED && game_status != GAME_MODE_EDITOR)
343 motion_status = TRUE;
346 printf("::: %d, %d\n", event->x, event->y);
349 HandleButton(event->x, event->y, button_status);
352 void HandleKeyEvent(KeyEvent *event)
354 int key_status = (event->type==EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
355 boolean with_modifiers = (game_status == GAME_MODE_PLAYING ? FALSE : TRUE);
356 Key key = GetEventKey(event, with_modifiers);
357 Key keymod = (with_modifiers ? GetEventKey(event, FALSE) : key);
359 HandleKeyModState(keymod, key_status);
360 HandleKey(key, key_status);
363 void HandleFocusEvent(FocusChangeEvent *event)
365 static int old_joystick_status = -1;
367 if (event->type == EVENT_FOCUSOUT)
369 KeyboardAutoRepeatOn();
370 old_joystick_status = joystick.status;
371 joystick.status = JOYSTICK_NOT_AVAILABLE;
375 else if (event->type == EVENT_FOCUSIN)
377 /* When there are two Rocks'n'Diamonds windows which overlap and
378 the player moves the pointer from one game window to the other,
379 a 'FocusOut' event is generated for the window the pointer is
380 leaving and a 'FocusIn' event is generated for the window the
381 pointer is entering. In some cases, it can happen that the
382 'FocusIn' event is handled by the one game process before the
383 'FocusOut' event by the other game process. In this case the
384 X11 environment would end up with activated keyboard auto repeat,
385 because unfortunately this is a global setting and not (which
386 would be far better) set for each X11 window individually.
387 The effect would be keyboard auto repeat while playing the game
388 (game_status == GAME_MODE_PLAYING), which is not desired.
389 To avoid this special case, we just wait 1/10 second before
390 processing the 'FocusIn' event.
393 if (game_status == GAME_MODE_PLAYING)
396 KeyboardAutoRepeatOffUnlessAutoplay();
399 if (old_joystick_status != -1)
400 joystick.status = old_joystick_status;
404 void HandleClientMessageEvent(ClientMessageEvent *event)
406 if (CheckCloseWindowEvent(event))
410 void HandleButton(int mx, int my, int button)
412 static int old_mx = 0, old_my = 0;
426 if (HandleGadgets(mx, my, button))
428 /* do not handle this button event anymore */
429 mx = my = -32; /* force mouse event to be outside screen tiles */
435 HandleMainMenu(mx,my, 0,0, button);
438 case GAME_MODE_PSEUDO_TYPENAME:
439 HandleTypeName(0, KSYM_Return);
442 case GAME_MODE_LEVELS:
443 HandleChooseLevel(mx,my, 0,0, button);
446 case GAME_MODE_SCORES:
447 HandleHallOfFame(0,0, 0,0, button);
450 case GAME_MODE_EDITOR:
454 HandleInfoScreen(mx,my, 0,0, button);
457 case GAME_MODE_SETUP:
458 HandleSetupScreen(mx,my, 0,0, button);
461 case GAME_MODE_PLAYING:
463 if (button == MB_PRESSED && !motion_status && IN_GFX_SCREEN(mx, my))
464 DumpTile(LEVELX((mx - SX) / TILEX), LEVELY((my - SY) / TILEY));
473 static boolean is_string_suffix(char *string, char *suffix)
475 int string_len = strlen(string);
476 int suffix_len = strlen(suffix);
478 if (suffix_len > string_len)
481 return (strcmp(&string[string_len - suffix_len], suffix) == 0);
484 #define MAX_CHEAT_INPUT_LEN 32
486 static void HandleKeysSpecial(Key key)
488 static char cheat_input[2 * MAX_CHEAT_INPUT_LEN + 1] = "";
489 char letter = getCharFromKey(key);
490 int cheat_input_len = strlen(cheat_input);
496 if (cheat_input_len >= 2 * MAX_CHEAT_INPUT_LEN)
498 for (i = 0; i < MAX_CHEAT_INPUT_LEN + 1; i++)
499 cheat_input[i] = cheat_input[MAX_CHEAT_INPUT_LEN + i];
501 cheat_input_len = MAX_CHEAT_INPUT_LEN;
504 cheat_input[cheat_input_len++] = letter;
505 cheat_input[cheat_input_len] = '\0';
508 printf("::: '%s' [%d]\n", cheat_input, cheat_input_len);
511 if (game_status == GAME_MODE_MAIN)
513 if (is_string_suffix(cheat_input, ":insert-solution-tape") ||
514 is_string_suffix(cheat_input, ":ist"))
516 InsertSolutionTape();
518 else if (is_string_suffix(cheat_input, ":reload-graphics") ||
519 is_string_suffix(cheat_input, ":rg"))
521 ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS);
524 else if (is_string_suffix(cheat_input, ":reload-sounds") ||
525 is_string_suffix(cheat_input, ":rs"))
527 ReloadCustomArtwork(1 << ARTWORK_TYPE_SOUNDS);
530 else if (is_string_suffix(cheat_input, ":reload-music") ||
531 is_string_suffix(cheat_input, ":rm"))
533 ReloadCustomArtwork(1 << ARTWORK_TYPE_MUSIC);
536 else if (is_string_suffix(cheat_input, ":reload-artwork") ||
537 is_string_suffix(cheat_input, ":ra"))
539 ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS |
540 1 << ARTWORK_TYPE_SOUNDS |
541 1 << ARTWORK_TYPE_MUSIC);
544 else if (is_string_suffix(cheat_input, ":dump-level") ||
545 is_string_suffix(cheat_input, ":dl"))
549 else if (is_string_suffix(cheat_input, ":dump-tape") ||
550 is_string_suffix(cheat_input, ":dt"))
555 else if (game_status == GAME_MODE_PLAYING)
558 if (is_string_suffix(cheat_input, ".q"))
559 for (i = 0; i < MAX_INVENTORY_SIZE; i++)
560 if (local_player->inventory_size < MAX_INVENTORY_SIZE)
561 local_player->inventory_element[local_player->inventory_size++] =
565 else if (game_status == GAME_MODE_EDITOR)
567 if (is_string_suffix(cheat_input, ":dump-brush") ||
568 is_string_suffix(cheat_input, ":DB"))
575 void HandleKey(Key key, int key_status)
578 boolean anyTextGadgetActiveOrJustFinished = anyTextGadgetActive();
579 static struct SetupKeyboardInfo custom_key;
587 { &custom_key.left, DEFAULT_KEY_LEFT, JOY_LEFT },
588 { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT },
589 { &custom_key.up, DEFAULT_KEY_UP, JOY_UP },
590 { &custom_key.down, DEFAULT_KEY_DOWN, JOY_DOWN },
591 { &custom_key.snap, DEFAULT_KEY_SNAP, JOY_BUTTON_1 },
592 { &custom_key.drop, DEFAULT_KEY_DROP, JOY_BUTTON_2 }
595 if (game_status == GAME_MODE_PLAYING)
597 /* only needed for single-step tape recording mode */
598 static boolean clear_button_2[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
599 static boolean element_dropped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
602 for (pnr = 0; pnr < MAX_PLAYERS; pnr++)
607 if (setup.input[pnr].use_joystick)
610 custom_key = setup.input[pnr].key;
612 for (i = 0; i < 6; i++)
613 if (key == *key_info[i].key_custom)
614 key_action |= key_info[i].action;
616 if (tape.single_step && clear_button_2[pnr])
618 stored_player[pnr].action &= ~KEY_BUTTON_2;
619 clear_button_2[pnr] = FALSE;
622 if (key_status == KEY_PRESSED)
623 stored_player[pnr].action |= key_action;
625 stored_player[pnr].action &= ~key_action;
627 if (tape.single_step && tape.recording && tape.pausing)
629 if (key_status == KEY_PRESSED &&
630 (key_action & (KEY_MOTION | KEY_BUTTON_1)))
632 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
634 if (key_action & KEY_MOTION)
636 if (stored_player[pnr].action & KEY_BUTTON_2)
637 element_dropped[pnr] = TRUE;
640 else if (key_status == KEY_RELEASED &&
641 (key_action & KEY_BUTTON_2))
643 if (!element_dropped[pnr])
645 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
647 stored_player[pnr].action |= KEY_BUTTON_2;
648 clear_button_2[pnr] = TRUE;
651 element_dropped[pnr] = FALSE;
654 else if (tape.recording && tape.pausing && (key_action & KEY_ACTION))
655 TapeTogglePause(TAPE_TOGGLE_MANUAL);
662 for (i = 0; i < 6; i++)
663 if (key == key_info[i].key_default)
664 joy |= key_info[i].action;
669 if (key_status == KEY_PRESSED)
670 key_joystick_mapping |= joy;
672 key_joystick_mapping &= ~joy;
677 if (game_status != GAME_MODE_PLAYING)
678 key_joystick_mapping = 0;
680 if (key_status == KEY_RELEASED)
683 if (game_status == GAME_MODE_PLAYING && AllPlayersGone &&
684 (key == KSYM_Return || key == setup.shortcut.toggle_pause))
686 CloseDoor(DOOR_CLOSE_1);
687 game_status = GAME_MODE_MAIN;
693 if (game_status == GAME_MODE_MAIN && key == setup.shortcut.toggle_pause)
695 if (setup.autorecord)
696 TapeStartRecording();
698 #if defined(NETWORK_AVALIABLE)
700 SendToServer_StartPlaying();
704 game_status = GAME_MODE_PLAYING;
712 if (game_status == GAME_MODE_MAIN || game_status == GAME_MODE_PLAYING)
714 if (key == setup.shortcut.save_game)
716 else if (key == setup.shortcut.load_game)
718 else if (key == setup.shortcut.toggle_pause)
719 TapeTogglePause(TAPE_TOGGLE_MANUAL);
722 HandleKeysSpecial(key);
724 if (HandleGadgetsKeyInput(key))
726 if (key != KSYM_Escape) /* always allow ESC key to be handled */
727 key = KSYM_UNDEFINED;
732 case GAME_MODE_PSEUDO_TYPENAME:
733 HandleTypeName(0, key);
737 case GAME_MODE_LEVELS:
738 case GAME_MODE_SETUP:
744 if (game_status == GAME_MODE_MAIN)
745 HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
746 else if (game_status == GAME_MODE_LEVELS)
747 HandleChooseLevel(0,0, 0,0, MB_MENU_CHOICE);
748 else if (game_status == GAME_MODE_SETUP)
749 HandleSetupScreen(0,0, 0,0, MB_MENU_CHOICE);
750 else if (game_status == GAME_MODE_INFO)
751 HandleInfoScreen(0,0, 0,0, MB_MENU_CHOICE);
755 if (game_status == GAME_MODE_LEVELS)
756 HandleChooseLevel(0,0, 0,0, MB_MENU_LEAVE);
757 else if (game_status == GAME_MODE_SETUP)
758 HandleSetupScreen(0,0, 0,0, MB_MENU_LEAVE);
759 else if (game_status == GAME_MODE_INFO)
760 HandleInfoScreen(0,0, 0,0, MB_MENU_LEAVE);
764 if (game_status == GAME_MODE_LEVELS)
765 HandleChooseLevel(0,0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
766 else if (game_status == GAME_MODE_SETUP)
767 HandleSetupScreen(0,0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
768 else if (game_status == GAME_MODE_INFO)
769 HandleInfoScreen(0,0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
773 if (game_status == GAME_MODE_LEVELS)
774 HandleChooseLevel(0,0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
775 else if (game_status == GAME_MODE_SETUP)
776 HandleSetupScreen(0,0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
777 else if (game_status == GAME_MODE_INFO)
778 HandleInfoScreen(0,0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
786 case GAME_MODE_SCORES:
792 game_status = GAME_MODE_MAIN;
797 HandleHallOfFame(0,0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
801 HandleHallOfFame(0,0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
809 case GAME_MODE_EDITOR:
810 if (!anyTextGadgetActiveOrJustFinished || key == KSYM_Escape)
811 HandleLevelEditorKeyInput(key);
814 case GAME_MODE_PLAYING:
819 RequestQuitGame(setup.ask_on_escape);
835 if (GameFrameDelay == 500)
836 GameFrameDelay = GAME_FRAME_DELAY;
838 GameFrameDelay = 500;
841 GameFrameDelay = (key - KSYM_0) * 10;
842 printf("Game speed == %d%% (%d ms delay between two frames)\n",
843 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
849 options.debug = FALSE;
850 printf("debug mode disabled\n");
854 options.debug = TRUE;
855 printf("debug mode enabled\n");
860 if (!global.fps_slowdown)
862 global.fps_slowdown = TRUE;
863 global.fps_slowdown_factor = 2;
864 printf("fps slowdown enabled -- display only every 2nd frame\n");
866 else if (global.fps_slowdown_factor == 2)
868 global.fps_slowdown_factor = 4;
869 printf("fps slowdown enabled -- display only every 4th frame\n");
873 global.fps_slowdown = FALSE;
874 global.fps_slowdown_factor = 1;
875 printf("fps slowdown disabled\n");
881 if (ScrollStepSize == TILEX/8)
882 ScrollStepSize = TILEX/4;
884 ScrollStepSize = TILEX/8;
885 printf("ScrollStepSize == %d\n", ScrollStepSize);
894 ScrollStepSize = TILEX/4;
899 ScrollStepSize = TILEX/8;
901 printf("MoveSpeed == %d\n", MoveSpeed);
906 ScrollStepSize = TILEX/8;
907 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
911 ScrollStepSize = TILEX/4;
912 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
916 ScrollStepSize = TILEX/2;
917 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
921 ScrollStepSize = TILEX;
922 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
926 printf("::: currently using game engine version %d\n",
927 game.engine_version);
936 for (i = 0; i < MAX_PLAYERS; i++)
938 printf("Player %d:\n", i);
939 printf(" jx == %d, jy == %d\n",
940 stored_player[i].jx, stored_player[i].jy);
941 printf(" last_jx == %d, last_jy == %d\n",
942 stored_player[i].last_jx, stored_player[i].last_jy);
958 if (key == KSYM_Escape)
960 game_status = GAME_MODE_MAIN;
970 if (button_status && game_status != GAME_MODE_PLAYING)
972 HandleButton(0, 0, -button_status);
976 #if defined(NETWORK_AVALIABLE)
984 static int HandleJoystickForAllPlayers()
989 for (i = 0; i < MAX_PLAYERS; i++)
994 if (!setup.input[i].use_joystick)
998 joy_action = Joystick(i);
999 result |= joy_action;
1001 if (!setup.input[i].use_joystick)
1004 stored_player[i].action = joy_action;
1010 void HandleJoystick()
1012 int joystick = HandleJoystickForAllPlayers();
1013 int keyboard = key_joystick_mapping;
1014 int joy = (joystick | keyboard);
1015 int left = joy & JOY_LEFT;
1016 int right = joy & JOY_RIGHT;
1017 int up = joy & JOY_UP;
1018 int down = joy & JOY_DOWN;
1019 int button = joy & JOY_BUTTON;
1020 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
1021 int dx = (left ? -1 : right ? 1 : 0);
1022 int dy = (up ? -1 : down ? 1 : 0);
1026 case GAME_MODE_MAIN:
1027 case GAME_MODE_LEVELS:
1028 case GAME_MODE_SETUP:
1029 case GAME_MODE_INFO:
1031 static unsigned long joystickmove_delay = 0;
1033 if (joystick && !button &&
1034 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
1035 newbutton = dx = dy = 0;
1037 if (game_status == GAME_MODE_MAIN)
1038 HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1039 else if (game_status == GAME_MODE_LEVELS)
1040 HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1041 else if (game_status == GAME_MODE_SETUP)
1042 HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1043 else if (game_status == GAME_MODE_INFO)
1044 HandleInfoScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1048 case GAME_MODE_SCORES:
1049 HandleHallOfFame(0,0, dx,dy, !newbutton);
1052 case GAME_MODE_EDITOR:
1053 HandleLevelEditorIdle();
1056 case GAME_MODE_PLAYING:
1057 if (tape.playing || keyboard)
1058 newbutton = ((joy & JOY_BUTTON) != 0);
1060 if (AllPlayersGone && newbutton)
1062 CloseDoor(DOOR_CLOSE_1);
1063 game_status = GAME_MODE_MAIN;