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)
700 StartGameActions(options.network, setup.autorecord, NEW_RANDOMIZE);
702 if (setup.autorecord)
703 TapeStartRecording();
705 #if defined(NETWORK_AVALIABLE)
707 SendToServer_StartPlaying();
711 game_status = GAME_MODE_PLAYING;
720 if (game_status == GAME_MODE_MAIN || game_status == GAME_MODE_PLAYING)
722 if (key == setup.shortcut.save_game)
724 else if (key == setup.shortcut.load_game)
726 else if (key == setup.shortcut.toggle_pause)
727 TapeTogglePause(TAPE_TOGGLE_MANUAL);
730 HandleKeysSpecial(key);
732 if (HandleGadgetsKeyInput(key))
734 if (key != KSYM_Escape) /* always allow ESC key to be handled */
735 key = KSYM_UNDEFINED;
740 case GAME_MODE_PSEUDO_TYPENAME:
741 HandleTypeName(0, key);
745 case GAME_MODE_LEVELS:
746 case GAME_MODE_SETUP:
752 if (game_status == GAME_MODE_MAIN)
753 HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
754 else if (game_status == GAME_MODE_LEVELS)
755 HandleChooseLevel(0,0, 0,0, MB_MENU_CHOICE);
756 else if (game_status == GAME_MODE_SETUP)
757 HandleSetupScreen(0,0, 0,0, MB_MENU_CHOICE);
758 else if (game_status == GAME_MODE_INFO)
759 HandleInfoScreen(0,0, 0,0, MB_MENU_CHOICE);
763 if (game_status == GAME_MODE_LEVELS)
764 HandleChooseLevel(0,0, 0,0, MB_MENU_LEAVE);
765 else if (game_status == GAME_MODE_SETUP)
766 HandleSetupScreen(0,0, 0,0, MB_MENU_LEAVE);
767 else if (game_status == GAME_MODE_INFO)
768 HandleInfoScreen(0,0, 0,0, MB_MENU_LEAVE);
772 if (game_status == GAME_MODE_LEVELS)
773 HandleChooseLevel(0,0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
774 else if (game_status == GAME_MODE_SETUP)
775 HandleSetupScreen(0,0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
776 else if (game_status == GAME_MODE_INFO)
777 HandleInfoScreen(0,0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
781 if (game_status == GAME_MODE_LEVELS)
782 HandleChooseLevel(0,0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
783 else if (game_status == GAME_MODE_SETUP)
784 HandleSetupScreen(0,0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
785 else if (game_status == GAME_MODE_INFO)
786 HandleInfoScreen(0,0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
794 case GAME_MODE_SCORES:
800 game_status = GAME_MODE_MAIN;
805 HandleHallOfFame(0,0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
809 HandleHallOfFame(0,0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
817 case GAME_MODE_EDITOR:
818 if (!anyTextGadgetActiveOrJustFinished || key == KSYM_Escape)
819 HandleLevelEditorKeyInput(key);
822 case GAME_MODE_PLAYING:
827 RequestQuitGame(setup.ask_on_escape);
843 if (GameFrameDelay == 500)
844 GameFrameDelay = GAME_FRAME_DELAY;
846 GameFrameDelay = 500;
849 GameFrameDelay = (key - KSYM_0) * 10;
850 printf("Game speed == %d%% (%d ms delay between two frames)\n",
851 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
857 options.debug = FALSE;
858 printf("debug mode disabled\n");
862 options.debug = TRUE;
863 printf("debug mode enabled\n");
868 if (!global.fps_slowdown)
870 global.fps_slowdown = TRUE;
871 global.fps_slowdown_factor = 2;
872 printf("fps slowdown enabled -- display only every 2nd frame\n");
874 else if (global.fps_slowdown_factor == 2)
876 global.fps_slowdown_factor = 4;
877 printf("fps slowdown enabled -- display only every 4th frame\n");
881 global.fps_slowdown = FALSE;
882 global.fps_slowdown_factor = 1;
883 printf("fps slowdown disabled\n");
889 if (ScrollStepSize == TILEX/8)
890 ScrollStepSize = TILEX/4;
892 ScrollStepSize = TILEX/8;
893 printf("ScrollStepSize == %d\n", ScrollStepSize);
902 ScrollStepSize = TILEX/4;
907 ScrollStepSize = TILEX/8;
909 printf("MoveSpeed == %d\n", MoveSpeed);
914 ScrollStepSize = TILEX/8;
915 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
919 ScrollStepSize = TILEX/4;
920 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
924 ScrollStepSize = TILEX/2;
925 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
929 ScrollStepSize = TILEX;
930 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
934 printf("::: currently using game engine version %d\n",
935 game.engine_version);
944 for (i = 0; i < MAX_PLAYERS; i++)
946 printf("Player %d:\n", i);
947 printf(" jx == %d, jy == %d\n",
948 stored_player[i].jx, stored_player[i].jy);
949 printf(" last_jx == %d, last_jy == %d\n",
950 stored_player[i].last_jx, stored_player[i].last_jy);
966 if (key == KSYM_Escape)
968 game_status = GAME_MODE_MAIN;
978 if (button_status && game_status != GAME_MODE_PLAYING)
980 HandleButton(0, 0, -button_status);
984 #if defined(NETWORK_AVALIABLE)
992 static int HandleJoystickForAllPlayers()
997 for (i = 0; i < MAX_PLAYERS; i++)
1002 if (!setup.input[i].use_joystick)
1006 joy_action = Joystick(i);
1007 result |= joy_action;
1009 if (!setup.input[i].use_joystick)
1012 stored_player[i].action = joy_action;
1018 void HandleJoystick()
1020 int joystick = HandleJoystickForAllPlayers();
1021 int keyboard = key_joystick_mapping;
1022 int joy = (joystick | keyboard);
1023 int left = joy & JOY_LEFT;
1024 int right = joy & JOY_RIGHT;
1025 int up = joy & JOY_UP;
1026 int down = joy & JOY_DOWN;
1027 int button = joy & JOY_BUTTON;
1028 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
1029 int dx = (left ? -1 : right ? 1 : 0);
1030 int dy = (up ? -1 : down ? 1 : 0);
1034 case GAME_MODE_MAIN:
1035 case GAME_MODE_LEVELS:
1036 case GAME_MODE_SETUP:
1037 case GAME_MODE_INFO:
1039 static unsigned long joystickmove_delay = 0;
1041 if (joystick && !button &&
1042 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
1043 newbutton = dx = dy = 0;
1045 if (game_status == GAME_MODE_MAIN)
1046 HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1047 else if (game_status == GAME_MODE_LEVELS)
1048 HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1049 else if (game_status == GAME_MODE_SETUP)
1050 HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1051 else if (game_status == GAME_MODE_INFO)
1052 HandleInfoScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1056 case GAME_MODE_SCORES:
1057 HandleHallOfFame(0,0, dx,dy, !newbutton);
1060 case GAME_MODE_EDITOR:
1061 HandleLevelEditorIdle();
1064 case GAME_MODE_PLAYING:
1065 if (tape.playing || keyboard)
1066 newbutton = ((joy & JOY_BUTTON) != 0);
1068 if (AllPlayersGone && newbutton)
1070 CloseDoor(DOOR_CLOSE_1);
1071 game_status = GAME_MODE_MAIN;