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"))
572 else if (is_string_suffix(cheat_input, ":DDB"))
579 void HandleKey(Key key, int key_status)
582 boolean anyTextGadgetActiveOrJustFinished = anyTextGadgetActive();
583 static struct SetupKeyboardInfo custom_key;
591 { &custom_key.left, DEFAULT_KEY_LEFT, JOY_LEFT },
592 { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT },
593 { &custom_key.up, DEFAULT_KEY_UP, JOY_UP },
594 { &custom_key.down, DEFAULT_KEY_DOWN, JOY_DOWN },
595 { &custom_key.snap, DEFAULT_KEY_SNAP, JOY_BUTTON_1 },
596 { &custom_key.drop, DEFAULT_KEY_DROP, JOY_BUTTON_2 }
599 if (game_status == GAME_MODE_PLAYING)
601 /* only needed for single-step tape recording mode */
602 static boolean clear_button_2[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
603 static boolean element_dropped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
606 for (pnr = 0; pnr < MAX_PLAYERS; pnr++)
611 if (setup.input[pnr].use_joystick)
614 custom_key = setup.input[pnr].key;
616 for (i = 0; i < 6; i++)
617 if (key == *key_info[i].key_custom)
618 key_action |= key_info[i].action;
620 if (tape.single_step && clear_button_2[pnr])
622 stored_player[pnr].action &= ~KEY_BUTTON_2;
623 clear_button_2[pnr] = FALSE;
626 if (key_status == KEY_PRESSED)
627 stored_player[pnr].action |= key_action;
629 stored_player[pnr].action &= ~key_action;
631 if (tape.single_step && tape.recording && tape.pausing)
633 if (key_status == KEY_PRESSED &&
634 (key_action & (KEY_MOTION | KEY_BUTTON_1)))
636 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
638 if (key_action & KEY_MOTION)
640 if (stored_player[pnr].action & KEY_BUTTON_2)
641 element_dropped[pnr] = TRUE;
644 else if (key_status == KEY_RELEASED &&
645 (key_action & KEY_BUTTON_2))
647 if (!element_dropped[pnr])
649 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
651 stored_player[pnr].action |= KEY_BUTTON_2;
652 clear_button_2[pnr] = TRUE;
655 element_dropped[pnr] = FALSE;
658 else if (tape.recording && tape.pausing && (key_action & KEY_ACTION))
659 TapeTogglePause(TAPE_TOGGLE_MANUAL);
666 for (i = 0; i < 6; i++)
667 if (key == key_info[i].key_default)
668 joy |= key_info[i].action;
673 if (key_status == KEY_PRESSED)
674 key_joystick_mapping |= joy;
676 key_joystick_mapping &= ~joy;
681 if (game_status != GAME_MODE_PLAYING)
682 key_joystick_mapping = 0;
684 if (key_status == KEY_RELEASED)
687 if (game_status == GAME_MODE_PLAYING && AllPlayersGone &&
688 (key == KSYM_Return || key == setup.shortcut.toggle_pause))
690 CloseDoor(DOOR_CLOSE_1);
691 game_status = GAME_MODE_MAIN;
697 if (game_status == GAME_MODE_MAIN && key == setup.shortcut.toggle_pause)
699 if (setup.autorecord)
700 TapeStartRecording();
702 #if defined(NETWORK_AVALIABLE)
704 SendToServer_StartPlaying();
708 game_status = GAME_MODE_PLAYING;
716 if (game_status == GAME_MODE_MAIN || game_status == GAME_MODE_PLAYING)
718 if (key == setup.shortcut.save_game)
720 else if (key == setup.shortcut.load_game)
722 else if (key == setup.shortcut.toggle_pause)
723 TapeTogglePause(TAPE_TOGGLE_MANUAL);
726 HandleKeysSpecial(key);
728 if (HandleGadgetsKeyInput(key))
730 if (key != KSYM_Escape) /* always allow ESC key to be handled */
731 key = KSYM_UNDEFINED;
736 case GAME_MODE_PSEUDO_TYPENAME:
737 HandleTypeName(0, key);
741 case GAME_MODE_LEVELS:
742 case GAME_MODE_SETUP:
748 if (game_status == GAME_MODE_MAIN)
749 HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
750 else if (game_status == GAME_MODE_LEVELS)
751 HandleChooseLevel(0,0, 0,0, MB_MENU_CHOICE);
752 else if (game_status == GAME_MODE_SETUP)
753 HandleSetupScreen(0,0, 0,0, MB_MENU_CHOICE);
754 else if (game_status == GAME_MODE_INFO)
755 HandleInfoScreen(0,0, 0,0, MB_MENU_CHOICE);
759 if (game_status == GAME_MODE_LEVELS)
760 HandleChooseLevel(0,0, 0,0, MB_MENU_LEAVE);
761 else if (game_status == GAME_MODE_SETUP)
762 HandleSetupScreen(0,0, 0,0, MB_MENU_LEAVE);
763 else if (game_status == GAME_MODE_INFO)
764 HandleInfoScreen(0,0, 0,0, MB_MENU_LEAVE);
768 if (game_status == GAME_MODE_LEVELS)
769 HandleChooseLevel(0,0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
770 else if (game_status == GAME_MODE_SETUP)
771 HandleSetupScreen(0,0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
772 else if (game_status == GAME_MODE_INFO)
773 HandleInfoScreen(0,0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
777 if (game_status == GAME_MODE_LEVELS)
778 HandleChooseLevel(0,0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
779 else if (game_status == GAME_MODE_SETUP)
780 HandleSetupScreen(0,0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
781 else if (game_status == GAME_MODE_INFO)
782 HandleInfoScreen(0,0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
790 case GAME_MODE_SCORES:
796 game_status = GAME_MODE_MAIN;
801 HandleHallOfFame(0,0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
805 HandleHallOfFame(0,0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
813 case GAME_MODE_EDITOR:
814 if (!anyTextGadgetActiveOrJustFinished || key == KSYM_Escape)
815 HandleLevelEditorKeyInput(key);
818 case GAME_MODE_PLAYING:
823 RequestQuitGame(setup.ask_on_escape);
839 if (GameFrameDelay == 500)
840 GameFrameDelay = GAME_FRAME_DELAY;
842 GameFrameDelay = 500;
845 GameFrameDelay = (key - KSYM_0) * 10;
846 printf("Game speed == %d%% (%d ms delay between two frames)\n",
847 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
853 options.debug = FALSE;
854 printf("debug mode disabled\n");
858 options.debug = TRUE;
859 printf("debug mode enabled\n");
864 if (!global.fps_slowdown)
866 global.fps_slowdown = TRUE;
867 global.fps_slowdown_factor = 2;
868 printf("fps slowdown enabled -- display only every 2nd frame\n");
870 else if (global.fps_slowdown_factor == 2)
872 global.fps_slowdown_factor = 4;
873 printf("fps slowdown enabled -- display only every 4th frame\n");
877 global.fps_slowdown = FALSE;
878 global.fps_slowdown_factor = 1;
879 printf("fps slowdown disabled\n");
885 if (ScrollStepSize == TILEX/8)
886 ScrollStepSize = TILEX/4;
888 ScrollStepSize = TILEX/8;
889 printf("ScrollStepSize == %d\n", ScrollStepSize);
898 ScrollStepSize = TILEX/4;
903 ScrollStepSize = TILEX/8;
905 printf("MoveSpeed == %d\n", MoveSpeed);
910 ScrollStepSize = TILEX/8;
911 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
915 ScrollStepSize = TILEX/4;
916 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
920 ScrollStepSize = TILEX/2;
921 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
925 ScrollStepSize = TILEX;
926 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
930 printf("::: currently using game engine version %d\n",
931 game.engine_version);
940 for (i = 0; i < MAX_PLAYERS; i++)
942 printf("Player %d:\n", i);
943 printf(" jx == %d, jy == %d\n",
944 stored_player[i].jx, stored_player[i].jy);
945 printf(" last_jx == %d, last_jy == %d\n",
946 stored_player[i].last_jx, stored_player[i].last_jy);
962 if (key == KSYM_Escape)
964 game_status = GAME_MODE_MAIN;
974 if (button_status && game_status != GAME_MODE_PLAYING)
976 HandleButton(0, 0, -button_status);
980 #if defined(NETWORK_AVALIABLE)
988 static int HandleJoystickForAllPlayers()
993 for (i = 0; i < MAX_PLAYERS; i++)
998 if (!setup.input[i].use_joystick)
1002 joy_action = Joystick(i);
1003 result |= joy_action;
1005 if (!setup.input[i].use_joystick)
1008 stored_player[i].action = joy_action;
1014 void HandleJoystick()
1016 int joystick = HandleJoystickForAllPlayers();
1017 int keyboard = key_joystick_mapping;
1018 int joy = (joystick | keyboard);
1019 int left = joy & JOY_LEFT;
1020 int right = joy & JOY_RIGHT;
1021 int up = joy & JOY_UP;
1022 int down = joy & JOY_DOWN;
1023 int button = joy & JOY_BUTTON;
1024 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
1025 int dx = (left ? -1 : right ? 1 : 0);
1026 int dy = (up ? -1 : down ? 1 : 0);
1030 case GAME_MODE_MAIN:
1031 case GAME_MODE_LEVELS:
1032 case GAME_MODE_SETUP:
1033 case GAME_MODE_INFO:
1035 static unsigned long joystickmove_delay = 0;
1037 if (joystick && !button &&
1038 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
1039 newbutton = dx = dy = 0;
1041 if (game_status == GAME_MODE_MAIN)
1042 HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1043 else if (game_status == GAME_MODE_LEVELS)
1044 HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1045 else if (game_status == GAME_MODE_SETUP)
1046 HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1047 else if (game_status == GAME_MODE_INFO)
1048 HandleInfoScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1052 case GAME_MODE_SCORES:
1053 HandleHallOfFame(0,0, dx,dy, !newbutton);
1056 case GAME_MODE_EDITOR:
1057 HandleLevelEditorIdle();
1060 case GAME_MODE_PLAYING:
1061 if (tape.playing || keyboard)
1062 newbutton = ((joy & JOY_BUTTON) != 0);
1064 if (AllPlayersGone && newbutton)
1066 CloseDoor(DOOR_CLOSE_1);
1067 game_status = GAME_MODE_MAIN;