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 && game_status != GAME_MODE_EDITOR &&
57 game_status != GAME_MODE_PLAYING)
63 /* this is only really needed for non-SDL targets to filter unwanted events;
64 when using SDL with properly installed event filter, this function can be
65 replaced with a simple "NextEvent()" call, but it doesn't hurt either */
67 static boolean NextValidEvent(Event *event)
69 while (PendingEvent())
73 if (FilterMouseMotionEvents(event))
84 if (PendingEvent()) /* got event */
88 if (NextValidEvent(&event))
92 case EVENT_BUTTONPRESS:
93 case EVENT_BUTTONRELEASE:
94 HandleButtonEvent((ButtonEvent *) &event);
97 case EVENT_MOTIONNOTIFY:
98 HandleMotionEvent((MotionEvent *) &event);
102 case EVENT_KEYRELEASE:
103 HandleKeyEvent((KeyEvent *) &event);
107 HandleOtherEvents(&event);
114 /* when playing, display a special mouse pointer inside the playfield */
115 if (game_status == GAME_MODE_PLAYING)
117 if (!playfield_cursor_set && cursor_inside_playfield &&
118 DelayReached(&playfield_cursor_delay, 1000))
120 SetMouseCursor(CURSOR_PLAYFIELD);
121 playfield_cursor_set = TRUE;
124 else if (playfield_cursor_set)
126 SetMouseCursor(CURSOR_DEFAULT);
127 playfield_cursor_set = FALSE;
133 /* don't use all CPU time when idle; the main loop while playing
134 has its own synchronization and is CPU friendly, too */
136 if (game_status == GAME_MODE_PLAYING)
141 if (!PendingEvent()) /* delay only if no pending events */
145 /* refresh window contents from drawing buffer, if needed */
148 if (game_status == GAME_MODE_QUIT)
153 void HandleOtherEvents(Event *event)
158 HandleExposeEvent((ExposeEvent *) event);
161 case EVENT_UNMAPNOTIFY:
163 /* This causes the game to stop not only when iconified, but also
164 when on another virtual desktop, which might be not desired. */
165 SleepWhileUnmapped();
171 HandleFocusEvent((FocusChangeEvent *) event);
174 case EVENT_CLIENTMESSAGE:
175 HandleClientMessageEvent((ClientMessageEvent *) event);
178 #if defined(TARGET_SDL)
179 case SDL_JOYAXISMOTION:
180 case SDL_JOYBUTTONDOWN:
181 case SDL_JOYBUTTONUP:
182 HandleJoystickEvent(event);
191 void ClearEventQueue()
193 while (PendingEvent())
201 case EVENT_BUTTONRELEASE:
202 button_status = MB_RELEASED;
205 case EVENT_KEYRELEASE:
206 key_joystick_mapping = 0;
210 HandleOtherEvents(&event);
216 void ClearPlayerAction()
220 /* simulate key release events for still pressed keys */
221 key_joystick_mapping = 0;
222 for (i = 0; i < MAX_PLAYERS; i++)
223 stored_player[i].action = 0;
226 void SleepWhileUnmapped()
228 boolean window_unmapped = TRUE;
230 KeyboardAutoRepeatOn();
232 while (window_unmapped)
240 case EVENT_BUTTONRELEASE:
241 button_status = MB_RELEASED;
244 case EVENT_KEYRELEASE:
245 key_joystick_mapping = 0;
248 case EVENT_MAPNOTIFY:
249 window_unmapped = FALSE;
252 case EVENT_UNMAPNOTIFY:
253 /* this is only to surely prevent the 'should not happen' case
254 * of recursively looping between 'SleepWhileUnmapped()' and
255 * 'HandleOtherEvents()' which usually calls this funtion.
260 HandleOtherEvents(&event);
265 if (game_status == GAME_MODE_PLAYING)
266 KeyboardAutoRepeatOffUnlessAutoplay();
269 void HandleExposeEvent(ExposeEvent *event)
272 RedrawPlayfield(FALSE, event->x, event->y, event->width, event->height);
277 void HandleButtonEvent(ButtonEvent *event)
279 motion_status = FALSE;
281 if (event->type == EVENT_BUTTONPRESS)
282 button_status = event->button;
284 button_status = MB_RELEASED;
286 HandleButton(event->x, event->y, button_status);
289 void HandleMotionEvent(MotionEvent *event)
291 if (!PointerInWindow(window))
292 return; /* window and pointer are on different screens */
295 if (button_status == MB_RELEASED && game_status != GAME_MODE_EDITOR)
299 motion_status = TRUE;
301 HandleButton(event->x, event->y, button_status);
304 void HandleKeyEvent(KeyEvent *event)
306 int key_status = (event->type==EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
307 boolean with_modifiers = (game_status == GAME_MODE_PLAYING ? FALSE : TRUE);
308 Key key = GetEventKey(event, with_modifiers);
309 Key keymod = (with_modifiers ? GetEventKey(event, FALSE) : key);
311 HandleKeyModState(keymod, key_status);
312 HandleKey(key, key_status);
315 void HandleFocusEvent(FocusChangeEvent *event)
317 static int old_joystick_status = -1;
319 if (event->type == EVENT_FOCUSOUT)
321 KeyboardAutoRepeatOn();
322 old_joystick_status = joystick.status;
323 joystick.status = JOYSTICK_NOT_AVAILABLE;
327 else if (event->type == EVENT_FOCUSIN)
329 /* When there are two Rocks'n'Diamonds windows which overlap and
330 the player moves the pointer from one game window to the other,
331 a 'FocusOut' event is generated for the window the pointer is
332 leaving and a 'FocusIn' event is generated for the window the
333 pointer is entering. In some cases, it can happen that the
334 'FocusIn' event is handled by the one game process before the
335 'FocusOut' event by the other game process. In this case the
336 X11 environment would end up with activated keyboard auto repeat,
337 because unfortunately this is a global setting and not (which
338 would be far better) set for each X11 window individually.
339 The effect would be keyboard auto repeat while playing the game
340 (game_status == GAME_MODE_PLAYING), which is not desired.
341 To avoid this special case, we just wait 1/10 second before
342 processing the 'FocusIn' event.
345 if (game_status == GAME_MODE_PLAYING)
348 KeyboardAutoRepeatOffUnlessAutoplay();
350 if (old_joystick_status != -1)
351 joystick.status = old_joystick_status;
355 void HandleClientMessageEvent(ClientMessageEvent *event)
357 if (CheckCloseWindowEvent(event))
361 void HandleButton(int mx, int my, int button)
363 static int old_mx = 0, old_my = 0;
377 if (HandleGadgets(mx, my, button))
379 /* do not handle this button event anymore */
380 mx = my = -32; /* force mouse event to be outside screen tiles */
386 HandleMainMenu(mx,my, 0,0, button);
389 case GAME_MODE_PSEUDO_TYPENAME:
390 HandleTypeName(0, KSYM_Return);
393 case GAME_MODE_LEVELS:
394 HandleChooseLevel(mx,my, 0,0, button);
397 case GAME_MODE_SCORES:
398 HandleHallOfFame(0,0, 0,0, button);
401 case GAME_MODE_EDITOR:
405 HandleInfoScreen(mx,my, 0,0, button);
408 case GAME_MODE_SETUP:
409 HandleSetupScreen(mx,my, 0,0, button);
412 case GAME_MODE_PLAYING:
414 if (button == MB_RELEASED)
416 if (IN_GFX_SCREEN(mx, my))
418 int sx = (mx - SX) / TILEX;
419 int sy = (my - SY) / TILEY;
423 printf("INFO: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
425 if (!IN_LEV_FIELD(x, y))
428 printf(" Feld[%d][%d] == %d ('%s')\n", x,y, Feld[x][y],
429 element_info[Feld[x][y]].token_name);
430 printf(" Back[%d][%d] == %d\n", x,y, Back[x][y]);
431 printf(" Store[%d][%d] == %d\n", x,y, Store[x][y]);
432 printf(" Store2[%d][%d] == %d\n", x,y, Store2[x][y]);
433 printf(" StorePlayer[%d][%d] == %d\n", x,y, StorePlayer[x][y]);
434 printf(" MovPos[%d][%d] == %d\n", x,y, MovPos[x][y]);
435 printf(" MovDir[%d][%d] == %d\n", x,y, MovDir[x][y]);
436 printf(" MovDelay[%d][%d] == %d\n", x,y, MovDelay[x][y]);
437 printf(" ChangeDelay[%d][%d] == %d\n", x,y, ChangeDelay[x][y]);
438 printf(" GfxElement[%d][%d] == %d\n", x,y, GfxElement[x][y]);
439 printf(" GfxAction[%d][%d] == %d\n", x,y, GfxAction[x][y]);
440 printf(" GfxFrame[%d][%d] == %d\n", x,y, GfxFrame[x][y]);
452 static boolean is_string_suffix(char *string, char *suffix)
454 int string_len = strlen(string);
455 int suffix_len = strlen(suffix);
457 if (suffix_len > string_len)
460 return (strcmp(&string[string_len - suffix_len], suffix) == 0);
463 #define MAX_CHEAT_INPUT_LEN 32
465 static void HandleKeysSpecial(Key key)
467 static char cheat_input[2 * MAX_CHEAT_INPUT_LEN + 1] = "";
468 char letter = getCharFromKey(key);
469 int cheat_input_len = strlen(cheat_input);
475 if (cheat_input_len >= 2 * MAX_CHEAT_INPUT_LEN)
477 for (i = 0; i < MAX_CHEAT_INPUT_LEN + 1; i++)
478 cheat_input[i] = cheat_input[MAX_CHEAT_INPUT_LEN + i];
480 cheat_input_len = MAX_CHEAT_INPUT_LEN;
483 cheat_input[cheat_input_len++] = letter;
484 cheat_input[cheat_input_len] = '\0';
487 printf("::: '%s' [%d]\n", cheat_input, cheat_input_len);
490 if (game_status == GAME_MODE_MAIN)
492 if (is_string_suffix(cheat_input, ":insert-solution-tape") ||
493 is_string_suffix(cheat_input, ":ist"))
495 InsertSolutionTape();
497 else if (is_string_suffix(cheat_input, ":reload-graphics") ||
498 is_string_suffix(cheat_input, ":rg"))
500 ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS);
503 else if (is_string_suffix(cheat_input, ":reload-sounds") ||
504 is_string_suffix(cheat_input, ":rs"))
506 ReloadCustomArtwork(1 << ARTWORK_TYPE_SOUNDS);
509 else if (is_string_suffix(cheat_input, ":reload-music") ||
510 is_string_suffix(cheat_input, ":rm"))
512 ReloadCustomArtwork(1 << ARTWORK_TYPE_MUSIC);
515 else if (is_string_suffix(cheat_input, ":reload-artwork") ||
516 is_string_suffix(cheat_input, ":ra"))
518 ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS |
519 1 << ARTWORK_TYPE_SOUNDS |
520 1 << ARTWORK_TYPE_MUSIC);
523 else if (is_string_suffix(cheat_input, ":dump-level") ||
524 is_string_suffix(cheat_input, ":dl"))
528 else if (is_string_suffix(cheat_input, ":dump-tape") ||
529 is_string_suffix(cheat_input, ":dt"))
534 else if (game_status == GAME_MODE_PLAYING)
537 if (is_string_suffix(cheat_input, ".q"))
538 for (i = 0; i < MAX_INVENTORY_SIZE; i++)
539 if (local_player->inventory_size < MAX_INVENTORY_SIZE)
540 local_player->inventory_element[local_player->inventory_size++] =
544 else if (game_status == GAME_MODE_EDITOR)
546 if (is_string_suffix(cheat_input, ":dump-brush") ||
547 is_string_suffix(cheat_input, ":DB"))
554 void HandleKey(Key key, int key_status)
557 boolean anyTextGadgetActiveOrJustFinished = anyTextGadgetActive();
558 static struct SetupKeyboardInfo custom_key;
566 { &custom_key.left, DEFAULT_KEY_LEFT, JOY_LEFT },
567 { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT },
568 { &custom_key.up, DEFAULT_KEY_UP, JOY_UP },
569 { &custom_key.down, DEFAULT_KEY_DOWN, JOY_DOWN },
570 { &custom_key.snap, DEFAULT_KEY_SNAP, JOY_BUTTON_1 },
571 { &custom_key.drop, DEFAULT_KEY_DROP, JOY_BUTTON_2 }
574 if (game_status == GAME_MODE_PLAYING)
576 /* only needed for single-step tape recording mode */
577 static boolean clear_button_2[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
578 static boolean element_dropped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
581 for (pnr = 0; pnr < MAX_PLAYERS; pnr++)
586 if (setup.input[pnr].use_joystick)
589 custom_key = setup.input[pnr].key;
591 for (i = 0; i < 6; i++)
592 if (key == *key_info[i].key_custom)
593 key_action |= key_info[i].action;
595 if (tape.single_step && clear_button_2[pnr])
597 stored_player[pnr].action &= ~KEY_BUTTON_2;
598 clear_button_2[pnr] = FALSE;
601 if (key_status == KEY_PRESSED)
602 stored_player[pnr].action |= key_action;
604 stored_player[pnr].action &= ~key_action;
606 if (tape.single_step && tape.recording && tape.pausing)
608 if (key_status == KEY_PRESSED &&
609 (key_action & (KEY_MOTION | KEY_BUTTON_1)))
611 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
613 if (key_action & KEY_MOTION)
615 if (stored_player[pnr].action & KEY_BUTTON_2)
616 element_dropped[pnr] = TRUE;
619 else if (key_status == KEY_RELEASED &&
620 (key_action & KEY_BUTTON_2))
622 if (!element_dropped[pnr])
624 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
626 stored_player[pnr].action |= KEY_BUTTON_2;
627 clear_button_2[pnr] = TRUE;
630 element_dropped[pnr] = FALSE;
633 else if (tape.recording && tape.pausing && (key_action & KEY_ACTION))
634 TapeTogglePause(TAPE_TOGGLE_MANUAL);
641 for (i = 0; i < 6; i++)
642 if (key == key_info[i].key_default)
643 joy |= key_info[i].action;
648 if (key_status == KEY_PRESSED)
649 key_joystick_mapping |= joy;
651 key_joystick_mapping &= ~joy;
656 if (game_status != GAME_MODE_PLAYING)
657 key_joystick_mapping = 0;
659 if (key_status == KEY_RELEASED)
662 if (game_status == GAME_MODE_PLAYING && AllPlayersGone &&
663 (key == KSYM_Return || key == setup.shortcut.toggle_pause))
665 CloseDoor(DOOR_CLOSE_1);
666 game_status = GAME_MODE_MAIN;
672 if (game_status == GAME_MODE_MAIN && key == setup.shortcut.toggle_pause)
674 if (setup.autorecord)
675 TapeStartRecording();
677 #if defined(PLATFORM_UNIX)
679 SendToServer_StartPlaying();
683 game_status = GAME_MODE_PLAYING;
691 if (game_status == GAME_MODE_MAIN || game_status == GAME_MODE_PLAYING)
693 if (key == setup.shortcut.save_game)
695 else if (key == setup.shortcut.load_game)
697 else if (key == setup.shortcut.toggle_pause)
698 TapeTogglePause(TAPE_TOGGLE_MANUAL);
701 HandleKeysSpecial(key);
703 if (HandleGadgetsKeyInput(key))
705 if (key != KSYM_Escape) /* always allow ESC key to be handled */
706 key = KSYM_UNDEFINED;
711 case GAME_MODE_PSEUDO_TYPENAME:
712 HandleTypeName(0, key);
716 case GAME_MODE_LEVELS:
717 case GAME_MODE_SETUP:
722 if (game_status == GAME_MODE_MAIN)
723 HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
724 else if (game_status == GAME_MODE_LEVELS)
725 HandleChooseLevel(0,0, 0,0, MB_MENU_CHOICE);
726 else if (game_status == GAME_MODE_SETUP)
727 HandleSetupScreen(0,0, 0,0, MB_MENU_CHOICE);
728 else if (game_status == GAME_MODE_INFO)
729 HandleInfoScreen(0,0, 0,0, MB_MENU_CHOICE);
733 if (game_status == GAME_MODE_LEVELS)
734 HandleChooseLevel(0,0, 0,0, MB_MENU_LEAVE);
735 else if (game_status == GAME_MODE_SETUP)
736 HandleSetupScreen(0,0, 0,0, MB_MENU_LEAVE);
737 else if (game_status == GAME_MODE_INFO)
738 HandleInfoScreen(0,0, 0,0, MB_MENU_LEAVE);
742 if (game_status == GAME_MODE_LEVELS)
743 HandleChooseLevel(0,0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
744 else if (game_status == GAME_MODE_SETUP)
745 HandleSetupScreen(0,0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
746 else if (game_status == GAME_MODE_INFO)
747 HandleInfoScreen(0,0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
751 if (game_status == GAME_MODE_LEVELS)
752 HandleChooseLevel(0,0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
753 else if (game_status == GAME_MODE_SETUP)
754 HandleSetupScreen(0,0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
755 else if (game_status == GAME_MODE_INFO)
756 HandleInfoScreen(0,0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
764 case GAME_MODE_SCORES:
769 game_status = GAME_MODE_MAIN;
774 HandleHallOfFame(0,0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
778 HandleHallOfFame(0,0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
786 case GAME_MODE_EDITOR:
787 if (!anyTextGadgetActiveOrJustFinished || key == KSYM_Escape)
788 HandleLevelEditorKeyInput(key);
791 case GAME_MODE_PLAYING:
796 RequestQuitGame(setup.ask_on_escape);
812 if (GameFrameDelay == 500)
813 GameFrameDelay = GAME_FRAME_DELAY;
815 GameFrameDelay = 500;
818 GameFrameDelay = (key - KSYM_0) * 10;
819 printf("Game speed == %d%% (%d ms delay between two frames)\n",
820 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
826 options.debug = FALSE;
827 printf("debug mode disabled\n");
831 options.debug = TRUE;
832 printf("debug mode enabled\n");
837 if (!global.fps_slowdown)
839 global.fps_slowdown = TRUE;
840 global.fps_slowdown_factor = 2;
841 printf("fps slowdown enabled -- display only every 2nd frame\n");
843 else if (global.fps_slowdown_factor == 2)
845 global.fps_slowdown_factor = 4;
846 printf("fps slowdown enabled -- display only every 4th frame\n");
850 global.fps_slowdown = FALSE;
851 global.fps_slowdown_factor = 1;
852 printf("fps slowdown disabled\n");
858 if (ScrollStepSize == TILEX/8)
859 ScrollStepSize = TILEX/4;
861 ScrollStepSize = TILEX/8;
862 printf("ScrollStepSize == %d\n", ScrollStepSize);
871 ScrollStepSize = TILEX/4;
876 ScrollStepSize = TILEX/8;
878 printf("MoveSpeed == %d\n", MoveSpeed);
883 ScrollStepSize = TILEX/8;
884 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
888 ScrollStepSize = TILEX/4;
889 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
893 ScrollStepSize = TILEX/2;
894 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
898 ScrollStepSize = TILEX;
899 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
908 for (i = 0; i < MAX_PLAYERS; i++)
910 printf("Player %d:\n", i);
911 printf(" jx == %d, jy == %d\n",
912 stored_player[i].jx, stored_player[i].jy);
913 printf(" last_jx == %d, last_jy == %d\n",
914 stored_player[i].last_jx, stored_player[i].last_jy);
930 if (key == KSYM_Escape)
932 game_status = GAME_MODE_MAIN;
942 if (button_status && game_status != GAME_MODE_PLAYING)
944 HandleButton(0, 0, -button_status);
948 #if defined(PLATFORM_UNIX)
956 static int HandleJoystickForAllPlayers()
961 for (i = 0; i < MAX_PLAYERS; i++)
966 if (!setup.input[i].use_joystick)
970 joy_action = Joystick(i);
971 result |= joy_action;
973 if (!setup.input[i].use_joystick)
976 stored_player[i].action = joy_action;
982 void HandleJoystick()
984 int joystick = HandleJoystickForAllPlayers();
985 int keyboard = key_joystick_mapping;
986 int joy = (joystick | keyboard);
987 int left = joy & JOY_LEFT;
988 int right = joy & JOY_RIGHT;
989 int up = joy & JOY_UP;
990 int down = joy & JOY_DOWN;
991 int button = joy & JOY_BUTTON;
992 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
993 int dx = (left ? -1 : right ? 1 : 0);
994 int dy = (up ? -1 : down ? 1 : 0);
999 case GAME_MODE_LEVELS:
1000 case GAME_MODE_SETUP:
1001 case GAME_MODE_INFO:
1003 static unsigned long joystickmove_delay = 0;
1005 if (joystick && !button &&
1006 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
1007 newbutton = dx = dy = 0;
1009 if (game_status == GAME_MODE_MAIN)
1010 HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1011 else if (game_status == GAME_MODE_LEVELS)
1012 HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1013 else if (game_status == GAME_MODE_SETUP)
1014 HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1015 else if (game_status == GAME_MODE_INFO)
1016 HandleInfoScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1020 case GAME_MODE_SCORES:
1021 HandleHallOfFame(0,0, dx,dy, !newbutton);
1024 case GAME_MODE_EDITOR:
1025 HandleLevelEditorIdle();
1028 case GAME_MODE_PLAYING:
1029 if (tape.playing || keyboard)
1030 newbutton = ((joy & JOY_BUTTON) != 0);
1032 if (AllPlayersGone && newbutton)
1034 CloseDoor(DOOR_CLOSE_1);
1035 game_status = GAME_MODE_MAIN;