+Release Version 3.1.0 [07 JUN 2004]
+-----------------------------------
+ - fixed obvious bug with wrong "Murphy" graphics (when digging etc.)
+ - fixed a lot of Emerald Mine and Supaplex game engine emulation bugs
+ - re-converted Emerald Mine and Supaplex levels to apply engine fixes
+ - changed default snap/drop keys from left/right Shift to Control keys
+ - added level loader for loading native Emerald Mine levels
+ - added level loader for loading native Supaplex packed levels
+ - added group elements for multiple matches and random element creation
+ - added elements that can be digged or left behind by custom elements
+ - added element "Sokoban field with player" missing for Sokoban levels
+ - added custom element features to allow building of teleporters
+ - added option to use step limit instead of time limit for level
+ - added pressing "space" key as valid action to select menu options
+ - added clipboard (cut and paste buttons) for custom and group elements
+ - added shortcut to dump brush (type ":DB" in editor) for use in forum
+ - added network multiplayer code for Windows (still only command line)
+ - replaced old tutorial level set with far better one by Niko Böhm
+ - "contributions" levels now separate package to make base set smaller
+ - too many bugfixes and changes to list them all here (see ChangeLog)
+
Release Version 3.0.8 [14 DEC 2003]
-----------------------------------
- added "musicinfo.conf" for menu and level music configuration
- added "editorsetup.conf" for editor element list configuration
- added "copy" and "exchange" functions for custom elements to editor
- added configurable "bored" and "sleeping" animations for the player
- - added "awakening" sound for player waking up after sleeping
+ - added "awakening" sound for player when waking up after sleeping
- added configurable element animations for info screen
- added configurable music credits for info screen
- added configurable level set information for info screen
- added warnings for undefined token values in artwork config files
- - menu text now directly clickable
+ - menu entries now also selectable by clicking on entry text
- better sniksnak turning movement (two steps instead of only one)
- fixed turning movement of butterflies and fireflies (no frame reset)
- fixed bug with wrong default impact sound for colored emeralds
--- /dev/null
+2004-06-07
+ * fixed bug with crash when writing user levelinfo.conf the first time
+
+2004-06-06
+ * added option "convert LEVELDIR [NR]" to command line batch commands
+ * re-converted Supaplex levels to apply latest engine fixes
+ * changed "use graphic/sound of element" to "use graphic of element"
+ due to compatibility problems with some levels ("bug machine" etc.)
+
+2004-05-23
+ * fixed bug with CE change replacing player with same or other player
+
+2004-05-16
+ * fixed bug with opaque font in envelope with background graphic when
+ background graphic is not transparent itself
+
+2004-05-12
+ * added "gravity on" and "gravity off" ports for Supaplex compatibility
+ * corrected original Supaplex level loading code to use these new ports
+ * also corrected Supaplex loader to auto-count infotrons if set to zero
+
+2004-05-10
+ * fixed bug with missing initialization of "modified" flag for GEs
+
+2004-05-09
+ * fixed bug that caused endless recursion loop when relocating player
+ * fixed tape recorder bug in "step mode" when using "pause before end"
+ * fixed tape recorder bug when changing from "warp forward" mode
+
+2004-05-08
+ * fixed bug with "when touching" for pushed elements at last position
+
+2004-05-05
+ * fixed bug that caused two activated toolbox buttons in level editor
+ * fixed bug with exploding dynabomb under player due to other explosion
+
+2004-05-02
+ * fixed bug with creating walkable custom element under player (again)
+ * fixed bug with not copying explosion type when copying CEs in editor
+ * fixed graphical bug when drawing player in setup menu (input devices)
+ * fixed graphical bug when the player is pushing an accessible element
+ * fixed bug with classic switchable elements triggering CE changes
+ * fixed bug with entering/leaving walkable element in RelocatePlayer()
+ * fixed crash bug when CE leaves behind the trigger player element
+
+2004-04-30
+ * fixed bug with broken tubes after placing/exploding dynamite in them
+ * fixed bug with exploding dynamite under player due to other explosion
+ * fixed bug with not resetting push delay under certain circumstances
+
+2004-04-27
+ * added option "handicap" for "levelinfo.conf" (thanks to Niko Böhm)
+ * added network multiplayer code for Windows (thanks to Niko Böhm)
+
+2004-04-25
+ * added option "reachable despite gravity" for gravity movement
+ * changed gravity movement of most classic walkable and passable
+ elements back to "not reachable" (for compatibility reasons)
+
+2004-04-24
+ * fixed (removed) "indestructible" / "can explode" dependency in editor
+ * fixed (removed) "accessible inside" / "protected" dependency
+ * fixed (removed) "step mode" / "shield time" dependency
+
+2004-04-23
+ * fixed dynabombs exploding now into anything diggable
+ * fixed Supaplex style gravity movement into buggy base now impossible
+ * added pressing key "space" as valid action to select menu options
+
+2004-04-20
+ * added "replace when walkable" to relocate player to walkable element
+ * added "enter"/"leave" event for elements affected by relocation
+ * fixed "direct"/"indirect" change order also for "when change" event
+ * fixed graphical bug when pushing things from elements walkable inside
+
+2004-04-18
+ * fixed graphic bug when player is snapping while moving in old levels
+ * fixed bug when a moving custom element leaves a player element behind
+ * fixed bug with mole not disappearing when moving into acid pool
+ * fixed bug with incomplete path setting when using "--basepath" option
+ * moving CE can now leave walkable elements behind under the player
+ * when relocating, player can be set on walkable element now
+ * fixed another gravity movement bug
+
+2004-04-12
+ * uploaded pre-release (test) version 3.1.0-2 binary and source code
+
+2004-04-10
+ * added "collectible" and "removable" to extended replacement types
+ (where "removable" replaces "diggable" and "collectible" elements)
+ * added "collectible & throwable" (to throw element to the next field)
+ * fixed bug with CEs digging elements that are just about to explode
+ * changed mouse cursor now always being visible when game is paused
+
+2004-04-09
+ * added possibility to push/press accessible elements from a side that
+ is not accessible
+ * fixed bug with not setting actual date when appending to tape
+
+2004-04-07
+ * fixed bug with incorrectly initialized custom element editor graphics
+
+2004-04-04
+ * corrected set "Contributions_1995-2000/rnd_kjell_kristiansson":
+ - number of levels corrected from 18 to 17 in "levelinfo.conf"
+
+2004-03-31
+ * fixed bug with destroyed robot wheel still attracting robots forever
+ * fixed bug with time gate switch deactivating after robot wheel time
+ (while the time gate itself is not affected by this misbehaviour)
+ * changed behaviour of BD style amoeba to always get blocked by player
+ (before it was different when there were non-BD elements in level)
+ * fixed bug with player destroying indestructable elements with shield
+
+2004-03-26
+ * added option to make growing elements grow into anything diggable
+ (for the various amoeba types, biomaze and "game of life")
+
+2004-03-24
+ * fixed bug with movable elements not moving after left behind by CEs
+ * changed gravity movement to anything diggable, not only sand/base
+ * optionally allowing passing to walkable element, not only empty space
+ * added option "can pass to walkable element" for players
+ * finally fixed gravity movement (hopefully)
+
+2004-03-23
+ * fixed bug with movable elements not moving anymore after falling down
+
+2004-03-22
+ * fixed another bug with custom elements digging and leaving elements
+ * fixed bug with "along left/right side" and automatic start direction
+ * trigger elements now also displayed when "more custom" deactivated
+ * fixed bug with clipboard element initialized when loading new level
+ * added option "drop delay" to set delay before dropping next element
+
+2004-03-21
+ * uploaded pre-release (test) version 3.1.0-1 binary and source code
+
+2004-03-20
+ * added copy and paste functions for custom change pages
+ * enhanced graphical display and functionality of tape recorder
+ * fixed bug with custom elements digging and leaving elements
+
+2004-03-19
+ * added move speed faster than "very fast" for custom elements
+ * fixed bug with 3+3 style explosions and missing border content
+ * fixed little bug when copying custom elements in the editor
+ * enhanced custom element changes by more side trigger actions
+
+2004-03-16
+ * added option "no scrolling when relocating" for instant teleporting
+ * uploaded pre-release (test) version 3.1.0-0 binary and source code
+
+2004-03-15
+ * added trigger element and trigger player to use as target elements
+ * added copy and paste functions for custom and group elements
+
+2004-03-14
+ * fixed graphical bug when displaying explosion animations
+ * fixed bug when appending to tapes, resulting in broken tapes
+ * re-recorded a few tapes broken by fixing gravity checking bug
+
+2004-03-13
+ * "can move into acid" property now for all elements independently
+ * "can fall into acid" property for player stored in same bitfield now
+ * added option for deadliness of Supaplex 'sniksnak' and 'electron'
+ * version number set to 3.1.0 (finally!)
+
+2004-03-09
+ * changed tape recording to only record input, not programmed actions
+
+2004-03-08
+ * fixed totally broken (every 8th frame skipped) step-by-step recording
+ * fixed bug with requester not displayed when quick-loading interrupted
+ * added option "can fall into acid (with gravity)" for players
+ * fixed bug with player not falling when snapping down with gravity
+
+2004-03-07
+ * fixed bug which messed up key config when using keypad number keys
+
+2004-03-03
+ * fixed bug which allowed moving upwards even when gravity was active
+ * fixed bug with missing error handling when dumping levels or tapes
+
+2004-03-02
+ * added different colored editor graphics for Supaplex gravity tubes
+
+2004-03-01
+ * fixed bug that allowed solvable tapes for unsolvable levels
+
+2004-02-28
+ * use unlimited number of droppable elements when "count" set to zero
+ * added option to use step limit instead of time limit for level
+
+2004-02-27
+ * added player and change page as trigger for custom element change
+
+2004-02-24
+ * fixed bug with exploding amoeba (explosion 3x3 instead of 1x1)
+
+2004-02-22
+ * fixed bug with dark yamyam changing to acid when moving over acid
+ * fixed handling of levels with more than 999 seconds level time
+ (example: level 76 of "Denmine")
+
+2004-02-21
+ * "spring push bug" reintroduced as configurable element property
+ * fixed bug with missing properties for "mole"
+ * fixed bug that showed up when fixing the above "mole" properties bug
+ * added option "can move into acid" for all movable elements
+ * fixed graphical bug for elements moving into acid
+ * changed event handling to handle all pending events before going on
+
+2004-02-17
+ * fixed bug which caused all CE change pages to be ignored which had
+ the same change event, but used a different element side
+ (reported by Simon Forsberg)
+
+ * fixed bug which caused elements that can move and fall and that are
+ transported by a conveyor belt to continue moving into that direction
+ after leaving the conveyor belt, regardless of their own movement
+ type; only elements which can not move are transported now
+ (reported by Simon Forsberg)
+
+ * fixed bug which could cause an array overflow in RelocatePlayer()
+ (reported by Niko Böhm)
+
+ * changed Emerald Mine style "passable / over" elements to "protected"
+ (fixing unsolvable level 10 of "Bondmine 9" with bug beside gate)
+
+ * added new option to select from which side a "walkable/passable"
+ element can be entered
+
+2004-02-16
+ * added explosion and ignition delay for elements that can explode
+
+2004-02-05
+ * fixed bug which caused player not being protected against enemies
+ when a CE was "walkable / inside" and was not "indestructible"
+ * added "walkable/passable" fields to be "protected/unprotected"
+ against enemies, even if not accessible "inside" but "over/under"
+
+2004-02-04
+ * corrected move pattern to 32 bit and initial move direction to 8 bit
+
+2004-02-03
+ * added second custom element base configuration page
+
+2004-02-02
+ * added some special EMC mappings to Emerald Mine level loader
+ (also covering previously unknown element in level 0 of "Bondmine 8")
+
+2004-01-30
+ * added option to block last field when player is moving (for Supaplex)
+ * adjusted push delay of Supaplex elements
+ * removed delays for envelopes etc. when replaying with maximum speed
+ * fixed bug when dropping element on a field that just changed to empty
+
+2004-01-29
+ * fixed bug: infotrons can now smash yellow disks
+ * fixed bug: when gravity active, port above player can now be entered
+ * removed "one white dot" mouse pointer which irritated some people
+
+2004-01-26
+ * added "choice type" for group element selection
+
+2004-01-25
+ * fixed bug with initial invulnerability of non-yellow player
+
+2004-01-23
+ * added level loader for loading native Supaplex packed levels
+ (including multi-part levels like the "splvls99" levels)
+
+2004-01-19
+ * fixed bug which allowed creating emeralds by escaping explosions
+
+2004-01-18
+ * custom elements can change (limited) or leave (unlimited) elements
+ * finally added multiple matches using group elements
+ * added shortcut to dump brush (type ":DB" in editor) for use in forum
+
+2004-01-17
+ * added new start movement type "previous" for continued CE movement
+ * added new start movement type "random" for random CE movement start
+
+2004-01-17
+ * added new element "sokoban_field_player" needed for Sokoban levels
+ (thanks to Ed Booker for pointing this out!)
+
+2004-01-15
+ * added elements that can be digged or left behind by custom elements
+
+2004-01-12
+ * added group elements for multiple matches and random element creation
+
+2004-01-11
+ * fixed some graphical errors displayed in old levels
+
+2004-01-10
+ * fixed wrong double speed movement after passing closing gates
+
+2004-01-03
+ * added level loader for loading native Emerald Mine levels
+
+2004-01-02
+ * changes for "shooting" style CE movement
+
+2004-01-01
+ * Happy New Year! ;-)
+
+2003-12-27
+ * changed default snap/drop keys from left/right Shift to Control keys
+
+2003-12-27
+ * fixed bug with dead player getting reanimated from custom element
+
+2003-12-14
+ * fixed bug with wrong penguin graphics (when entering exit)
+
+2003-12-14
+ * fixed bug with wrong "Murphy" graphics (when digging etc.)
+
+2003-12-14
+ * version number set to 3.0.9
+
+2003-12-14
+ * version 3.0.8 released
+
+2003-12-13
+ * added function checked_free()
+
+2003-12-13
+ * fixed bug with double nut cracking sound
+ (by eliminating "default element action sound" assignment in init.c)
+
+2003-12-10
+ * fixed crash when no music info files are available
+
+2003-12-07
+ * fixed boring and sleeping sounds
+
+2003-12-05
+ * added "maze runner" and "maze hunter" movement types
+ * added extended collision conditions for custom elements
+
+2003-12-03
+ * added warnings for undefined token values in artwork config files
+
+2003-12-02
+ * added menu entry for level set information to the info screen
+
+2003-12-02
+ * fixed bug with wrong default impact sound for colored emeralds
+
+2003-11-30
+ * added several sub-screens for the info screen
+ * menu text now also clickable (not only blue/red sphere left of it)
+
+2003-11-25
+ * added configurable "bored" and "sleeping" animations for the player
+ * added "awakening" sound for player when waking up after sleeping
+
+2003-11-22
+ * added "copy" and "exchange" functions for custom elements to editor
+
+2003-11-21
+ * added configurable element animations for info screen
+
+2003-11-20
+ * added configurable music credits for info screen
+
+2003-11-19
+ * finally fixed tape recording when player is created from CE change
+
+2003-11-18
+ * added "editorsetup.conf" for editor element list configuration
+
+2003-11-16
+ * added "musicinfo.conf" for menu and level music configuration
+
+2003-11-14
+ * fixed a very nasty bug in dragon turning code in TurnRoundExt()
+ (that only showed up on Linux, but not on Windows systems)
+
+2003-11-13
+ * fixed turning movement of butterflies and fireflies (no frame reset)
+ * enhanced sniksnak turning movement (two steps instead of only one)
+
+2003-11-10
+ * version number set to 3.0.8
+
+2003-11-10
+ * version 3.0.7 released
+
+2003-11-09
+ * fixed reset of player animation frame when, for example,
+ walking, digging or collecting share the same animation
+ * fixed CE with "deadly when touching" exploding when touching amoeba
+
+2003-11-08
+ * fixed tape recording when player is created from CE element change
+
+2003-11-04
+ * introduced "turning..." action graphic for elements with move delay
+ (non-CE: bug, spaceship, sniksnak, mole, pacman, yamyam)
+ * added turning animations for bug, spaceship and sniksnak
+
+2003-11-03
+ * prevent "extended" changed elements from delay change in same frame
+
+2003-11-02
+ * fixed bug when pushing element that can move away to the side
+ (like pushing falling elements, but now with moving elements)
+
+2003-11-01
+ * finally fixed serious bug in code for delayed element pushing (again)
+
+2003-10-19
+ * unavailable setup options now marked as "n/a" instead of "off"
+ * new boolean directive "latest_engine" for "levelinfo.conf": when set
+ to "true", levels are always played with the latest game engine,
+ which is desired for levels that are imported from other games; all
+ other levels are played with the engine version stored in level file
+ (which is normally the engine version the level was created with)
+
+2003-10-18
+ * fixed serious bug in code for delayed element pushing
+ * fixed little bug in animation frame selection for pushed elements
+ * speed-up of reading config file for verbose output
+
+2003-10-08
+ * added configuration option for opening and closing Supaplex exit
+ * added configuration option for moving up/down animation for Murphy
+ * fixed incorrectly displayed animation for attacking dragon
+ * fixed bug with not setting initial gravity for each new game
+ * fixed bug with teleportation of player by custom element change
+ * fixed bug with player not getting smashed by rock sometimes
+
+2003-10-06
+ * version number set to 3.0.7
+
+2003-10-06
+ * version 3.0.6 released
+
+2003-10-05
+ * added support for MP3 music for SDL version through SMPEG library
+
+2003-10-03
+ * fixed bug when initializing font graphic structure
+ * fixed bug with animation mode "pingpong" when using only 1 frame
+ * fixed bug with extended change target introduced in 3.0.5
+ * fixed bug where passing over moving element doubles player speed
+ * fixed bug with elements continuing to move into push direction
+ * fixed bug with duplicated player when dropping bomb with shield on
+ * added "switching" event for custom elements ("pressing" only once)
+ * fixed switching bug (resetting flag when not switching but not idle)
+
+2003-09-29
+ * fixed element tokens for certain file elements with ".active" etc.
+
+2003-09-29
+ * version number set to 3.0.6
+
+2003-09-29
+ * version 3.0.5 released
+
+2003-09-28
+ * now four envelope elements available
+ * font, background, animation and sound for envelope now configurable
+ * main menu doors opening/closing animation type now configurable
+
+2003-09-27
+ * active/inactive sides configurable for custom element changes
+ * new movement type "move when pushed" available for custom elements
+
+2003-09-20
+ * fixed bug in multiple config pages loader code that caused crashes
+
+2003-09-13
+ * enhanced (remaining low-resolution) Supaplex graphics
+
+2003-09-13
+ * version number set to 3.0.5
+
+2003-09-13
+ * version 3.0.4 released
+
+2003-09-12 src/tools.c
+ * fixed bug in custom definition of crumbled element graphics
+
+2003-09-11 src/files.c
+ * fixed bug in multiple config pages code that caused crashes
+
+2003-09-08
+ * version number set to 3.0.4
+
+2003-09-08
+ * version 3.0.3 released
+
+2003-09-07
+ * added music to Supaplex classic level set
+
+2003-09-07 src/libgame/misc.c
+ * added support for loading various music formats through SDL_mixer
+
+2003-09-06 (various source files)
+ * fixed several nasty bugs that may have caused crashes on some systems
+ * added envelope content which gets displayed when collecting envelope
+ * added multiple change event pages for custom elements
+
+2003-08-24 src/game.c
+ * fixed problem with player animation when snapping and moving
+
+2003-08-23 src/screens.c, src/cartoons.c, src/libgame/toons.c
+ * fixed problem with flickering when drawing toon animations
+
+2003-08-23 src/libgame/sdl.c
+ * fixed problem with setting mouse cursor in SDL version in fullscreen
+
+2003-08-23 src/game.c
+ * fixed bug (missing array boundary check) which could crash the game
+
+2003-08-23
+ * version number set to 3.0.3
+
+2003-08-22
+ * version 3.0.2 released
+
+2003-08-21 src/game.c
+ * fixed bug with creating inaccessible elements at player position
+
+2003-08-20 src/init.c
+ * fixed bug with not finding current level artwork directory
+
+2003-08-20 src/files.c
+ * fixed bug with choosing wrong engine version when playing tapes
+ * fixed bug with messing up custom element properties in 3.0.0 levels
+
+2003-08-18
+ * version number set to 3.0.2
+
+2003-08-18
+ * version 3.0.1 released
+
+2003-08-17 (no source files affected)
+ * changed all "classic" PCX image files with 16 colors or less to
+ 256 color (8 bit) storage format, because the Allegro game library
+ cannot handle PCX files with less than 256 colors (contributed
+ graphics are not affected and might look wrong in the DOS version)
+
+2003-08-16 src/init.c
+ * fixed bug which (for example) crashed the level editor when defining
+ "dynamite.EDITOR: [NONE]", because graphics may not be undefined
+ (only set to default) -- invalid graphics now set to default graphic
+
+2003-08-16 src/init.c
+ * fixed graphical bug of player digging/collecting/snapping element
+ when no corresponding graphic/animation is defined for this action,
+ resulting in player being drawn as EL_EMPTY (which should only be
+ done to elements being collected, but not to the player)
+
+2003-08-16 src/game.c
+ * fixed small graphical bug of player not totally moving into exit
+
+2003-08-16 src/libgame/setup.c
+ * fixed bug with wrong MS-DOS 8.3 filename conversion
+
+2003-08-16 src/tools.c
+ * fixed bug with invisible mouse cursor when pressing ESC while playing
+
+2003-08-16 (various source files)
+ * added another 128 custom elements (disabled in editor by default)
+
+2003-08-16 src/editor.c
+ * fixed NULL string bug causing Solaris to crash in sprintf()
+
+2003-08-16 src/screen.c
+ * fixed drawing over scrollbar on level selection with custom fonts
+
+2003-08-15 src/game.c
+ * cleanup of simple sounds / loop sounds / music settings
+
+2003-08-08 (various source files)
+ * added custom element property for dropping collected elements
+
+2003-08-08 src/conf_gfx.c
+ * fixed bug with missing graphic for active red disk bomb
+
+2003-08-07 src/files.c, src/editor.c src/game.c, src/main.h
+ * extended variable "level.gravity" to "level.initial_gravity" and
+ "game.current_gravity" to prevent level setting from being changed
+ by playing the level (keeping the runtime value after playing)
+
+ * fixed graphics bug when digging element that has 'crumbled' graphic
+ definition, but not 'diggable' graphic definition
+
+2003-08-06
+ * version number set to 3.0.1
+
+2003-08-05
+ * version 3.0.0 released
+
+2003-08-05
+ * various bug fixes; among others:
+ - fixed bug with pushing spring over empty space
+ - fixed bug with leaving tube while placing dynamite
+ - fixed bug with explosion of smashed penguins
+ - allow Murphy player graphic in levels with non-Supaplex elements
+
+2003-04-07
+ * various changes
+ * I have forgotten to document changes for some time
+
+2002-12-31
+ * pre-release version 2.2.0rc1 released
+
+2002-08-25
+ * version number set to 2.1.2
+
+2002-08-13
+ * version 2.1.1 released
+
+2002-08-10
+ * version number set to 2.1.1
+
+2002-08-05
+ * version 2.1.0 released
+
+2002-05-19
+ * version number set to 2.1.0
+
+2002-04-03 to 2002-05-19 (various source files)
+ * graphics, sounds and music now fully configurable
+ * bug fixed that prevented walking through tubes when gravity on
+
+2002-04-02 src/events.c, src/editor.c
+ * Make Escape key less aggressive when playing or when editing level.
+ This can be configured as an option in the setup menu. (Default is
+ "less aggressive" which means "ask user if something can be lost"
+ when pressing the Escape key.)
+
+2002-04-02 src/screen.c
+ * Added "graphics setup" screen.
+
+2002-04-01 src/screen.c
+ * Changed "choose level" setup screen stuff to be more generic (to
+ make it easier to add more "choose from generic tree" setup screens).
+
+2002-04-01 src/config.c, src/timestamp.h
+ * Added source files "src/config.[ch]" and "src/timestamp.h" (which
+ automatically gets created by "src/Makefile" and contains an actual
+ compile-time timestamp to identify development versions of the game).
+
+2002-03-31 src/tape.c, src/events.c
+ * Added quick game/tape save/load functions to tape stuff which can be
+ invoked by a keyboard shortcut. Default: "F1" saves game/tape, "F2"
+ loads previously recorded tape and directly goes into recording mode
+ from the end of the tape (therefore appending to the tape).
+
+2002-03-31 src/tape.c
+ * Added "index mark" function to tape recorder. When playing or
+ recording, "eject" button changes to "index" button. Setting index
+ mark is not yet implemented, but pressing index button when playing
+ allows very quick advancing to end of tape (when normal playing),
+ very fast forward mode (when playing with normal fast forward) or
+ very fast reaching of "pause before end of tape" (when playing with
+ "pause before end" playing mode).
+
+2002-03-30 src/cartoons.c
+ * Moved some stuff from cartoons.c to the new "src/libgame/toons.c".
+
+2002-03-29 src/screen.c
+ * Changed setup screen stuff to be more generic (to make it easier
+ to add more setup screens).
+
+2002-03-23 src/main.c, src/main.h
+ * Various changes due to the introduction of the new libgame files
+ "setup.c" and "joystick.c".
+
+2002-03-23 src/files.c
+ * Generic parts of "src/files.c" (mainly setup and level directory
+ stuff) moved to new libgame file "src/libgame/setup.c".
+
+2002-03-23 src/joystick.c
+ * File "src/joystick.c" moved to libgame source tree, with
+ correspondig changes.
+
+2002-03-22 src/screens.c
+ * "HandleChooseLevel()": Another bug in level series navigation fixed.
+ (Wrong level series information displayed when entering main group.)
+
+2002-03-22 src/editor.c
+ * Slight change to support new gadget event "GD_EVENT_INFO_LEAVING".
+
+2002-03-22 src/editor.c
+ * Changed behaviour of "Escape" key in level editor to be more
+ intuitive: When in "Element Properties" or "Level Info" mode,
+ return to "Drawing Mode" instead of leaving the level editor.
+
+2002-03-21 src/game.c, src/editor.c, src/files.c
+ * 2.0.1 introduced the corrected "Emerald Mine" style behaviour of
+ gems (emeralds, diamonds, ...) slipping down from normal wall,
+ steel wall and growing wall (as in E.M.C. style levels). Although
+ the behaviour of contributed and private levels wasn't changed (due
+ to the use of "level.game_version"; see previous entry), editing
+ those levels will (of course) change the behaviour accordingly.
+
+ This change seems a bit too hard after thinking about it, because
+ the EM style behaviour is not the "expected" behaviour (gems would
+ normally only slip down from "rounded" walls). Therefore this was
+ now changed to an element property for gem style elements, with the
+ default setting "off" (which means: no special EM style behaviour).
+ To fix older converted levels, this flag is set to "on" for pre-2.0
+ levels that are neither contributed nor private levels.
+
+2002-03-20 src/files.h
+ * Corrected settings for "level.game_version" depending of level type.
+ (Contributed and private levels always get played with game engine
+ version they were created with, while converted levels always get
+ played with the most recent version of the game engine, to let new
+ corrections of the emulation behaviour take effect.)
+
+2002-03-20 src/main.h
+ * Added "#include <time.h>". This seems to be needed by "tape.c" for
+ compiling the SDL version on some systems.
+ Thanks to the several people who pointed this out.
+
+2002-03-19
+ * Version number set to 2.0.2.
+
+2002-03-19
+ * Version 2.0.1 released.
+
+2002-03-18 src/screens.c
+ * "HandleChooseLevel()": Small bug in level series navigation fixed.
+
+2002-03-18 src/files.c [src/libgame/misc.c]
+ * Moved some common functions from src/files.c to src/libgame/misc.c.
+
+2002-03-18 src/files.c [src/libgame/misc.c]
+ * Changed permissions for new directories and saved files (especially
+ score files) according to suggestions of Debian users and mantainers.
+ Thanks to Drew Parsons <dparsons@emerall.com> for the patch.
+
+2002-03-17 src/files.c
+ * Changed "{Load|Save}{Level|Tape}()" to IFF style file format:
+ Replaced "cookie" header string ("ROCKSNDIAMONDS_...\n") with
+ real IFF style header "RND1....XXXX" (where "XXXX" is "CAVE"
+ for levels and "TAPE" for tapes). Old "cookie" style format is
+ still supported for reading. New level and tape files are written
+ in new format.
+
+ * New IFF chunk "VERS" contains version numbers for file and game
+ (where "game version" is the version of the program that wrote the
+ file, and "file version" is a version number to distinguish files
+ with different format, for example after adding new features).
+
+2002-03-15 src/screen.c
+ * "DrawHallOfFame()": "FadeSounds()" when entering the hall of fame.
+ (Before, you heard a mixture of the in-game music and the
+ hall-of-fame music.)
+
+2002-03-14 src/events.c
+ * Function "DumpTape()" (files.c) now available by pressing 't' from
+ main menu (when in DEBUG mode).
+
+2002-03-14 src/game.c
+ * "GameWon()": When game was won playing a tape, now there is no delay
+ raising the score and no corresponding sound is played.
+
+2002-03-14 src/files.c
+ * Changed "LoadTape()" for real chunk support and also adjusted
+ "SaveTape()" accordingly.
+
+2002-03-14 src/game.c, src/tape.c, src/files.c
+ * Important changes to tape format: The old tape format stored all
+ actions with a real effect with a corresponding delay between the
+ stored actions. This had some major disadvantages (for example,
+ push delays had to be ignored, pressing a button for some seconds
+ mutated to several single button presses because of the non-action
+ delays between two action frames etc.). The new tape format just
+ stupidly records all device actions and replays them later. I really
+ don't know why I haven't solved it that way before?! Old-style tapes
+ (with tape file version less than 2.0) get converted to the new
+ format on-the-fly when loading and can therefore still be played;
+ only some minor parts of the old-style tape handling code was needed.
+ (A perfect conversion is not possible, because there is information
+ missing about the device actions between two action frames.)
+
+2002-03-14 src/files.c
+ * New function "DumpTape()" to dump the contents of the current tape
+ in a human readable format.
+
+2002-03-14 src/game.c
+ * Small tape bug fixed: When automatically advancing to next level
+ after a game was won, the tape from the previous level still was
+ loaded as a tape for the new level.
+
+2002-03-14 src/tape.c
+ * Small graphical bug fixed: When pressing ""Record" or "Play" on
+ tape, cartoons did not get completely removed because
+ StopAnimation() was not called.
+
+2002-03-13 src/files.c
+ * Changed "LoadLevel()" and "SaveLevel()" to add new chunk "CNT2".
+ Fixed bug of "CONT" and "BODY" (chunk size was set to 8-bit element
+ size even when using 16-bit elements). Added new chunk "CNT2" for
+ 16-bit amoeba content (previously written in 8-bit field in "HEAD"
+ chunk even when content was 16-bit element). "CNT2" should now be
+ able to store content for arbitrary elements (up to eight blocks of
+ 3 x 3 element arrays). All "CNT2" elements will always be stored as
+ 16-bit elements. "CONT" (with 8/16-bit elements) now obsolete.
+
+2002-03-13 src/files.c
+ * Changed "LoadLevel()" for real chunk support.
+
+2002-03-12 src/game.c
+ * Fixed problem (introduced after 2.0.0 release) with penguins
+ not getting killed by enemies
+
+2002-02-24 src/game.c, src/main.h
+ * Added "player->is_moving"; now "player->last_move_dir" does
+ not contain any information if the player is just moving at
+ the moment or not.
+ Before, "player->last_move_dir" was misused for this purpose
+ for the robot stuff (robots don't kill players when they are
+ moving). But setting "player->last_move_dir" to MV_NO_MOVING
+ broke tapes when walking through pipes!
+ ("IS_MOVING()" uses "MovPos[][]", but this fails when it is 0
+ in a continuous movement. This fact is ignored for friends and
+ enemies, though.)
msdos:
@$(MAKE_CMD) PLATFORM=msdos
+os2:
+ @$(MAKE_CMD) PLATFORM=os2
+
cross-msdos:
@PATH=$(CROSS_PATH_MSDOS)/bin:${PATH} $(MAKE_CMD) PLATFORM=cross-msdos
auto-conf:
@$(MAKE_CMD) auto-conf
-run:
- @$(MAKE_CMD) TARGET=$(DEFAULT_TARGET) && ./rocksndiamonds --verbose
+run: all
+ @./rocksndiamonds --verbose
-gdb:
- @$(MAKE_CMD) TARGET=$(DEFAULT_TARGET) && gdb ./rocksndiamonds
+gdb: all
+ @gdb ./rocksndiamonds
-valgrind:
- valgrind -v --leak-check=yes ./rocksndiamonds 2> valgrind.out
+valgrind: all
+ @valgrind -v --leak-check=yes ./rocksndiamonds 2> valgrind.out
-enginetest:
+enginetest: all
./Scripts/make_enginetest.sh
-enginetestcustom:
+enginetestcustom: all
./Scripts/make_enginetest.sh custom
-enginetestfast:
+enginetestfast: all
./Scripts/make_enginetest.sh fast
+enginetestnew: all
+ ./Scripts/make_enginetest.sh new
+
backup:
./Scripts/make_backup.sh src
XINC_PATH = $(X11_PATH)/include
XLIB_PATH = $(X11_PATH)/lib
X11_INCL = -I$(XINC_PATH)
-X11_LIBS = -L$(XLIB_PATH)
+X11_LIBS = -L$(XLIB_PATH) -lX11
endif
AR = ar
ifeq ($(PLATFORM),macosx)
PLATFORM = unix
-TARGET=sdl
+TARGET = sdl
+endif
+
+ifeq ($(PLATFORM),os2)
+RANLIB = echo
+PROGNAME = ../$(PROGBASE).exe
+EXTRA_CFLAGS = -Zbin-files -D__ST_MT_ERRNO__ -Zmtd -fomit-frame-pointer
+EXTRA_LDFLAGS = -lsocket
+PLATFORM = unix
+TARGET = x11
endif
ifeq ($(PLATFORM),unix)
endif
ifeq ($(PLATFORM),cross-win32)
-EXTRA_LDFLAGS = -lshfolder
+EXTRA_LDFLAGS = -lshfolder -lwsock32
PROGNAME = ../$(PROGBASE).exe
TARGET = sdl
endif
ifeq ($(TARGET),x11)
SYS_CFLAGS = -DTARGET_X11 $(X11_INCL)
-SYS_LDFLAGS = $(X11_LIBS) -lX11
+SYS_LDFLAGS = $(X11_LIBS)
endif
ifeq ($(TARGET),sdl)
SYS_CFLAGS = -DTARGET_SDL $(shell sdl-config --cflags)
-ifeq ($(PLATFORM),macosx)
-SYS_LDFLAGS = -lSDL_image -lSDL_mixer -lsmpeg $(shell sdl-config --libs)
-else
-SYS_LDFLAGS = -lSDL_image -lSDL_mixer $(shell sdl-config --libs)
-endif
+SDL_LIBS = -lSDL_image -lSDL_mixer -lSDL_net -lsmpeg
+SYS_LDFLAGS = $(SDL_LIBS) $(shell sdl-config --libs)
endif
ifeq ($(TARGET),allegro)
OPTIONS = -O3 -Wall
endif
-CFLAGS = $(OPTIONS) $(SYS_CFLAGS) $(CONFIG)
-LDFLAGS = $(SYS_LDFLAGS) $(EXTRA_LDFLAGS) -lm
+CFLAGS = $(OPTIONS) $(SYS_CFLAGS) $(EXTRA_CFLAGS) $(CONFIG)
+LDFLAGS = $(SYS_LDFLAGS) $(EXTRA_LDFLAGS) -lm
SRCS = main.c \
conf_chr.h \
conf_cus.c \
conf_cus.h \
+ conf_grp.c \
+ conf_grp.h \
conf_e2g.c \
conf_esg.c \
conf_e2s.c \
EL_SP_GRAVITY_PORT_UP, -1, -1, FALSE,
IMG_SP_GRAVITY_PORT_UP
},
+ {
+ EL_SP_GRAVITY_ON_PORT_RIGHT, -1, -1, FALSE,
+ IMG_SP_GRAVITY_ON_PORT_RIGHT
+ },
+ {
+ EL_SP_GRAVITY_ON_PORT_DOWN, -1, -1, FALSE,
+ IMG_SP_GRAVITY_ON_PORT_DOWN
+ },
+ {
+ EL_SP_GRAVITY_ON_PORT_LEFT, -1, -1, FALSE,
+ IMG_SP_GRAVITY_ON_PORT_LEFT
+ },
+ {
+ EL_SP_GRAVITY_ON_PORT_UP, -1, -1, FALSE,
+ IMG_SP_GRAVITY_ON_PORT_UP
+ },
+ {
+ EL_SP_GRAVITY_OFF_PORT_RIGHT, -1, -1, FALSE,
+ IMG_SP_GRAVITY_OFF_PORT_RIGHT
+ },
+ {
+ EL_SP_GRAVITY_OFF_PORT_DOWN, -1, -1, FALSE,
+ IMG_SP_GRAVITY_OFF_PORT_DOWN
+ },
+ {
+ EL_SP_GRAVITY_OFF_PORT_LEFT, -1, -1, FALSE,
+ IMG_SP_GRAVITY_OFF_PORT_LEFT
+ },
+ {
+ EL_SP_GRAVITY_OFF_PORT_UP, -1, -1, FALSE,
+ IMG_SP_GRAVITY_OFF_PORT_UP
+ },
{
EL_SP_SNIKSNAK, -1, -1, FALSE,
IMG_SP_SNIKSNAK
EL_SOKOBAN_FIELD_FULL, -1, -1, FALSE,
IMG_SOKOBAN_FIELD_FULL
},
+ {
+ EL_SOKOBAN_FIELD_PLAYER, -1, -1, FALSE,
+ IMG_SOKOBAN_FIELD_PLAYER
+ },
{
EL_EMPTY_SPACE, -1, -1, FALSE,
IMG_EMPTY_SPACE
EL_STONEBLOCK, -1, -1, FALSE,
IMG_STONEBLOCK
},
- {
- EL_MAZE_RUNNER, -1, -1, FALSE,
- IMG_MAZE_RUNNER
- },
{
EL_PLAYER_1, -1, -1, FALSE,
IMG_PLAYER_1
EL_ARROW_DOWN, -1, -1, FALSE,
IMG_ARROW_DOWN
},
+ {
+ EL_UNKNOWN, -1, -1, FALSE,
+ IMG_UNKNOWN
+ },
+ {
+ EL_TRIGGER_ELEMENT, -1, -1, FALSE,
+ IMG_TRIGGER_ELEMENT
+ },
+ {
+ EL_TRIGGER_PLAYER, -1, -1, FALSE,
+ IMG_TRIGGER_PLAYER
+ },
+ {
+ EL_BD_BUTTERFLY_DOWN, -1, -1, FALSE,
+ IMG_BD_BUTTERFLY
+ },
+ {
+ EL_BD_BUTTERFLY_LEFT, -1, -1, FALSE,
+ IMG_BD_BUTTERFLY
+ },
+ {
+ EL_BD_BUTTERFLY_RIGHT, -1, -1, FALSE,
+ IMG_BD_BUTTERFLY
+ },
+ {
+ EL_BD_BUTTERFLY_UP, -1, -1, FALSE,
+ IMG_BD_BUTTERFLY
+ },
+ {
+ EL_BD_FIREFLY_DOWN, -1, -1, FALSE,
+ IMG_BD_FIREFLY
+ },
+ {
+ EL_BD_FIREFLY_LEFT, -1, -1, FALSE,
+ IMG_BD_FIREFLY
+ },
+ {
+ EL_BD_FIREFLY_RIGHT, -1, -1, FALSE,
+ IMG_BD_FIREFLY
+ },
+ {
+ EL_BD_FIREFLY_UP, -1, -1, FALSE,
+ IMG_BD_FIREFLY
+ },
{
EL_DOOR_WHITE, -1, -1, FALSE,
IMG_CHAR_QUESTION
EL_CUSTOM_256, -1, -1, FALSE,
IMG_CUSTOM_256
},
+ {
+ EL_GROUP_1, -1, -1, FALSE,
+ IMG_GROUP_1
+ },
+ {
+ EL_GROUP_2, -1, -1, FALSE,
+ IMG_GROUP_2
+ },
+ {
+ EL_GROUP_3, -1, -1, FALSE,
+ IMG_GROUP_3
+ },
+ {
+ EL_GROUP_4, -1, -1, FALSE,
+ IMG_GROUP_4
+ },
+ {
+ EL_GROUP_5, -1, -1, FALSE,
+ IMG_GROUP_5
+ },
+ {
+ EL_GROUP_6, -1, -1, FALSE,
+ IMG_GROUP_6
+ },
+ {
+ EL_GROUP_7, -1, -1, FALSE,
+ IMG_GROUP_7
+ },
+ {
+ EL_GROUP_8, -1, -1, FALSE,
+ IMG_GROUP_8
+ },
+ {
+ EL_GROUP_9, -1, -1, FALSE,
+ IMG_GROUP_9
+ },
+ {
+ EL_GROUP_10, -1, -1, FALSE,
+ IMG_GROUP_10
+ },
+ {
+ EL_GROUP_11, -1, -1, FALSE,
+ IMG_GROUP_11
+ },
+ {
+ EL_GROUP_12, -1, -1, FALSE,
+ IMG_GROUP_12
+ },
+ {
+ EL_GROUP_13, -1, -1, FALSE,
+ IMG_GROUP_13
+ },
+ {
+ EL_GROUP_14, -1, -1, FALSE,
+ IMG_GROUP_14
+ },
+ {
+ EL_GROUP_15, -1, -1, FALSE,
+ IMG_GROUP_15
+ },
+ {
+ EL_GROUP_16, -1, -1, FALSE,
+ IMG_GROUP_16
+ },
+ {
+ EL_GROUP_17, -1, -1, FALSE,
+ IMG_GROUP_17
+ },
+ {
+ EL_GROUP_18, -1, -1, FALSE,
+ IMG_GROUP_18
+ },
+ {
+ EL_GROUP_19, -1, -1, FALSE,
+ IMG_GROUP_19
+ },
+ {
+ EL_GROUP_20, -1, -1, FALSE,
+ IMG_GROUP_20
+ },
+ {
+ EL_GROUP_21, -1, -1, FALSE,
+ IMG_GROUP_21
+ },
+ {
+ EL_GROUP_22, -1, -1, FALSE,
+ IMG_GROUP_22
+ },
+ {
+ EL_GROUP_23, -1, -1, FALSE,
+ IMG_GROUP_23
+ },
+ {
+ EL_GROUP_24, -1, -1, FALSE,
+ IMG_GROUP_24
+ },
+ {
+ EL_GROUP_25, -1, -1, FALSE,
+ IMG_GROUP_25
+ },
+ {
+ EL_GROUP_26, -1, -1, FALSE,
+ IMG_GROUP_26
+ },
+ {
+ EL_GROUP_27, -1, -1, FALSE,
+ IMG_GROUP_27
+ },
+ {
+ EL_GROUP_28, -1, -1, FALSE,
+ IMG_GROUP_28
+ },
+ {
+ EL_GROUP_29, -1, -1, FALSE,
+ IMG_GROUP_29
+ },
+ {
+ EL_GROUP_30, -1, -1, FALSE,
+ IMG_GROUP_30
+ },
+ {
+ EL_GROUP_31, -1, -1, FALSE,
+ IMG_GROUP_31
+ },
+ {
+ EL_GROUP_32, -1, -1, FALSE,
+ IMG_GROUP_32
+ },
{
-1, -1, -1, FALSE,
-1
SND_SP_TERMINAL_ACTIVE
},
{
- EL_SOKOBAN_OBJECT, TRUE, ACTION_PUSHING,
+ EL_SOKOBAN_FIELD_PLAYER, TRUE, ACTION_PUSHING,
SND_CLASS_SOKOBAN_PUSHING
},
{
- EL_SOKOBAN_OBJECT, TRUE, ACTION_FILLING,
+ EL_SOKOBAN_FIELD_PLAYER, TRUE, ACTION_FILLING,
SND_CLASS_SOKOBAN_FILLING
},
{
- EL_SOKOBAN_OBJECT, TRUE, ACTION_EMPTYING,
+ EL_SOKOBAN_FIELD_PLAYER, TRUE, ACTION_EMPTYING,
SND_CLASS_SOKOBAN_EMPTYING
},
{
EL_SP_INFOTRON, GFX_SPECIAL_ARG_EDITOR,
IMG_SP_INFOTRON_EDITOR
},
+ {
+ EL_SP_GRAVITY_PORT_RIGHT, GFX_SPECIAL_ARG_EDITOR,
+ IMG_SP_GRAVITY_PORT_RIGHT_EDITOR
+ },
+ {
+ EL_SP_GRAVITY_PORT_DOWN, GFX_SPECIAL_ARG_EDITOR,
+ IMG_SP_GRAVITY_PORT_DOWN_EDITOR
+ },
+ {
+ EL_SP_GRAVITY_PORT_LEFT, GFX_SPECIAL_ARG_EDITOR,
+ IMG_SP_GRAVITY_PORT_LEFT_EDITOR
+ },
+ {
+ EL_SP_GRAVITY_PORT_UP, GFX_SPECIAL_ARG_EDITOR,
+ IMG_SP_GRAVITY_PORT_UP_EDITOR
+ },
+ {
+ EL_SP_GRAVITY_ON_PORT_RIGHT, GFX_SPECIAL_ARG_EDITOR,
+ IMG_SP_GRAVITY_ON_PORT_RIGHT_EDITOR
+ },
+ {
+ EL_SP_GRAVITY_ON_PORT_DOWN, GFX_SPECIAL_ARG_EDITOR,
+ IMG_SP_GRAVITY_ON_PORT_DOWN_EDITOR
+ },
+ {
+ EL_SP_GRAVITY_ON_PORT_LEFT, GFX_SPECIAL_ARG_EDITOR,
+ IMG_SP_GRAVITY_ON_PORT_LEFT_EDITOR
+ },
+ {
+ EL_SP_GRAVITY_ON_PORT_UP, GFX_SPECIAL_ARG_EDITOR,
+ IMG_SP_GRAVITY_ON_PORT_UP_EDITOR
+ },
+ {
+ EL_SP_GRAVITY_OFF_PORT_RIGHT, GFX_SPECIAL_ARG_EDITOR,
+ IMG_SP_GRAVITY_OFF_PORT_RIGHT_EDITOR
+ },
+ {
+ EL_SP_GRAVITY_OFF_PORT_DOWN, GFX_SPECIAL_ARG_EDITOR,
+ IMG_SP_GRAVITY_OFF_PORT_DOWN_EDITOR
+ },
+ {
+ EL_SP_GRAVITY_OFF_PORT_LEFT, GFX_SPECIAL_ARG_EDITOR,
+ IMG_SP_GRAVITY_OFF_PORT_LEFT_EDITOR
+ },
+ {
+ EL_SP_GRAVITY_OFF_PORT_UP, GFX_SPECIAL_ARG_EDITOR,
+ IMG_SP_GRAVITY_OFF_PORT_UP_EDITOR
+ },
{
EL_SP_ELECTRON, GFX_SPECIAL_ARG_EDITOR,
IMG_SP_ELECTRON_EDITOR
EL_SOKOBAN_OBJECT, GFX_SPECIAL_ARG_EDITOR,
IMG_SOKOBAN_OBJECT_EDITOR
},
+ {
+ EL_SOKOBAN_FIELD_PLAYER, GFX_SPECIAL_ARG_EDITOR,
+ IMG_SOKOBAN_FIELD_PLAYER_EDITOR
+ },
{
EL_DYNAMITE, GFX_SPECIAL_ARG_EDITOR,
IMG_DYNAMITE_EDITOR
EL_CUSTOM_256, GFX_SPECIAL_ARG_EDITOR,
IMG_CUSTOM_256_EDITOR
},
+ {
+ EL_GROUP_1, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_1_EDITOR
+ },
+ {
+ EL_GROUP_2, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_2_EDITOR
+ },
+ {
+ EL_GROUP_3, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_3_EDITOR
+ },
+ {
+ EL_GROUP_4, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_4_EDITOR
+ },
+ {
+ EL_GROUP_5, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_5_EDITOR
+ },
+ {
+ EL_GROUP_6, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_6_EDITOR
+ },
+ {
+ EL_GROUP_7, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_7_EDITOR
+ },
+ {
+ EL_GROUP_8, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_8_EDITOR
+ },
+ {
+ EL_GROUP_9, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_9_EDITOR
+ },
+ {
+ EL_GROUP_10, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_10_EDITOR
+ },
+ {
+ EL_GROUP_11, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_11_EDITOR
+ },
+ {
+ EL_GROUP_12, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_12_EDITOR
+ },
+ {
+ EL_GROUP_13, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_13_EDITOR
+ },
+ {
+ EL_GROUP_14, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_14_EDITOR
+ },
+ {
+ EL_GROUP_15, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_15_EDITOR
+ },
+ {
+ EL_GROUP_16, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_16_EDITOR
+ },
+ {
+ EL_GROUP_17, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_17_EDITOR
+ },
+ {
+ EL_GROUP_18, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_18_EDITOR
+ },
+ {
+ EL_GROUP_19, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_19_EDITOR
+ },
+ {
+ EL_GROUP_20, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_20_EDITOR
+ },
+ {
+ EL_GROUP_21, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_21_EDITOR
+ },
+ {
+ EL_GROUP_22, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_22_EDITOR
+ },
+ {
+ EL_GROUP_23, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_23_EDITOR
+ },
+ {
+ EL_GROUP_24, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_24_EDITOR
+ },
+ {
+ EL_GROUP_25, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_25_EDITOR
+ },
+ {
+ EL_GROUP_26, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_26_EDITOR
+ },
+ {
+ EL_GROUP_27, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_27_EDITOR
+ },
+ {
+ EL_GROUP_28, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_28_EDITOR
+ },
+ {
+ EL_GROUP_29, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_29_EDITOR
+ },
+ {
+ EL_GROUP_30, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_30_EDITOR
+ },
+ {
+ EL_GROUP_31, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_31_EDITOR
+ },
+ {
+ EL_GROUP_32, GFX_SPECIAL_ARG_EDITOR,
+ IMG_GROUP_32_EDITOR
+ },
{
-1, -1,
-1
{ "sp_port_any.ypos", "2" },
{ "sp_port_any.frames", "1" },
{ "sp_gravity_port_right", "RocksSP.pcx" },
- { "sp_gravity_port_right.xpos", "5" },
+ { "sp_gravity_port_right.xpos", "1" },
{ "sp_gravity_port_right.ypos", "1" },
{ "sp_gravity_port_right.frames", "1" },
+ { "sp_gravity_port_right.EDITOR", "RocksSP.pcx" },
+ { "sp_gravity_port_right.EDITOR.xpos", "5" },
+ { "sp_gravity_port_right.EDITOR.ypos", "1" },
{ "sp_gravity_port_down", "RocksSP.pcx" },
- { "sp_gravity_port_down.xpos", "6" },
+ { "sp_gravity_port_down.xpos", "2" },
{ "sp_gravity_port_down.ypos", "1" },
{ "sp_gravity_port_down.frames", "1" },
+ { "sp_gravity_port_down.EDITOR", "RocksSP.pcx" },
+ { "sp_gravity_port_down.EDITOR.xpos", "6" },
+ { "sp_gravity_port_down.EDITOR.ypos", "1" },
{ "sp_gravity_port_left", "RocksSP.pcx" },
- { "sp_gravity_port_left.xpos", "7" },
+ { "sp_gravity_port_left.xpos", "3" },
{ "sp_gravity_port_left.ypos", "1" },
{ "sp_gravity_port_left.frames", "1" },
+ { "sp_gravity_port_left.EDITOR", "RocksSP.pcx" },
+ { "sp_gravity_port_left.EDITOR.xpos", "7" },
+ { "sp_gravity_port_left.EDITOR.ypos", "1" },
{ "sp_gravity_port_up", "RocksSP.pcx" },
- { "sp_gravity_port_up.xpos", "0" },
- { "sp_gravity_port_up.ypos", "2" },
+ { "sp_gravity_port_up.xpos", "4" },
+ { "sp_gravity_port_up.ypos", "1" },
{ "sp_gravity_port_up.frames", "1" },
+ { "sp_gravity_port_up.EDITOR", "RocksSP.pcx" },
+ { "sp_gravity_port_up.EDITOR.xpos", "0" },
+ { "sp_gravity_port_up.EDITOR.ypos", "2" },
+ { "sp_gravity_on_port_right", "RocksSP.pcx" },
+ { "sp_gravity_on_port_right.xpos", "1" },
+ { "sp_gravity_on_port_right.ypos", "1" },
+ { "sp_gravity_on_port_right.frames", "1" },
+ { "sp_gravity_on_port_right.EDITOR", "RocksSP.pcx" },
+ { "sp_gravity_on_port_right.EDITOR.xpos", "5" },
+ { "sp_gravity_on_port_right.EDITOR.ypos", "1" },
+ { "sp_gravity_on_port_down", "RocksSP.pcx" },
+ { "sp_gravity_on_port_down.xpos", "2" },
+ { "sp_gravity_on_port_down.ypos", "1" },
+ { "sp_gravity_on_port_down.frames", "1" },
+ { "sp_gravity_on_port_down.EDITOR", "RocksSP.pcx" },
+ { "sp_gravity_on_port_down.EDITOR.xpos", "6" },
+ { "sp_gravity_on_port_down.EDITOR.ypos", "1" },
+ { "sp_gravity_on_port_left", "RocksSP.pcx" },
+ { "sp_gravity_on_port_left.xpos", "3" },
+ { "sp_gravity_on_port_left.ypos", "1" },
+ { "sp_gravity_on_port_left.frames", "1" },
+ { "sp_gravity_on_port_left.EDITOR", "RocksSP.pcx" },
+ { "sp_gravity_on_port_left.EDITOR.xpos", "7" },
+ { "sp_gravity_on_port_left.EDITOR.ypos", "1" },
+ { "sp_gravity_on_port_up", "RocksSP.pcx" },
+ { "sp_gravity_on_port_up.xpos", "4" },
+ { "sp_gravity_on_port_up.ypos", "1" },
+ { "sp_gravity_on_port_up.frames", "1" },
+ { "sp_gravity_on_port_up.EDITOR", "RocksSP.pcx" },
+ { "sp_gravity_on_port_up.EDITOR.xpos", "0" },
+ { "sp_gravity_on_port_up.EDITOR.ypos", "2" },
+ { "sp_gravity_off_port_right", "RocksSP.pcx" },
+ { "sp_gravity_off_port_right.xpos", "1" },
+ { "sp_gravity_off_port_right.ypos", "1" },
+ { "sp_gravity_off_port_right.frames", "1" },
+ { "sp_gravity_off_port_right.EDITOR", "RocksSP.pcx" },
+ { "sp_gravity_off_port_right.EDITOR.xpos", "5" },
+ { "sp_gravity_off_port_right.EDITOR.ypos", "1" },
+ { "sp_gravity_off_port_down", "RocksSP.pcx" },
+ { "sp_gravity_off_port_down.xpos", "2" },
+ { "sp_gravity_off_port_down.ypos", "1" },
+ { "sp_gravity_off_port_down.frames", "1" },
+ { "sp_gravity_off_port_down.EDITOR", "RocksSP.pcx" },
+ { "sp_gravity_off_port_down.EDITOR.xpos", "6" },
+ { "sp_gravity_off_port_down.EDITOR.ypos", "1" },
+ { "sp_gravity_off_port_left", "RocksSP.pcx" },
+ { "sp_gravity_off_port_left.xpos", "3" },
+ { "sp_gravity_off_port_left.ypos", "1" },
+ { "sp_gravity_off_port_left.frames", "1" },
+ { "sp_gravity_off_port_left.EDITOR", "RocksSP.pcx" },
+ { "sp_gravity_off_port_left.EDITOR.xpos", "7" },
+ { "sp_gravity_off_port_left.EDITOR.ypos", "1" },
+ { "sp_gravity_off_port_up", "RocksSP.pcx" },
+ { "sp_gravity_off_port_up.xpos", "4" },
+ { "sp_gravity_off_port_up.ypos", "1" },
+ { "sp_gravity_off_port_up.frames", "1" },
+ { "sp_gravity_off_port_up.EDITOR", "RocksSP.pcx" },
+ { "sp_gravity_off_port_up.EDITOR.xpos", "0" },
+ { "sp_gravity_off_port_up.EDITOR.ypos", "2" },
{ "sp_sniksnak", "RocksSP.pcx" },
{ "sp_sniksnak.xpos", "1" },
{ "sp_electron.xpos", "8" },
{ "sp_electron.ypos", "10" },
{ "sp_electron.frames", "8" },
- { "sp_electron.delay", "2" },
+ { "sp_electron.delay", "4" },
+ { "sp_electron.global_sync", "true" },
{ "sp_electron.EDITOR", "RocksSP.pcx" },
{ "sp_electron.EDITOR.xpos", "10" },
{ "sp_electron.EDITOR.ypos", "11" },
{ "sokoban_field_full.ypos", "7" },
{ "sokoban_field_full.frames", "1" },
+ { "sokoban_field_player", "RocksHeroes.pcx" },
+ { "sokoban_field_player.xpos", "0" },
+ { "sokoban_field_player.ypos", "15" },
+ { "sokoban_field_player.frames", "1" },
+ { "sokoban_field_player.EDITOR", "RocksHeroes.pcx" },
+ { "sokoban_field_player.EDITOR.xpos", "1" },
+ { "sokoban_field_player.EDITOR.ypos", "15" },
+
/* images for Emerald Mine style elements and actions */
{ "empty_space", "RocksSP.pcx" },
{ "stoneblock.ypos", "1" },
{ "stoneblock.frames", "1" },
- { "maze_runner", "RocksHeroes.pcx" },
- { "maze_runner.xpos", "15" },
- { "maze_runner.ypos", "8" },
- { "maze_runner.frames", "1" },
-
/* images for other elements and actions */
{ "player_1", "RocksHeroes.pcx" },
{ "arrow_down.ypos", "8" },
{ "arrow_down.frames", "1" },
+ { "unknown", "RocksFontEM.pcx" },
+ { "unknown.xpos", "15" },
+ { "unknown.ypos", "1" },
+ { "unknown.frames", "1" },
+
+ { "trigger_element", "RocksDC.pcx" },
+ { "trigger_element.xpos", "15" },
+ { "trigger_element.ypos", "14" },
+ { "trigger_element.frames", "1" },
+
+ { "trigger_player", "RocksDC.pcx" },
+ { "trigger_player.xpos", "15" },
+ { "trigger_player.ypos", "13" },
+ { "trigger_player.frames", "1" },
+
#include "conf_chr.c" /* include auto-generated data structure definitions */
#include "conf_cus.c" /* include auto-generated data structure definitions */
+#include "conf_grp.c" /* include auto-generated data structure definitions */
/* images not associated to game elements (used for menu screens etc.) */
/* keyword to stop parser: "NO_MORE_ELEMENT_IMAGES" <-- do not change! */
{ "background.SCORES", UNDEFINED_FILENAME },
{ "background.EDITOR", UNDEFINED_FILENAME },
{ "background.INFO", UNDEFINED_FILENAME },
+ { "background.INFO[ELEMENTS]", UNDEFINED_FILENAME },
{ "background.SETUP", UNDEFINED_FILENAME },
{ "background.DOOR", UNDEFINED_FILENAME },
#define IMG_SP_PORT_VERTICAL 76
#define IMG_SP_PORT_ANY 77
#define IMG_SP_GRAVITY_PORT_RIGHT 78
-#define IMG_SP_GRAVITY_PORT_DOWN 79
-#define IMG_SP_GRAVITY_PORT_LEFT 80
-#define IMG_SP_GRAVITY_PORT_UP 81
-#define IMG_SP_SNIKSNAK 82
-#define IMG_SP_SNIKSNAK_LEFT 83
-#define IMG_SP_SNIKSNAK_RIGHT 84
-#define IMG_SP_SNIKSNAK_UP 85
-#define IMG_SP_SNIKSNAK_DOWN 86
-#define IMG_SP_SNIKSNAK_TURNING_FROM_LEFT_UP 87
-#define IMG_SP_SNIKSNAK_TURNING_FROM_LEFT_DOWN 88
-#define IMG_SP_SNIKSNAK_TURNING_FROM_RIGHT_UP 89
-#define IMG_SP_SNIKSNAK_TURNING_FROM_RIGHT_DOWN 90
-#define IMG_SP_SNIKSNAK_TURNING_FROM_UP_LEFT 91
-#define IMG_SP_SNIKSNAK_TURNING_FROM_UP_RIGHT 92
-#define IMG_SP_SNIKSNAK_TURNING_FROM_DOWN_LEFT 93
-#define IMG_SP_SNIKSNAK_TURNING_FROM_DOWN_RIGHT 94
-#define IMG_SP_ELECTRON 95
-#define IMG_SP_ELECTRON_EDITOR 96
-#define IMG_SP_ELECTRON_EXPLODING 97
-#define IMG_SP_TERMINAL 98
-#define IMG_SP_TERMINAL_EDITOR 99
-#define IMG_SP_TERMINAL_ACTIVE 100
-#define IMG_SP_BUGGY_BASE 101
-#define IMG_SP_BUGGY_BASE_EDITOR 102
-#define IMG_SP_BUGGY_BASE_ACTIVATING 103
-#define IMG_SP_BUGGY_BASE_ACTIVE 104
-#define IMG_SP_HARDWARE_BASE_1 105
-#define IMG_SP_HARDWARE_BASE_2 106
-#define IMG_SP_HARDWARE_BASE_3 107
-#define IMG_SP_HARDWARE_BASE_4 108
-#define IMG_SP_HARDWARE_BASE_5 109
-#define IMG_SP_HARDWARE_BASE_6 110
-#define IMG_SOKOBAN_OBJECT 111
-#define IMG_SOKOBAN_OBJECT_EDITOR 112
-#define IMG_SOKOBAN_FIELD_EMPTY 113
-#define IMG_SOKOBAN_FIELD_FULL 114
-#define IMG_EMPTY_SPACE 115
-#define IMG_SAND 116
-#define IMG_SAND_CRUMBLED 117
-#define IMG_SAND_DIGGING_LEFT 118
-#define IMG_SAND_DIGGING_RIGHT 119
-#define IMG_SAND_DIGGING_UP 120
-#define IMG_SAND_DIGGING_DOWN 121
-#define IMG_SAND_DIGGING_LEFT_CRUMBLED 122
-#define IMG_SAND_DIGGING_RIGHT_CRUMBLED 123
-#define IMG_SAND_DIGGING_UP_CRUMBLED 124
-#define IMG_SAND_DIGGING_DOWN_CRUMBLED 125
-#define IMG_WALL 126
-#define IMG_WALL_SLIPPERY 127
-#define IMG_STEELWALL 128
-#define IMG_ROCK 129
-#define IMG_ROCK_MOVING_LEFT 130
-#define IMG_ROCK_MOVING_RIGHT 131
-#define IMG_ROCK_PUSHING_LEFT 132
-#define IMG_ROCK_PUSHING_RIGHT 133
-#define IMG_EMERALD 134
-#define IMG_EMERALD_MOVING 135
-#define IMG_EMERALD_FALLING 136
-#define IMG_EMERALD_COLLECTING 137
-#define IMG_DIAMOND 138
-#define IMG_DIAMOND_MOVING 139
-#define IMG_DIAMOND_FALLING 140
-#define IMG_DIAMOND_COLLECTING 141
-#define IMG_BOMB 142
-#define IMG_NUT 143
-#define IMG_NUT_BREAKING 144
-#define IMG_DYNAMITE 145
-#define IMG_DYNAMITE_EDITOR 146
-#define IMG_DYNAMITE_ACTIVE 147
-#define IMG_DYNAMITE_ACTIVE_EDITOR 148
-#define IMG_WALL_EMERALD 149
-#define IMG_WALL_DIAMOND 150
-#define IMG_BUG 151
-#define IMG_BUG_RIGHT 152
-#define IMG_BUG_UP 153
-#define IMG_BUG_LEFT 154
-#define IMG_BUG_DOWN 155
-#define IMG_BUG_MOVING_RIGHT 156
-#define IMG_BUG_MOVING_UP 157
-#define IMG_BUG_MOVING_LEFT 158
-#define IMG_BUG_MOVING_DOWN 159
-#define IMG_BUG_TURNING_FROM_RIGHT_UP 160
-#define IMG_BUG_TURNING_FROM_UP_LEFT 161
-#define IMG_BUG_TURNING_FROM_LEFT_DOWN 162
-#define IMG_BUG_TURNING_FROM_DOWN_RIGHT 163
-#define IMG_BUG_TURNING_FROM_RIGHT_DOWN 164
-#define IMG_BUG_TURNING_FROM_UP_RIGHT 165
-#define IMG_BUG_TURNING_FROM_LEFT_UP 166
-#define IMG_BUG_TURNING_FROM_DOWN_LEFT 167
-#define IMG_SPACESHIP 168
-#define IMG_SPACESHIP_RIGHT 169
-#define IMG_SPACESHIP_UP 170
-#define IMG_SPACESHIP_LEFT 171
-#define IMG_SPACESHIP_DOWN 172
-#define IMG_SPACESHIP_MOVING_RIGHT 173
-#define IMG_SPACESHIP_MOVING_UP 174
-#define IMG_SPACESHIP_MOVING_LEFT 175
-#define IMG_SPACESHIP_MOVING_DOWN 176
-#define IMG_SPACESHIP_TURNING_FROM_RIGHT_UP 177
-#define IMG_SPACESHIP_TURNING_FROM_UP_LEFT 178
-#define IMG_SPACESHIP_TURNING_FROM_LEFT_DOWN 179
-#define IMG_SPACESHIP_TURNING_FROM_DOWN_RIGHT 180
-#define IMG_SPACESHIP_TURNING_FROM_RIGHT_DOWN 181
-#define IMG_SPACESHIP_TURNING_FROM_UP_RIGHT 182
-#define IMG_SPACESHIP_TURNING_FROM_LEFT_UP 183
-#define IMG_SPACESHIP_TURNING_FROM_DOWN_LEFT 184
-#define IMG_YAMYAM 185
-#define IMG_YAMYAM_MOVING 186
-#define IMG_ROBOT 187
-#define IMG_ROBOT_MOVING 188
-#define IMG_ROBOT_WHEEL 189
-#define IMG_ROBOT_WHEEL_ACTIVE 190
-#define IMG_MAGIC_WALL 191
-#define IMG_MAGIC_WALL_ACTIVE 192
-#define IMG_MAGIC_WALL_FILLING 193
-#define IMG_MAGIC_WALL_FULL 194
-#define IMG_MAGIC_WALL_EMPTYING 195
-#define IMG_MAGIC_WALL_DEAD 196
-#define IMG_QUICKSAND_EMPTY 197
-#define IMG_QUICKSAND_FILLING 198
-#define IMG_QUICKSAND_FULL 199
-#define IMG_QUICKSAND_FULL_EDITOR 200
-#define IMG_QUICKSAND_EMPTYING 201
-#define IMG_ACID_POOL_TOPLEFT 202
-#define IMG_ACID_POOL_TOPRIGHT 203
-#define IMG_ACID_POOL_BOTTOMLEFT 204
-#define IMG_ACID_POOL_BOTTOM 205
-#define IMG_ACID_POOL_BOTTOMRIGHT 206
-#define IMG_ACID 207
-#define IMG_ACID_SPLASH_LEFT 208
-#define IMG_ACID_SPLASH_RIGHT 209
-#define IMG_AMOEBA_DROP 210
-#define IMG_AMOEBA_GROWING 211
-#define IMG_AMOEBA_SHRINKING 212
-#define IMG_AMOEBA_WET 213
-#define IMG_AMOEBA_WET_EDITOR 214
-#define IMG_AMOEBA_DROPPING 215
-#define IMG_AMOEBA_DRY 216
-#define IMG_AMOEBA_FULL 217
-#define IMG_AMOEBA_FULL_EDITOR 218
-#define IMG_AMOEBA_DEAD 219
-#define IMG_AMOEBA_DEAD_EDITOR 220
-#define IMG_EM_KEY_1 221
-#define IMG_EM_KEY_2 222
-#define IMG_EM_KEY_3 223
-#define IMG_EM_KEY_4 224
-#define IMG_EM_GATE_1 225
-#define IMG_EM_GATE_2 226
-#define IMG_EM_GATE_3 227
-#define IMG_EM_GATE_4 228
-#define IMG_EM_GATE_1_GRAY 229
-#define IMG_EM_GATE_1_GRAY_EDITOR 230
-#define IMG_EM_GATE_2_GRAY 231
-#define IMG_EM_GATE_2_GRAY_EDITOR 232
-#define IMG_EM_GATE_3_GRAY 233
-#define IMG_EM_GATE_3_GRAY_EDITOR 234
-#define IMG_EM_GATE_4_GRAY 235
-#define IMG_EM_GATE_4_GRAY_EDITOR 236
-#define IMG_EXIT_CLOSED 237
-#define IMG_EXIT_OPENING 238
-#define IMG_EXIT_OPEN 239
-#define IMG_EXIT_CLOSING 240
-#define IMG_BALLOON 241
-#define IMG_BALLOON_MOVING 242
-#define IMG_BALLOON_PUSHING 243
-#define IMG_BALLOON_SWITCH_LEFT 244
-#define IMG_BALLOON_SWITCH_RIGHT 245
-#define IMG_BALLOON_SWITCH_UP 246
-#define IMG_BALLOON_SWITCH_DOWN 247
-#define IMG_BALLOON_SWITCH_ANY 248
-#define IMG_SPRING 249
-#define IMG_EMC_STEELWALL_1 250
-#define IMG_EMC_STEELWALL_2 251
-#define IMG_EMC_STEELWALL_3 252
-#define IMG_EMC_STEELWALL_4 253
-#define IMG_EMC_WALL_1 254
-#define IMG_EMC_WALL_2 255
-#define IMG_EMC_WALL_3 256
-#define IMG_EMC_WALL_4 257
-#define IMG_EMC_WALL_5 258
-#define IMG_EMC_WALL_6 259
-#define IMG_EMC_WALL_7 260
-#define IMG_EMC_WALL_8 261
-#define IMG_INVISIBLE_STEELWALL 262
-#define IMG_INVISIBLE_STEELWALL_EDITOR 263
-#define IMG_INVISIBLE_STEELWALL_ACTIVE 264
-#define IMG_INVISIBLE_WALL 265
-#define IMG_INVISIBLE_WALL_EDITOR 266
-#define IMG_INVISIBLE_WALL_ACTIVE 267
-#define IMG_INVISIBLE_SAND 268
-#define IMG_INVISIBLE_SAND_EDITOR 269
-#define IMG_INVISIBLE_SAND_ACTIVE 270
-#define IMG_CONVEYOR_BELT_1_MIDDLE 271
-#define IMG_CONVEYOR_BELT_1_MIDDLE_ACTIVE 272
-#define IMG_CONVEYOR_BELT_1_LEFT 273
-#define IMG_CONVEYOR_BELT_1_LEFT_ACTIVE 274
-#define IMG_CONVEYOR_BELT_1_RIGHT 275
-#define IMG_CONVEYOR_BELT_1_RIGHT_ACTIVE 276
-#define IMG_CONVEYOR_BELT_1_SWITCH_LEFT 277
-#define IMG_CONVEYOR_BELT_1_SWITCH_MIDDLE 278
-#define IMG_CONVEYOR_BELT_1_SWITCH_RIGHT 279
-#define IMG_CONVEYOR_BELT_2_MIDDLE 280
-#define IMG_CONVEYOR_BELT_2_MIDDLE_ACTIVE 281
-#define IMG_CONVEYOR_BELT_2_LEFT 282
-#define IMG_CONVEYOR_BELT_2_LEFT_ACTIVE 283
-#define IMG_CONVEYOR_BELT_2_RIGHT 284
-#define IMG_CONVEYOR_BELT_2_RIGHT_ACTIVE 285
-#define IMG_CONVEYOR_BELT_2_SWITCH_LEFT 286
-#define IMG_CONVEYOR_BELT_2_SWITCH_MIDDLE 287
-#define IMG_CONVEYOR_BELT_2_SWITCH_RIGHT 288
-#define IMG_CONVEYOR_BELT_3_MIDDLE 289
-#define IMG_CONVEYOR_BELT_3_MIDDLE_ACTIVE 290
-#define IMG_CONVEYOR_BELT_3_LEFT 291
-#define IMG_CONVEYOR_BELT_3_LEFT_ACTIVE 292
-#define IMG_CONVEYOR_BELT_3_RIGHT 293
-#define IMG_CONVEYOR_BELT_3_RIGHT_ACTIVE 294
-#define IMG_CONVEYOR_BELT_3_SWITCH_LEFT 295
-#define IMG_CONVEYOR_BELT_3_SWITCH_MIDDLE 296
-#define IMG_CONVEYOR_BELT_3_SWITCH_RIGHT 297
-#define IMG_CONVEYOR_BELT_4_MIDDLE 298
-#define IMG_CONVEYOR_BELT_4_MIDDLE_ACTIVE 299
-#define IMG_CONVEYOR_BELT_4_LEFT 300
-#define IMG_CONVEYOR_BELT_4_LEFT_ACTIVE 301
-#define IMG_CONVEYOR_BELT_4_RIGHT 302
-#define IMG_CONVEYOR_BELT_4_RIGHT_ACTIVE 303
-#define IMG_CONVEYOR_BELT_4_SWITCH_LEFT 304
-#define IMG_CONVEYOR_BELT_4_SWITCH_MIDDLE 305
-#define IMG_CONVEYOR_BELT_4_SWITCH_RIGHT 306
-#define IMG_SWITCHGATE_SWITCH_UP 307
-#define IMG_SWITCHGATE_SWITCH_DOWN 308
-#define IMG_LIGHT_SWITCH 309
-#define IMG_LIGHT_SWITCH_ACTIVE 310
-#define IMG_TIMEGATE_SWITCH 311
-#define IMG_TIMEGATE_SWITCH_ACTIVE 312
-#define IMG_ENVELOPE_1 313
-#define IMG_ENVELOPE_1_COLLECTING 314
-#define IMG_ENVELOPE_2 315
-#define IMG_ENVELOPE_2_COLLECTING 316
-#define IMG_ENVELOPE_3 317
-#define IMG_ENVELOPE_3_COLLECTING 318
-#define IMG_ENVELOPE_4 319
-#define IMG_ENVELOPE_4_COLLECTING 320
-#define IMG_SIGN_EXCLAMATION 321
-#define IMG_SIGN_STOP 322
-#define IMG_LANDMINE 323
-#define IMG_STEELWALL_SLIPPERY 324
-#define IMG_EXTRA_TIME 325
-#define IMG_SHIELD_NORMAL 326
-#define IMG_SHIELD_NORMAL_ACTIVE 327
-#define IMG_SHIELD_DEADLY 328
-#define IMG_SHIELD_DEADLY_ACTIVE 329
-#define IMG_SWITCHGATE_CLOSED 330
-#define IMG_SWITCHGATE_OPENING 331
-#define IMG_SWITCHGATE_OPEN 332
-#define IMG_SWITCHGATE_CLOSING 333
-#define IMG_TIMEGATE_CLOSED 334
-#define IMG_TIMEGATE_OPENING 335
-#define IMG_TIMEGATE_OPEN 336
-#define IMG_TIMEGATE_CLOSING 337
-#define IMG_PEARL 338
-#define IMG_PEARL_BREAKING 339
-#define IMG_CRYSTAL 340
-#define IMG_WALL_PEARL 341
-#define IMG_WALL_CRYSTAL 342
-#define IMG_TUBE_RIGHT_DOWN 343
-#define IMG_TUBE_HORIZONTAL_DOWN 344
-#define IMG_TUBE_LEFT_DOWN 345
-#define IMG_TUBE_HORIZONTAL 346
-#define IMG_TUBE_VERTICAL_RIGHT 347
-#define IMG_TUBE_ANY 348
-#define IMG_TUBE_VERTICAL_LEFT 349
-#define IMG_TUBE_VERTICAL 350
-#define IMG_TUBE_RIGHT_UP 351
-#define IMG_TUBE_HORIZONTAL_UP 352
-#define IMG_TUBE_LEFT_UP 353
-#define IMG_TRAP 354
-#define IMG_TRAP_ACTIVE 355
-#define IMG_DX_SUPABOMB 356
-#define IMG_KEY_1 357
-#define IMG_KEY_1_EDITOR 358
-#define IMG_KEY_2 359
-#define IMG_KEY_2_EDITOR 360
-#define IMG_KEY_3 361
-#define IMG_KEY_3_EDITOR 362
-#define IMG_KEY_4 363
-#define IMG_KEY_4_EDITOR 364
-#define IMG_GATE_1 365
-#define IMG_GATE_2 366
-#define IMG_GATE_3 367
-#define IMG_GATE_4 368
-#define IMG_GATE_1_GRAY 369
-#define IMG_GATE_1_GRAY_EDITOR 370
-#define IMG_GATE_2_GRAY 371
-#define IMG_GATE_2_GRAY_EDITOR 372
-#define IMG_GATE_3_GRAY 373
-#define IMG_GATE_3_GRAY_EDITOR 374
-#define IMG_GATE_4_GRAY 375
-#define IMG_GATE_4_GRAY_EDITOR 376
-#define IMG_GAME_OF_LIFE 377
-#define IMG_BIOMAZE 378
-#define IMG_PACMAN 379
-#define IMG_PACMAN_RIGHT 380
-#define IMG_PACMAN_UP 381
-#define IMG_PACMAN_LEFT 382
-#define IMG_PACMAN_DOWN 383
-#define IMG_PACMAN_TURNING_FROM_RIGHT 384
-#define IMG_PACMAN_TURNING_FROM_UP 385
-#define IMG_PACMAN_TURNING_FROM_LEFT 386
-#define IMG_PACMAN_TURNING_FROM_DOWN 387
-#define IMG_LAMP 388
-#define IMG_LAMP_EDITOR 389
-#define IMG_LAMP_ACTIVE 390
-#define IMG_TIME_ORB_FULL 391
-#define IMG_TIME_ORB_EMPTY 392
-#define IMG_EMERALD_YELLOW 393
-#define IMG_EMERALD_YELLOW_MOVING 394
-#define IMG_EMERALD_YELLOW_FALLING 395
-#define IMG_EMERALD_RED 396
-#define IMG_EMERALD_RED_MOVING 397
-#define IMG_EMERALD_RED_FALLING 398
-#define IMG_EMERALD_PURPLE 399
-#define IMG_EMERALD_PURPLE_MOVING 400
-#define IMG_EMERALD_PURPLE_FALLING 401
-#define IMG_WALL_EMERALD_YELLOW 402
-#define IMG_WALL_EMERALD_RED 403
-#define IMG_WALL_EMERALD_PURPLE 404
-#define IMG_WALL_BD_DIAMOND 405
-#define IMG_EXPANDABLE_WALL 406
-#define IMG_EXPANDABLE_WALL_HORIZONTAL 407
-#define IMG_EXPANDABLE_WALL_HORIZONTAL_EDITOR 408
-#define IMG_EXPANDABLE_WALL_VERTICAL 409
-#define IMG_EXPANDABLE_WALL_VERTICAL_EDITOR 410
-#define IMG_EXPANDABLE_WALL_ANY 411
-#define IMG_EXPANDABLE_WALL_ANY_EDITOR 412
-#define IMG_EXPANDABLE_WALL_GROWING_LEFT 413
-#define IMG_EXPANDABLE_WALL_GROWING_RIGHT 414
-#define IMG_EXPANDABLE_WALL_GROWING_UP 415
-#define IMG_EXPANDABLE_WALL_GROWING_DOWN 416
-#define IMG_BLACK_ORB 417
-#define IMG_SPEED_PILL 418
-#define IMG_DARK_YAMYAM 419
-#define IMG_DYNABOMB 420
-#define IMG_DYNABOMB_ACTIVE 421
-#define IMG_DYNABOMB_PLAYER_1 422
-#define IMG_DYNABOMB_PLAYER_1_ACTIVE 423
-#define IMG_DYNABOMB_PLAYER_2 424
-#define IMG_DYNABOMB_PLAYER_2_ACTIVE 425
-#define IMG_DYNABOMB_PLAYER_3 426
-#define IMG_DYNABOMB_PLAYER_3_ACTIVE 427
-#define IMG_DYNABOMB_PLAYER_4 428
-#define IMG_DYNABOMB_PLAYER_4_ACTIVE 429
-#define IMG_DYNABOMB_INCREASE_NUMBER 430
-#define IMG_DYNABOMB_INCREASE_SIZE 431
-#define IMG_DYNABOMB_INCREASE_POWER 432
-#define IMG_PIG 433
-#define IMG_PIG_DOWN 434
-#define IMG_PIG_UP 435
-#define IMG_PIG_LEFT 436
-#define IMG_PIG_RIGHT 437
-#define IMG_PIG_MOVING_DOWN 438
-#define IMG_PIG_MOVING_UP 439
-#define IMG_PIG_MOVING_LEFT 440
-#define IMG_PIG_MOVING_RIGHT 441
-#define IMG_PIG_DIGGING_DOWN 442
-#define IMG_PIG_DIGGING_UP 443
-#define IMG_PIG_DIGGING_LEFT 444
-#define IMG_PIG_DIGGING_RIGHT 445
-#define IMG_DRAGON 446
-#define IMG_DRAGON_DOWN 447
-#define IMG_DRAGON_UP 448
-#define IMG_DRAGON_LEFT 449
-#define IMG_DRAGON_RIGHT 450
-#define IMG_DRAGON_MOVING_DOWN 451
-#define IMG_DRAGON_MOVING_UP 452
-#define IMG_DRAGON_MOVING_LEFT 453
-#define IMG_DRAGON_MOVING_RIGHT 454
-#define IMG_DRAGON_ATTACKING_DOWN 455
-#define IMG_DRAGON_ATTACKING_UP 456
-#define IMG_DRAGON_ATTACKING_LEFT 457
-#define IMG_DRAGON_ATTACKING_RIGHT 458
-#define IMG_MOLE 459
-#define IMG_MOLE_DOWN 460
-#define IMG_MOLE_UP 461
-#define IMG_MOLE_LEFT 462
-#define IMG_MOLE_RIGHT 463
-#define IMG_MOLE_MOVING_DOWN 464
-#define IMG_MOLE_MOVING_UP 465
-#define IMG_MOLE_MOVING_LEFT 466
-#define IMG_MOLE_MOVING_RIGHT 467
-#define IMG_MOLE_DIGGING_DOWN 468
-#define IMG_MOLE_DIGGING_UP 469
-#define IMG_MOLE_DIGGING_LEFT 470
-#define IMG_MOLE_DIGGING_RIGHT 471
-#define IMG_PENGUIN 472
-#define IMG_PENGUIN_EDITOR 473
-#define IMG_PENGUIN_DOWN 474
-#define IMG_PENGUIN_UP 475
-#define IMG_PENGUIN_LEFT 476
-#define IMG_PENGUIN_RIGHT 477
-#define IMG_PENGUIN_MOVING_DOWN 478
-#define IMG_PENGUIN_MOVING_UP 479
-#define IMG_PENGUIN_MOVING_LEFT 480
-#define IMG_PENGUIN_MOVING_RIGHT 481
-#define IMG_SATELLITE 482
-#define IMG_FLAMES_1_LEFT 483
-#define IMG_FLAMES_2_LEFT 484
-#define IMG_FLAMES_3_LEFT 485
-#define IMG_FLAMES_1_RIGHT 486
-#define IMG_FLAMES_2_RIGHT 487
-#define IMG_FLAMES_3_RIGHT 488
-#define IMG_FLAMES_1_UP 489
-#define IMG_FLAMES_2_UP 490
-#define IMG_FLAMES_3_UP 491
-#define IMG_FLAMES_1_DOWN 492
-#define IMG_FLAMES_2_DOWN 493
-#define IMG_FLAMES_3_DOWN 494
-#define IMG_STONEBLOCK 495
-#define IMG_MAZE_RUNNER 496
-#define IMG_PLAYER_1 497
-#define IMG_PLAYER_1_EDITOR 498
-#define IMG_PLAYER_1_DOWN 499
-#define IMG_PLAYER_1_UP 500
-#define IMG_PLAYER_1_LEFT 501
-#define IMG_PLAYER_1_RIGHT 502
-#define IMG_PLAYER_1_MOVING_DOWN 503
-#define IMG_PLAYER_1_MOVING_UP 504
-#define IMG_PLAYER_1_MOVING_LEFT 505
-#define IMG_PLAYER_1_MOVING_RIGHT 506
-#define IMG_PLAYER_1_DIGGING_DOWN 507
-#define IMG_PLAYER_1_DIGGING_UP 508
-#define IMG_PLAYER_1_DIGGING_LEFT 509
-#define IMG_PLAYER_1_DIGGING_RIGHT 510
-#define IMG_PLAYER_1_COLLECTING_DOWN 511
-#define IMG_PLAYER_1_COLLECTING_UP 512
-#define IMG_PLAYER_1_COLLECTING_LEFT 513
-#define IMG_PLAYER_1_COLLECTING_RIGHT 514
-#define IMG_PLAYER_1_PUSHING_DOWN 515
-#define IMG_PLAYER_1_PUSHING_UP 516
-#define IMG_PLAYER_1_PUSHING_LEFT 517
-#define IMG_PLAYER_1_PUSHING_RIGHT 518
-#define IMG_PLAYER_1_SNAPPING_DOWN 519
-#define IMG_PLAYER_1_SNAPPING_UP 520
-#define IMG_PLAYER_1_SNAPPING_LEFT 521
-#define IMG_PLAYER_1_SNAPPING_RIGHT 522
-#define IMG_PLAYER_2 523
-#define IMG_PLAYER_2_EDITOR 524
-#define IMG_PLAYER_2_DOWN 525
-#define IMG_PLAYER_2_UP 526
-#define IMG_PLAYER_2_LEFT 527
-#define IMG_PLAYER_2_RIGHT 528
-#define IMG_PLAYER_2_MOVING_DOWN 529
-#define IMG_PLAYER_2_MOVING_UP 530
-#define IMG_PLAYER_2_MOVING_LEFT 531
-#define IMG_PLAYER_2_MOVING_RIGHT 532
-#define IMG_PLAYER_2_DIGGING_DOWN 533
-#define IMG_PLAYER_2_DIGGING_UP 534
-#define IMG_PLAYER_2_DIGGING_LEFT 535
-#define IMG_PLAYER_2_DIGGING_RIGHT 536
-#define IMG_PLAYER_2_COLLECTING_DOWN 537
-#define IMG_PLAYER_2_COLLECTING_UP 538
-#define IMG_PLAYER_2_COLLECTING_LEFT 539
-#define IMG_PLAYER_2_COLLECTING_RIGHT 540
-#define IMG_PLAYER_2_PUSHING_DOWN 541
-#define IMG_PLAYER_2_PUSHING_UP 542
-#define IMG_PLAYER_2_PUSHING_LEFT 543
-#define IMG_PLAYER_2_PUSHING_RIGHT 544
-#define IMG_PLAYER_2_SNAPPING_DOWN 545
-#define IMG_PLAYER_2_SNAPPING_UP 546
-#define IMG_PLAYER_2_SNAPPING_LEFT 547
-#define IMG_PLAYER_2_SNAPPING_RIGHT 548
-#define IMG_PLAYER_3 549
-#define IMG_PLAYER_3_EDITOR 550
-#define IMG_PLAYER_3_DOWN 551
-#define IMG_PLAYER_3_UP 552
-#define IMG_PLAYER_3_LEFT 553
-#define IMG_PLAYER_3_RIGHT 554
-#define IMG_PLAYER_3_MOVING_DOWN 555
-#define IMG_PLAYER_3_MOVING_UP 556
-#define IMG_PLAYER_3_MOVING_LEFT 557
-#define IMG_PLAYER_3_MOVING_RIGHT 558
-#define IMG_PLAYER_3_DIGGING_DOWN 559
-#define IMG_PLAYER_3_DIGGING_UP 560
-#define IMG_PLAYER_3_DIGGING_LEFT 561
-#define IMG_PLAYER_3_DIGGING_RIGHT 562
-#define IMG_PLAYER_3_COLLECTING_DOWN 563
-#define IMG_PLAYER_3_COLLECTING_UP 564
-#define IMG_PLAYER_3_COLLECTING_LEFT 565
-#define IMG_PLAYER_3_COLLECTING_RIGHT 566
-#define IMG_PLAYER_3_PUSHING_DOWN 567
-#define IMG_PLAYER_3_PUSHING_UP 568
-#define IMG_PLAYER_3_PUSHING_LEFT 569
-#define IMG_PLAYER_3_PUSHING_RIGHT 570
-#define IMG_PLAYER_3_SNAPPING_DOWN 571
-#define IMG_PLAYER_3_SNAPPING_UP 572
-#define IMG_PLAYER_3_SNAPPING_LEFT 573
-#define IMG_PLAYER_3_SNAPPING_RIGHT 574
-#define IMG_PLAYER_4 575
-#define IMG_PLAYER_4_EDITOR 576
-#define IMG_PLAYER_4_DOWN 577
-#define IMG_PLAYER_4_UP 578
-#define IMG_PLAYER_4_LEFT 579
-#define IMG_PLAYER_4_RIGHT 580
-#define IMG_PLAYER_4_MOVING_DOWN 581
-#define IMG_PLAYER_4_MOVING_UP 582
-#define IMG_PLAYER_4_MOVING_LEFT 583
-#define IMG_PLAYER_4_MOVING_RIGHT 584
-#define IMG_PLAYER_4_DIGGING_DOWN 585
-#define IMG_PLAYER_4_DIGGING_UP 586
-#define IMG_PLAYER_4_DIGGING_LEFT 587
-#define IMG_PLAYER_4_DIGGING_RIGHT 588
-#define IMG_PLAYER_4_COLLECTING_DOWN 589
-#define IMG_PLAYER_4_COLLECTING_UP 590
-#define IMG_PLAYER_4_COLLECTING_LEFT 591
-#define IMG_PLAYER_4_COLLECTING_RIGHT 592
-#define IMG_PLAYER_4_PUSHING_DOWN 593
-#define IMG_PLAYER_4_PUSHING_UP 594
-#define IMG_PLAYER_4_PUSHING_LEFT 595
-#define IMG_PLAYER_4_PUSHING_RIGHT 596
-#define IMG_PLAYER_4_SNAPPING_DOWN 597
-#define IMG_PLAYER_4_SNAPPING_UP 598
-#define IMG_PLAYER_4_SNAPPING_LEFT 599
-#define IMG_PLAYER_4_SNAPPING_RIGHT 600
-#define IMG_DEFAULT_EXPLODING 601
-#define IMG_TWINKLE_BLUE 602
-#define IMG_TWINKLE_WHITE 603
-#define IMG_STEELWALL_TOPLEFT 604
-#define IMG_STEELWALL_TOPRIGHT 605
-#define IMG_STEELWALL_BOTTOMLEFT 606
-#define IMG_STEELWALL_BOTTOMRIGHT 607
-#define IMG_STEELWALL_HORIZONTAL 608
-#define IMG_STEELWALL_VERTICAL 609
-#define IMG_STEELWALL_TOPLEFT_EDITOR 610
-#define IMG_STEELWALL_TOPRIGHT_EDITOR 611
-#define IMG_STEELWALL_BOTTOMLEFT_EDITOR 612
-#define IMG_STEELWALL_BOTTOMRIGHT_EDITOR 613
-#define IMG_STEELWALL_HORIZONTAL_EDITOR 614
-#define IMG_STEELWALL_VERTICAL_EDITOR 615
-#define IMG_INVISIBLE_STEELWALL_TOPLEFT 616
-#define IMG_INVISIBLE_STEELWALL_TOPRIGHT 617
-#define IMG_INVISIBLE_STEELWALL_BOTTOMLEFT 618
-#define IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT 619
-#define IMG_INVISIBLE_STEELWALL_HORIZONTAL 620
-#define IMG_INVISIBLE_STEELWALL_VERTICAL 621
-#define IMG_INVISIBLE_STEELWALL_TOPLEFT_EDITOR 622
-#define IMG_INVISIBLE_STEELWALL_TOPRIGHT_EDITOR 623
-#define IMG_INVISIBLE_STEELWALL_BOTTOMLEFT_EDITOR 624
-#define IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT_EDITOR 625
-#define IMG_INVISIBLE_STEELWALL_HORIZONTAL_EDITOR 626
-#define IMG_INVISIBLE_STEELWALL_VERTICAL_EDITOR 627
-#define IMG_ARROW_LEFT 628
-#define IMG_ARROW_RIGHT 629
-#define IMG_ARROW_UP 630
-#define IMG_ARROW_DOWN 631
-#define IMG_CHAR_SPACE 632
-#define IMG_CHAR_EXCLAM 633
-#define IMG_CHAR_QUOTEDBL 634
-#define IMG_CHAR_NUMBERSIGN 635
-#define IMG_CHAR_DOLLAR 636
-#define IMG_CHAR_PROCENT 637
-#define IMG_CHAR_AMPERSAND 638
-#define IMG_CHAR_APOSTROPHE 639
-#define IMG_CHAR_PARENLEFT 640
-#define IMG_CHAR_PARENRIGHT 641
-#define IMG_CHAR_ASTERISK 642
-#define IMG_CHAR_PLUS 643
-#define IMG_CHAR_COMMA 644
-#define IMG_CHAR_MINUS 645
-#define IMG_CHAR_PERIOD 646
-#define IMG_CHAR_SLASH 647
-#define IMG_CHAR_0 648
-#define IMG_CHAR_1 649
-#define IMG_CHAR_2 650
-#define IMG_CHAR_3 651
-#define IMG_CHAR_4 652
-#define IMG_CHAR_5 653
-#define IMG_CHAR_6 654
-#define IMG_CHAR_7 655
-#define IMG_CHAR_8 656
-#define IMG_CHAR_9 657
-#define IMG_CHAR_COLON 658
-#define IMG_CHAR_SEMICOLON 659
-#define IMG_CHAR_LESS 660
-#define IMG_CHAR_EQUAL 661
-#define IMG_CHAR_GREATER 662
-#define IMG_CHAR_QUESTION 663
-#define IMG_CHAR_AT 664
-#define IMG_CHAR_A 665
-#define IMG_CHAR_B 666
-#define IMG_CHAR_C 667
-#define IMG_CHAR_D 668
-#define IMG_CHAR_E 669
-#define IMG_CHAR_F 670
-#define IMG_CHAR_G 671
-#define IMG_CHAR_H 672
-#define IMG_CHAR_I 673
-#define IMG_CHAR_J 674
-#define IMG_CHAR_K 675
-#define IMG_CHAR_L 676
-#define IMG_CHAR_M 677
-#define IMG_CHAR_N 678
-#define IMG_CHAR_O 679
-#define IMG_CHAR_P 680
-#define IMG_CHAR_Q 681
-#define IMG_CHAR_R 682
-#define IMG_CHAR_S 683
-#define IMG_CHAR_T 684
-#define IMG_CHAR_U 685
-#define IMG_CHAR_V 686
-#define IMG_CHAR_W 687
-#define IMG_CHAR_X 688
-#define IMG_CHAR_Y 689
-#define IMG_CHAR_Z 690
-#define IMG_CHAR_BRACKETLEFT 691
-#define IMG_CHAR_BACKSLASH 692
-#define IMG_CHAR_BRACKETRIGHT 693
-#define IMG_CHAR_ASCIICIRCUM 694
-#define IMG_CHAR_UNDERSCORE 695
-#define IMG_CHAR_COPYRIGHT 696
-#define IMG_CHAR_AUMLAUT 697
-#define IMG_CHAR_OUMLAUT 698
-#define IMG_CHAR_UUMLAUT 699
-#define IMG_CHAR_DEGREE 700
-#define IMG_CHAR_TRADEMARK 701
-#define IMG_CHAR_CURSOR 702
-#define IMG_CUSTOM_1 703
-#define IMG_CUSTOM_1_EDITOR 704
-#define IMG_CUSTOM_2 705
-#define IMG_CUSTOM_2_EDITOR 706
-#define IMG_CUSTOM_3 707
-#define IMG_CUSTOM_3_EDITOR 708
-#define IMG_CUSTOM_4 709
-#define IMG_CUSTOM_4_EDITOR 710
-#define IMG_CUSTOM_5 711
-#define IMG_CUSTOM_5_EDITOR 712
-#define IMG_CUSTOM_6 713
-#define IMG_CUSTOM_6_EDITOR 714
-#define IMG_CUSTOM_7 715
-#define IMG_CUSTOM_7_EDITOR 716
-#define IMG_CUSTOM_8 717
-#define IMG_CUSTOM_8_EDITOR 718
-#define IMG_CUSTOM_9 719
-#define IMG_CUSTOM_9_EDITOR 720
-#define IMG_CUSTOM_10 721
-#define IMG_CUSTOM_10_EDITOR 722
-#define IMG_CUSTOM_11 723
-#define IMG_CUSTOM_11_EDITOR 724
-#define IMG_CUSTOM_12 725
-#define IMG_CUSTOM_12_EDITOR 726
-#define IMG_CUSTOM_13 727
-#define IMG_CUSTOM_13_EDITOR 728
-#define IMG_CUSTOM_14 729
-#define IMG_CUSTOM_14_EDITOR 730
-#define IMG_CUSTOM_15 731
-#define IMG_CUSTOM_15_EDITOR 732
-#define IMG_CUSTOM_16 733
-#define IMG_CUSTOM_16_EDITOR 734
-#define IMG_CUSTOM_17 735
-#define IMG_CUSTOM_17_EDITOR 736
-#define IMG_CUSTOM_18 737
-#define IMG_CUSTOM_18_EDITOR 738
-#define IMG_CUSTOM_19 739
-#define IMG_CUSTOM_19_EDITOR 740
-#define IMG_CUSTOM_20 741
-#define IMG_CUSTOM_20_EDITOR 742
-#define IMG_CUSTOM_21 743
-#define IMG_CUSTOM_21_EDITOR 744
-#define IMG_CUSTOM_22 745
-#define IMG_CUSTOM_22_EDITOR 746
-#define IMG_CUSTOM_23 747
-#define IMG_CUSTOM_23_EDITOR 748
-#define IMG_CUSTOM_24 749
-#define IMG_CUSTOM_24_EDITOR 750
-#define IMG_CUSTOM_25 751
-#define IMG_CUSTOM_25_EDITOR 752
-#define IMG_CUSTOM_26 753
-#define IMG_CUSTOM_26_EDITOR 754
-#define IMG_CUSTOM_27 755
-#define IMG_CUSTOM_27_EDITOR 756
-#define IMG_CUSTOM_28 757
-#define IMG_CUSTOM_28_EDITOR 758
-#define IMG_CUSTOM_29 759
-#define IMG_CUSTOM_29_EDITOR 760
-#define IMG_CUSTOM_30 761
-#define IMG_CUSTOM_30_EDITOR 762
-#define IMG_CUSTOM_31 763
-#define IMG_CUSTOM_31_EDITOR 764
-#define IMG_CUSTOM_32 765
-#define IMG_CUSTOM_32_EDITOR 766
-#define IMG_CUSTOM_33 767
-#define IMG_CUSTOM_33_EDITOR 768
-#define IMG_CUSTOM_34 769
-#define IMG_CUSTOM_34_EDITOR 770
-#define IMG_CUSTOM_35 771
-#define IMG_CUSTOM_35_EDITOR 772
-#define IMG_CUSTOM_36 773
-#define IMG_CUSTOM_36_EDITOR 774
-#define IMG_CUSTOM_37 775
-#define IMG_CUSTOM_37_EDITOR 776
-#define IMG_CUSTOM_38 777
-#define IMG_CUSTOM_38_EDITOR 778
-#define IMG_CUSTOM_39 779
-#define IMG_CUSTOM_39_EDITOR 780
-#define IMG_CUSTOM_40 781
-#define IMG_CUSTOM_40_EDITOR 782
-#define IMG_CUSTOM_41 783
-#define IMG_CUSTOM_41_EDITOR 784
-#define IMG_CUSTOM_42 785
-#define IMG_CUSTOM_42_EDITOR 786
-#define IMG_CUSTOM_43 787
-#define IMG_CUSTOM_43_EDITOR 788
-#define IMG_CUSTOM_44 789
-#define IMG_CUSTOM_44_EDITOR 790
-#define IMG_CUSTOM_45 791
-#define IMG_CUSTOM_45_EDITOR 792
-#define IMG_CUSTOM_46 793
-#define IMG_CUSTOM_46_EDITOR 794
-#define IMG_CUSTOM_47 795
-#define IMG_CUSTOM_47_EDITOR 796
-#define IMG_CUSTOM_48 797
-#define IMG_CUSTOM_48_EDITOR 798
-#define IMG_CUSTOM_49 799
-#define IMG_CUSTOM_49_EDITOR 800
-#define IMG_CUSTOM_50 801
-#define IMG_CUSTOM_50_EDITOR 802
-#define IMG_CUSTOM_51 803
-#define IMG_CUSTOM_51_EDITOR 804
-#define IMG_CUSTOM_52 805
-#define IMG_CUSTOM_52_EDITOR 806
-#define IMG_CUSTOM_53 807
-#define IMG_CUSTOM_53_EDITOR 808
-#define IMG_CUSTOM_54 809
-#define IMG_CUSTOM_54_EDITOR 810
-#define IMG_CUSTOM_55 811
-#define IMG_CUSTOM_55_EDITOR 812
-#define IMG_CUSTOM_56 813
-#define IMG_CUSTOM_56_EDITOR 814
-#define IMG_CUSTOM_57 815
-#define IMG_CUSTOM_57_EDITOR 816
-#define IMG_CUSTOM_58 817
-#define IMG_CUSTOM_58_EDITOR 818
-#define IMG_CUSTOM_59 819
-#define IMG_CUSTOM_59_EDITOR 820
-#define IMG_CUSTOM_60 821
-#define IMG_CUSTOM_60_EDITOR 822
-#define IMG_CUSTOM_61 823
-#define IMG_CUSTOM_61_EDITOR 824
-#define IMG_CUSTOM_62 825
-#define IMG_CUSTOM_62_EDITOR 826
-#define IMG_CUSTOM_63 827
-#define IMG_CUSTOM_63_EDITOR 828
-#define IMG_CUSTOM_64 829
-#define IMG_CUSTOM_64_EDITOR 830
-#define IMG_CUSTOM_65 831
-#define IMG_CUSTOM_65_EDITOR 832
-#define IMG_CUSTOM_66 833
-#define IMG_CUSTOM_66_EDITOR 834
-#define IMG_CUSTOM_67 835
-#define IMG_CUSTOM_67_EDITOR 836
-#define IMG_CUSTOM_68 837
-#define IMG_CUSTOM_68_EDITOR 838
-#define IMG_CUSTOM_69 839
-#define IMG_CUSTOM_69_EDITOR 840
-#define IMG_CUSTOM_70 841
-#define IMG_CUSTOM_70_EDITOR 842
-#define IMG_CUSTOM_71 843
-#define IMG_CUSTOM_71_EDITOR 844
-#define IMG_CUSTOM_72 845
-#define IMG_CUSTOM_72_EDITOR 846
-#define IMG_CUSTOM_73 847
-#define IMG_CUSTOM_73_EDITOR 848
-#define IMG_CUSTOM_74 849
-#define IMG_CUSTOM_74_EDITOR 850
-#define IMG_CUSTOM_75 851
-#define IMG_CUSTOM_75_EDITOR 852
-#define IMG_CUSTOM_76 853
-#define IMG_CUSTOM_76_EDITOR 854
-#define IMG_CUSTOM_77 855
-#define IMG_CUSTOM_77_EDITOR 856
-#define IMG_CUSTOM_78 857
-#define IMG_CUSTOM_78_EDITOR 858
-#define IMG_CUSTOM_79 859
-#define IMG_CUSTOM_79_EDITOR 860
-#define IMG_CUSTOM_80 861
-#define IMG_CUSTOM_80_EDITOR 862
-#define IMG_CUSTOM_81 863
-#define IMG_CUSTOM_81_EDITOR 864
-#define IMG_CUSTOM_82 865
-#define IMG_CUSTOM_82_EDITOR 866
-#define IMG_CUSTOM_83 867
-#define IMG_CUSTOM_83_EDITOR 868
-#define IMG_CUSTOM_84 869
-#define IMG_CUSTOM_84_EDITOR 870
-#define IMG_CUSTOM_85 871
-#define IMG_CUSTOM_85_EDITOR 872
-#define IMG_CUSTOM_86 873
-#define IMG_CUSTOM_86_EDITOR 874
-#define IMG_CUSTOM_87 875
-#define IMG_CUSTOM_87_EDITOR 876
-#define IMG_CUSTOM_88 877
-#define IMG_CUSTOM_88_EDITOR 878
-#define IMG_CUSTOM_89 879
-#define IMG_CUSTOM_89_EDITOR 880
-#define IMG_CUSTOM_90 881
-#define IMG_CUSTOM_90_EDITOR 882
-#define IMG_CUSTOM_91 883
-#define IMG_CUSTOM_91_EDITOR 884
-#define IMG_CUSTOM_92 885
-#define IMG_CUSTOM_92_EDITOR 886
-#define IMG_CUSTOM_93 887
-#define IMG_CUSTOM_93_EDITOR 888
-#define IMG_CUSTOM_94 889
-#define IMG_CUSTOM_94_EDITOR 890
-#define IMG_CUSTOM_95 891
-#define IMG_CUSTOM_95_EDITOR 892
-#define IMG_CUSTOM_96 893
-#define IMG_CUSTOM_96_EDITOR 894
-#define IMG_CUSTOM_97 895
-#define IMG_CUSTOM_97_EDITOR 896
-#define IMG_CUSTOM_98 897
-#define IMG_CUSTOM_98_EDITOR 898
-#define IMG_CUSTOM_99 899
-#define IMG_CUSTOM_99_EDITOR 900
-#define IMG_CUSTOM_100 901
-#define IMG_CUSTOM_100_EDITOR 902
-#define IMG_CUSTOM_101 903
-#define IMG_CUSTOM_101_EDITOR 904
-#define IMG_CUSTOM_102 905
-#define IMG_CUSTOM_102_EDITOR 906
-#define IMG_CUSTOM_103 907
-#define IMG_CUSTOM_103_EDITOR 908
-#define IMG_CUSTOM_104 909
-#define IMG_CUSTOM_104_EDITOR 910
-#define IMG_CUSTOM_105 911
-#define IMG_CUSTOM_105_EDITOR 912
-#define IMG_CUSTOM_106 913
-#define IMG_CUSTOM_106_EDITOR 914
-#define IMG_CUSTOM_107 915
-#define IMG_CUSTOM_107_EDITOR 916
-#define IMG_CUSTOM_108 917
-#define IMG_CUSTOM_108_EDITOR 918
-#define IMG_CUSTOM_109 919
-#define IMG_CUSTOM_109_EDITOR 920
-#define IMG_CUSTOM_110 921
-#define IMG_CUSTOM_110_EDITOR 922
-#define IMG_CUSTOM_111 923
-#define IMG_CUSTOM_111_EDITOR 924
-#define IMG_CUSTOM_112 925
-#define IMG_CUSTOM_112_EDITOR 926
-#define IMG_CUSTOM_113 927
-#define IMG_CUSTOM_113_EDITOR 928
-#define IMG_CUSTOM_114 929
-#define IMG_CUSTOM_114_EDITOR 930
-#define IMG_CUSTOM_115 931
-#define IMG_CUSTOM_115_EDITOR 932
-#define IMG_CUSTOM_116 933
-#define IMG_CUSTOM_116_EDITOR 934
-#define IMG_CUSTOM_117 935
-#define IMG_CUSTOM_117_EDITOR 936
-#define IMG_CUSTOM_118 937
-#define IMG_CUSTOM_118_EDITOR 938
-#define IMG_CUSTOM_119 939
-#define IMG_CUSTOM_119_EDITOR 940
-#define IMG_CUSTOM_120 941
-#define IMG_CUSTOM_120_EDITOR 942
-#define IMG_CUSTOM_121 943
-#define IMG_CUSTOM_121_EDITOR 944
-#define IMG_CUSTOM_122 945
-#define IMG_CUSTOM_122_EDITOR 946
-#define IMG_CUSTOM_123 947
-#define IMG_CUSTOM_123_EDITOR 948
-#define IMG_CUSTOM_124 949
-#define IMG_CUSTOM_124_EDITOR 950
-#define IMG_CUSTOM_125 951
-#define IMG_CUSTOM_125_EDITOR 952
-#define IMG_CUSTOM_126 953
-#define IMG_CUSTOM_126_EDITOR 954
-#define IMG_CUSTOM_127 955
-#define IMG_CUSTOM_127_EDITOR 956
-#define IMG_CUSTOM_128 957
-#define IMG_CUSTOM_128_EDITOR 958
-#define IMG_CUSTOM_129 959
-#define IMG_CUSTOM_129_EDITOR 960
-#define IMG_CUSTOM_130 961
-#define IMG_CUSTOM_130_EDITOR 962
-#define IMG_CUSTOM_131 963
-#define IMG_CUSTOM_131_EDITOR 964
-#define IMG_CUSTOM_132 965
-#define IMG_CUSTOM_132_EDITOR 966
-#define IMG_CUSTOM_133 967
-#define IMG_CUSTOM_133_EDITOR 968
-#define IMG_CUSTOM_134 969
-#define IMG_CUSTOM_134_EDITOR 970
-#define IMG_CUSTOM_135 971
-#define IMG_CUSTOM_135_EDITOR 972
-#define IMG_CUSTOM_136 973
-#define IMG_CUSTOM_136_EDITOR 974
-#define IMG_CUSTOM_137 975
-#define IMG_CUSTOM_137_EDITOR 976
-#define IMG_CUSTOM_138 977
-#define IMG_CUSTOM_138_EDITOR 978
-#define IMG_CUSTOM_139 979
-#define IMG_CUSTOM_139_EDITOR 980
-#define IMG_CUSTOM_140 981
-#define IMG_CUSTOM_140_EDITOR 982
-#define IMG_CUSTOM_141 983
-#define IMG_CUSTOM_141_EDITOR 984
-#define IMG_CUSTOM_142 985
-#define IMG_CUSTOM_142_EDITOR 986
-#define IMG_CUSTOM_143 987
-#define IMG_CUSTOM_143_EDITOR 988
-#define IMG_CUSTOM_144 989
-#define IMG_CUSTOM_144_EDITOR 990
-#define IMG_CUSTOM_145 991
-#define IMG_CUSTOM_145_EDITOR 992
-#define IMG_CUSTOM_146 993
-#define IMG_CUSTOM_146_EDITOR 994
-#define IMG_CUSTOM_147 995
-#define IMG_CUSTOM_147_EDITOR 996
-#define IMG_CUSTOM_148 997
-#define IMG_CUSTOM_148_EDITOR 998
-#define IMG_CUSTOM_149 999
-#define IMG_CUSTOM_149_EDITOR 1000
-#define IMG_CUSTOM_150 1001
-#define IMG_CUSTOM_150_EDITOR 1002
-#define IMG_CUSTOM_151 1003
-#define IMG_CUSTOM_151_EDITOR 1004
-#define IMG_CUSTOM_152 1005
-#define IMG_CUSTOM_152_EDITOR 1006
-#define IMG_CUSTOM_153 1007
-#define IMG_CUSTOM_153_EDITOR 1008
-#define IMG_CUSTOM_154 1009
-#define IMG_CUSTOM_154_EDITOR 1010
-#define IMG_CUSTOM_155 1011
-#define IMG_CUSTOM_155_EDITOR 1012
-#define IMG_CUSTOM_156 1013
-#define IMG_CUSTOM_156_EDITOR 1014
-#define IMG_CUSTOM_157 1015
-#define IMG_CUSTOM_157_EDITOR 1016
-#define IMG_CUSTOM_158 1017
-#define IMG_CUSTOM_158_EDITOR 1018
-#define IMG_CUSTOM_159 1019
-#define IMG_CUSTOM_159_EDITOR 1020
-#define IMG_CUSTOM_160 1021
-#define IMG_CUSTOM_160_EDITOR 1022
-#define IMG_CUSTOM_161 1023
-#define IMG_CUSTOM_161_EDITOR 1024
-#define IMG_CUSTOM_162 1025
-#define IMG_CUSTOM_162_EDITOR 1026
-#define IMG_CUSTOM_163 1027
-#define IMG_CUSTOM_163_EDITOR 1028
-#define IMG_CUSTOM_164 1029
-#define IMG_CUSTOM_164_EDITOR 1030
-#define IMG_CUSTOM_165 1031
-#define IMG_CUSTOM_165_EDITOR 1032
-#define IMG_CUSTOM_166 1033
-#define IMG_CUSTOM_166_EDITOR 1034
-#define IMG_CUSTOM_167 1035
-#define IMG_CUSTOM_167_EDITOR 1036
-#define IMG_CUSTOM_168 1037
-#define IMG_CUSTOM_168_EDITOR 1038
-#define IMG_CUSTOM_169 1039
-#define IMG_CUSTOM_169_EDITOR 1040
-#define IMG_CUSTOM_170 1041
-#define IMG_CUSTOM_170_EDITOR 1042
-#define IMG_CUSTOM_171 1043
-#define IMG_CUSTOM_171_EDITOR 1044
-#define IMG_CUSTOM_172 1045
-#define IMG_CUSTOM_172_EDITOR 1046
-#define IMG_CUSTOM_173 1047
-#define IMG_CUSTOM_173_EDITOR 1048
-#define IMG_CUSTOM_174 1049
-#define IMG_CUSTOM_174_EDITOR 1050
-#define IMG_CUSTOM_175 1051
-#define IMG_CUSTOM_175_EDITOR 1052
-#define IMG_CUSTOM_176 1053
-#define IMG_CUSTOM_176_EDITOR 1054
-#define IMG_CUSTOM_177 1055
-#define IMG_CUSTOM_177_EDITOR 1056
-#define IMG_CUSTOM_178 1057
-#define IMG_CUSTOM_178_EDITOR 1058
-#define IMG_CUSTOM_179 1059
-#define IMG_CUSTOM_179_EDITOR 1060
-#define IMG_CUSTOM_180 1061
-#define IMG_CUSTOM_180_EDITOR 1062
-#define IMG_CUSTOM_181 1063
-#define IMG_CUSTOM_181_EDITOR 1064
-#define IMG_CUSTOM_182 1065
-#define IMG_CUSTOM_182_EDITOR 1066
-#define IMG_CUSTOM_183 1067
-#define IMG_CUSTOM_183_EDITOR 1068
-#define IMG_CUSTOM_184 1069
-#define IMG_CUSTOM_184_EDITOR 1070
-#define IMG_CUSTOM_185 1071
-#define IMG_CUSTOM_185_EDITOR 1072
-#define IMG_CUSTOM_186 1073
-#define IMG_CUSTOM_186_EDITOR 1074
-#define IMG_CUSTOM_187 1075
-#define IMG_CUSTOM_187_EDITOR 1076
-#define IMG_CUSTOM_188 1077
-#define IMG_CUSTOM_188_EDITOR 1078
-#define IMG_CUSTOM_189 1079
-#define IMG_CUSTOM_189_EDITOR 1080
-#define IMG_CUSTOM_190 1081
-#define IMG_CUSTOM_190_EDITOR 1082
-#define IMG_CUSTOM_191 1083
-#define IMG_CUSTOM_191_EDITOR 1084
-#define IMG_CUSTOM_192 1085
-#define IMG_CUSTOM_192_EDITOR 1086
-#define IMG_CUSTOM_193 1087
-#define IMG_CUSTOM_193_EDITOR 1088
-#define IMG_CUSTOM_194 1089
-#define IMG_CUSTOM_194_EDITOR 1090
-#define IMG_CUSTOM_195 1091
-#define IMG_CUSTOM_195_EDITOR 1092
-#define IMG_CUSTOM_196 1093
-#define IMG_CUSTOM_196_EDITOR 1094
-#define IMG_CUSTOM_197 1095
-#define IMG_CUSTOM_197_EDITOR 1096
-#define IMG_CUSTOM_198 1097
-#define IMG_CUSTOM_198_EDITOR 1098
-#define IMG_CUSTOM_199 1099
-#define IMG_CUSTOM_199_EDITOR 1100
-#define IMG_CUSTOM_200 1101
-#define IMG_CUSTOM_200_EDITOR 1102
-#define IMG_CUSTOM_201 1103
-#define IMG_CUSTOM_201_EDITOR 1104
-#define IMG_CUSTOM_202 1105
-#define IMG_CUSTOM_202_EDITOR 1106
-#define IMG_CUSTOM_203 1107
-#define IMG_CUSTOM_203_EDITOR 1108
-#define IMG_CUSTOM_204 1109
-#define IMG_CUSTOM_204_EDITOR 1110
-#define IMG_CUSTOM_205 1111
-#define IMG_CUSTOM_205_EDITOR 1112
-#define IMG_CUSTOM_206 1113
-#define IMG_CUSTOM_206_EDITOR 1114
-#define IMG_CUSTOM_207 1115
-#define IMG_CUSTOM_207_EDITOR 1116
-#define IMG_CUSTOM_208 1117
-#define IMG_CUSTOM_208_EDITOR 1118
-#define IMG_CUSTOM_209 1119
-#define IMG_CUSTOM_209_EDITOR 1120
-#define IMG_CUSTOM_210 1121
-#define IMG_CUSTOM_210_EDITOR 1122
-#define IMG_CUSTOM_211 1123
-#define IMG_CUSTOM_211_EDITOR 1124
-#define IMG_CUSTOM_212 1125
-#define IMG_CUSTOM_212_EDITOR 1126
-#define IMG_CUSTOM_213 1127
-#define IMG_CUSTOM_213_EDITOR 1128
-#define IMG_CUSTOM_214 1129
-#define IMG_CUSTOM_214_EDITOR 1130
-#define IMG_CUSTOM_215 1131
-#define IMG_CUSTOM_215_EDITOR 1132
-#define IMG_CUSTOM_216 1133
-#define IMG_CUSTOM_216_EDITOR 1134
-#define IMG_CUSTOM_217 1135
-#define IMG_CUSTOM_217_EDITOR 1136
-#define IMG_CUSTOM_218 1137
-#define IMG_CUSTOM_218_EDITOR 1138
-#define IMG_CUSTOM_219 1139
-#define IMG_CUSTOM_219_EDITOR 1140
-#define IMG_CUSTOM_220 1141
-#define IMG_CUSTOM_220_EDITOR 1142
-#define IMG_CUSTOM_221 1143
-#define IMG_CUSTOM_221_EDITOR 1144
-#define IMG_CUSTOM_222 1145
-#define IMG_CUSTOM_222_EDITOR 1146
-#define IMG_CUSTOM_223 1147
-#define IMG_CUSTOM_223_EDITOR 1148
-#define IMG_CUSTOM_224 1149
-#define IMG_CUSTOM_224_EDITOR 1150
-#define IMG_CUSTOM_225 1151
-#define IMG_CUSTOM_225_EDITOR 1152
-#define IMG_CUSTOM_226 1153
-#define IMG_CUSTOM_226_EDITOR 1154
-#define IMG_CUSTOM_227 1155
-#define IMG_CUSTOM_227_EDITOR 1156
-#define IMG_CUSTOM_228 1157
-#define IMG_CUSTOM_228_EDITOR 1158
-#define IMG_CUSTOM_229 1159
-#define IMG_CUSTOM_229_EDITOR 1160
-#define IMG_CUSTOM_230 1161
-#define IMG_CUSTOM_230_EDITOR 1162
-#define IMG_CUSTOM_231 1163
-#define IMG_CUSTOM_231_EDITOR 1164
-#define IMG_CUSTOM_232 1165
-#define IMG_CUSTOM_232_EDITOR 1166
-#define IMG_CUSTOM_233 1167
-#define IMG_CUSTOM_233_EDITOR 1168
-#define IMG_CUSTOM_234 1169
-#define IMG_CUSTOM_234_EDITOR 1170
-#define IMG_CUSTOM_235 1171
-#define IMG_CUSTOM_235_EDITOR 1172
-#define IMG_CUSTOM_236 1173
-#define IMG_CUSTOM_236_EDITOR 1174
-#define IMG_CUSTOM_237 1175
-#define IMG_CUSTOM_237_EDITOR 1176
-#define IMG_CUSTOM_238 1177
-#define IMG_CUSTOM_238_EDITOR 1178
-#define IMG_CUSTOM_239 1179
-#define IMG_CUSTOM_239_EDITOR 1180
-#define IMG_CUSTOM_240 1181
-#define IMG_CUSTOM_240_EDITOR 1182
-#define IMG_CUSTOM_241 1183
-#define IMG_CUSTOM_241_EDITOR 1184
-#define IMG_CUSTOM_242 1185
-#define IMG_CUSTOM_242_EDITOR 1186
-#define IMG_CUSTOM_243 1187
-#define IMG_CUSTOM_243_EDITOR 1188
-#define IMG_CUSTOM_244 1189
-#define IMG_CUSTOM_244_EDITOR 1190
-#define IMG_CUSTOM_245 1191
-#define IMG_CUSTOM_245_EDITOR 1192
-#define IMG_CUSTOM_246 1193
-#define IMG_CUSTOM_246_EDITOR 1194
-#define IMG_CUSTOM_247 1195
-#define IMG_CUSTOM_247_EDITOR 1196
-#define IMG_CUSTOM_248 1197
-#define IMG_CUSTOM_248_EDITOR 1198
-#define IMG_CUSTOM_249 1199
-#define IMG_CUSTOM_249_EDITOR 1200
-#define IMG_CUSTOM_250 1201
-#define IMG_CUSTOM_250_EDITOR 1202
-#define IMG_CUSTOM_251 1203
-#define IMG_CUSTOM_251_EDITOR 1204
-#define IMG_CUSTOM_252 1205
-#define IMG_CUSTOM_252_EDITOR 1206
-#define IMG_CUSTOM_253 1207
-#define IMG_CUSTOM_253_EDITOR 1208
-#define IMG_CUSTOM_254 1209
-#define IMG_CUSTOM_254_EDITOR 1210
-#define IMG_CUSTOM_255 1211
-#define IMG_CUSTOM_255_EDITOR 1212
-#define IMG_CUSTOM_256 1213
-#define IMG_CUSTOM_256_EDITOR 1214
-#define IMG_TOON_1 1215
-#define IMG_TOON_2 1216
-#define IMG_TOON_3 1217
-#define IMG_TOON_4 1218
-#define IMG_TOON_5 1219
-#define IMG_TOON_6 1220
-#define IMG_TOON_7 1221
-#define IMG_TOON_8 1222
-#define IMG_TOON_9 1223
-#define IMG_TOON_10 1224
-#define IMG_TOON_11 1225
-#define IMG_TOON_12 1226
-#define IMG_TOON_13 1227
-#define IMG_TOON_14 1228
-#define IMG_TOON_15 1229
-#define IMG_TOON_16 1230
-#define IMG_TOON_17 1231
-#define IMG_TOON_18 1232
-#define IMG_TOON_19 1233
-#define IMG_TOON_20 1234
-#define IMG_MENU_CALIBRATE_RED 1235
-#define IMG_MENU_CALIBRATE_BLUE 1236
-#define IMG_MENU_CALIBRATE_YELLOW 1237
-#define IMG_MENU_BUTTON 1238
-#define IMG_MENU_BUTTON_ACTIVE 1239
-#define IMG_MENU_BUTTON_LEFT 1240
-#define IMG_MENU_BUTTON_RIGHT 1241
-#define IMG_MENU_BUTTON_UP 1242
-#define IMG_MENU_BUTTON_DOWN 1243
-#define IMG_MENU_BUTTON_LEFT_ACTIVE 1244
-#define IMG_MENU_BUTTON_RIGHT_ACTIVE 1245
-#define IMG_MENU_BUTTON_UP_ACTIVE 1246
-#define IMG_MENU_BUTTON_DOWN_ACTIVE 1247
-#define IMG_MENU_SCROLLBAR 1248
-#define IMG_MENU_SCROLLBAR_ACTIVE 1249
-#define IMG_FONT_INITIAL_1 1250
-#define IMG_FONT_INITIAL_2 1251
-#define IMG_FONT_INITIAL_3 1252
-#define IMG_FONT_INITIAL_4 1253
-#define IMG_FONT_TITLE_1 1254
-#define IMG_FONT_TITLE_1_LEVELS 1255
-#define IMG_FONT_TITLE_2 1256
-#define IMG_FONT_MENU_1 1257
-#define IMG_FONT_MENU_2 1258
-#define IMG_FONT_TEXT_1 1259
-#define IMG_FONT_TEXT_1_LEVELS 1260
-#define IMG_FONT_TEXT_1_PREVIEW 1261
-#define IMG_FONT_TEXT_1_SCORES 1262
-#define IMG_FONT_TEXT_1_ACTIVE_SCORES 1263
-#define IMG_FONT_TEXT_2 1264
-#define IMG_FONT_TEXT_2_LEVELS 1265
-#define IMG_FONT_TEXT_2_PREVIEW 1266
-#define IMG_FONT_TEXT_2_SCORES 1267
-#define IMG_FONT_TEXT_2_ACTIVE_SCORES 1268
-#define IMG_FONT_TEXT_3 1269
-#define IMG_FONT_TEXT_3_LEVELS 1270
-#define IMG_FONT_TEXT_3_PREVIEW 1271
-#define IMG_FONT_TEXT_3_SCORES 1272
-#define IMG_FONT_TEXT_3_ACTIVE_SCORES 1273
-#define IMG_FONT_TEXT_4 1274
-#define IMG_FONT_TEXT_4_LEVELS 1275
-#define IMG_FONT_TEXT_4_SCORES 1276
-#define IMG_FONT_TEXT_4_ACTIVE_SCORES 1277
-#define IMG_FONT_ENVELOPE_1 1278
-#define IMG_FONT_ENVELOPE_2 1279
-#define IMG_FONT_ENVELOPE_3 1280
-#define IMG_FONT_ENVELOPE_4 1281
-#define IMG_FONT_INPUT_1 1282
-#define IMG_FONT_INPUT_1_MAIN 1283
-#define IMG_FONT_INPUT_1_ACTIVE 1284
-#define IMG_FONT_INPUT_1_ACTIVE_MAIN 1285
-#define IMG_FONT_INPUT_1_ACTIVE_SETUP 1286
-#define IMG_FONT_INPUT_2 1287
-#define IMG_FONT_INPUT_2_ACTIVE 1288
-#define IMG_FONT_OPTION_OFF 1289
-#define IMG_FONT_OPTION_ON 1290
-#define IMG_FONT_VALUE_1 1291
-#define IMG_FONT_VALUE_2 1292
-#define IMG_FONT_VALUE_OLD 1293
-#define IMG_FONT_LEVEL_NUMBER 1294
-#define IMG_FONT_TAPE_RECORDER 1295
-#define IMG_FONT_GAME_INFO 1296
-#define IMG_GLOBAL_BORDER 1297
-#define IMG_GLOBAL_DOOR 1298
-#define IMG_EDITOR_ELEMENT_BORDER 1299
-#define IMG_EDITOR_ELEMENT_BORDER_INPUT 1300
-#define IMG_BACKGROUND_ENVELOPE_1 1301
-#define IMG_BACKGROUND_ENVELOPE_2 1302
-#define IMG_BACKGROUND_ENVELOPE_3 1303
-#define IMG_BACKGROUND_ENVELOPE_4 1304
-#define IMG_BACKGROUND 1305
-#define IMG_BACKGROUND_MAIN 1306
-#define IMG_BACKGROUND_LEVELS 1307
-#define IMG_BACKGROUND_SCORES 1308
-#define IMG_BACKGROUND_EDITOR 1309
-#define IMG_BACKGROUND_INFO 1310
-#define IMG_BACKGROUND_SETUP 1311
-#define IMG_BACKGROUND_DOOR 1312
+#define IMG_SP_GRAVITY_PORT_RIGHT_EDITOR 79
+#define IMG_SP_GRAVITY_PORT_DOWN 80
+#define IMG_SP_GRAVITY_PORT_DOWN_EDITOR 81
+#define IMG_SP_GRAVITY_PORT_LEFT 82
+#define IMG_SP_GRAVITY_PORT_LEFT_EDITOR 83
+#define IMG_SP_GRAVITY_PORT_UP 84
+#define IMG_SP_GRAVITY_PORT_UP_EDITOR 85
+#define IMG_SP_GRAVITY_ON_PORT_RIGHT 86
+#define IMG_SP_GRAVITY_ON_PORT_RIGHT_EDITOR 87
+#define IMG_SP_GRAVITY_ON_PORT_DOWN 88
+#define IMG_SP_GRAVITY_ON_PORT_DOWN_EDITOR 89
+#define IMG_SP_GRAVITY_ON_PORT_LEFT 90
+#define IMG_SP_GRAVITY_ON_PORT_LEFT_EDITOR 91
+#define IMG_SP_GRAVITY_ON_PORT_UP 92
+#define IMG_SP_GRAVITY_ON_PORT_UP_EDITOR 93
+#define IMG_SP_GRAVITY_OFF_PORT_RIGHT 94
+#define IMG_SP_GRAVITY_OFF_PORT_RIGHT_EDITOR 95
+#define IMG_SP_GRAVITY_OFF_PORT_DOWN 96
+#define IMG_SP_GRAVITY_OFF_PORT_DOWN_EDITOR 97
+#define IMG_SP_GRAVITY_OFF_PORT_LEFT 98
+#define IMG_SP_GRAVITY_OFF_PORT_LEFT_EDITOR 99
+#define IMG_SP_GRAVITY_OFF_PORT_UP 100
+#define IMG_SP_GRAVITY_OFF_PORT_UP_EDITOR 101
+#define IMG_SP_SNIKSNAK 102
+#define IMG_SP_SNIKSNAK_LEFT 103
+#define IMG_SP_SNIKSNAK_RIGHT 104
+#define IMG_SP_SNIKSNAK_UP 105
+#define IMG_SP_SNIKSNAK_DOWN 106
+#define IMG_SP_SNIKSNAK_TURNING_FROM_LEFT_UP 107
+#define IMG_SP_SNIKSNAK_TURNING_FROM_LEFT_DOWN 108
+#define IMG_SP_SNIKSNAK_TURNING_FROM_RIGHT_UP 109
+#define IMG_SP_SNIKSNAK_TURNING_FROM_RIGHT_DOWN 110
+#define IMG_SP_SNIKSNAK_TURNING_FROM_UP_LEFT 111
+#define IMG_SP_SNIKSNAK_TURNING_FROM_UP_RIGHT 112
+#define IMG_SP_SNIKSNAK_TURNING_FROM_DOWN_LEFT 113
+#define IMG_SP_SNIKSNAK_TURNING_FROM_DOWN_RIGHT 114
+#define IMG_SP_ELECTRON 115
+#define IMG_SP_ELECTRON_EDITOR 116
+#define IMG_SP_ELECTRON_EXPLODING 117
+#define IMG_SP_TERMINAL 118
+#define IMG_SP_TERMINAL_EDITOR 119
+#define IMG_SP_TERMINAL_ACTIVE 120
+#define IMG_SP_BUGGY_BASE 121
+#define IMG_SP_BUGGY_BASE_EDITOR 122
+#define IMG_SP_BUGGY_BASE_ACTIVATING 123
+#define IMG_SP_BUGGY_BASE_ACTIVE 124
+#define IMG_SP_HARDWARE_BASE_1 125
+#define IMG_SP_HARDWARE_BASE_2 126
+#define IMG_SP_HARDWARE_BASE_3 127
+#define IMG_SP_HARDWARE_BASE_4 128
+#define IMG_SP_HARDWARE_BASE_5 129
+#define IMG_SP_HARDWARE_BASE_6 130
+#define IMG_SOKOBAN_OBJECT 131
+#define IMG_SOKOBAN_OBJECT_EDITOR 132
+#define IMG_SOKOBAN_FIELD_EMPTY 133
+#define IMG_SOKOBAN_FIELD_FULL 134
+#define IMG_SOKOBAN_FIELD_PLAYER 135
+#define IMG_SOKOBAN_FIELD_PLAYER_EDITOR 136
+#define IMG_EMPTY_SPACE 137
+#define IMG_SAND 138
+#define IMG_SAND_CRUMBLED 139
+#define IMG_SAND_DIGGING_LEFT 140
+#define IMG_SAND_DIGGING_RIGHT 141
+#define IMG_SAND_DIGGING_UP 142
+#define IMG_SAND_DIGGING_DOWN 143
+#define IMG_SAND_DIGGING_LEFT_CRUMBLED 144
+#define IMG_SAND_DIGGING_RIGHT_CRUMBLED 145
+#define IMG_SAND_DIGGING_UP_CRUMBLED 146
+#define IMG_SAND_DIGGING_DOWN_CRUMBLED 147
+#define IMG_WALL 148
+#define IMG_WALL_SLIPPERY 149
+#define IMG_STEELWALL 150
+#define IMG_ROCK 151
+#define IMG_ROCK_MOVING_LEFT 152
+#define IMG_ROCK_MOVING_RIGHT 153
+#define IMG_ROCK_PUSHING_LEFT 154
+#define IMG_ROCK_PUSHING_RIGHT 155
+#define IMG_EMERALD 156
+#define IMG_EMERALD_MOVING 157
+#define IMG_EMERALD_FALLING 158
+#define IMG_EMERALD_COLLECTING 159
+#define IMG_DIAMOND 160
+#define IMG_DIAMOND_MOVING 161
+#define IMG_DIAMOND_FALLING 162
+#define IMG_DIAMOND_COLLECTING 163
+#define IMG_BOMB 164
+#define IMG_NUT 165
+#define IMG_NUT_BREAKING 166
+#define IMG_DYNAMITE 167
+#define IMG_DYNAMITE_EDITOR 168
+#define IMG_DYNAMITE_ACTIVE 169
+#define IMG_DYNAMITE_ACTIVE_EDITOR 170
+#define IMG_WALL_EMERALD 171
+#define IMG_WALL_DIAMOND 172
+#define IMG_BUG 173
+#define IMG_BUG_RIGHT 174
+#define IMG_BUG_UP 175
+#define IMG_BUG_LEFT 176
+#define IMG_BUG_DOWN 177
+#define IMG_BUG_MOVING_RIGHT 178
+#define IMG_BUG_MOVING_UP 179
+#define IMG_BUG_MOVING_LEFT 180
+#define IMG_BUG_MOVING_DOWN 181
+#define IMG_BUG_TURNING_FROM_RIGHT_UP 182
+#define IMG_BUG_TURNING_FROM_UP_LEFT 183
+#define IMG_BUG_TURNING_FROM_LEFT_DOWN 184
+#define IMG_BUG_TURNING_FROM_DOWN_RIGHT 185
+#define IMG_BUG_TURNING_FROM_RIGHT_DOWN 186
+#define IMG_BUG_TURNING_FROM_UP_RIGHT 187
+#define IMG_BUG_TURNING_FROM_LEFT_UP 188
+#define IMG_BUG_TURNING_FROM_DOWN_LEFT 189
+#define IMG_SPACESHIP 190
+#define IMG_SPACESHIP_RIGHT 191
+#define IMG_SPACESHIP_UP 192
+#define IMG_SPACESHIP_LEFT 193
+#define IMG_SPACESHIP_DOWN 194
+#define IMG_SPACESHIP_MOVING_RIGHT 195
+#define IMG_SPACESHIP_MOVING_UP 196
+#define IMG_SPACESHIP_MOVING_LEFT 197
+#define IMG_SPACESHIP_MOVING_DOWN 198
+#define IMG_SPACESHIP_TURNING_FROM_RIGHT_UP 199
+#define IMG_SPACESHIP_TURNING_FROM_UP_LEFT 200
+#define IMG_SPACESHIP_TURNING_FROM_LEFT_DOWN 201
+#define IMG_SPACESHIP_TURNING_FROM_DOWN_RIGHT 202
+#define IMG_SPACESHIP_TURNING_FROM_RIGHT_DOWN 203
+#define IMG_SPACESHIP_TURNING_FROM_UP_RIGHT 204
+#define IMG_SPACESHIP_TURNING_FROM_LEFT_UP 205
+#define IMG_SPACESHIP_TURNING_FROM_DOWN_LEFT 206
+#define IMG_YAMYAM 207
+#define IMG_YAMYAM_MOVING 208
+#define IMG_ROBOT 209
+#define IMG_ROBOT_MOVING 210
+#define IMG_ROBOT_WHEEL 211
+#define IMG_ROBOT_WHEEL_ACTIVE 212
+#define IMG_MAGIC_WALL 213
+#define IMG_MAGIC_WALL_ACTIVE 214
+#define IMG_MAGIC_WALL_FILLING 215
+#define IMG_MAGIC_WALL_FULL 216
+#define IMG_MAGIC_WALL_EMPTYING 217
+#define IMG_MAGIC_WALL_DEAD 218
+#define IMG_QUICKSAND_EMPTY 219
+#define IMG_QUICKSAND_FILLING 220
+#define IMG_QUICKSAND_FULL 221
+#define IMG_QUICKSAND_FULL_EDITOR 222
+#define IMG_QUICKSAND_EMPTYING 223
+#define IMG_ACID_POOL_TOPLEFT 224
+#define IMG_ACID_POOL_TOPRIGHT 225
+#define IMG_ACID_POOL_BOTTOMLEFT 226
+#define IMG_ACID_POOL_BOTTOM 227
+#define IMG_ACID_POOL_BOTTOMRIGHT 228
+#define IMG_ACID 229
+#define IMG_ACID_SPLASH_LEFT 230
+#define IMG_ACID_SPLASH_RIGHT 231
+#define IMG_AMOEBA_DROP 232
+#define IMG_AMOEBA_GROWING 233
+#define IMG_AMOEBA_SHRINKING 234
+#define IMG_AMOEBA_WET 235
+#define IMG_AMOEBA_WET_EDITOR 236
+#define IMG_AMOEBA_DROPPING 237
+#define IMG_AMOEBA_DRY 238
+#define IMG_AMOEBA_FULL 239
+#define IMG_AMOEBA_FULL_EDITOR 240
+#define IMG_AMOEBA_DEAD 241
+#define IMG_AMOEBA_DEAD_EDITOR 242
+#define IMG_EM_KEY_1 243
+#define IMG_EM_KEY_2 244
+#define IMG_EM_KEY_3 245
+#define IMG_EM_KEY_4 246
+#define IMG_EM_GATE_1 247
+#define IMG_EM_GATE_2 248
+#define IMG_EM_GATE_3 249
+#define IMG_EM_GATE_4 250
+#define IMG_EM_GATE_1_GRAY 251
+#define IMG_EM_GATE_1_GRAY_EDITOR 252
+#define IMG_EM_GATE_2_GRAY 253
+#define IMG_EM_GATE_2_GRAY_EDITOR 254
+#define IMG_EM_GATE_3_GRAY 255
+#define IMG_EM_GATE_3_GRAY_EDITOR 256
+#define IMG_EM_GATE_4_GRAY 257
+#define IMG_EM_GATE_4_GRAY_EDITOR 258
+#define IMG_EXIT_CLOSED 259
+#define IMG_EXIT_OPENING 260
+#define IMG_EXIT_OPEN 261
+#define IMG_EXIT_CLOSING 262
+#define IMG_BALLOON 263
+#define IMG_BALLOON_MOVING 264
+#define IMG_BALLOON_PUSHING 265
+#define IMG_BALLOON_SWITCH_LEFT 266
+#define IMG_BALLOON_SWITCH_RIGHT 267
+#define IMG_BALLOON_SWITCH_UP 268
+#define IMG_BALLOON_SWITCH_DOWN 269
+#define IMG_BALLOON_SWITCH_ANY 270
+#define IMG_SPRING 271
+#define IMG_EMC_STEELWALL_1 272
+#define IMG_EMC_STEELWALL_2 273
+#define IMG_EMC_STEELWALL_3 274
+#define IMG_EMC_STEELWALL_4 275
+#define IMG_EMC_WALL_1 276
+#define IMG_EMC_WALL_2 277
+#define IMG_EMC_WALL_3 278
+#define IMG_EMC_WALL_4 279
+#define IMG_EMC_WALL_5 280
+#define IMG_EMC_WALL_6 281
+#define IMG_EMC_WALL_7 282
+#define IMG_EMC_WALL_8 283
+#define IMG_INVISIBLE_STEELWALL 284
+#define IMG_INVISIBLE_STEELWALL_EDITOR 285
+#define IMG_INVISIBLE_STEELWALL_ACTIVE 286
+#define IMG_INVISIBLE_WALL 287
+#define IMG_INVISIBLE_WALL_EDITOR 288
+#define IMG_INVISIBLE_WALL_ACTIVE 289
+#define IMG_INVISIBLE_SAND 290
+#define IMG_INVISIBLE_SAND_EDITOR 291
+#define IMG_INVISIBLE_SAND_ACTIVE 292
+#define IMG_CONVEYOR_BELT_1_MIDDLE 293
+#define IMG_CONVEYOR_BELT_1_MIDDLE_ACTIVE 294
+#define IMG_CONVEYOR_BELT_1_LEFT 295
+#define IMG_CONVEYOR_BELT_1_LEFT_ACTIVE 296
+#define IMG_CONVEYOR_BELT_1_RIGHT 297
+#define IMG_CONVEYOR_BELT_1_RIGHT_ACTIVE 298
+#define IMG_CONVEYOR_BELT_1_SWITCH_LEFT 299
+#define IMG_CONVEYOR_BELT_1_SWITCH_MIDDLE 300
+#define IMG_CONVEYOR_BELT_1_SWITCH_RIGHT 301
+#define IMG_CONVEYOR_BELT_2_MIDDLE 302
+#define IMG_CONVEYOR_BELT_2_MIDDLE_ACTIVE 303
+#define IMG_CONVEYOR_BELT_2_LEFT 304
+#define IMG_CONVEYOR_BELT_2_LEFT_ACTIVE 305
+#define IMG_CONVEYOR_BELT_2_RIGHT 306
+#define IMG_CONVEYOR_BELT_2_RIGHT_ACTIVE 307
+#define IMG_CONVEYOR_BELT_2_SWITCH_LEFT 308
+#define IMG_CONVEYOR_BELT_2_SWITCH_MIDDLE 309
+#define IMG_CONVEYOR_BELT_2_SWITCH_RIGHT 310
+#define IMG_CONVEYOR_BELT_3_MIDDLE 311
+#define IMG_CONVEYOR_BELT_3_MIDDLE_ACTIVE 312
+#define IMG_CONVEYOR_BELT_3_LEFT 313
+#define IMG_CONVEYOR_BELT_3_LEFT_ACTIVE 314
+#define IMG_CONVEYOR_BELT_3_RIGHT 315
+#define IMG_CONVEYOR_BELT_3_RIGHT_ACTIVE 316
+#define IMG_CONVEYOR_BELT_3_SWITCH_LEFT 317
+#define IMG_CONVEYOR_BELT_3_SWITCH_MIDDLE 318
+#define IMG_CONVEYOR_BELT_3_SWITCH_RIGHT 319
+#define IMG_CONVEYOR_BELT_4_MIDDLE 320
+#define IMG_CONVEYOR_BELT_4_MIDDLE_ACTIVE 321
+#define IMG_CONVEYOR_BELT_4_LEFT 322
+#define IMG_CONVEYOR_BELT_4_LEFT_ACTIVE 323
+#define IMG_CONVEYOR_BELT_4_RIGHT 324
+#define IMG_CONVEYOR_BELT_4_RIGHT_ACTIVE 325
+#define IMG_CONVEYOR_BELT_4_SWITCH_LEFT 326
+#define IMG_CONVEYOR_BELT_4_SWITCH_MIDDLE 327
+#define IMG_CONVEYOR_BELT_4_SWITCH_RIGHT 328
+#define IMG_SWITCHGATE_SWITCH_UP 329
+#define IMG_SWITCHGATE_SWITCH_DOWN 330
+#define IMG_LIGHT_SWITCH 331
+#define IMG_LIGHT_SWITCH_ACTIVE 332
+#define IMG_TIMEGATE_SWITCH 333
+#define IMG_TIMEGATE_SWITCH_ACTIVE 334
+#define IMG_ENVELOPE_1 335
+#define IMG_ENVELOPE_1_COLLECTING 336
+#define IMG_ENVELOPE_2 337
+#define IMG_ENVELOPE_2_COLLECTING 338
+#define IMG_ENVELOPE_3 339
+#define IMG_ENVELOPE_3_COLLECTING 340
+#define IMG_ENVELOPE_4 341
+#define IMG_ENVELOPE_4_COLLECTING 342
+#define IMG_SIGN_EXCLAMATION 343
+#define IMG_SIGN_STOP 344
+#define IMG_LANDMINE 345
+#define IMG_STEELWALL_SLIPPERY 346
+#define IMG_EXTRA_TIME 347
+#define IMG_SHIELD_NORMAL 348
+#define IMG_SHIELD_NORMAL_ACTIVE 349
+#define IMG_SHIELD_DEADLY 350
+#define IMG_SHIELD_DEADLY_ACTIVE 351
+#define IMG_SWITCHGATE_CLOSED 352
+#define IMG_SWITCHGATE_OPENING 353
+#define IMG_SWITCHGATE_OPEN 354
+#define IMG_SWITCHGATE_CLOSING 355
+#define IMG_TIMEGATE_CLOSED 356
+#define IMG_TIMEGATE_OPENING 357
+#define IMG_TIMEGATE_OPEN 358
+#define IMG_TIMEGATE_CLOSING 359
+#define IMG_PEARL 360
+#define IMG_PEARL_BREAKING 361
+#define IMG_CRYSTAL 362
+#define IMG_WALL_PEARL 363
+#define IMG_WALL_CRYSTAL 364
+#define IMG_TUBE_RIGHT_DOWN 365
+#define IMG_TUBE_HORIZONTAL_DOWN 366
+#define IMG_TUBE_LEFT_DOWN 367
+#define IMG_TUBE_HORIZONTAL 368
+#define IMG_TUBE_VERTICAL_RIGHT 369
+#define IMG_TUBE_ANY 370
+#define IMG_TUBE_VERTICAL_LEFT 371
+#define IMG_TUBE_VERTICAL 372
+#define IMG_TUBE_RIGHT_UP 373
+#define IMG_TUBE_HORIZONTAL_UP 374
+#define IMG_TUBE_LEFT_UP 375
+#define IMG_TRAP 376
+#define IMG_TRAP_ACTIVE 377
+#define IMG_DX_SUPABOMB 378
+#define IMG_KEY_1 379
+#define IMG_KEY_1_EDITOR 380
+#define IMG_KEY_2 381
+#define IMG_KEY_2_EDITOR 382
+#define IMG_KEY_3 383
+#define IMG_KEY_3_EDITOR 384
+#define IMG_KEY_4 385
+#define IMG_KEY_4_EDITOR 386
+#define IMG_GATE_1 387
+#define IMG_GATE_2 388
+#define IMG_GATE_3 389
+#define IMG_GATE_4 390
+#define IMG_GATE_1_GRAY 391
+#define IMG_GATE_1_GRAY_EDITOR 392
+#define IMG_GATE_2_GRAY 393
+#define IMG_GATE_2_GRAY_EDITOR 394
+#define IMG_GATE_3_GRAY 395
+#define IMG_GATE_3_GRAY_EDITOR 396
+#define IMG_GATE_4_GRAY 397
+#define IMG_GATE_4_GRAY_EDITOR 398
+#define IMG_GAME_OF_LIFE 399
+#define IMG_BIOMAZE 400
+#define IMG_PACMAN 401
+#define IMG_PACMAN_RIGHT 402
+#define IMG_PACMAN_UP 403
+#define IMG_PACMAN_LEFT 404
+#define IMG_PACMAN_DOWN 405
+#define IMG_PACMAN_TURNING_FROM_RIGHT 406
+#define IMG_PACMAN_TURNING_FROM_UP 407
+#define IMG_PACMAN_TURNING_FROM_LEFT 408
+#define IMG_PACMAN_TURNING_FROM_DOWN 409
+#define IMG_LAMP 410
+#define IMG_LAMP_EDITOR 411
+#define IMG_LAMP_ACTIVE 412
+#define IMG_TIME_ORB_FULL 413
+#define IMG_TIME_ORB_EMPTY 414
+#define IMG_EMERALD_YELLOW 415
+#define IMG_EMERALD_YELLOW_MOVING 416
+#define IMG_EMERALD_YELLOW_FALLING 417
+#define IMG_EMERALD_RED 418
+#define IMG_EMERALD_RED_MOVING 419
+#define IMG_EMERALD_RED_FALLING 420
+#define IMG_EMERALD_PURPLE 421
+#define IMG_EMERALD_PURPLE_MOVING 422
+#define IMG_EMERALD_PURPLE_FALLING 423
+#define IMG_WALL_EMERALD_YELLOW 424
+#define IMG_WALL_EMERALD_RED 425
+#define IMG_WALL_EMERALD_PURPLE 426
+#define IMG_WALL_BD_DIAMOND 427
+#define IMG_EXPANDABLE_WALL 428
+#define IMG_EXPANDABLE_WALL_HORIZONTAL 429
+#define IMG_EXPANDABLE_WALL_HORIZONTAL_EDITOR 430
+#define IMG_EXPANDABLE_WALL_VERTICAL 431
+#define IMG_EXPANDABLE_WALL_VERTICAL_EDITOR 432
+#define IMG_EXPANDABLE_WALL_ANY 433
+#define IMG_EXPANDABLE_WALL_ANY_EDITOR 434
+#define IMG_EXPANDABLE_WALL_GROWING_LEFT 435
+#define IMG_EXPANDABLE_WALL_GROWING_RIGHT 436
+#define IMG_EXPANDABLE_WALL_GROWING_UP 437
+#define IMG_EXPANDABLE_WALL_GROWING_DOWN 438
+#define IMG_BLACK_ORB 439
+#define IMG_SPEED_PILL 440
+#define IMG_DARK_YAMYAM 441
+#define IMG_DYNABOMB 442
+#define IMG_DYNABOMB_ACTIVE 443
+#define IMG_DYNABOMB_PLAYER_1 444
+#define IMG_DYNABOMB_PLAYER_1_ACTIVE 445
+#define IMG_DYNABOMB_PLAYER_2 446
+#define IMG_DYNABOMB_PLAYER_2_ACTIVE 447
+#define IMG_DYNABOMB_PLAYER_3 448
+#define IMG_DYNABOMB_PLAYER_3_ACTIVE 449
+#define IMG_DYNABOMB_PLAYER_4 450
+#define IMG_DYNABOMB_PLAYER_4_ACTIVE 451
+#define IMG_DYNABOMB_INCREASE_NUMBER 452
+#define IMG_DYNABOMB_INCREASE_SIZE 453
+#define IMG_DYNABOMB_INCREASE_POWER 454
+#define IMG_PIG 455
+#define IMG_PIG_DOWN 456
+#define IMG_PIG_UP 457
+#define IMG_PIG_LEFT 458
+#define IMG_PIG_RIGHT 459
+#define IMG_PIG_MOVING_DOWN 460
+#define IMG_PIG_MOVING_UP 461
+#define IMG_PIG_MOVING_LEFT 462
+#define IMG_PIG_MOVING_RIGHT 463
+#define IMG_PIG_DIGGING_DOWN 464
+#define IMG_PIG_DIGGING_UP 465
+#define IMG_PIG_DIGGING_LEFT 466
+#define IMG_PIG_DIGGING_RIGHT 467
+#define IMG_DRAGON 468
+#define IMG_DRAGON_DOWN 469
+#define IMG_DRAGON_UP 470
+#define IMG_DRAGON_LEFT 471
+#define IMG_DRAGON_RIGHT 472
+#define IMG_DRAGON_MOVING_DOWN 473
+#define IMG_DRAGON_MOVING_UP 474
+#define IMG_DRAGON_MOVING_LEFT 475
+#define IMG_DRAGON_MOVING_RIGHT 476
+#define IMG_DRAGON_ATTACKING_DOWN 477
+#define IMG_DRAGON_ATTACKING_UP 478
+#define IMG_DRAGON_ATTACKING_LEFT 479
+#define IMG_DRAGON_ATTACKING_RIGHT 480
+#define IMG_MOLE 481
+#define IMG_MOLE_DOWN 482
+#define IMG_MOLE_UP 483
+#define IMG_MOLE_LEFT 484
+#define IMG_MOLE_RIGHT 485
+#define IMG_MOLE_MOVING_DOWN 486
+#define IMG_MOLE_MOVING_UP 487
+#define IMG_MOLE_MOVING_LEFT 488
+#define IMG_MOLE_MOVING_RIGHT 489
+#define IMG_MOLE_DIGGING_DOWN 490
+#define IMG_MOLE_DIGGING_UP 491
+#define IMG_MOLE_DIGGING_LEFT 492
+#define IMG_MOLE_DIGGING_RIGHT 493
+#define IMG_PENGUIN 494
+#define IMG_PENGUIN_EDITOR 495
+#define IMG_PENGUIN_DOWN 496
+#define IMG_PENGUIN_UP 497
+#define IMG_PENGUIN_LEFT 498
+#define IMG_PENGUIN_RIGHT 499
+#define IMG_PENGUIN_MOVING_DOWN 500
+#define IMG_PENGUIN_MOVING_UP 501
+#define IMG_PENGUIN_MOVING_LEFT 502
+#define IMG_PENGUIN_MOVING_RIGHT 503
+#define IMG_SATELLITE 504
+#define IMG_FLAMES_1_LEFT 505
+#define IMG_FLAMES_2_LEFT 506
+#define IMG_FLAMES_3_LEFT 507
+#define IMG_FLAMES_1_RIGHT 508
+#define IMG_FLAMES_2_RIGHT 509
+#define IMG_FLAMES_3_RIGHT 510
+#define IMG_FLAMES_1_UP 511
+#define IMG_FLAMES_2_UP 512
+#define IMG_FLAMES_3_UP 513
+#define IMG_FLAMES_1_DOWN 514
+#define IMG_FLAMES_2_DOWN 515
+#define IMG_FLAMES_3_DOWN 516
+#define IMG_STONEBLOCK 517
+#define IMG_PLAYER_1 518
+#define IMG_PLAYER_1_EDITOR 519
+#define IMG_PLAYER_1_DOWN 520
+#define IMG_PLAYER_1_UP 521
+#define IMG_PLAYER_1_LEFT 522
+#define IMG_PLAYER_1_RIGHT 523
+#define IMG_PLAYER_1_MOVING_DOWN 524
+#define IMG_PLAYER_1_MOVING_UP 525
+#define IMG_PLAYER_1_MOVING_LEFT 526
+#define IMG_PLAYER_1_MOVING_RIGHT 527
+#define IMG_PLAYER_1_DIGGING_DOWN 528
+#define IMG_PLAYER_1_DIGGING_UP 529
+#define IMG_PLAYER_1_DIGGING_LEFT 530
+#define IMG_PLAYER_1_DIGGING_RIGHT 531
+#define IMG_PLAYER_1_COLLECTING_DOWN 532
+#define IMG_PLAYER_1_COLLECTING_UP 533
+#define IMG_PLAYER_1_COLLECTING_LEFT 534
+#define IMG_PLAYER_1_COLLECTING_RIGHT 535
+#define IMG_PLAYER_1_PUSHING_DOWN 536
+#define IMG_PLAYER_1_PUSHING_UP 537
+#define IMG_PLAYER_1_PUSHING_LEFT 538
+#define IMG_PLAYER_1_PUSHING_RIGHT 539
+#define IMG_PLAYER_1_SNAPPING_DOWN 540
+#define IMG_PLAYER_1_SNAPPING_UP 541
+#define IMG_PLAYER_1_SNAPPING_LEFT 542
+#define IMG_PLAYER_1_SNAPPING_RIGHT 543
+#define IMG_PLAYER_2 544
+#define IMG_PLAYER_2_EDITOR 545
+#define IMG_PLAYER_2_DOWN 546
+#define IMG_PLAYER_2_UP 547
+#define IMG_PLAYER_2_LEFT 548
+#define IMG_PLAYER_2_RIGHT 549
+#define IMG_PLAYER_2_MOVING_DOWN 550
+#define IMG_PLAYER_2_MOVING_UP 551
+#define IMG_PLAYER_2_MOVING_LEFT 552
+#define IMG_PLAYER_2_MOVING_RIGHT 553
+#define IMG_PLAYER_2_DIGGING_DOWN 554
+#define IMG_PLAYER_2_DIGGING_UP 555
+#define IMG_PLAYER_2_DIGGING_LEFT 556
+#define IMG_PLAYER_2_DIGGING_RIGHT 557
+#define IMG_PLAYER_2_COLLECTING_DOWN 558
+#define IMG_PLAYER_2_COLLECTING_UP 559
+#define IMG_PLAYER_2_COLLECTING_LEFT 560
+#define IMG_PLAYER_2_COLLECTING_RIGHT 561
+#define IMG_PLAYER_2_PUSHING_DOWN 562
+#define IMG_PLAYER_2_PUSHING_UP 563
+#define IMG_PLAYER_2_PUSHING_LEFT 564
+#define IMG_PLAYER_2_PUSHING_RIGHT 565
+#define IMG_PLAYER_2_SNAPPING_DOWN 566
+#define IMG_PLAYER_2_SNAPPING_UP 567
+#define IMG_PLAYER_2_SNAPPING_LEFT 568
+#define IMG_PLAYER_2_SNAPPING_RIGHT 569
+#define IMG_PLAYER_3 570
+#define IMG_PLAYER_3_EDITOR 571
+#define IMG_PLAYER_3_DOWN 572
+#define IMG_PLAYER_3_UP 573
+#define IMG_PLAYER_3_LEFT 574
+#define IMG_PLAYER_3_RIGHT 575
+#define IMG_PLAYER_3_MOVING_DOWN 576
+#define IMG_PLAYER_3_MOVING_UP 577
+#define IMG_PLAYER_3_MOVING_LEFT 578
+#define IMG_PLAYER_3_MOVING_RIGHT 579
+#define IMG_PLAYER_3_DIGGING_DOWN 580
+#define IMG_PLAYER_3_DIGGING_UP 581
+#define IMG_PLAYER_3_DIGGING_LEFT 582
+#define IMG_PLAYER_3_DIGGING_RIGHT 583
+#define IMG_PLAYER_3_COLLECTING_DOWN 584
+#define IMG_PLAYER_3_COLLECTING_UP 585
+#define IMG_PLAYER_3_COLLECTING_LEFT 586
+#define IMG_PLAYER_3_COLLECTING_RIGHT 587
+#define IMG_PLAYER_3_PUSHING_DOWN 588
+#define IMG_PLAYER_3_PUSHING_UP 589
+#define IMG_PLAYER_3_PUSHING_LEFT 590
+#define IMG_PLAYER_3_PUSHING_RIGHT 591
+#define IMG_PLAYER_3_SNAPPING_DOWN 592
+#define IMG_PLAYER_3_SNAPPING_UP 593
+#define IMG_PLAYER_3_SNAPPING_LEFT 594
+#define IMG_PLAYER_3_SNAPPING_RIGHT 595
+#define IMG_PLAYER_4 596
+#define IMG_PLAYER_4_EDITOR 597
+#define IMG_PLAYER_4_DOWN 598
+#define IMG_PLAYER_4_UP 599
+#define IMG_PLAYER_4_LEFT 600
+#define IMG_PLAYER_4_RIGHT 601
+#define IMG_PLAYER_4_MOVING_DOWN 602
+#define IMG_PLAYER_4_MOVING_UP 603
+#define IMG_PLAYER_4_MOVING_LEFT 604
+#define IMG_PLAYER_4_MOVING_RIGHT 605
+#define IMG_PLAYER_4_DIGGING_DOWN 606
+#define IMG_PLAYER_4_DIGGING_UP 607
+#define IMG_PLAYER_4_DIGGING_LEFT 608
+#define IMG_PLAYER_4_DIGGING_RIGHT 609
+#define IMG_PLAYER_4_COLLECTING_DOWN 610
+#define IMG_PLAYER_4_COLLECTING_UP 611
+#define IMG_PLAYER_4_COLLECTING_LEFT 612
+#define IMG_PLAYER_4_COLLECTING_RIGHT 613
+#define IMG_PLAYER_4_PUSHING_DOWN 614
+#define IMG_PLAYER_4_PUSHING_UP 615
+#define IMG_PLAYER_4_PUSHING_LEFT 616
+#define IMG_PLAYER_4_PUSHING_RIGHT 617
+#define IMG_PLAYER_4_SNAPPING_DOWN 618
+#define IMG_PLAYER_4_SNAPPING_UP 619
+#define IMG_PLAYER_4_SNAPPING_LEFT 620
+#define IMG_PLAYER_4_SNAPPING_RIGHT 621
+#define IMG_DEFAULT_EXPLODING 622
+#define IMG_TWINKLE_BLUE 623
+#define IMG_TWINKLE_WHITE 624
+#define IMG_STEELWALL_TOPLEFT 625
+#define IMG_STEELWALL_TOPRIGHT 626
+#define IMG_STEELWALL_BOTTOMLEFT 627
+#define IMG_STEELWALL_BOTTOMRIGHT 628
+#define IMG_STEELWALL_HORIZONTAL 629
+#define IMG_STEELWALL_VERTICAL 630
+#define IMG_STEELWALL_TOPLEFT_EDITOR 631
+#define IMG_STEELWALL_TOPRIGHT_EDITOR 632
+#define IMG_STEELWALL_BOTTOMLEFT_EDITOR 633
+#define IMG_STEELWALL_BOTTOMRIGHT_EDITOR 634
+#define IMG_STEELWALL_HORIZONTAL_EDITOR 635
+#define IMG_STEELWALL_VERTICAL_EDITOR 636
+#define IMG_INVISIBLE_STEELWALL_TOPLEFT 637
+#define IMG_INVISIBLE_STEELWALL_TOPRIGHT 638
+#define IMG_INVISIBLE_STEELWALL_BOTTOMLEFT 639
+#define IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT 640
+#define IMG_INVISIBLE_STEELWALL_HORIZONTAL 641
+#define IMG_INVISIBLE_STEELWALL_VERTICAL 642
+#define IMG_INVISIBLE_STEELWALL_TOPLEFT_EDITOR 643
+#define IMG_INVISIBLE_STEELWALL_TOPRIGHT_EDITOR 644
+#define IMG_INVISIBLE_STEELWALL_BOTTOMLEFT_EDITOR 645
+#define IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT_EDITOR 646
+#define IMG_INVISIBLE_STEELWALL_HORIZONTAL_EDITOR 647
+#define IMG_INVISIBLE_STEELWALL_VERTICAL_EDITOR 648
+#define IMG_ARROW_LEFT 649
+#define IMG_ARROW_RIGHT 650
+#define IMG_ARROW_UP 651
+#define IMG_ARROW_DOWN 652
+#define IMG_UNKNOWN 653
+#define IMG_TRIGGER_ELEMENT 654
+#define IMG_TRIGGER_PLAYER 655
+#define IMG_CHAR_SPACE 656
+#define IMG_CHAR_EXCLAM 657
+#define IMG_CHAR_QUOTEDBL 658
+#define IMG_CHAR_NUMBERSIGN 659
+#define IMG_CHAR_DOLLAR 660
+#define IMG_CHAR_PROCENT 661
+#define IMG_CHAR_AMPERSAND 662
+#define IMG_CHAR_APOSTROPHE 663
+#define IMG_CHAR_PARENLEFT 664
+#define IMG_CHAR_PARENRIGHT 665
+#define IMG_CHAR_ASTERISK 666
+#define IMG_CHAR_PLUS 667
+#define IMG_CHAR_COMMA 668
+#define IMG_CHAR_MINUS 669
+#define IMG_CHAR_PERIOD 670
+#define IMG_CHAR_SLASH 671
+#define IMG_CHAR_0 672
+#define IMG_CHAR_1 673
+#define IMG_CHAR_2 674
+#define IMG_CHAR_3 675
+#define IMG_CHAR_4 676
+#define IMG_CHAR_5 677
+#define IMG_CHAR_6 678
+#define IMG_CHAR_7 679
+#define IMG_CHAR_8 680
+#define IMG_CHAR_9 681
+#define IMG_CHAR_COLON 682
+#define IMG_CHAR_SEMICOLON 683
+#define IMG_CHAR_LESS 684
+#define IMG_CHAR_EQUAL 685
+#define IMG_CHAR_GREATER 686
+#define IMG_CHAR_QUESTION 687
+#define IMG_CHAR_AT 688
+#define IMG_CHAR_A 689
+#define IMG_CHAR_B 690
+#define IMG_CHAR_C 691
+#define IMG_CHAR_D 692
+#define IMG_CHAR_E 693
+#define IMG_CHAR_F 694
+#define IMG_CHAR_G 695
+#define IMG_CHAR_H 696
+#define IMG_CHAR_I 697
+#define IMG_CHAR_J 698
+#define IMG_CHAR_K 699
+#define IMG_CHAR_L 700
+#define IMG_CHAR_M 701
+#define IMG_CHAR_N 702
+#define IMG_CHAR_O 703
+#define IMG_CHAR_P 704
+#define IMG_CHAR_Q 705
+#define IMG_CHAR_R 706
+#define IMG_CHAR_S 707
+#define IMG_CHAR_T 708
+#define IMG_CHAR_U 709
+#define IMG_CHAR_V 710
+#define IMG_CHAR_W 711
+#define IMG_CHAR_X 712
+#define IMG_CHAR_Y 713
+#define IMG_CHAR_Z 714
+#define IMG_CHAR_BRACKETLEFT 715
+#define IMG_CHAR_BACKSLASH 716
+#define IMG_CHAR_BRACKETRIGHT 717
+#define IMG_CHAR_ASCIICIRCUM 718
+#define IMG_CHAR_UNDERSCORE 719
+#define IMG_CHAR_COPYRIGHT 720
+#define IMG_CHAR_AUMLAUT 721
+#define IMG_CHAR_OUMLAUT 722
+#define IMG_CHAR_UUMLAUT 723
+#define IMG_CHAR_DEGREE 724
+#define IMG_CHAR_TRADEMARK 725
+#define IMG_CHAR_CURSOR 726
+#define IMG_CUSTOM_1 727
+#define IMG_CUSTOM_1_EDITOR 728
+#define IMG_CUSTOM_2 729
+#define IMG_CUSTOM_2_EDITOR 730
+#define IMG_CUSTOM_3 731
+#define IMG_CUSTOM_3_EDITOR 732
+#define IMG_CUSTOM_4 733
+#define IMG_CUSTOM_4_EDITOR 734
+#define IMG_CUSTOM_5 735
+#define IMG_CUSTOM_5_EDITOR 736
+#define IMG_CUSTOM_6 737
+#define IMG_CUSTOM_6_EDITOR 738
+#define IMG_CUSTOM_7 739
+#define IMG_CUSTOM_7_EDITOR 740
+#define IMG_CUSTOM_8 741
+#define IMG_CUSTOM_8_EDITOR 742
+#define IMG_CUSTOM_9 743
+#define IMG_CUSTOM_9_EDITOR 744
+#define IMG_CUSTOM_10 745
+#define IMG_CUSTOM_10_EDITOR 746
+#define IMG_CUSTOM_11 747
+#define IMG_CUSTOM_11_EDITOR 748
+#define IMG_CUSTOM_12 749
+#define IMG_CUSTOM_12_EDITOR 750
+#define IMG_CUSTOM_13 751
+#define IMG_CUSTOM_13_EDITOR 752
+#define IMG_CUSTOM_14 753
+#define IMG_CUSTOM_14_EDITOR 754
+#define IMG_CUSTOM_15 755
+#define IMG_CUSTOM_15_EDITOR 756
+#define IMG_CUSTOM_16 757
+#define IMG_CUSTOM_16_EDITOR 758
+#define IMG_CUSTOM_17 759
+#define IMG_CUSTOM_17_EDITOR 760
+#define IMG_CUSTOM_18 761
+#define IMG_CUSTOM_18_EDITOR 762
+#define IMG_CUSTOM_19 763
+#define IMG_CUSTOM_19_EDITOR 764
+#define IMG_CUSTOM_20 765
+#define IMG_CUSTOM_20_EDITOR 766
+#define IMG_CUSTOM_21 767
+#define IMG_CUSTOM_21_EDITOR 768
+#define IMG_CUSTOM_22 769
+#define IMG_CUSTOM_22_EDITOR 770
+#define IMG_CUSTOM_23 771
+#define IMG_CUSTOM_23_EDITOR 772
+#define IMG_CUSTOM_24 773
+#define IMG_CUSTOM_24_EDITOR 774
+#define IMG_CUSTOM_25 775
+#define IMG_CUSTOM_25_EDITOR 776
+#define IMG_CUSTOM_26 777
+#define IMG_CUSTOM_26_EDITOR 778
+#define IMG_CUSTOM_27 779
+#define IMG_CUSTOM_27_EDITOR 780
+#define IMG_CUSTOM_28 781
+#define IMG_CUSTOM_28_EDITOR 782
+#define IMG_CUSTOM_29 783
+#define IMG_CUSTOM_29_EDITOR 784
+#define IMG_CUSTOM_30 785
+#define IMG_CUSTOM_30_EDITOR 786
+#define IMG_CUSTOM_31 787
+#define IMG_CUSTOM_31_EDITOR 788
+#define IMG_CUSTOM_32 789
+#define IMG_CUSTOM_32_EDITOR 790
+#define IMG_CUSTOM_33 791
+#define IMG_CUSTOM_33_EDITOR 792
+#define IMG_CUSTOM_34 793
+#define IMG_CUSTOM_34_EDITOR 794
+#define IMG_CUSTOM_35 795
+#define IMG_CUSTOM_35_EDITOR 796
+#define IMG_CUSTOM_36 797
+#define IMG_CUSTOM_36_EDITOR 798
+#define IMG_CUSTOM_37 799
+#define IMG_CUSTOM_37_EDITOR 800
+#define IMG_CUSTOM_38 801
+#define IMG_CUSTOM_38_EDITOR 802
+#define IMG_CUSTOM_39 803
+#define IMG_CUSTOM_39_EDITOR 804
+#define IMG_CUSTOM_40 805
+#define IMG_CUSTOM_40_EDITOR 806
+#define IMG_CUSTOM_41 807
+#define IMG_CUSTOM_41_EDITOR 808
+#define IMG_CUSTOM_42 809
+#define IMG_CUSTOM_42_EDITOR 810
+#define IMG_CUSTOM_43 811
+#define IMG_CUSTOM_43_EDITOR 812
+#define IMG_CUSTOM_44 813
+#define IMG_CUSTOM_44_EDITOR 814
+#define IMG_CUSTOM_45 815
+#define IMG_CUSTOM_45_EDITOR 816
+#define IMG_CUSTOM_46 817
+#define IMG_CUSTOM_46_EDITOR 818
+#define IMG_CUSTOM_47 819
+#define IMG_CUSTOM_47_EDITOR 820
+#define IMG_CUSTOM_48 821
+#define IMG_CUSTOM_48_EDITOR 822
+#define IMG_CUSTOM_49 823
+#define IMG_CUSTOM_49_EDITOR 824
+#define IMG_CUSTOM_50 825
+#define IMG_CUSTOM_50_EDITOR 826
+#define IMG_CUSTOM_51 827
+#define IMG_CUSTOM_51_EDITOR 828
+#define IMG_CUSTOM_52 829
+#define IMG_CUSTOM_52_EDITOR 830
+#define IMG_CUSTOM_53 831
+#define IMG_CUSTOM_53_EDITOR 832
+#define IMG_CUSTOM_54 833
+#define IMG_CUSTOM_54_EDITOR 834
+#define IMG_CUSTOM_55 835
+#define IMG_CUSTOM_55_EDITOR 836
+#define IMG_CUSTOM_56 837
+#define IMG_CUSTOM_56_EDITOR 838
+#define IMG_CUSTOM_57 839
+#define IMG_CUSTOM_57_EDITOR 840
+#define IMG_CUSTOM_58 841
+#define IMG_CUSTOM_58_EDITOR 842
+#define IMG_CUSTOM_59 843
+#define IMG_CUSTOM_59_EDITOR 844
+#define IMG_CUSTOM_60 845
+#define IMG_CUSTOM_60_EDITOR 846
+#define IMG_CUSTOM_61 847
+#define IMG_CUSTOM_61_EDITOR 848
+#define IMG_CUSTOM_62 849
+#define IMG_CUSTOM_62_EDITOR 850
+#define IMG_CUSTOM_63 851
+#define IMG_CUSTOM_63_EDITOR 852
+#define IMG_CUSTOM_64 853
+#define IMG_CUSTOM_64_EDITOR 854
+#define IMG_CUSTOM_65 855
+#define IMG_CUSTOM_65_EDITOR 856
+#define IMG_CUSTOM_66 857
+#define IMG_CUSTOM_66_EDITOR 858
+#define IMG_CUSTOM_67 859
+#define IMG_CUSTOM_67_EDITOR 860
+#define IMG_CUSTOM_68 861
+#define IMG_CUSTOM_68_EDITOR 862
+#define IMG_CUSTOM_69 863
+#define IMG_CUSTOM_69_EDITOR 864
+#define IMG_CUSTOM_70 865
+#define IMG_CUSTOM_70_EDITOR 866
+#define IMG_CUSTOM_71 867
+#define IMG_CUSTOM_71_EDITOR 868
+#define IMG_CUSTOM_72 869
+#define IMG_CUSTOM_72_EDITOR 870
+#define IMG_CUSTOM_73 871
+#define IMG_CUSTOM_73_EDITOR 872
+#define IMG_CUSTOM_74 873
+#define IMG_CUSTOM_74_EDITOR 874
+#define IMG_CUSTOM_75 875
+#define IMG_CUSTOM_75_EDITOR 876
+#define IMG_CUSTOM_76 877
+#define IMG_CUSTOM_76_EDITOR 878
+#define IMG_CUSTOM_77 879
+#define IMG_CUSTOM_77_EDITOR 880
+#define IMG_CUSTOM_78 881
+#define IMG_CUSTOM_78_EDITOR 882
+#define IMG_CUSTOM_79 883
+#define IMG_CUSTOM_79_EDITOR 884
+#define IMG_CUSTOM_80 885
+#define IMG_CUSTOM_80_EDITOR 886
+#define IMG_CUSTOM_81 887
+#define IMG_CUSTOM_81_EDITOR 888
+#define IMG_CUSTOM_82 889
+#define IMG_CUSTOM_82_EDITOR 890
+#define IMG_CUSTOM_83 891
+#define IMG_CUSTOM_83_EDITOR 892
+#define IMG_CUSTOM_84 893
+#define IMG_CUSTOM_84_EDITOR 894
+#define IMG_CUSTOM_85 895
+#define IMG_CUSTOM_85_EDITOR 896
+#define IMG_CUSTOM_86 897
+#define IMG_CUSTOM_86_EDITOR 898
+#define IMG_CUSTOM_87 899
+#define IMG_CUSTOM_87_EDITOR 900
+#define IMG_CUSTOM_88 901
+#define IMG_CUSTOM_88_EDITOR 902
+#define IMG_CUSTOM_89 903
+#define IMG_CUSTOM_89_EDITOR 904
+#define IMG_CUSTOM_90 905
+#define IMG_CUSTOM_90_EDITOR 906
+#define IMG_CUSTOM_91 907
+#define IMG_CUSTOM_91_EDITOR 908
+#define IMG_CUSTOM_92 909
+#define IMG_CUSTOM_92_EDITOR 910
+#define IMG_CUSTOM_93 911
+#define IMG_CUSTOM_93_EDITOR 912
+#define IMG_CUSTOM_94 913
+#define IMG_CUSTOM_94_EDITOR 914
+#define IMG_CUSTOM_95 915
+#define IMG_CUSTOM_95_EDITOR 916
+#define IMG_CUSTOM_96 917
+#define IMG_CUSTOM_96_EDITOR 918
+#define IMG_CUSTOM_97 919
+#define IMG_CUSTOM_97_EDITOR 920
+#define IMG_CUSTOM_98 921
+#define IMG_CUSTOM_98_EDITOR 922
+#define IMG_CUSTOM_99 923
+#define IMG_CUSTOM_99_EDITOR 924
+#define IMG_CUSTOM_100 925
+#define IMG_CUSTOM_100_EDITOR 926
+#define IMG_CUSTOM_101 927
+#define IMG_CUSTOM_101_EDITOR 928
+#define IMG_CUSTOM_102 929
+#define IMG_CUSTOM_102_EDITOR 930
+#define IMG_CUSTOM_103 931
+#define IMG_CUSTOM_103_EDITOR 932
+#define IMG_CUSTOM_104 933
+#define IMG_CUSTOM_104_EDITOR 934
+#define IMG_CUSTOM_105 935
+#define IMG_CUSTOM_105_EDITOR 936
+#define IMG_CUSTOM_106 937
+#define IMG_CUSTOM_106_EDITOR 938
+#define IMG_CUSTOM_107 939
+#define IMG_CUSTOM_107_EDITOR 940
+#define IMG_CUSTOM_108 941
+#define IMG_CUSTOM_108_EDITOR 942
+#define IMG_CUSTOM_109 943
+#define IMG_CUSTOM_109_EDITOR 944
+#define IMG_CUSTOM_110 945
+#define IMG_CUSTOM_110_EDITOR 946
+#define IMG_CUSTOM_111 947
+#define IMG_CUSTOM_111_EDITOR 948
+#define IMG_CUSTOM_112 949
+#define IMG_CUSTOM_112_EDITOR 950
+#define IMG_CUSTOM_113 951
+#define IMG_CUSTOM_113_EDITOR 952
+#define IMG_CUSTOM_114 953
+#define IMG_CUSTOM_114_EDITOR 954
+#define IMG_CUSTOM_115 955
+#define IMG_CUSTOM_115_EDITOR 956
+#define IMG_CUSTOM_116 957
+#define IMG_CUSTOM_116_EDITOR 958
+#define IMG_CUSTOM_117 959
+#define IMG_CUSTOM_117_EDITOR 960
+#define IMG_CUSTOM_118 961
+#define IMG_CUSTOM_118_EDITOR 962
+#define IMG_CUSTOM_119 963
+#define IMG_CUSTOM_119_EDITOR 964
+#define IMG_CUSTOM_120 965
+#define IMG_CUSTOM_120_EDITOR 966
+#define IMG_CUSTOM_121 967
+#define IMG_CUSTOM_121_EDITOR 968
+#define IMG_CUSTOM_122 969
+#define IMG_CUSTOM_122_EDITOR 970
+#define IMG_CUSTOM_123 971
+#define IMG_CUSTOM_123_EDITOR 972
+#define IMG_CUSTOM_124 973
+#define IMG_CUSTOM_124_EDITOR 974
+#define IMG_CUSTOM_125 975
+#define IMG_CUSTOM_125_EDITOR 976
+#define IMG_CUSTOM_126 977
+#define IMG_CUSTOM_126_EDITOR 978
+#define IMG_CUSTOM_127 979
+#define IMG_CUSTOM_127_EDITOR 980
+#define IMG_CUSTOM_128 981
+#define IMG_CUSTOM_128_EDITOR 982
+#define IMG_CUSTOM_129 983
+#define IMG_CUSTOM_129_EDITOR 984
+#define IMG_CUSTOM_130 985
+#define IMG_CUSTOM_130_EDITOR 986
+#define IMG_CUSTOM_131 987
+#define IMG_CUSTOM_131_EDITOR 988
+#define IMG_CUSTOM_132 989
+#define IMG_CUSTOM_132_EDITOR 990
+#define IMG_CUSTOM_133 991
+#define IMG_CUSTOM_133_EDITOR 992
+#define IMG_CUSTOM_134 993
+#define IMG_CUSTOM_134_EDITOR 994
+#define IMG_CUSTOM_135 995
+#define IMG_CUSTOM_135_EDITOR 996
+#define IMG_CUSTOM_136 997
+#define IMG_CUSTOM_136_EDITOR 998
+#define IMG_CUSTOM_137 999
+#define IMG_CUSTOM_137_EDITOR 1000
+#define IMG_CUSTOM_138 1001
+#define IMG_CUSTOM_138_EDITOR 1002
+#define IMG_CUSTOM_139 1003
+#define IMG_CUSTOM_139_EDITOR 1004
+#define IMG_CUSTOM_140 1005
+#define IMG_CUSTOM_140_EDITOR 1006
+#define IMG_CUSTOM_141 1007
+#define IMG_CUSTOM_141_EDITOR 1008
+#define IMG_CUSTOM_142 1009
+#define IMG_CUSTOM_142_EDITOR 1010
+#define IMG_CUSTOM_143 1011
+#define IMG_CUSTOM_143_EDITOR 1012
+#define IMG_CUSTOM_144 1013
+#define IMG_CUSTOM_144_EDITOR 1014
+#define IMG_CUSTOM_145 1015
+#define IMG_CUSTOM_145_EDITOR 1016
+#define IMG_CUSTOM_146 1017
+#define IMG_CUSTOM_146_EDITOR 1018
+#define IMG_CUSTOM_147 1019
+#define IMG_CUSTOM_147_EDITOR 1020
+#define IMG_CUSTOM_148 1021
+#define IMG_CUSTOM_148_EDITOR 1022
+#define IMG_CUSTOM_149 1023
+#define IMG_CUSTOM_149_EDITOR 1024
+#define IMG_CUSTOM_150 1025
+#define IMG_CUSTOM_150_EDITOR 1026
+#define IMG_CUSTOM_151 1027
+#define IMG_CUSTOM_151_EDITOR 1028
+#define IMG_CUSTOM_152 1029
+#define IMG_CUSTOM_152_EDITOR 1030
+#define IMG_CUSTOM_153 1031
+#define IMG_CUSTOM_153_EDITOR 1032
+#define IMG_CUSTOM_154 1033
+#define IMG_CUSTOM_154_EDITOR 1034
+#define IMG_CUSTOM_155 1035
+#define IMG_CUSTOM_155_EDITOR 1036
+#define IMG_CUSTOM_156 1037
+#define IMG_CUSTOM_156_EDITOR 1038
+#define IMG_CUSTOM_157 1039
+#define IMG_CUSTOM_157_EDITOR 1040
+#define IMG_CUSTOM_158 1041
+#define IMG_CUSTOM_158_EDITOR 1042
+#define IMG_CUSTOM_159 1043
+#define IMG_CUSTOM_159_EDITOR 1044
+#define IMG_CUSTOM_160 1045
+#define IMG_CUSTOM_160_EDITOR 1046
+#define IMG_CUSTOM_161 1047
+#define IMG_CUSTOM_161_EDITOR 1048
+#define IMG_CUSTOM_162 1049
+#define IMG_CUSTOM_162_EDITOR 1050
+#define IMG_CUSTOM_163 1051
+#define IMG_CUSTOM_163_EDITOR 1052
+#define IMG_CUSTOM_164 1053
+#define IMG_CUSTOM_164_EDITOR 1054
+#define IMG_CUSTOM_165 1055
+#define IMG_CUSTOM_165_EDITOR 1056
+#define IMG_CUSTOM_166 1057
+#define IMG_CUSTOM_166_EDITOR 1058
+#define IMG_CUSTOM_167 1059
+#define IMG_CUSTOM_167_EDITOR 1060
+#define IMG_CUSTOM_168 1061
+#define IMG_CUSTOM_168_EDITOR 1062
+#define IMG_CUSTOM_169 1063
+#define IMG_CUSTOM_169_EDITOR 1064
+#define IMG_CUSTOM_170 1065
+#define IMG_CUSTOM_170_EDITOR 1066
+#define IMG_CUSTOM_171 1067
+#define IMG_CUSTOM_171_EDITOR 1068
+#define IMG_CUSTOM_172 1069
+#define IMG_CUSTOM_172_EDITOR 1070
+#define IMG_CUSTOM_173 1071
+#define IMG_CUSTOM_173_EDITOR 1072
+#define IMG_CUSTOM_174 1073
+#define IMG_CUSTOM_174_EDITOR 1074
+#define IMG_CUSTOM_175 1075
+#define IMG_CUSTOM_175_EDITOR 1076
+#define IMG_CUSTOM_176 1077
+#define IMG_CUSTOM_176_EDITOR 1078
+#define IMG_CUSTOM_177 1079
+#define IMG_CUSTOM_177_EDITOR 1080
+#define IMG_CUSTOM_178 1081
+#define IMG_CUSTOM_178_EDITOR 1082
+#define IMG_CUSTOM_179 1083
+#define IMG_CUSTOM_179_EDITOR 1084
+#define IMG_CUSTOM_180 1085
+#define IMG_CUSTOM_180_EDITOR 1086
+#define IMG_CUSTOM_181 1087
+#define IMG_CUSTOM_181_EDITOR 1088
+#define IMG_CUSTOM_182 1089
+#define IMG_CUSTOM_182_EDITOR 1090
+#define IMG_CUSTOM_183 1091
+#define IMG_CUSTOM_183_EDITOR 1092
+#define IMG_CUSTOM_184 1093
+#define IMG_CUSTOM_184_EDITOR 1094
+#define IMG_CUSTOM_185 1095
+#define IMG_CUSTOM_185_EDITOR 1096
+#define IMG_CUSTOM_186 1097
+#define IMG_CUSTOM_186_EDITOR 1098
+#define IMG_CUSTOM_187 1099
+#define IMG_CUSTOM_187_EDITOR 1100
+#define IMG_CUSTOM_188 1101
+#define IMG_CUSTOM_188_EDITOR 1102
+#define IMG_CUSTOM_189 1103
+#define IMG_CUSTOM_189_EDITOR 1104
+#define IMG_CUSTOM_190 1105
+#define IMG_CUSTOM_190_EDITOR 1106
+#define IMG_CUSTOM_191 1107
+#define IMG_CUSTOM_191_EDITOR 1108
+#define IMG_CUSTOM_192 1109
+#define IMG_CUSTOM_192_EDITOR 1110
+#define IMG_CUSTOM_193 1111
+#define IMG_CUSTOM_193_EDITOR 1112
+#define IMG_CUSTOM_194 1113
+#define IMG_CUSTOM_194_EDITOR 1114
+#define IMG_CUSTOM_195 1115
+#define IMG_CUSTOM_195_EDITOR 1116
+#define IMG_CUSTOM_196 1117
+#define IMG_CUSTOM_196_EDITOR 1118
+#define IMG_CUSTOM_197 1119
+#define IMG_CUSTOM_197_EDITOR 1120
+#define IMG_CUSTOM_198 1121
+#define IMG_CUSTOM_198_EDITOR 1122
+#define IMG_CUSTOM_199 1123
+#define IMG_CUSTOM_199_EDITOR 1124
+#define IMG_CUSTOM_200 1125
+#define IMG_CUSTOM_200_EDITOR 1126
+#define IMG_CUSTOM_201 1127
+#define IMG_CUSTOM_201_EDITOR 1128
+#define IMG_CUSTOM_202 1129
+#define IMG_CUSTOM_202_EDITOR 1130
+#define IMG_CUSTOM_203 1131
+#define IMG_CUSTOM_203_EDITOR 1132
+#define IMG_CUSTOM_204 1133
+#define IMG_CUSTOM_204_EDITOR 1134
+#define IMG_CUSTOM_205 1135
+#define IMG_CUSTOM_205_EDITOR 1136
+#define IMG_CUSTOM_206 1137
+#define IMG_CUSTOM_206_EDITOR 1138
+#define IMG_CUSTOM_207 1139
+#define IMG_CUSTOM_207_EDITOR 1140
+#define IMG_CUSTOM_208 1141
+#define IMG_CUSTOM_208_EDITOR 1142
+#define IMG_CUSTOM_209 1143
+#define IMG_CUSTOM_209_EDITOR 1144
+#define IMG_CUSTOM_210 1145
+#define IMG_CUSTOM_210_EDITOR 1146
+#define IMG_CUSTOM_211 1147
+#define IMG_CUSTOM_211_EDITOR 1148
+#define IMG_CUSTOM_212 1149
+#define IMG_CUSTOM_212_EDITOR 1150
+#define IMG_CUSTOM_213 1151
+#define IMG_CUSTOM_213_EDITOR 1152
+#define IMG_CUSTOM_214 1153
+#define IMG_CUSTOM_214_EDITOR 1154
+#define IMG_CUSTOM_215 1155
+#define IMG_CUSTOM_215_EDITOR 1156
+#define IMG_CUSTOM_216 1157
+#define IMG_CUSTOM_216_EDITOR 1158
+#define IMG_CUSTOM_217 1159
+#define IMG_CUSTOM_217_EDITOR 1160
+#define IMG_CUSTOM_218 1161
+#define IMG_CUSTOM_218_EDITOR 1162
+#define IMG_CUSTOM_219 1163
+#define IMG_CUSTOM_219_EDITOR 1164
+#define IMG_CUSTOM_220 1165
+#define IMG_CUSTOM_220_EDITOR 1166
+#define IMG_CUSTOM_221 1167
+#define IMG_CUSTOM_221_EDITOR 1168
+#define IMG_CUSTOM_222 1169
+#define IMG_CUSTOM_222_EDITOR 1170
+#define IMG_CUSTOM_223 1171
+#define IMG_CUSTOM_223_EDITOR 1172
+#define IMG_CUSTOM_224 1173
+#define IMG_CUSTOM_224_EDITOR 1174
+#define IMG_CUSTOM_225 1175
+#define IMG_CUSTOM_225_EDITOR 1176
+#define IMG_CUSTOM_226 1177
+#define IMG_CUSTOM_226_EDITOR 1178
+#define IMG_CUSTOM_227 1179
+#define IMG_CUSTOM_227_EDITOR 1180
+#define IMG_CUSTOM_228 1181
+#define IMG_CUSTOM_228_EDITOR 1182
+#define IMG_CUSTOM_229 1183
+#define IMG_CUSTOM_229_EDITOR 1184
+#define IMG_CUSTOM_230 1185
+#define IMG_CUSTOM_230_EDITOR 1186
+#define IMG_CUSTOM_231 1187
+#define IMG_CUSTOM_231_EDITOR 1188
+#define IMG_CUSTOM_232 1189
+#define IMG_CUSTOM_232_EDITOR 1190
+#define IMG_CUSTOM_233 1191
+#define IMG_CUSTOM_233_EDITOR 1192
+#define IMG_CUSTOM_234 1193
+#define IMG_CUSTOM_234_EDITOR 1194
+#define IMG_CUSTOM_235 1195
+#define IMG_CUSTOM_235_EDITOR 1196
+#define IMG_CUSTOM_236 1197
+#define IMG_CUSTOM_236_EDITOR 1198
+#define IMG_CUSTOM_237 1199
+#define IMG_CUSTOM_237_EDITOR 1200
+#define IMG_CUSTOM_238 1201
+#define IMG_CUSTOM_238_EDITOR 1202
+#define IMG_CUSTOM_239 1203
+#define IMG_CUSTOM_239_EDITOR 1204
+#define IMG_CUSTOM_240 1205
+#define IMG_CUSTOM_240_EDITOR 1206
+#define IMG_CUSTOM_241 1207
+#define IMG_CUSTOM_241_EDITOR 1208
+#define IMG_CUSTOM_242 1209
+#define IMG_CUSTOM_242_EDITOR 1210
+#define IMG_CUSTOM_243 1211
+#define IMG_CUSTOM_243_EDITOR 1212
+#define IMG_CUSTOM_244 1213
+#define IMG_CUSTOM_244_EDITOR 1214
+#define IMG_CUSTOM_245 1215
+#define IMG_CUSTOM_245_EDITOR 1216
+#define IMG_CUSTOM_246 1217
+#define IMG_CUSTOM_246_EDITOR 1218
+#define IMG_CUSTOM_247 1219
+#define IMG_CUSTOM_247_EDITOR 1220
+#define IMG_CUSTOM_248 1221
+#define IMG_CUSTOM_248_EDITOR 1222
+#define IMG_CUSTOM_249 1223
+#define IMG_CUSTOM_249_EDITOR 1224
+#define IMG_CUSTOM_250 1225
+#define IMG_CUSTOM_250_EDITOR 1226
+#define IMG_CUSTOM_251 1227
+#define IMG_CUSTOM_251_EDITOR 1228
+#define IMG_CUSTOM_252 1229
+#define IMG_CUSTOM_252_EDITOR 1230
+#define IMG_CUSTOM_253 1231
+#define IMG_CUSTOM_253_EDITOR 1232
+#define IMG_CUSTOM_254 1233
+#define IMG_CUSTOM_254_EDITOR 1234
+#define IMG_CUSTOM_255 1235
+#define IMG_CUSTOM_255_EDITOR 1236
+#define IMG_CUSTOM_256 1237
+#define IMG_CUSTOM_256_EDITOR 1238
+#define IMG_GROUP_1 1239
+#define IMG_GROUP_1_EDITOR 1240
+#define IMG_GROUP_2 1241
+#define IMG_GROUP_2_EDITOR 1242
+#define IMG_GROUP_3 1243
+#define IMG_GROUP_3_EDITOR 1244
+#define IMG_GROUP_4 1245
+#define IMG_GROUP_4_EDITOR 1246
+#define IMG_GROUP_5 1247
+#define IMG_GROUP_5_EDITOR 1248
+#define IMG_GROUP_6 1249
+#define IMG_GROUP_6_EDITOR 1250
+#define IMG_GROUP_7 1251
+#define IMG_GROUP_7_EDITOR 1252
+#define IMG_GROUP_8 1253
+#define IMG_GROUP_8_EDITOR 1254
+#define IMG_GROUP_9 1255
+#define IMG_GROUP_9_EDITOR 1256
+#define IMG_GROUP_10 1257
+#define IMG_GROUP_10_EDITOR 1258
+#define IMG_GROUP_11 1259
+#define IMG_GROUP_11_EDITOR 1260
+#define IMG_GROUP_12 1261
+#define IMG_GROUP_12_EDITOR 1262
+#define IMG_GROUP_13 1263
+#define IMG_GROUP_13_EDITOR 1264
+#define IMG_GROUP_14 1265
+#define IMG_GROUP_14_EDITOR 1266
+#define IMG_GROUP_15 1267
+#define IMG_GROUP_15_EDITOR 1268
+#define IMG_GROUP_16 1269
+#define IMG_GROUP_16_EDITOR 1270
+#define IMG_GROUP_17 1271
+#define IMG_GROUP_17_EDITOR 1272
+#define IMG_GROUP_18 1273
+#define IMG_GROUP_18_EDITOR 1274
+#define IMG_GROUP_19 1275
+#define IMG_GROUP_19_EDITOR 1276
+#define IMG_GROUP_20 1277
+#define IMG_GROUP_20_EDITOR 1278
+#define IMG_GROUP_21 1279
+#define IMG_GROUP_21_EDITOR 1280
+#define IMG_GROUP_22 1281
+#define IMG_GROUP_22_EDITOR 1282
+#define IMG_GROUP_23 1283
+#define IMG_GROUP_23_EDITOR 1284
+#define IMG_GROUP_24 1285
+#define IMG_GROUP_24_EDITOR 1286
+#define IMG_GROUP_25 1287
+#define IMG_GROUP_25_EDITOR 1288
+#define IMG_GROUP_26 1289
+#define IMG_GROUP_26_EDITOR 1290
+#define IMG_GROUP_27 1291
+#define IMG_GROUP_27_EDITOR 1292
+#define IMG_GROUP_28 1293
+#define IMG_GROUP_28_EDITOR 1294
+#define IMG_GROUP_29 1295
+#define IMG_GROUP_29_EDITOR 1296
+#define IMG_GROUP_30 1297
+#define IMG_GROUP_30_EDITOR 1298
+#define IMG_GROUP_31 1299
+#define IMG_GROUP_31_EDITOR 1300
+#define IMG_GROUP_32 1301
+#define IMG_GROUP_32_EDITOR 1302
+#define IMG_TOON_1 1303
+#define IMG_TOON_2 1304
+#define IMG_TOON_3 1305
+#define IMG_TOON_4 1306
+#define IMG_TOON_5 1307
+#define IMG_TOON_6 1308
+#define IMG_TOON_7 1309
+#define IMG_TOON_8 1310
+#define IMG_TOON_9 1311
+#define IMG_TOON_10 1312
+#define IMG_TOON_11 1313
+#define IMG_TOON_12 1314
+#define IMG_TOON_13 1315
+#define IMG_TOON_14 1316
+#define IMG_TOON_15 1317
+#define IMG_TOON_16 1318
+#define IMG_TOON_17 1319
+#define IMG_TOON_18 1320
+#define IMG_TOON_19 1321
+#define IMG_TOON_20 1322
+#define IMG_MENU_CALIBRATE_RED 1323
+#define IMG_MENU_CALIBRATE_BLUE 1324
+#define IMG_MENU_CALIBRATE_YELLOW 1325
+#define IMG_MENU_BUTTON 1326
+#define IMG_MENU_BUTTON_ACTIVE 1327
+#define IMG_MENU_BUTTON_LEFT 1328
+#define IMG_MENU_BUTTON_RIGHT 1329
+#define IMG_MENU_BUTTON_UP 1330
+#define IMG_MENU_BUTTON_DOWN 1331
+#define IMG_MENU_BUTTON_LEFT_ACTIVE 1332
+#define IMG_MENU_BUTTON_RIGHT_ACTIVE 1333
+#define IMG_MENU_BUTTON_UP_ACTIVE 1334
+#define IMG_MENU_BUTTON_DOWN_ACTIVE 1335
+#define IMG_MENU_SCROLLBAR 1336
+#define IMG_MENU_SCROLLBAR_ACTIVE 1337
+#define IMG_FONT_INITIAL_1 1338
+#define IMG_FONT_INITIAL_2 1339
+#define IMG_FONT_INITIAL_3 1340
+#define IMG_FONT_INITIAL_4 1341
+#define IMG_FONT_TITLE_1 1342
+#define IMG_FONT_TITLE_1_LEVELS 1343
+#define IMG_FONT_TITLE_2 1344
+#define IMG_FONT_MENU_1 1345
+#define IMG_FONT_MENU_2 1346
+#define IMG_FONT_TEXT_1 1347
+#define IMG_FONT_TEXT_1_LEVELS 1348
+#define IMG_FONT_TEXT_1_PREVIEW 1349
+#define IMG_FONT_TEXT_1_SCORES 1350
+#define IMG_FONT_TEXT_1_ACTIVE_SCORES 1351
+#define IMG_FONT_TEXT_2 1352
+#define IMG_FONT_TEXT_2_LEVELS 1353
+#define IMG_FONT_TEXT_2_PREVIEW 1354
+#define IMG_FONT_TEXT_2_SCORES 1355
+#define IMG_FONT_TEXT_2_ACTIVE_SCORES 1356
+#define IMG_FONT_TEXT_3 1357
+#define IMG_FONT_TEXT_3_LEVELS 1358
+#define IMG_FONT_TEXT_3_PREVIEW 1359
+#define IMG_FONT_TEXT_3_SCORES 1360
+#define IMG_FONT_TEXT_3_ACTIVE_SCORES 1361
+#define IMG_FONT_TEXT_4 1362
+#define IMG_FONT_TEXT_4_LEVELS 1363
+#define IMG_FONT_TEXT_4_SCORES 1364
+#define IMG_FONT_TEXT_4_ACTIVE_SCORES 1365
+#define IMG_FONT_ENVELOPE_1 1366
+#define IMG_FONT_ENVELOPE_2 1367
+#define IMG_FONT_ENVELOPE_3 1368
+#define IMG_FONT_ENVELOPE_4 1369
+#define IMG_FONT_INPUT_1 1370
+#define IMG_FONT_INPUT_1_MAIN 1371
+#define IMG_FONT_INPUT_1_ACTIVE 1372
+#define IMG_FONT_INPUT_1_ACTIVE_MAIN 1373
+#define IMG_FONT_INPUT_1_ACTIVE_SETUP 1374
+#define IMG_FONT_INPUT_2 1375
+#define IMG_FONT_INPUT_2_ACTIVE 1376
+#define IMG_FONT_OPTION_OFF 1377
+#define IMG_FONT_OPTION_ON 1378
+#define IMG_FONT_VALUE_1 1379
+#define IMG_FONT_VALUE_2 1380
+#define IMG_FONT_VALUE_OLD 1381
+#define IMG_FONT_LEVEL_NUMBER 1382
+#define IMG_FONT_TAPE_RECORDER 1383
+#define IMG_FONT_GAME_INFO 1384
+#define IMG_GLOBAL_BORDER 1385
+#define IMG_GLOBAL_DOOR 1386
+#define IMG_EDITOR_ELEMENT_BORDER 1387
+#define IMG_EDITOR_ELEMENT_BORDER_INPUT 1388
+#define IMG_BACKGROUND_ENVELOPE_1 1389
+#define IMG_BACKGROUND_ENVELOPE_2 1390
+#define IMG_BACKGROUND_ENVELOPE_3 1391
+#define IMG_BACKGROUND_ENVELOPE_4 1392
+#define IMG_BACKGROUND 1393
+#define IMG_BACKGROUND_MAIN 1394
+#define IMG_BACKGROUND_LEVELS 1395
+#define IMG_BACKGROUND_SCORES 1396
+#define IMG_BACKGROUND_EDITOR 1397
+#define IMG_BACKGROUND_INFO 1398
+#define IMG_BACKGROUND_INFO_ELEMENTS 1399
+#define IMG_BACKGROUND_SETUP 1400
+#define IMG_BACKGROUND_DOOR 1401
-#define NUM_IMAGE_FILES 1313
+#define NUM_IMAGE_FILES 1402
#endif /* CONF_GFX_H */
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* (c) 1995-2002 Artsoft Entertainment *
+* Holger Schemel *
+* Detmolder Strasse 189 *
+* 33604 Bielefeld *
+* Germany *
+* e-mail: info@artsoft.org *
+*----------------------------------------------------------*
+* conf_grp.c *
+***********************************************************/
+
+/* ----- this file was automatically generated -- do not edit by hand ----- */
+
+#ifndef CONF_GRP_C
+#define CONF_GRP_C
+
+/* values for graphics configuration (group elements) */
+
+ { "group_1", "RocksDC.pcx" },
+ { "group_1.xpos", "4" },
+ { "group_1.ypos", "15" },
+ { "group_1.frames", "1" },
+ { "group_1.EDITOR", "RocksDC.pcx" },
+ { "group_1.EDITOR.xpos", "14" },
+ { "group_1.EDITOR.ypos", "15" },
+
+ { "group_2", "RocksDC.pcx" },
+ { "group_2.xpos", "4" },
+ { "group_2.ypos", "15" },
+ { "group_2.frames", "1" },
+ { "group_2.EDITOR", "RocksDC.pcx" },
+ { "group_2.EDITOR.xpos", "14" },
+ { "group_2.EDITOR.ypos", "15" },
+
+ { "group_3", "RocksDC.pcx" },
+ { "group_3.xpos", "4" },
+ { "group_3.ypos", "15" },
+ { "group_3.frames", "1" },
+ { "group_3.EDITOR", "RocksDC.pcx" },
+ { "group_3.EDITOR.xpos", "14" },
+ { "group_3.EDITOR.ypos", "15" },
+
+ { "group_4", "RocksDC.pcx" },
+ { "group_4.xpos", "4" },
+ { "group_4.ypos", "15" },
+ { "group_4.frames", "1" },
+ { "group_4.EDITOR", "RocksDC.pcx" },
+ { "group_4.EDITOR.xpos", "14" },
+ { "group_4.EDITOR.ypos", "15" },
+
+ { "group_5", "RocksDC.pcx" },
+ { "group_5.xpos", "4" },
+ { "group_5.ypos", "15" },
+ { "group_5.frames", "1" },
+ { "group_5.EDITOR", "RocksDC.pcx" },
+ { "group_5.EDITOR.xpos", "14" },
+ { "group_5.EDITOR.ypos", "15" },
+
+ { "group_6", "RocksDC.pcx" },
+ { "group_6.xpos", "4" },
+ { "group_6.ypos", "15" },
+ { "group_6.frames", "1" },
+ { "group_6.EDITOR", "RocksDC.pcx" },
+ { "group_6.EDITOR.xpos", "14" },
+ { "group_6.EDITOR.ypos", "15" },
+
+ { "group_7", "RocksDC.pcx" },
+ { "group_7.xpos", "4" },
+ { "group_7.ypos", "15" },
+ { "group_7.frames", "1" },
+ { "group_7.EDITOR", "RocksDC.pcx" },
+ { "group_7.EDITOR.xpos", "14" },
+ { "group_7.EDITOR.ypos", "15" },
+
+ { "group_8", "RocksDC.pcx" },
+ { "group_8.xpos", "4" },
+ { "group_8.ypos", "15" },
+ { "group_8.frames", "1" },
+ { "group_8.EDITOR", "RocksDC.pcx" },
+ { "group_8.EDITOR.xpos", "14" },
+ { "group_8.EDITOR.ypos", "15" },
+
+ { "group_9", "RocksDC.pcx" },
+ { "group_9.xpos", "4" },
+ { "group_9.ypos", "15" },
+ { "group_9.frames", "1" },
+ { "group_9.EDITOR", "RocksDC.pcx" },
+ { "group_9.EDITOR.xpos", "14" },
+ { "group_9.EDITOR.ypos", "15" },
+
+ { "group_10", "RocksDC.pcx" },
+ { "group_10.xpos", "4" },
+ { "group_10.ypos", "15" },
+ { "group_10.frames", "1" },
+ { "group_10.EDITOR", "RocksDC.pcx" },
+ { "group_10.EDITOR.xpos", "14" },
+ { "group_10.EDITOR.ypos", "15" },
+
+ { "group_11", "RocksDC.pcx" },
+ { "group_11.xpos", "4" },
+ { "group_11.ypos", "15" },
+ { "group_11.frames", "1" },
+ { "group_11.EDITOR", "RocksDC.pcx" },
+ { "group_11.EDITOR.xpos", "14" },
+ { "group_11.EDITOR.ypos", "15" },
+
+ { "group_12", "RocksDC.pcx" },
+ { "group_12.xpos", "4" },
+ { "group_12.ypos", "15" },
+ { "group_12.frames", "1" },
+ { "group_12.EDITOR", "RocksDC.pcx" },
+ { "group_12.EDITOR.xpos", "14" },
+ { "group_12.EDITOR.ypos", "15" },
+
+ { "group_13", "RocksDC.pcx" },
+ { "group_13.xpos", "4" },
+ { "group_13.ypos", "15" },
+ { "group_13.frames", "1" },
+ { "group_13.EDITOR", "RocksDC.pcx" },
+ { "group_13.EDITOR.xpos", "14" },
+ { "group_13.EDITOR.ypos", "15" },
+
+ { "group_14", "RocksDC.pcx" },
+ { "group_14.xpos", "4" },
+ { "group_14.ypos", "15" },
+ { "group_14.frames", "1" },
+ { "group_14.EDITOR", "RocksDC.pcx" },
+ { "group_14.EDITOR.xpos", "14" },
+ { "group_14.EDITOR.ypos", "15" },
+
+ { "group_15", "RocksDC.pcx" },
+ { "group_15.xpos", "4" },
+ { "group_15.ypos", "15" },
+ { "group_15.frames", "1" },
+ { "group_15.EDITOR", "RocksDC.pcx" },
+ { "group_15.EDITOR.xpos", "14" },
+ { "group_15.EDITOR.ypos", "15" },
+
+ { "group_16", "RocksDC.pcx" },
+ { "group_16.xpos", "4" },
+ { "group_16.ypos", "15" },
+ { "group_16.frames", "1" },
+ { "group_16.EDITOR", "RocksDC.pcx" },
+ { "group_16.EDITOR.xpos", "14" },
+ { "group_16.EDITOR.ypos", "15" },
+
+ { "group_17", "RocksDC.pcx" },
+ { "group_17.xpos", "4" },
+ { "group_17.ypos", "15" },
+ { "group_17.frames", "1" },
+ { "group_17.EDITOR", "RocksDC.pcx" },
+ { "group_17.EDITOR.xpos", "14" },
+ { "group_17.EDITOR.ypos", "15" },
+
+ { "group_18", "RocksDC.pcx" },
+ { "group_18.xpos", "4" },
+ { "group_18.ypos", "15" },
+ { "group_18.frames", "1" },
+ { "group_18.EDITOR", "RocksDC.pcx" },
+ { "group_18.EDITOR.xpos", "14" },
+ { "group_18.EDITOR.ypos", "15" },
+
+ { "group_19", "RocksDC.pcx" },
+ { "group_19.xpos", "4" },
+ { "group_19.ypos", "15" },
+ { "group_19.frames", "1" },
+ { "group_19.EDITOR", "RocksDC.pcx" },
+ { "group_19.EDITOR.xpos", "14" },
+ { "group_19.EDITOR.ypos", "15" },
+
+ { "group_20", "RocksDC.pcx" },
+ { "group_20.xpos", "4" },
+ { "group_20.ypos", "15" },
+ { "group_20.frames", "1" },
+ { "group_20.EDITOR", "RocksDC.pcx" },
+ { "group_20.EDITOR.xpos", "14" },
+ { "group_20.EDITOR.ypos", "15" },
+
+ { "group_21", "RocksDC.pcx" },
+ { "group_21.xpos", "4" },
+ { "group_21.ypos", "15" },
+ { "group_21.frames", "1" },
+ { "group_21.EDITOR", "RocksDC.pcx" },
+ { "group_21.EDITOR.xpos", "14" },
+ { "group_21.EDITOR.ypos", "15" },
+
+ { "group_22", "RocksDC.pcx" },
+ { "group_22.xpos", "4" },
+ { "group_22.ypos", "15" },
+ { "group_22.frames", "1" },
+ { "group_22.EDITOR", "RocksDC.pcx" },
+ { "group_22.EDITOR.xpos", "14" },
+ { "group_22.EDITOR.ypos", "15" },
+
+ { "group_23", "RocksDC.pcx" },
+ { "group_23.xpos", "4" },
+ { "group_23.ypos", "15" },
+ { "group_23.frames", "1" },
+ { "group_23.EDITOR", "RocksDC.pcx" },
+ { "group_23.EDITOR.xpos", "14" },
+ { "group_23.EDITOR.ypos", "15" },
+
+ { "group_24", "RocksDC.pcx" },
+ { "group_24.xpos", "4" },
+ { "group_24.ypos", "15" },
+ { "group_24.frames", "1" },
+ { "group_24.EDITOR", "RocksDC.pcx" },
+ { "group_24.EDITOR.xpos", "14" },
+ { "group_24.EDITOR.ypos", "15" },
+
+ { "group_25", "RocksDC.pcx" },
+ { "group_25.xpos", "4" },
+ { "group_25.ypos", "15" },
+ { "group_25.frames", "1" },
+ { "group_25.EDITOR", "RocksDC.pcx" },
+ { "group_25.EDITOR.xpos", "14" },
+ { "group_25.EDITOR.ypos", "15" },
+
+ { "group_26", "RocksDC.pcx" },
+ { "group_26.xpos", "4" },
+ { "group_26.ypos", "15" },
+ { "group_26.frames", "1" },
+ { "group_26.EDITOR", "RocksDC.pcx" },
+ { "group_26.EDITOR.xpos", "14" },
+ { "group_26.EDITOR.ypos", "15" },
+
+ { "group_27", "RocksDC.pcx" },
+ { "group_27.xpos", "4" },
+ { "group_27.ypos", "15" },
+ { "group_27.frames", "1" },
+ { "group_27.EDITOR", "RocksDC.pcx" },
+ { "group_27.EDITOR.xpos", "14" },
+ { "group_27.EDITOR.ypos", "15" },
+
+ { "group_28", "RocksDC.pcx" },
+ { "group_28.xpos", "4" },
+ { "group_28.ypos", "15" },
+ { "group_28.frames", "1" },
+ { "group_28.EDITOR", "RocksDC.pcx" },
+ { "group_28.EDITOR.xpos", "14" },
+ { "group_28.EDITOR.ypos", "15" },
+
+ { "group_29", "RocksDC.pcx" },
+ { "group_29.xpos", "4" },
+ { "group_29.ypos", "15" },
+ { "group_29.frames", "1" },
+ { "group_29.EDITOR", "RocksDC.pcx" },
+ { "group_29.EDITOR.xpos", "14" },
+ { "group_29.EDITOR.ypos", "15" },
+
+ { "group_30", "RocksDC.pcx" },
+ { "group_30.xpos", "4" },
+ { "group_30.ypos", "15" },
+ { "group_30.frames", "1" },
+ { "group_30.EDITOR", "RocksDC.pcx" },
+ { "group_30.EDITOR.xpos", "14" },
+ { "group_30.EDITOR.ypos", "15" },
+
+ { "group_31", "RocksDC.pcx" },
+ { "group_31.xpos", "4" },
+ { "group_31.ypos", "15" },
+ { "group_31.frames", "1" },
+ { "group_31.EDITOR", "RocksDC.pcx" },
+ { "group_31.EDITOR.xpos", "14" },
+ { "group_31.EDITOR.ypos", "15" },
+
+ { "group_32", "RocksDC.pcx" },
+ { "group_32.xpos", "4" },
+ { "group_32.ypos", "15" },
+ { "group_32.frames", "1" },
+ { "group_32.EDITOR", "RocksDC.pcx" },
+ { "group_32.EDITOR.xpos", "14" },
+ { "group_32.EDITOR.ypos", "15" },
+
+
+#endif /* CONF_GRP_C */
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* (c) 1995-2002 Artsoft Entertainment *
+* Holger Schemel *
+* Detmolder Strasse 189 *
+* 33604 Bielefeld *
+* Germany *
+* e-mail: info@artsoft.org *
+*----------------------------------------------------------*
+* conf_grp.h *
+***********************************************************/
+
+/* ----- this file was automatically generated -- do not edit by hand ----- */
+
+#ifndef CONF_GRP_H
+#define CONF_GRP_H
+
+/* values for elements configuration (group elements) */
+
+#define EL_GROUP_1 (EL_GROUP_START + 0)
+#define EL_GROUP_2 (EL_GROUP_START + 1)
+#define EL_GROUP_3 (EL_GROUP_START + 2)
+#define EL_GROUP_4 (EL_GROUP_START + 3)
+#define EL_GROUP_5 (EL_GROUP_START + 4)
+#define EL_GROUP_6 (EL_GROUP_START + 5)
+#define EL_GROUP_7 (EL_GROUP_START + 6)
+#define EL_GROUP_8 (EL_GROUP_START + 7)
+#define EL_GROUP_9 (EL_GROUP_START + 8)
+#define EL_GROUP_10 (EL_GROUP_START + 9)
+#define EL_GROUP_11 (EL_GROUP_START + 10)
+#define EL_GROUP_12 (EL_GROUP_START + 11)
+#define EL_GROUP_13 (EL_GROUP_START + 12)
+#define EL_GROUP_14 (EL_GROUP_START + 13)
+#define EL_GROUP_15 (EL_GROUP_START + 14)
+#define EL_GROUP_16 (EL_GROUP_START + 15)
+#define EL_GROUP_17 (EL_GROUP_START + 16)
+#define EL_GROUP_18 (EL_GROUP_START + 17)
+#define EL_GROUP_19 (EL_GROUP_START + 18)
+#define EL_GROUP_20 (EL_GROUP_START + 19)
+#define EL_GROUP_21 (EL_GROUP_START + 20)
+#define EL_GROUP_22 (EL_GROUP_START + 21)
+#define EL_GROUP_23 (EL_GROUP_START + 22)
+#define EL_GROUP_24 (EL_GROUP_START + 23)
+#define EL_GROUP_25 (EL_GROUP_START + 24)
+#define EL_GROUP_26 (EL_GROUP_START + 25)
+#define EL_GROUP_27 (EL_GROUP_START + 26)
+#define EL_GROUP_28 (EL_GROUP_START + 27)
+#define EL_GROUP_29 (EL_GROUP_START + 28)
+#define EL_GROUP_30 (EL_GROUP_START + 29)
+#define EL_GROUP_31 (EL_GROUP_START + 30)
+#define EL_GROUP_32 (EL_GROUP_START + 31)
+
+#endif /* CONF_GRP_C */
},
{
"yamyam",
- "Cruncher: Eats diamonds and you, if you're not careful"
+ "Yam Yam: Eats diamonds and you, if you're not careful"
},
{
"dark_yamyam",
- "Cruncher (BD style): Eats almost everything"
+ "Dark Yam Yam: Eats almost everything"
},
{
"robot",
-#define COMPILE_DATE_STRING "[2003-12-14 02:31]"
+#define COMPILE_DATE_STRING "[2004-06-07 01:56]"
#define ED_CTRL1_BUTTONS_GFX_YPOS 236
#define ED_CTRL2_BUTTONS_GFX_YPOS 236
#define ED_CTRL3_BUTTONS_GFX_YPOS 324
+#define ED_CTRL4_BUTTONS_GFX_XPOS 44
+#define ED_CTRL4_BUTTONS_GFX_YPOS 214
#define ED_CTRL1_BUTTONS_ALT_GFX_YPOS 142
#define ED_CTRL3_BUTTONS_ALT_GFX_YPOS 302
#define ED_CTRL3_BUTTON_YSIZE 22
#define ED_CTRL3_BUTTONS_XPOS 6
#define ED_CTRL3_BUTTONS_YPOS 6
+#define ED_CTRL4_BUTTON_XSIZE 22
+#define ED_CTRL4_BUTTON_YSIZE 22
+#define ED_CTRL4_BUTTONS_XPOS 6
+#define ED_CTRL4_BUTTONS_YPOS 6
#define ED_CTRL1_BUTTONS_HORIZ 4
#define ED_CTRL1_BUTTONS_VERT 4
#define ED_CTRL2_BUTTONS_VERT 2
#define ED_CTRL3_BUTTONS_HORIZ 3
#define ED_CTRL3_BUTTONS_VERT 1
+#define ED_CTRL4_BUTTONS_HORIZ 2
+#define ED_CTRL4_BUTTONS_VERT 1
#define ED_NUM_CTRL1_BUTTONS (ED_CTRL1_BUTTONS_HORIZ * ED_CTRL1_BUTTONS_VERT)
#define ED_NUM_CTRL2_BUTTONS (ED_CTRL2_BUTTONS_HORIZ * ED_CTRL2_BUTTONS_VERT)
#define ED_NUM_CTRL3_BUTTONS (ED_CTRL3_BUTTONS_HORIZ * ED_CTRL3_BUTTONS_VERT)
-#define ED_NUM_CTRL1_2_BUTTONS (ED_NUM_CTRL1_BUTTONS + ED_NUM_CTRL2_BUTTONS)
-#define ED_NUM_CTRL_BUTTONS (ED_NUM_CTRL1_BUTTONS + \
- ED_NUM_CTRL2_BUTTONS + \
- ED_NUM_CTRL3_BUTTONS)
+#define ED_NUM_CTRL4_BUTTONS (ED_CTRL4_BUTTONS_HORIZ * ED_CTRL4_BUTTONS_VERT)
+#define ED_NUM_CTRL1_2_BUTTONS (ED_NUM_CTRL1_BUTTONS + ED_NUM_CTRL2_BUTTONS)
+#define ED_NUM_CTRL1_3_BUTTONS (ED_NUM_CTRL1_2_BUTTONS + ED_NUM_CTRL3_BUTTONS)
+#define ED_NUM_CTRL_BUTTONS (ED_NUM_CTRL1_BUTTONS + \
+ ED_NUM_CTRL2_BUTTONS + \
+ ED_NUM_CTRL3_BUTTONS + \
+ ED_NUM_CTRL4_BUTTONS)
/* values for the element list */
#define ED_ELEMENTLIST_XPOS 5
#define ED_ELEMENTLIST_YSIZE 20
#define ED_ELEMENTLIST_BUTTONS_HORIZ 4
#define ED_ELEMENTLIST_BUTTONS_VERT 11
-#define ED_NUM_ELEMENTLIST_BUTTONS (ED_ELEMENTLIST_BUTTONS_HORIZ * \
+#define ED_NUM_ELEMENTLIST_BUTTONS (ED_ELEMENTLIST_BUTTONS_HORIZ * \
ED_ELEMENTLIST_BUTTONS_VERT)
/* standard distances */
#define ED_GADGET_DISTANCE 2
#define ED_GADGET_TEXT_DISTANCE (2 * ED_GADGET_DISTANCE)
-#define ED_DRAWINGAREA_TEXT_DISTANCE (ED_GADGET_TEXT_DISTANCE + \
+#define ED_DRAWINGAREA_TEXT_DISTANCE (ED_GADGET_TEXT_DISTANCE + \
MINI_TILEX / 2)
-/* values for the setting windows */
+/* values for the settings windows */
#define ED_SETTINGS_XSTART (3 * MINI_TILEX / 2)
#define ED_SETTINGS_YSTART (MINI_TILEY * 10)
-#define ED_XOFFSET_CHECKBOX (ED_CHECKBUTTON_XSIZE + \
+#define ED_XOFFSET_CHECKBOX (ED_CHECKBUTTON_XSIZE + \
2 * ED_GADGET_DISTANCE)
#define ED_SETTINGS_XOFFSET ED_XOFFSET_CHECKBOX
#define ED_SETTINGS_YOFFSET (3 * MINI_TILEY / 2)
-#define ED_SETTINGS_XPOS(n) (ED_SETTINGS_XSTART + \
- n * ED_SETTINGS_XOFFSET)
-#define ED_SETTINGS_YPOS(n) (ED_SETTINGS_YSTART + \
- n * ED_SETTINGS_YOFFSET)
+#define ED_SETTINGS_XPOS(n) (ED_SETTINGS_XSTART + \
+ (n) * ED_SETTINGS_XOFFSET)
+#define ED_SETTINGS_YPOS(n) (ED_SETTINGS_YSTART + \
+ (n) * ED_SETTINGS_YOFFSET)
#define ED_SETTINGS1_YPOS MINI_TILEY
#define ED_SETTINGS2_XPOS MINI_TILEX
/* values for counter gadgets */
#define ED_COUNTER_YSTART (ED_SETTINGS1_YPOS + 2 * TILEY)
#define ED_COUNTER_YDISTANCE (3 * MINI_TILEY)
-#define ED_COUNTER_YPOS(n) (ED_COUNTER_YSTART + \
- n * ED_COUNTER_YDISTANCE)
-#define ED_COUNTER2_YPOS(n) (ED_COUNTER_YSTART + \
- n * ED_COUNTER_YDISTANCE - 2)
+#define ED_COUNTER_YPOS(n) (ED_COUNTER_YSTART + \
+ (n) * ED_COUNTER_YDISTANCE)
+#define ED_COUNTER2_YPOS(n) (ED_COUNTER_YSTART + \
+ (n) * ED_COUNTER_YDISTANCE - 2)
/* values for element content drawing areas */
-/* amoeba content */
-#define ED_AREA_ELEM_CONTENT_XPOS ( 2 * MINI_TILEX)
-#define ED_AREA_ELEM_CONTENT_YPOS (22 * MINI_TILEY)
-
-/* yamyam content */
-#define ED_AREA_YAMYAM_CONTENT_XPOS(n) (ED_AREA_ELEM_CONTENT_XPOS + \
- 5 * (n % 4) * MINI_TILEX)
-#define ED_AREA_YAMYAM_CONTENT_YPOS(n) (ED_AREA_ELEM_CONTENT_YPOS + \
- 6 * (n / 4) * MINI_TILEY)
-
-/* custom change target */
-#define ED_AREA_ELEM_CONTENT2_YPOS (ED_SETTINGS_YPOS(2) + \
- ED_GADGET_DISTANCE)
-/* optional custom graphic */
-#define ED_AREA_ELEM_CONTENT3_YPOS (ED_SETTINGS_YPOS(1) + \
+#define ED_AREA_1X1_SETTINGS_XPOS(n) (ED_SETTINGS_XPOS(n))
+#define ED_AREA_1X1_SETTINGS_YPOS(n) (ED_SETTINGS_YPOS(n) + \
ED_GADGET_DISTANCE)
-/* custom element content */
-#define ED_AREA_ELEM_CONTENT4_XPOS (29 * MINI_TILEX)
-#define ED_AREA_ELEM_CONTENT4_YPOS (ED_SETTINGS_YPOS(12) + \
- ED_GADGET_DISTANCE - MINI_TILEY)
-/* custom change trigger element */
-#define ED_AREA_ELEM_CONTENT5_YPOS (ED_SETTINGS_YPOS(6) + \
- ED_GADGET_DISTANCE)
-/* extended custom change target */
-#define ED_AREA_ELEM_CONTENT6_XPOS (29 * MINI_TILEX)
-#define ED_AREA_ELEM_CONTENT6_YPOS (ED_SETTINGS_YPOS(10) + \
+
+#define ED_AREA_3X3_SETTINGS_XPOS(n) (ED_SETTINGS_XPOS(n))
+#define ED_AREA_3X3_SETTINGS_YPOS(n) (ED_SETTINGS_YPOS(n) + \
ED_GADGET_DISTANCE - MINI_TILEY)
-/* values for random placement background drawing area */
-#define ED_AREA_RANDOM_BACKGROUND_YPOS (31 * MINI_TILEY)
+/* yamyam content */
+#define ED_AREA_YAMYAM_CONTENT_XPOS(n) (2 * MINI_TILEX + \
+ 5 * ((n) % 4) * MINI_TILEX)
+#define ED_AREA_YAMYAM_CONTENT_YPOS(n) (17 * MINI_TILEY + \
+ 6 * ((n) / 4) * MINI_TILEY)
/* values for scrolling gadgets for drawing area */
#define ED_SCROLLBUTTON_XPOS 24
#define ED_SCROLL_LEFT_YPOS (SYSIZE - 2 * ED_SCROLLBUTTON_YSIZE)
#define ED_SCROLL_RIGHT_XPOS (SXSIZE - 2 * ED_SCROLLBUTTON_XSIZE)
#define ED_SCROLL_RIGHT_YPOS ED_SCROLL_LEFT_YPOS
-#define ED_SCROLL_HORIZONTAL_XPOS (ED_SCROLL_LEFT_XPOS + ED_SCROLLBUTTON_XSIZE)
+#define ED_SCROLL_HORIZONTAL_XPOS (ED_SCROLL_LEFT_XPOS + \
+ ED_SCROLLBUTTON_XSIZE)
#define ED_SCROLL_HORIZONTAL_YPOS ED_SCROLL_LEFT_YPOS
#define ED_SCROLL_HORIZONTAL_XSIZE (SXSIZE - 3 * ED_SCROLLBUTTON_XSIZE)
#define ED_SCROLL_HORIZONTAL_YSIZE ED_SCROLLBUTTON_YSIZE
#define ED_SCROLL_VERTICAL_XPOS ED_SCROLL_UP_XPOS
-#define ED_SCROLL_VERTICAL_YPOS (ED_SCROLL_UP_YPOS + ED_SCROLLBUTTON_YSIZE)
+#define ED_SCROLL_VERTICAL_YPOS (ED_SCROLL_UP_YPOS + \
+ ED_SCROLLBUTTON_YSIZE)
#define ED_SCROLL_VERTICAL_XSIZE ED_SCROLLBUTTON_XSIZE
#define ED_SCROLL_VERTICAL_YSIZE (SYSIZE - 4 * ED_SCROLLBUTTON_YSIZE)
#define ED_SCROLL2_UP_XPOS 85
#define ED_SCROLL2_UP_YPOS 30
#define ED_SCROLL2_DOWN_XPOS ED_SCROLL2_UP_XPOS
-#define ED_SCROLL2_DOWN_YPOS (ED_SCROLL2_UP_YPOS + \
- ED_ELEMENTLIST_BUTTONS_VERT * \
- ED_ELEMENTLIST_YSIZE - \
+#define ED_SCROLL2_DOWN_YPOS (ED_SCROLL2_UP_YPOS + \
+ ED_ELEMENTLIST_BUTTONS_VERT * \
+ ED_ELEMENTLIST_YSIZE - \
ED_SCROLLBUTTON2_YSIZE)
#define ED_SCROLL2_VERTICAL_XPOS ED_SCROLL2_UP_XPOS
-#define ED_SCROLL2_VERTICAL_YPOS (ED_SCROLL2_UP_YPOS + \
+#define ED_SCROLL2_VERTICAL_YPOS (ED_SCROLL2_UP_YPOS + \
ED_SCROLLBUTTON2_YSIZE)
#define ED_SCROLL2_VERTICAL_XSIZE ED_SCROLLBUTTON2_XSIZE
-#define ED_SCROLL2_VERTICAL_YSIZE (ED_ELEMENTLIST_BUTTONS_VERT * \
- ED_ELEMENTLIST_YSIZE - \
+#define ED_SCROLL2_VERTICAL_YSIZE (ED_ELEMENTLIST_BUTTONS_VERT * \
+ ED_ELEMENTLIST_YSIZE - \
2 * ED_SCROLLBUTTON2_YSIZE)
/* values for checkbutton gadgets */
#define ED_RADIOBUTTON_YPOS (ED_BUTTON_MINUS_YPOS + 44)
#define ED_STICKYBUTTON_YPOS (ED_BUTTON_MINUS_YPOS + 66)
-/* some positions in the editor control window */
-#define ED_BUTTON_ELEM_XPOS 6
-#define ED_BUTTON_ELEM_YPOS 30
-#define ED_BUTTON_ELEM_XSIZE 22
-#define ED_BUTTON_ELEM_YSIZE 22
+/* values for some special graphic buttons */
+#define ED_COPY_CHANGE_PAGE_XPOS 25
+#define ED_COPY_CHANGE_PAGE_YPOS 50
+#define ED_PASTE_CHANGE_PAGE_XPOS 25
+#define ED_PASTE_CHANGE_PAGE_YPOS 70
/* some values for text input, selectbox and counter gadgets */
#define ED_BUTTON_COUNT_YPOS 60
#define ED_BUTTON_MINUS_YPOS ED_BUTTON_COUNT_YPOS
#define ED_BUTTON_MINUS_XSIZE ED_BUTTON_COUNT_XSIZE
#define ED_BUTTON_MINUS_YSIZE ED_BUTTON_COUNT_YSIZE
-#define ED_BUTTON_PLUS_XPOS (ED_WIN_COUNT_XPOS + \
+#define ED_BUTTON_PLUS_XPOS (ED_WIN_COUNT_XPOS + \
ED_WIN_COUNT_XSIZE + 2)
#define ED_BUTTON_PLUS_YPOS ED_BUTTON_COUNT_YPOS
#define ED_BUTTON_PLUS_XSIZE ED_BUTTON_COUNT_XSIZE
#define ED_BUTTON_PLUS_YSIZE ED_BUTTON_COUNT_YSIZE
#define ED_SELECTBOX_XPOS ED_WIN_COUNT_XPOS
-#define ED_SELECTBOX_YPOS (ED_WIN_COUNT_YPOS + \
+#define ED_SELECTBOX_YPOS (ED_WIN_COUNT_YPOS + \
2 + ED_WIN_COUNT_YSIZE)
#define ED_SELECTBOX_XSIZE ED_WIN_COUNT_XSIZE
#define ED_SELECTBOX_YSIZE ED_WIN_COUNT_YSIZE
#define ED_SELECTBOX_BUTTON_XSIZE 14
#define ED_TEXTBUTTON_XPOS ED_WIN_COUNT_XPOS
-#define ED_TEXTBUTTON_YPOS (ED_WIN_COUNT_YPOS + \
+#define ED_TEXTBUTTON_YPOS (ED_WIN_COUNT_YPOS + \
4 * (2 + ED_WIN_COUNT_YSIZE))
#define ED_TEXTBUTTON_INACTIVE_YPOS ED_TEXTBUTTON_YPOS
#define ED_TEXTBUTTON_TAB_XPOS ED_WIN_COUNT_XPOS
-#define ED_TEXTBUTTON_TAB_YPOS (ED_WIN_COUNT_YPOS + \
+#define ED_TEXTBUTTON_TAB_YPOS (ED_WIN_COUNT_YPOS + \
2 * (2 + ED_WIN_COUNT_YSIZE))
-#define ED_TEXTBUTTON_TAB_INACTIVE_YPOS (ED_WIN_COUNT_YPOS + \
+#define ED_TEXTBUTTON_TAB_INACTIVE_YPOS (ED_WIN_COUNT_YPOS + \
3 * (2 + ED_WIN_COUNT_YSIZE))
#define ED_TEXTBUTTON_XSIZE ED_WIN_COUNT_XSIZE
#define GADGET_ID_CUSTOM_COPY_FROM (GADGET_ID_TOOLBOX_FIRST + 22)
#define GADGET_ID_CUSTOM_COPY_TO (GADGET_ID_TOOLBOX_FIRST + 23)
#define GADGET_ID_CUSTOM_EXCHANGE (GADGET_ID_TOOLBOX_FIRST + 24)
+#define GADGET_ID_CUSTOM_COPY (GADGET_ID_TOOLBOX_FIRST + 25)
+#define GADGET_ID_CUSTOM_PASTE (GADGET_ID_TOOLBOX_FIRST + 26)
/* counter button identifiers */
-#define GADGET_ID_COUNTER_FIRST (GADGET_ID_TOOLBOX_FIRST + 25)
+#define GADGET_ID_COUNTER_FIRST (GADGET_ID_TOOLBOX_FIRST + 27)
#define GADGET_ID_SELECT_LEVEL_DOWN (GADGET_ID_COUNTER_FIRST + 0)
#define GADGET_ID_SELECT_LEVEL_TEXT (GADGET_ID_COUNTER_FIRST + 1)
#define GADGET_ID_PUSH_DELAY_RND_DOWN (GADGET_ID_COUNTER_FIRST + 42)
#define GADGET_ID_PUSH_DELAY_RND_TEXT (GADGET_ID_COUNTER_FIRST + 43)
#define GADGET_ID_PUSH_DELAY_RND_UP (GADGET_ID_COUNTER_FIRST + 44)
-#define GADGET_ID_MOVE_DELAY_FIX_DOWN (GADGET_ID_COUNTER_FIRST + 45)
-#define GADGET_ID_MOVE_DELAY_FIX_TEXT (GADGET_ID_COUNTER_FIRST + 46)
-#define GADGET_ID_MOVE_DELAY_FIX_UP (GADGET_ID_COUNTER_FIRST + 47)
-#define GADGET_ID_MOVE_DELAY_RND_DOWN (GADGET_ID_COUNTER_FIRST + 48)
-#define GADGET_ID_MOVE_DELAY_RND_TEXT (GADGET_ID_COUNTER_FIRST + 49)
-#define GADGET_ID_MOVE_DELAY_RND_UP (GADGET_ID_COUNTER_FIRST + 50)
-#define GADGET_ID_CHANGE_DELAY_FIX_DOWN (GADGET_ID_COUNTER_FIRST + 51)
-#define GADGET_ID_CHANGE_DELAY_FIX_TEXT (GADGET_ID_COUNTER_FIRST + 52)
-#define GADGET_ID_CHANGE_DELAY_FIX_UP (GADGET_ID_COUNTER_FIRST + 53)
-#define GADGET_ID_CHANGE_DELAY_RND_DOWN (GADGET_ID_COUNTER_FIRST + 54)
-#define GADGET_ID_CHANGE_DELAY_RND_TEXT (GADGET_ID_COUNTER_FIRST + 55)
-#define GADGET_ID_CHANGE_DELAY_RND_UP (GADGET_ID_COUNTER_FIRST + 56)
-#define GADGET_ID_CHANGE_CONT_RND_DOWN (GADGET_ID_COUNTER_FIRST + 57)
-#define GADGET_ID_CHANGE_CONT_RND_TEXT (GADGET_ID_COUNTER_FIRST + 58)
-#define GADGET_ID_CHANGE_CONT_RND_UP (GADGET_ID_COUNTER_FIRST + 59)
+#define GADGET_ID_DROP_DELAY_FIX_DOWN (GADGET_ID_COUNTER_FIRST + 45)
+#define GADGET_ID_DROP_DELAY_FIX_TEXT (GADGET_ID_COUNTER_FIRST + 46)
+#define GADGET_ID_DROP_DELAY_FIX_UP (GADGET_ID_COUNTER_FIRST + 47)
+#define GADGET_ID_DROP_DELAY_RND_DOWN (GADGET_ID_COUNTER_FIRST + 48)
+#define GADGET_ID_DROP_DELAY_RND_TEXT (GADGET_ID_COUNTER_FIRST + 49)
+#define GADGET_ID_DROP_DELAY_RND_UP (GADGET_ID_COUNTER_FIRST + 50)
+#define GADGET_ID_MOVE_DELAY_FIX_DOWN (GADGET_ID_COUNTER_FIRST + 51)
+#define GADGET_ID_MOVE_DELAY_FIX_TEXT (GADGET_ID_COUNTER_FIRST + 52)
+#define GADGET_ID_MOVE_DELAY_FIX_UP (GADGET_ID_COUNTER_FIRST + 53)
+#define GADGET_ID_MOVE_DELAY_RND_DOWN (GADGET_ID_COUNTER_FIRST + 54)
+#define GADGET_ID_MOVE_DELAY_RND_TEXT (GADGET_ID_COUNTER_FIRST + 55)
+#define GADGET_ID_MOVE_DELAY_RND_UP (GADGET_ID_COUNTER_FIRST + 56)
+#define GADGET_ID_EXPLOSION_DELAY_DOWN (GADGET_ID_COUNTER_FIRST + 57)
+#define GADGET_ID_EXPLOSION_DELAY_TEXT (GADGET_ID_COUNTER_FIRST + 58)
+#define GADGET_ID_EXPLOSION_DELAY_UP (GADGET_ID_COUNTER_FIRST + 59)
+#define GADGET_ID_IGNITION_DELAY_DOWN (GADGET_ID_COUNTER_FIRST + 60)
+#define GADGET_ID_IGNITION_DELAY_TEXT (GADGET_ID_COUNTER_FIRST + 61)
+#define GADGET_ID_IGNITION_DELAY_UP (GADGET_ID_COUNTER_FIRST + 62)
+#define GADGET_ID_CHANGE_DELAY_FIX_DOWN (GADGET_ID_COUNTER_FIRST + 63)
+#define GADGET_ID_CHANGE_DELAY_FIX_TEXT (GADGET_ID_COUNTER_FIRST + 64)
+#define GADGET_ID_CHANGE_DELAY_FIX_UP (GADGET_ID_COUNTER_FIRST + 65)
+#define GADGET_ID_CHANGE_DELAY_RND_DOWN (GADGET_ID_COUNTER_FIRST + 66)
+#define GADGET_ID_CHANGE_DELAY_RND_TEXT (GADGET_ID_COUNTER_FIRST + 67)
+#define GADGET_ID_CHANGE_DELAY_RND_UP (GADGET_ID_COUNTER_FIRST + 68)
+#define GADGET_ID_CHANGE_CONT_RND_DOWN (GADGET_ID_COUNTER_FIRST + 69)
+#define GADGET_ID_CHANGE_CONT_RND_TEXT (GADGET_ID_COUNTER_FIRST + 70)
+#define GADGET_ID_CHANGE_CONT_RND_UP (GADGET_ID_COUNTER_FIRST + 71)
+#define GADGET_ID_GROUP_CONTENT_DOWN (GADGET_ID_COUNTER_FIRST + 72)
+#define GADGET_ID_GROUP_CONTENT_TEXT (GADGET_ID_COUNTER_FIRST + 73)
+#define GADGET_ID_GROUP_CONTENT_UP (GADGET_ID_COUNTER_FIRST + 74)
/* drawing area identifiers */
-#define GADGET_ID_DRAWING_AREA_FIRST (GADGET_ID_COUNTER_FIRST + 60)
+#define GADGET_ID_DRAWING_AREA_FIRST (GADGET_ID_COUNTER_FIRST + 75)
#define GADGET_ID_DRAWING_LEVEL (GADGET_ID_DRAWING_AREA_FIRST + 0)
#define GADGET_ID_ELEMENT_CONTENT_0 (GADGET_ID_DRAWING_AREA_FIRST + 1)
#define GADGET_ID_AMOEBA_CONTENT (GADGET_ID_DRAWING_AREA_FIRST + 9)
#define GADGET_ID_CUSTOM_GRAPHIC (GADGET_ID_DRAWING_AREA_FIRST + 10)
#define GADGET_ID_CUSTOM_CONTENT (GADGET_ID_DRAWING_AREA_FIRST + 11)
-#define GADGET_ID_CUSTOM_CHANGE_TARGET (GADGET_ID_DRAWING_AREA_FIRST + 12)
-#define GADGET_ID_CUSTOM_CHANGE_CONTENT (GADGET_ID_DRAWING_AREA_FIRST + 13)
-#define GADGET_ID_CUSTOM_CHANGE_TRIGGER (GADGET_ID_DRAWING_AREA_FIRST + 14)
-#define GADGET_ID_RANDOM_BACKGROUND (GADGET_ID_DRAWING_AREA_FIRST + 15)
+#define GADGET_ID_CUSTOM_MOVE_ENTER (GADGET_ID_DRAWING_AREA_FIRST + 12)
+#define GADGET_ID_CUSTOM_MOVE_LEAVE (GADGET_ID_DRAWING_AREA_FIRST + 13)
+#define GADGET_ID_CUSTOM_CHANGE_TARGET (GADGET_ID_DRAWING_AREA_FIRST + 14)
+#define GADGET_ID_CUSTOM_CHANGE_CONTENT (GADGET_ID_DRAWING_AREA_FIRST + 15)
+#define GADGET_ID_CUSTOM_CHANGE_TRIGGER (GADGET_ID_DRAWING_AREA_FIRST + 16)
+#define GADGET_ID_GROUP_CONTENT (GADGET_ID_DRAWING_AREA_FIRST + 17)
+#define GADGET_ID_RANDOM_BACKGROUND (GADGET_ID_DRAWING_AREA_FIRST + 18)
/* text input identifiers */
-#define GADGET_ID_TEXT_INPUT_FIRST (GADGET_ID_DRAWING_AREA_FIRST + 16)
+#define GADGET_ID_TEXT_INPUT_FIRST (GADGET_ID_DRAWING_AREA_FIRST + 19)
#define GADGET_ID_LEVEL_NAME (GADGET_ID_TEXT_INPUT_FIRST + 0)
#define GADGET_ID_LEVEL_AUTHOR (GADGET_ID_TEXT_INPUT_FIRST + 1)
/* selectbox identifiers */
#define GADGET_ID_SELECTBOX_FIRST (GADGET_ID_TEXT_AREA_FIRST + 1)
-#define GADGET_ID_CUSTOM_WALK_TO_ACTION (GADGET_ID_SELECTBOX_FIRST + 0)
-#define GADGET_ID_CUSTOM_CONSISTENCY (GADGET_ID_SELECTBOX_FIRST + 1)
-#define GADGET_ID_CUSTOM_DEADLINESS (GADGET_ID_SELECTBOX_FIRST + 2)
-#define GADGET_ID_CUSTOM_MOVE_PATTERN (GADGET_ID_SELECTBOX_FIRST + 3)
-#define GADGET_ID_CUSTOM_MOVE_DIRECTION (GADGET_ID_SELECTBOX_FIRST + 4)
-#define GADGET_ID_CUSTOM_MOVE_STEPSIZE (GADGET_ID_SELECTBOX_FIRST + 5)
-#define GADGET_ID_CUSTOM_SMASH_TARGETS (GADGET_ID_SELECTBOX_FIRST + 6)
-#define GADGET_ID_CUSTOM_SLIPPERY_TYPE (GADGET_ID_SELECTBOX_FIRST + 7)
-#define GADGET_ID_CUSTOM_ACCESS_TYPE (GADGET_ID_SELECTBOX_FIRST + 8)
-#define GADGET_ID_CUSTOM_ACCESS_LAYER (GADGET_ID_SELECTBOX_FIRST + 9)
-#define GADGET_ID_CHANGE_TIME_UNITS (GADGET_ID_SELECTBOX_FIRST + 10)
-#define GADGET_ID_CHANGE_DIRECT_ACTION (GADGET_ID_SELECTBOX_FIRST + 11)
-#define GADGET_ID_CHANGE_OTHER_ACTION (GADGET_ID_SELECTBOX_FIRST + 12)
-#define GADGET_ID_CHANGE_SIDES (GADGET_ID_SELECTBOX_FIRST + 13)
-#define GADGET_ID_CHANGE_POWER (GADGET_ID_SELECTBOX_FIRST + 14)
-#define GADGET_ID_SELECT_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 15)
+#define GADGET_ID_TIME_OR_STEPS (GADGET_ID_SELECTBOX_FIRST + 0)
+#define GADGET_ID_CUSTOM_WALK_TO_ACTION (GADGET_ID_SELECTBOX_FIRST + 1)
+#define GADGET_ID_CUSTOM_EXPLOSION_TYPE (GADGET_ID_SELECTBOX_FIRST + 2)
+#define GADGET_ID_CUSTOM_DEADLINESS (GADGET_ID_SELECTBOX_FIRST + 3)
+#define GADGET_ID_CUSTOM_MOVE_PATTERN (GADGET_ID_SELECTBOX_FIRST + 4)
+#define GADGET_ID_CUSTOM_MOVE_DIRECTION (GADGET_ID_SELECTBOX_FIRST + 5)
+#define GADGET_ID_CUSTOM_MOVE_STEPSIZE (GADGET_ID_SELECTBOX_FIRST + 6)
+#define GADGET_ID_CUSTOM_MOVE_LEAVE_TYPE (GADGET_ID_SELECTBOX_FIRST + 7)
+#define GADGET_ID_CUSTOM_SMASH_TARGETS (GADGET_ID_SELECTBOX_FIRST + 8)
+#define GADGET_ID_CUSTOM_SLIPPERY_TYPE (GADGET_ID_SELECTBOX_FIRST + 9)
+#define GADGET_ID_CUSTOM_ACCESS_TYPE (GADGET_ID_SELECTBOX_FIRST + 10)
+#define GADGET_ID_CUSTOM_ACCESS_LAYER (GADGET_ID_SELECTBOX_FIRST + 11)
+#define GADGET_ID_CUSTOM_ACCESS_PROTECTED (GADGET_ID_SELECTBOX_FIRST + 12)
+#define GADGET_ID_CUSTOM_ACCESS_DIRECTION (GADGET_ID_SELECTBOX_FIRST + 13)
+#define GADGET_ID_CHANGE_TIME_UNITS (GADGET_ID_SELECTBOX_FIRST + 14)
+#define GADGET_ID_CHANGE_DIRECT_ACTION (GADGET_ID_SELECTBOX_FIRST + 15)
+#define GADGET_ID_CHANGE_OTHER_ACTION (GADGET_ID_SELECTBOX_FIRST + 16)
+#define GADGET_ID_CHANGE_SIDE (GADGET_ID_SELECTBOX_FIRST + 17)
+#define GADGET_ID_CHANGE_PLAYER (GADGET_ID_SELECTBOX_FIRST + 18)
+#define GADGET_ID_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 19)
+#define GADGET_ID_CHANGE_REPLACE_WHEN (GADGET_ID_SELECTBOX_FIRST + 20)
+#define GADGET_ID_SELECT_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 21)
+#define GADGET_ID_GROUP_CHOICE_MODE (GADGET_ID_SELECTBOX_FIRST + 22)
/* textbutton identifiers */
-#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 16)
+#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 23)
#define GADGET_ID_PROPERTIES_INFO (GADGET_ID_TEXTBUTTON_FIRST + 0)
#define GADGET_ID_PROPERTIES_CONFIG (GADGET_ID_TEXTBUTTON_FIRST + 1)
-#define GADGET_ID_PROPERTIES_ADVANCED (GADGET_ID_TEXTBUTTON_FIRST + 2)
-#define GADGET_ID_SAVE_AS_TEMPLATE (GADGET_ID_TEXTBUTTON_FIRST + 3)
-#define GADGET_ID_ADD_CHANGE_PAGE (GADGET_ID_TEXTBUTTON_FIRST + 4)
-#define GADGET_ID_DEL_CHANGE_PAGE (GADGET_ID_TEXTBUTTON_FIRST + 5)
+#define GADGET_ID_PROPERTIES_CONFIG_1 (GADGET_ID_TEXTBUTTON_FIRST + 2)
+#define GADGET_ID_PROPERTIES_CONFIG_2 (GADGET_ID_TEXTBUTTON_FIRST + 3)
+#define GADGET_ID_PROPERTIES_CHANGE (GADGET_ID_TEXTBUTTON_FIRST + 4)
+#define GADGET_ID_SAVE_AS_TEMPLATE (GADGET_ID_TEXTBUTTON_FIRST + 5)
+#define GADGET_ID_ADD_CHANGE_PAGE (GADGET_ID_TEXTBUTTON_FIRST + 6)
+#define GADGET_ID_DEL_CHANGE_PAGE (GADGET_ID_TEXTBUTTON_FIRST + 7)
/* graphicbutton identifiers */
-#define GADGET_ID_GRAPHICBUTTON_FIRST (GADGET_ID_TEXTBUTTON_FIRST + 6)
+#define GADGET_ID_GRAPHICBUTTON_FIRST (GADGET_ID_TEXTBUTTON_FIRST + 8)
#define GADGET_ID_PREV_CHANGE_PAGE (GADGET_ID_GRAPHICBUTTON_FIRST + 0)
#define GADGET_ID_NEXT_CHANGE_PAGE (GADGET_ID_GRAPHICBUTTON_FIRST + 1)
+#define GADGET_ID_COPY_CHANGE_PAGE (GADGET_ID_GRAPHICBUTTON_FIRST + 2)
+#define GADGET_ID_PASTE_CHANGE_PAGE (GADGET_ID_GRAPHICBUTTON_FIRST + 3)
/* gadgets for scrolling of drawing area */
-#define GADGET_ID_SCROLLING_FIRST (GADGET_ID_GRAPHICBUTTON_FIRST + 2)
+#define GADGET_ID_SCROLLING_FIRST (GADGET_ID_GRAPHICBUTTON_FIRST + 4)
#define GADGET_ID_SCROLL_UP (GADGET_ID_SCROLLING_FIRST + 0)
#define GADGET_ID_SCROLL_DOWN (GADGET_ID_SCROLLING_FIRST + 1)
#define GADGET_ID_SCROLL_LIST_DOWN (GADGET_ID_SCROLLING_LIST_FIRST + 1)
#define GADGET_ID_SCROLL_LIST_VERTICAL (GADGET_ID_SCROLLING_LIST_FIRST + 2)
-/* checkbuttons for level/element properties */
+/* checkbuttons/radiobuttons for level/element properties */
#define GADGET_ID_CHECKBUTTON_FIRST (GADGET_ID_SCROLLING_LIST_FIRST + 3)
#define GADGET_ID_RANDOM_PERCENTAGE (GADGET_ID_CHECKBUTTON_FIRST + 0)
#define GADGET_ID_GRAVITY (GADGET_ID_CHECKBUTTON_FIRST + 4)
#define GADGET_ID_STICK_ELEMENT (GADGET_ID_CHECKBUTTON_FIRST + 5)
#define GADGET_ID_EM_SLIPPERY_GEMS (GADGET_ID_CHECKBUTTON_FIRST + 6)
-#define GADGET_ID_CUSTOM_EXPLODE_RESULT (GADGET_ID_CHECKBUTTON_FIRST + 7)
-#define GADGET_ID_CUSTOM_EXPLODE_FIRE (GADGET_ID_CHECKBUTTON_FIRST + 8)
-#define GADGET_ID_CUSTOM_EXPLODE_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 9)
-#define GADGET_ID_CUSTOM_EXPLODE_IMPACT (GADGET_ID_CHECKBUTTON_FIRST + 10)
-#define GADGET_ID_CUSTOM_WALK_TO_OBJECT (GADGET_ID_CHECKBUTTON_FIRST + 11)
-#define GADGET_ID_CUSTOM_DEADLY (GADGET_ID_CHECKBUTTON_FIRST + 12)
-#define GADGET_ID_CUSTOM_CAN_MOVE (GADGET_ID_CHECKBUTTON_FIRST + 13)
-#define GADGET_ID_CUSTOM_CAN_FALL (GADGET_ID_CHECKBUTTON_FIRST + 14)
-#define GADGET_ID_CUSTOM_CAN_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 15)
-#define GADGET_ID_CUSTOM_SLIPPERY (GADGET_ID_CHECKBUTTON_FIRST + 16)
-#define GADGET_ID_CUSTOM_ACCESSIBLE (GADGET_ID_CHECKBUTTON_FIRST + 17)
-#define GADGET_ID_CUSTOM_USE_GRAPHIC (GADGET_ID_CHECKBUTTON_FIRST + 18)
-#define GADGET_ID_CUSTOM_USE_TEMPLATE (GADGET_ID_CHECKBUTTON_FIRST + 19)
-#define GADGET_ID_CUSTOM_CAN_CHANGE (GADGET_ID_CHECKBUTTON_FIRST + 20)
-#define GADGET_ID_CHANGE_USE_CONTENT (GADGET_ID_CHECKBUTTON_FIRST + 21)
-#define GADGET_ID_CHANGE_USE_EXPLOSION (GADGET_ID_CHECKBUTTON_FIRST + 22)
-#define GADGET_ID_CHANGE_ONLY_COMPLETE (GADGET_ID_CHECKBUTTON_FIRST + 23)
-#define GADGET_ID_CHANGE_USE_RANDOM (GADGET_ID_CHECKBUTTON_FIRST + 24)
-#define GADGET_ID_CHANGE_DELAY (GADGET_ID_CHECKBUTTON_FIRST + 25)
-#define GADGET_ID_CHANGE_BY_DIRECT_ACT (GADGET_ID_CHECKBUTTON_FIRST + 26)
-#define GADGET_ID_CHANGE_BY_OTHER_ACT (GADGET_ID_CHECKBUTTON_FIRST + 27)
+#define GADGET_ID_USE_SPRING_BUG (GADGET_ID_CHECKBUTTON_FIRST + 7)
+#define GADGET_ID_GROW_INTO_DIGGABLE (GADGET_ID_CHECKBUTTON_FIRST + 8)
+#define GADGET_ID_BLOCK_LAST_FIELD (GADGET_ID_CHECKBUTTON_FIRST + 9)
+#define GADGET_ID_SP_BLOCK_LAST_FIELD (GADGET_ID_CHECKBUTTON_FIRST + 10)
+#define GADGET_ID_INSTANT_RELOCATION (GADGET_ID_CHECKBUTTON_FIRST + 11)
+#define GADGET_ID_CAN_PASS_TO_WALKABLE (GADGET_ID_CHECKBUTTON_FIRST + 12)
+#define GADGET_ID_CAN_FALL_INTO_ACID (GADGET_ID_CHECKBUTTON_FIRST + 13)
+#define GADGET_ID_CAN_MOVE_INTO_ACID (GADGET_ID_CHECKBUTTON_FIRST + 14)
+#define GADGET_ID_DONT_COLLIDE_WITH (GADGET_ID_CHECKBUTTON_FIRST + 15)
+#define GADGET_ID_CUSTOM_INDESTRUCTIBLE (GADGET_ID_CHECKBUTTON_FIRST + 16)
+#define GADGET_ID_CUSTOM_CAN_EXPLODE (GADGET_ID_CHECKBUTTON_FIRST + 17)
+#define GADGET_ID_CUSTOM_EXPLODE_FIRE (GADGET_ID_CHECKBUTTON_FIRST + 18)
+#define GADGET_ID_CUSTOM_EXPLODE_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 19)
+#define GADGET_ID_CUSTOM_EXPLODE_IMPACT (GADGET_ID_CHECKBUTTON_FIRST + 20)
+#define GADGET_ID_CUSTOM_WALK_TO_OBJECT (GADGET_ID_CHECKBUTTON_FIRST + 21)
+#define GADGET_ID_CUSTOM_DEADLY (GADGET_ID_CHECKBUTTON_FIRST + 22)
+#define GADGET_ID_CUSTOM_CAN_MOVE (GADGET_ID_CHECKBUTTON_FIRST + 23)
+#define GADGET_ID_CUSTOM_CAN_FALL (GADGET_ID_CHECKBUTTON_FIRST + 24)
+#define GADGET_ID_CUSTOM_CAN_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 25)
+#define GADGET_ID_CUSTOM_SLIPPERY (GADGET_ID_CHECKBUTTON_FIRST + 26)
+#define GADGET_ID_CUSTOM_ACCESSIBLE (GADGET_ID_CHECKBUTTON_FIRST + 27)
+#define GADGET_ID_CUSTOM_GRAV_REACHABLE (GADGET_ID_CHECKBUTTON_FIRST + 28)
+#define GADGET_ID_CUSTOM_USE_GRAPHIC (GADGET_ID_CHECKBUTTON_FIRST + 29)
+#define GADGET_ID_CUSTOM_USE_TEMPLATE (GADGET_ID_CHECKBUTTON_FIRST + 30)
+#define GADGET_ID_CUSTOM_CAN_CHANGE (GADGET_ID_CHECKBUTTON_FIRST + 31)
+#define GADGET_ID_CHANGE_USE_CONTENT (GADGET_ID_CHECKBUTTON_FIRST + 32)
+#define GADGET_ID_CHANGE_USE_EXPLOSION (GADGET_ID_CHECKBUTTON_FIRST + 33)
+#define GADGET_ID_CHANGE_ONLY_COMPLETE (GADGET_ID_CHECKBUTTON_FIRST + 34)
+#define GADGET_ID_CHANGE_USE_RANDOM (GADGET_ID_CHECKBUTTON_FIRST + 35)
+#define GADGET_ID_CHANGE_DELAY (GADGET_ID_CHECKBUTTON_FIRST + 36)
+#define GADGET_ID_CHANGE_BY_DIRECT_ACT (GADGET_ID_CHECKBUTTON_FIRST + 37)
+#define GADGET_ID_CHANGE_BY_OTHER_ACT (GADGET_ID_CHECKBUTTON_FIRST + 38)
/* gadgets for buttons in element list */
-#define GADGET_ID_ELEMENTLIST_FIRST (GADGET_ID_CHECKBUTTON_FIRST + 28)
+#define GADGET_ID_ELEMENTLIST_FIRST (GADGET_ID_CHECKBUTTON_FIRST + 39)
#define GADGET_ID_ELEMENTLIST_LAST (GADGET_ID_ELEMENTLIST_FIRST + \
ED_NUM_ELEMENTLIST_BUTTONS - 1)
#define ED_COUNTER_ID_CUSTOM_GEMCOUNT 12
#define ED_COUNTER_ID_PUSH_DELAY_FIX 13
#define ED_COUNTER_ID_PUSH_DELAY_RND 14
-#define ED_COUNTER_ID_MOVE_DELAY_FIX 15
-#define ED_COUNTER_ID_MOVE_DELAY_RND 16
-#define ED_COUNTER_ID_CHANGE_DELAY_FIX 17
-#define ED_COUNTER_ID_CHANGE_DELAY_RND 18
-#define ED_COUNTER_ID_CHANGE_CONT_RND 19
-
-#define ED_NUM_COUNTERBUTTONS 20
+#define ED_COUNTER_ID_DROP_DELAY_FIX 15
+#define ED_COUNTER_ID_DROP_DELAY_RND 16
+#define ED_COUNTER_ID_MOVE_DELAY_FIX 17
+#define ED_COUNTER_ID_MOVE_DELAY_RND 18
+#define ED_COUNTER_ID_EXPLOSION_DELAY 19
+#define ED_COUNTER_ID_IGNITION_DELAY 20
+#define ED_COUNTER_ID_GROUP_CONTENT 21
+#define ED_COUNTER_ID_CHANGE_DELAY_FIX 22
+#define ED_COUNTER_ID_CHANGE_DELAY_RND 23
+#define ED_COUNTER_ID_CHANGE_CONT_RND 24
+
+#define ED_NUM_COUNTERBUTTONS 25
#define ED_COUNTER_ID_LEVEL_FIRST ED_COUNTER_ID_LEVEL_XSIZE
#define ED_COUNTER_ID_LEVEL_LAST ED_COUNTER_ID_LEVEL_RANDOM
-#define ED_COUNTER_ID_CUSTOM_FIRST ED_COUNTER_ID_CUSTOM_SCORE
-#define ED_COUNTER_ID_CUSTOM_LAST ED_COUNTER_ID_MOVE_DELAY_RND
+#define ED_COUNTER_ID_CUSTOM1_FIRST ED_COUNTER_ID_CUSTOM_SCORE
+#define ED_COUNTER_ID_CUSTOM1_LAST ED_COUNTER_ID_DROP_DELAY_RND
+#define ED_COUNTER_ID_CUSTOM2_FIRST ED_COUNTER_ID_MOVE_DELAY_FIX
+#define ED_COUNTER_ID_CUSTOM2_LAST ED_COUNTER_ID_IGNITION_DELAY
+#define ED_COUNTER_ID_CUSTOM_FIRST ED_COUNTER_ID_CUSTOM1_FIRST
+#define ED_COUNTER_ID_CUSTOM_LAST ED_COUNTER_ID_CUSTOM2_LAST
#define ED_COUNTER_ID_CHANGE_FIRST ED_COUNTER_ID_CHANGE_DELAY_FIX
#define ED_COUNTER_ID_CHANGE_LAST ED_COUNTER_ID_CHANGE_CONT_RND
#define ED_TEXTAREA_ID_LEVEL_LAST ED_TEXTAREA_ID_ENVELOPE
/* values for selectbox gadgets */
-#define ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE 0
-#define ED_SELECTBOX_ID_CUSTOM_ACCESS_LAYER 1
-#define ED_SELECTBOX_ID_CUSTOM_WALK_TO_ACTION 2
-#define ED_SELECTBOX_ID_CUSTOM_MOVE_PATTERN 3
-#define ED_SELECTBOX_ID_CUSTOM_MOVE_DIRECTION 4
-#define ED_SELECTBOX_ID_CUSTOM_MOVE_STEPSIZE 5
-#define ED_SELECTBOX_ID_CUSTOM_SMASH_TARGETS 6
-#define ED_SELECTBOX_ID_CUSTOM_SLIPPERY_TYPE 7
-#define ED_SELECTBOX_ID_CUSTOM_DEADLINESS 8
-#define ED_SELECTBOX_ID_CUSTOM_CONSISTENCY 9
-#define ED_SELECTBOX_ID_CHANGE_TIME_UNITS 10
-#define ED_SELECTBOX_ID_CHANGE_DIRECT_ACTION 11
-#define ED_SELECTBOX_ID_CHANGE_OTHER_ACTION 12
-#define ED_SELECTBOX_ID_CHANGE_SIDES 13
-#define ED_SELECTBOX_ID_CHANGE_POWER 14
-#define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE 15
-
-#define ED_NUM_SELECTBOX 16
-
-#define ED_SELECTBOX_ID_CUSTOM_FIRST ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE
-#define ED_SELECTBOX_ID_CUSTOM_LAST ED_SELECTBOX_ID_CUSTOM_CONSISTENCY
+#define ED_SELECTBOX_ID_TIME_OR_STEPS 0
+#define ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE 1
+#define ED_SELECTBOX_ID_CUSTOM_ACCESS_LAYER 2
+#define ED_SELECTBOX_ID_CUSTOM_ACCESS_PROTECTED 3
+#define ED_SELECTBOX_ID_CUSTOM_ACCESS_DIRECTION 4
+#define ED_SELECTBOX_ID_CUSTOM_WALK_TO_ACTION 5
+#define ED_SELECTBOX_ID_CUSTOM_MOVE_PATTERN 6
+#define ED_SELECTBOX_ID_CUSTOM_MOVE_DIRECTION 7
+#define ED_SELECTBOX_ID_CUSTOM_MOVE_STEPSIZE 8
+#define ED_SELECTBOX_ID_CUSTOM_MOVE_LEAVE_TYPE 9
+#define ED_SELECTBOX_ID_CUSTOM_SMASH_TARGETS 10
+#define ED_SELECTBOX_ID_CUSTOM_SLIPPERY_TYPE 11
+#define ED_SELECTBOX_ID_CUSTOM_DEADLINESS 12
+#define ED_SELECTBOX_ID_CUSTOM_EXPLOSION_TYPE 13
+#define ED_SELECTBOX_ID_CHANGE_TIME_UNITS 14
+#define ED_SELECTBOX_ID_CHANGE_DIRECT_ACTION 15
+#define ED_SELECTBOX_ID_CHANGE_OTHER_ACTION 16
+#define ED_SELECTBOX_ID_CHANGE_SIDE 17
+#define ED_SELECTBOX_ID_CHANGE_PLAYER 18
+#define ED_SELECTBOX_ID_CHANGE_PAGE 19
+#define ED_SELECTBOX_ID_CHANGE_REPLACE_WHEN 20
+#define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE 21
+#define ED_SELECTBOX_ID_GROUP_CHOICE_MODE 22
+
+#define ED_NUM_SELECTBOX 23
+
+#define ED_SELECTBOX_ID_LEVEL_FIRST ED_SELECTBOX_ID_TIME_OR_STEPS
+#define ED_SELECTBOX_ID_LEVEL_LAST ED_SELECTBOX_ID_TIME_OR_STEPS
+
+#define ED_SELECTBOX_ID_CUSTOM1_FIRST ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE
+#define ED_SELECTBOX_ID_CUSTOM1_LAST ED_SELECTBOX_ID_CUSTOM_WALK_TO_ACTION
+#define ED_SELECTBOX_ID_CUSTOM2_FIRST ED_SELECTBOX_ID_CUSTOM_MOVE_PATTERN
+#define ED_SELECTBOX_ID_CUSTOM2_LAST ED_SELECTBOX_ID_CUSTOM_EXPLOSION_TYPE
+#define ED_SELECTBOX_ID_CUSTOM_FIRST ED_SELECTBOX_ID_CUSTOM1_FIRST
+#define ED_SELECTBOX_ID_CUSTOM_LAST ED_SELECTBOX_ID_CUSTOM2_LAST
#define ED_SELECTBOX_ID_CHANGE_FIRST ED_SELECTBOX_ID_CHANGE_TIME_UNITS
#define ED_SELECTBOX_ID_CHANGE_LAST ED_SELECTBOX_ID_SELECT_CHANGE_PAGE
/* values for textbutton gadgets */
#define ED_TEXTBUTTON_ID_PROPERTIES_INFO 0
#define ED_TEXTBUTTON_ID_PROPERTIES_CONFIG 1
-#define ED_TEXTBUTTON_ID_PROPERTIES_ADVANCED 2
-#define ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE 3
-#define ED_TEXTBUTTON_ID_ADD_CHANGE_PAGE 4
-#define ED_TEXTBUTTON_ID_DEL_CHANGE_PAGE 5
+#define ED_TEXTBUTTON_ID_PROPERTIES_CONFIG_1 2
+#define ED_TEXTBUTTON_ID_PROPERTIES_CONFIG_2 3
+#define ED_TEXTBUTTON_ID_PROPERTIES_CHANGE 4
+#define ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE 5
+#define ED_TEXTBUTTON_ID_ADD_CHANGE_PAGE 6
+#define ED_TEXTBUTTON_ID_DEL_CHANGE_PAGE 7
-#define ED_NUM_TEXTBUTTONS 6
+#define ED_NUM_TEXTBUTTONS 8
#define ED_TEXTBUTTON_ID_PROPERTIES_FIRST ED_TEXTBUTTON_ID_PROPERTIES_INFO
-#define ED_TEXTBUTTON_ID_PROPERTIES_LAST ED_TEXTBUTTON_ID_PROPERTIES_ADVANCED
+#define ED_TEXTBUTTON_ID_PROPERTIES_LAST ED_TEXTBUTTON_ID_PROPERTIES_CHANGE
-#define ED_TEXTBUTTON_ID_CHANGE_FIRST ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE
+#define ED_TEXTBUTTON_ID_CHANGE_FIRST ED_TEXTBUTTON_ID_ADD_CHANGE_PAGE
#define ED_TEXTBUTTON_ID_CHANGE_LAST ED_TEXTBUTTON_ID_DEL_CHANGE_PAGE
/* values for graphicbutton gadgets */
#define ED_GRAPHICBUTTON_ID_PREV_CHANGE_PAGE 0
#define ED_GRAPHICBUTTON_ID_NEXT_CHANGE_PAGE 1
+#define ED_GRAPHICBUTTON_ID_COPY_CHANGE_PAGE 2
+#define ED_GRAPHICBUTTON_ID_PASTE_CHANGE_PAGE 3
-#define ED_NUM_GRAPHICBUTTONS 2
+#define ED_NUM_GRAPHICBUTTONS 4
-#define ED_GRAPHICBUTTON_ID_CHANGE_FIRST ED_GRAPHICBUTTON_ID_PREV_CHANGE_PAGE
-#define ED_GRAPHICBUTTON_ID_CHANGE_LAST ED_GRAPHICBUTTON_ID_NEXT_CHANGE_PAGE
+#define ED_GRAPHICBUTTON_ID_CHANGE_FIRST ED_GRAPHICBUTTON_ID_PREV_CHANGE_PAGE
+#define ED_GRAPHICBUTTON_ID_CHANGE_LAST ED_GRAPHICBUTTON_ID_PASTE_CHANGE_PAGE
/* values for checkbutton gadgets */
#define ED_CHECKBUTTON_ID_DOUBLE_SPEED 0
#define ED_CHECKBUTTON_ID_RANDOM_RESTRICTED 2
#define ED_CHECKBUTTON_ID_STICK_ELEMENT 3
#define ED_CHECKBUTTON_ID_EM_SLIPPERY_GEMS 4
-#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE 5
-#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT 6
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE 7
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL 8
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH 9
-#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY 10
-#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY 11
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_RESULT 12
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE 13
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH 14
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT 15
-#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC 16
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE 17
-#define ED_CHECKBUTTON_ID_CHANGE_DELAY 18
-#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT 19
-#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT 20
-#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 21
-#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT 22
-#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 23
-#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM 24
-#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE 25
-
-#define ED_NUM_CHECKBUTTONS 26
+#define ED_CHECKBUTTON_ID_USE_SPRING_BUG 5
+#define ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE 6
+#define ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD 7
+#define ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD 8
+#define ED_CHECKBUTTON_ID_INSTANT_RELOCATION 9
+#define ED_CHECKBUTTON_ID_CAN_PASS_TO_WALKABLE 10
+#define ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID 11
+#define ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID 12
+#define ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH 13
+#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC 14
+#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE 15
+#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE 16
+#define ED_CHECKBUTTON_ID_CUSTOM_GRAV_REACHABLE 17
+#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT 18
+#define ED_CHECKBUTTON_ID_CUSTOM_INDESTRUCTIBLE 19
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE 20
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL 21
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH 22
+#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY 23
+#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY 24
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_EXPLODE 25
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE 26
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH 27
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT 28
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE 29
+#define ED_CHECKBUTTON_ID_CHANGE_DELAY 30
+#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT 31
+#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT 32
+#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 33
+#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT 34
+#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 35
+#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM 36
+
+#define ED_NUM_CHECKBUTTONS 37
#define ED_CHECKBUTTON_ID_LEVEL_FIRST ED_CHECKBUTTON_ID_DOUBLE_SPEED
#define ED_CHECKBUTTON_ID_LEVEL_LAST ED_CHECKBUTTON_ID_RANDOM_RESTRICTED
-#define ED_CHECKBUTTON_ID_CUSTOM_FIRST ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE
-#define ED_CHECKBUTTON_ID_CUSTOM_LAST ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT
+#define ED_CHECKBUTTON_ID_CUSTOM1_FIRST ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC
+#define ED_CHECKBUTTON_ID_CUSTOM1_LAST ED_CHECKBUTTON_ID_CUSTOM_INDESTRUCTIBLE
+#define ED_CHECKBUTTON_ID_CUSTOM2_FIRST ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE
+#define ED_CHECKBUTTON_ID_CUSTOM2_LAST ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT
+#define ED_CHECKBUTTON_ID_CUSTOM_FIRST ED_CHECKBUTTON_ID_CUSTOM1_FIRST
+#define ED_CHECKBUTTON_ID_CUSTOM_LAST ED_CHECKBUTTON_ID_CUSTOM2_LAST
-#define ED_CHECKBUTTON_ID_CHANGE_FIRST ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC
-#define ED_CHECKBUTTON_ID_CHANGE_LAST ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE
+#define ED_CHECKBUTTON_ID_CHANGE_FIRST ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE
+#define ED_CHECKBUTTON_ID_CHANGE_LAST ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM
/* values for radiobutton gadgets */
#define ED_RADIOBUTTON_ID_PERCENTAGE 0
#define ED_DRAWING_ID_AMOEBA_CONTENT 9
#define ED_DRAWING_ID_CUSTOM_GRAPHIC 10
#define ED_DRAWING_ID_CUSTOM_CONTENT 11
-#define ED_DRAWING_ID_CUSTOM_CHANGE_TARGET 12
-#define ED_DRAWING_ID_CUSTOM_CHANGE_CONTENT 13
-#define ED_DRAWING_ID_CUSTOM_CHANGE_TRIGGER 14
-#define ED_DRAWING_ID_RANDOM_BACKGROUND 15
+#define ED_DRAWING_ID_CUSTOM_MOVE_ENTER 12
+#define ED_DRAWING_ID_CUSTOM_MOVE_LEAVE 13
+#define ED_DRAWING_ID_CUSTOM_CHANGE_TARGET 14
+#define ED_DRAWING_ID_CUSTOM_CHANGE_CONTENT 15
+#define ED_DRAWING_ID_CUSTOM_CHANGE_TRIGGER 16
+#define ED_DRAWING_ID_GROUP_CONTENT 17
+#define ED_DRAWING_ID_RANDOM_BACKGROUND 18
-#define ED_NUM_DRAWING_AREAS 16
+#define ED_NUM_DRAWING_AREAS 19
/*
/* sub-screens in the element properties section */
#define ED_MODE_PROPERTIES_INFO ED_TEXTBUTTON_ID_PROPERTIES_INFO
#define ED_MODE_PROPERTIES_CONFIG ED_TEXTBUTTON_ID_PROPERTIES_CONFIG
-#define ED_MODE_PROPERTIES_ADVANCED ED_TEXTBUTTON_ID_PROPERTIES_ADVANCED
+#define ED_MODE_PROPERTIES_CONFIG_1 ED_TEXTBUTTON_ID_PROPERTIES_CONFIG_1
+#define ED_MODE_PROPERTIES_CONFIG_2 ED_TEXTBUTTON_ID_PROPERTIES_CONFIG_2
+#define ED_MODE_PROPERTIES_CHANGE ED_TEXTBUTTON_ID_PROPERTIES_CHANGE
/* how many steps can be cancelled */
#define NUM_UNDO_STEPS (10 + 1)
{ '\0', "copy settings from other element" },
{ '\0', "copy settings to other element" },
- { '\0', "exchange settings with other element" },
+ { '\0', "exchange element with other element" },
+
+ { '\0', "copy settings from this element" },
+ { '\0', "paste settings to this element" },
};
static int random_placement_value = 10;
static boolean custom_element_properties[NUM_ELEMENT_PROPERTIES];
static boolean custom_element_change_events[NUM_CHANGE_EVENTS];
static struct ElementChangeInfo custom_element_change;
+static struct ElementGroupInfo group_element_info;
static struct ElementInfo custom_element;
static struct
GADGET_ID_LEVEL_GEMSLIMIT_DOWN, GADGET_ID_LEVEL_GEMSLIMIT_UP,
GADGET_ID_LEVEL_GEMSLIMIT_TEXT, GADGET_ID_NONE,
&level.gems_needed,
- "number of emeralds to collect:", NULL, NULL
+ "number of gems to collect:", NULL, NULL
},
{
ED_SETTINGS_XPOS(0), ED_COUNTER_YPOS(4),
- 0, 999,
+ 0, 9999,
GADGET_ID_LEVEL_TIMELIMIT_DOWN, GADGET_ID_LEVEL_TIMELIMIT_UP,
GADGET_ID_LEVEL_TIMELIMIT_TEXT, GADGET_ID_NONE,
&level.time,
- "time available to solve level:", NULL, "(0 => no time limit)"
+ "time or step limit to solve level:", NULL, NULL
},
{
ED_SETTINGS_XPOS(0), ED_COUNTER_YPOS(5),
GADGET_ID_LEVEL_TIMESCORE_DOWN, GADGET_ID_LEVEL_TIMESCORE_UP,
GADGET_ID_LEVEL_TIMESCORE_TEXT, GADGET_ID_NONE,
&level.score[SC_TIME_BONUS],
- "score for each 10 seconds left:", NULL, NULL
+ "score for each 10 sec/steps left:", NULL, NULL
},
{
ED_SETTINGS_XPOS(0), ED_COUNTER2_YPOS(8),
NULL, NULL, NULL
},
{
- ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(6),
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(3),
MIN_ELEMENT_CONTENTS, MAX_ELEMENT_CONTENTS,
GADGET_ID_ELEMENT_CONTENT_DOWN, GADGET_ID_ELEMENT_CONTENT_UP,
GADGET_ID_ELEMENT_CONTENT_TEXT, GADGET_ID_NONE,
NULL, " ", "height",
},
- /* ---------- element settings: configure (custom elements) ------------- */
+ /* ---------- element settings: configure 1 (custom elements) ------------ */
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(3),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(6),
MIN_SCORE, MAX_SCORE,
GADGET_ID_CUSTOM_SCORE_DOWN, GADGET_ID_CUSTOM_SCORE_UP,
GADGET_ID_CUSTOM_SCORE_TEXT, GADGET_ID_NONE,
NULL, "score", " "
},
{
- -1, ED_SETTINGS_YPOS(3),
+ -1, ED_SETTINGS_YPOS(6),
MIN_COLLECT_COUNT, MAX_COLLECT_COUNT,
GADGET_ID_CUSTOM_GEMCOUNT_DOWN, GADGET_ID_CUSTOM_GEMCOUNT_UP,
GADGET_ID_CUSTOM_GEMCOUNT_TEXT, GADGET_ID_CUSTOM_SCORE_UP,
NULL, "count", NULL
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(4),
- 0, 999,
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(7),
+ 0, 255,
GADGET_ID_PUSH_DELAY_FIX_DOWN, GADGET_ID_PUSH_DELAY_FIX_UP,
GADGET_ID_PUSH_DELAY_FIX_TEXT, GADGET_ID_NONE,
&custom_element.push_delay_fixed,
NULL, "push delay", NULL
},
{
- -1, ED_SETTINGS_YPOS(4),
- 0, 999,
+ -1, ED_SETTINGS_YPOS(7),
+ 0, 255,
GADGET_ID_PUSH_DELAY_RND_DOWN, GADGET_ID_PUSH_DELAY_RND_UP,
GADGET_ID_PUSH_DELAY_RND_TEXT, GADGET_ID_PUSH_DELAY_FIX_UP,
&custom_element.push_delay_random,
NULL, "+random", NULL
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(7),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(8),
+ 0, 255,
+ GADGET_ID_DROP_DELAY_FIX_DOWN, GADGET_ID_DROP_DELAY_FIX_UP,
+ GADGET_ID_DROP_DELAY_FIX_TEXT, GADGET_ID_NONE,
+ &custom_element.drop_delay_fixed,
+ NULL, "drop delay", NULL
+ },
+ {
+ -1, ED_SETTINGS_YPOS(8),
+ 0, 255,
+ GADGET_ID_DROP_DELAY_RND_DOWN, GADGET_ID_DROP_DELAY_RND_UP,
+ GADGET_ID_DROP_DELAY_RND_TEXT, GADGET_ID_DROP_DELAY_FIX_UP,
+ &custom_element.drop_delay_random,
+ NULL, "+random", NULL
+ },
+
+ /* ---------- element settings: configure 2 (custom elements) ------------ */
+
+ {
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(5),
0, 999,
GADGET_ID_MOVE_DELAY_FIX_DOWN, GADGET_ID_MOVE_DELAY_FIX_UP,
GADGET_ID_MOVE_DELAY_FIX_TEXT, GADGET_ID_NONE,
NULL, "move delay", NULL
},
{
- -1, ED_SETTINGS_YPOS(7),
+ -1, ED_SETTINGS_YPOS(5),
0, 999,
GADGET_ID_MOVE_DELAY_RND_DOWN, GADGET_ID_MOVE_DELAY_RND_UP,
GADGET_ID_MOVE_DELAY_RND_TEXT, GADGET_ID_MOVE_DELAY_FIX_UP,
&custom_element.move_delay_random,
NULL, "+random", NULL
},
+ {
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(12),
+ 0, 255,
+ GADGET_ID_EXPLOSION_DELAY_DOWN, GADGET_ID_EXPLOSION_DELAY_UP,
+ GADGET_ID_EXPLOSION_DELAY_TEXT, GADGET_ID_NONE,
+ &custom_element.explosion_delay,
+ NULL, "explosion delay", NULL
+ },
+ {
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(13),
+ 0, 255,
+ GADGET_ID_IGNITION_DELAY_DOWN, GADGET_ID_IGNITION_DELAY_UP,
+ GADGET_ID_IGNITION_DELAY_TEXT, GADGET_ID_NONE,
+ &custom_element.ignition_delay,
+ NULL, "ignition delay", "(by fire)"
+ },
+
+ /* ---------- element settings: configure (group elements) --------------- */
+
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(5),
+ MIN_ELEMENTS_IN_GROUP, MAX_ELEMENTS_IN_GROUP,
+ GADGET_ID_GROUP_CONTENT_DOWN, GADGET_ID_GROUP_CONTENT_UP,
+ GADGET_ID_GROUP_CONTENT_TEXT, GADGET_ID_NONE,
+ &group_element_info.num_elements,
+ NULL, NULL, "number of elements in group"
+ },
/* ---------- element settings: advanced (custom elements) --------------- */
{
- ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(3),
+ ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(2),
0, 999,
GADGET_ID_CHANGE_DELAY_FIX_DOWN, GADGET_ID_CHANGE_DELAY_FIX_UP,
GADGET_ID_CHANGE_DELAY_FIX_TEXT, GADGET_ID_NONE,
NULL, "delay", NULL,
},
{
- -1, ED_SETTINGS_YPOS(3),
+ -1, ED_SETTINGS_YPOS(2),
0, 999,
GADGET_ID_CHANGE_DELAY_RND_DOWN, GADGET_ID_CHANGE_DELAY_RND_UP,
GADGET_ID_CHANGE_DELAY_RND_TEXT, GADGET_ID_CHANGE_DELAY_FIX_UP,
0, 100,
GADGET_ID_CHANGE_CONT_RND_DOWN, GADGET_ID_CHANGE_CONT_RND_UP,
GADGET_ID_CHANGE_CONT_RND_TEXT, GADGET_ID_NONE,
- &custom_element_change.random,
+ &custom_element_change.random_percentage,
NULL, "use random replace:", "%"
},
};
"Author:", "Author"
},
{
- 5 * MINI_TILEX, 5 * MINI_TILEY - ED_BORDER_SIZE,
+ 5 * MINI_TILEX - 2, 5 * MINI_TILEY - ED_BORDER_SIZE + 1,
GADGET_ID_ELEMENT_NAME,
MAX_ELEMENT_NAME_LEN - 2, /* currently 2 chars less editable */
custom_element.description,
}
};
+static struct ValueTextInfo options_time_or_steps[] =
+{
+ { 0, "seconds" },
+ { 1, "steps" },
+
+ { -1, NULL }
+};
+
static struct ValueTextInfo options_access_type[] =
{
- { EP_WALKABLE, "walk" },
- { EP_PASSABLE, "pass" },
+ { EP_WALKABLE, "walkable" },
+ { EP_PASSABLE, "passable" },
+
{ -1, NULL }
};
{ EP_ACCESSIBLE_OVER, "over" },
{ EP_ACCESSIBLE_INSIDE, "inside" },
{ EP_ACCESSIBLE_UNDER, "under" },
+
+ { -1, NULL }
+};
+
+static struct ValueTextInfo options_access_protected[] =
+{
+ { 0, "unprotected" },
+ { 1, "protected" },
+
+ { -1, NULL }
+};
+
+static struct ValueTextInfo options_access_direction[] =
+{
+ { MV_LEFT, "left" },
+ { MV_RIGHT, "right" },
+ { MV_UP, "up" },
+ { MV_DOWN, "down" },
+ { MV_LEFT | MV_UP, "left + up" },
+ { MV_LEFT | MV_DOWN, "left + down" },
+ { MV_RIGHT | MV_UP, "right + up" },
+ { MV_RIGHT | MV_DOWN, "right + down" },
+ { MV_HORIZONTAL, "horizontal" },
+ { MV_VERTICAL, "vertical" },
+ { MV_HORIZONTAL | MV_UP, "horizontal + up" },
+ { MV_HORIZONTAL | MV_DOWN, "horizontal + down" },
+ { MV_VERTICAL | MV_LEFT, "vertical + left" },
+ { MV_VERTICAL | MV_RIGHT, "vertical + right" },
+ { MV_ALL_DIRECTIONS, "all directions" },
+
{ -1, NULL }
};
{ EP_DIGGABLE, "diggable" },
{ EP_COLLECTIBLE_ONLY, "collectible" },
{ EP_DROPPABLE, "collectible & droppable" },
+ { EP_THROWABLE, "collectible & throwable" },
{ EP_PUSHABLE, "pushable" },
+
{ -1, NULL }
};
{ MV_ALONG_RIGHT_SIDE, "along right side" },
{ MV_TURNING_LEFT, "turning left" },
{ MV_TURNING_RIGHT, "turning right" },
- { MV_WHEN_PUSHED, "when pushed" },
-#if 0
+ { MV_TURNING_LEFT_RIGHT, "turning left, right" },
+ { MV_TURNING_RIGHT_LEFT, "turning right, left" },
+ { MV_TURNING_RANDOM, "turning random" },
{ MV_MAZE_RUNNER, "maze runner style" },
{ MV_MAZE_HUNTER, "maze hunter style" },
-#endif
+ { MV_WHEN_PUSHED, "when pushed" },
+ { MV_WHEN_DROPPED, "when dropped/thrown" },
+
{ -1, NULL }
};
static struct ValueTextInfo options_move_direction[] =
{
- { MV_NO_MOVING, "automatic" },
- { MV_LEFT, "left" },
- { MV_RIGHT, "right" },
- { MV_UP, "up" },
- { MV_DOWN, "down" },
+ { MV_START_AUTOMATIC, "automatic" },
+ { MV_START_LEFT, "left" },
+ { MV_START_RIGHT, "right" },
+ { MV_START_UP, "up" },
+ { MV_START_DOWN, "down" },
+ { MV_START_RANDOM, "random" },
+ { MV_START_PREVIOUS, "previous" },
+
{ -1, NULL }
};
{ 4, "normal" },
{ 8, "fast" },
{ 16, "very fast" },
+#if 1
+ { 32, "even faster" },
+#endif
+
+ { -1, NULL }
+};
+
+static struct ValueTextInfo options_move_leave_type[] =
+{
+ { LEAVE_TYPE_UNLIMITED, "leave behind" },
+ { LEAVE_TYPE_LIMITED, "change it to" },
+
{ -1, NULL }
};
{ EP_CAN_SMASH_ENEMIES, "enemies" },
#endif
{ EP_CAN_SMASH_EVERYTHING, "everything" },
+
{ -1, NULL }
};
{ SLIPPERY_ANY_RIGHT_LEFT, "right, left" },
{ SLIPPERY_ONLY_LEFT, "only left" },
{ SLIPPERY_ONLY_RIGHT, "only right" },
+
{ -1, NULL }
};
{ EP_DONT_RUN_INTO, "running into" },
{ EP_DONT_COLLIDE_WITH, "colliding with" },
{ EP_DONT_TOUCH, "touching" },
+
{ -1, NULL }
};
-static struct ValueTextInfo options_consistency[] =
+static struct ValueTextInfo options_explosion_type[] =
{
- { EP_CAN_EXPLODE_3X3, "can explode 3x3" },
- { EP_CAN_EXPLODE_1X1, "can explode 1x1" },
+ { EXPLODES_3X3, "3x3" },
+ { EXPLODES_CROSS, "3+3" },
+ { EXPLODES_1X1, "1x1" },
+#if 0
{ EP_INDESTRUCTIBLE, "indestructible" },
+#endif
+
{ -1, NULL }
};
{
{ 1, "frames" },
{ FRAMES_PER_SECOND, "seconds" },
+
{ -1, NULL }
};
static struct ValueTextInfo options_change_direct_action[] =
{
- { CE_TOUCHED_BY_PLAYER, "touched by player ..." },
- { CE_PRESSED_BY_PLAYER, "pressed by player ..." },
- { CE_PUSHED_BY_PLAYER, "pushed by player ..." },
- { CE_ENTERED_BY_PLAYER, "entered by player ..." },
- { CE_LEFT_BY_PLAYER, "left by player ..." },
- { CE_DROPPED_BY_PLAYER, "dropped by player" },
- { CE_SWITCHED, "switched ..." },
-#if 0
- { CE_COLLISION_ACTIVE, "hitting something ..." },
- { CE_COLLISION_PASSIVE, "hit by something ..." },
+ { CE_TOUCHED_BY_PLAYER, "touched by player" },
+ { CE_PRESSED_BY_PLAYER, "pressed by player" },
+ { CE_PUSHED_BY_PLAYER, "pushed by player" },
+ { CE_ENTERED_BY_PLAYER, "entered by player" },
+ { CE_LEFT_BY_PLAYER, "left by player" },
+ { CE_DROPPED_BY_PLAYER, "dropped/thrown by player" },
+ { CE_SWITCHED, "switched" },
+#if 1
+ { CE_HITTING_SOMETHING, "hitting something" },
+ { CE_HIT_BY_SOMETHING, "hit by something" },
#else
- { CE_COLLISION_ACTIVE, "collision ..." },
+ { CE_HITTING_SOMETHING, "collision" },
+#endif
+#if 1
+ { CE_BLOCKED, "blocked" },
#endif
{ CE_IMPACT, "impact (on something)" },
{ CE_SMASHED, "smashed (from above)" },
+
{ -1, NULL }
};
static struct ValueTextInfo options_change_other_action[] =
{
- { CE_OTHER_GETS_TOUCHED, "player touches ..." },
- { CE_OTHER_GETS_PRESSED, "player presses ..." },
- { CE_OTHER_GETS_PUSHED, "player pushes ..." },
- { CE_OTHER_GETS_ENTERED, "player enters ..." },
- { CE_OTHER_GETS_LEFT, "player leaves ..." },
+ { CE_OTHER_GETS_TOUCHED, "player touches" },
+ { CE_OTHER_GETS_PRESSED, "player presses" },
+ { CE_OTHER_GETS_PUSHED, "player pushes" },
+ { CE_OTHER_GETS_ENTERED, "player enters" },
+ { CE_OTHER_GETS_LEFT, "player leaves" },
{ CE_OTHER_GETS_DIGGED, "player digs" },
{ CE_OTHER_GETS_COLLECTED, "player collects" },
- { CE_OTHER_GETS_DROPPED, "player drops" },
- { CE_OTHER_IS_TOUCHING, "touching ..." },
-#if 0
- { CE_OTHER_IS_COLL_ACTIVE, "hitting ..." },
- { CE_OTHER_IS_COLL_PASSIVE, "hit by ..." },
+ { CE_OTHER_GETS_DROPPED, "player drops/throws" },
+ { CE_OTHER_IS_TOUCHING, "touching" },
+#if 1
+ { CE_OTHER_IS_HITTING, "hitting" },
+ { CE_OTHER_GETS_HIT, "hit by" },
#endif
- { CE_OTHER_IS_SWITCHING, "switch of ..." },
- { CE_OTHER_IS_CHANGING, "change of" },
+ { CE_OTHER_IS_SWITCHING, "switch of" },
+ { CE_OTHER_IS_CHANGING, "change by page of" },
{ CE_OTHER_IS_EXPLODING, "explosion of" },
+
+ { -1, NULL }
+};
+
+static struct ValueTextInfo options_change_trigger_side[] =
+{
+ { CH_SIDE_LEFT, "left" },
+ { CH_SIDE_RIGHT, "right" },
+ { CH_SIDE_TOP, "top" },
+ { CH_SIDE_BOTTOM, "bottom" },
+ { CH_SIDE_LEFT_RIGHT, "left/right" },
+ { CH_SIDE_TOP_BOTTOM, "top/bottom" },
+ { CH_SIDE_ANY, "any" },
+
{ -1, NULL }
};
-static struct ValueTextInfo options_change_sides[] =
+static struct ValueTextInfo options_change_trigger_player[] =
{
- { CH_SIDE_LEFT, "left side" },
- { CH_SIDE_RIGHT, "right side" },
- { CH_SIDE_TOP, "top side" },
- { CH_SIDE_BOTTOM, "bottom side" },
- { CH_SIDE_LEFT_RIGHT, "left/right side" },
- { CH_SIDE_TOP_BOTTOM, "top/bottom side" },
- { CH_SIDE_ANY, "any side" },
+ { CH_PLAYER_1, "1" },
+ { CH_PLAYER_2, "2" },
+ { CH_PLAYER_3, "3" },
+ { CH_PLAYER_4, "4" },
+ { CH_PLAYER_ANY, "any" },
+
+ { -1, NULL }
+};
+
+static struct ValueTextInfo options_change_trigger_page[] =
+{
+ { (1 << 0), "1" },
+ { (1 << 1), "2" },
+ { (1 << 2), "3" },
+ { (1 << 3), "4" },
+ { (1 << 4), "5" },
+ { (1 << 5), "6" },
+ { (1 << 6), "7" },
+ { (1 << 7), "8" },
+ { (1 << 8), "9" },
+ { (1 << 9), "10" },
+ { (1 << 10), "11" },
+ { (1 << 11), "12" },
+ { (1 << 12), "13" },
+ { (1 << 13), "14" },
+ { (1 << 14), "15" },
+ { (1 << 15), "16" },
+ { (1 << 16), "17" },
+ { (1 << 17), "18" },
+ { (1 << 18), "19" },
+ { (1 << 19), "20" },
+ { (1 << 20), "21" },
+ { (1 << 21), "22" },
+ { (1 << 22), "23" },
+ { (1 << 23), "24" },
+ { (1 << 24), "25" },
+ { (1 << 25), "26" },
+ { (1 << 26), "27" },
+ { (1 << 27), "28" },
+ { (1 << 28), "29" },
+ { (1 << 29), "30" },
+ { (1 << 30), "31" },
+ { (1 << 31), "32" },
+ { CH_PAGE_ANY, "any" },
+
{ -1, NULL }
};
-static struct ValueTextInfo options_change_power[] =
+static struct ValueTextInfo options_change_replace_when[] =
{
- { CP_NON_DESTRUCTIVE, "empty" },
- { CP_HALF_DESTRUCTIVE, "diggable" },
- { CP_FULL_DESTRUCTIVE, "destructible" },
+ { CP_WHEN_EMPTY, "empty" },
+ { CP_WHEN_WALKABLE, "walkable" },
+ { CP_WHEN_DIGGABLE, "diggable" },
+ { CP_WHEN_COLLECTIBLE, "collectible" },
+ { CP_WHEN_REMOVABLE, "removable" },
+ { CP_WHEN_DESTRUCTIBLE, "destructible" },
+
{ -1, NULL }
};
{ -1, NULL }
};
+static struct ValueTextInfo options_group_choice_mode[] =
+{
+ { ANIM_RANDOM, "random" },
+ { ANIM_LOOP, "loop" },
+ { ANIM_LINEAR, "linear" },
+ { ANIM_PINGPONG, "pingpong" },
+ { ANIM_PINGPONG2, "pingpong 2" },
+
+ { -1, NULL }
+};
+
static struct
{
int x, y;
char *text_left, *text_right, *infotext;
} selectbox_info[ED_NUM_SELECTBOX] =
{
- /* ---------- element settings: configure (custom elements) ------------- */
+ /* ---------- level and editor settings ---------------------------------- */
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(1),
+ -1, ED_COUNTER_YPOS(4),
+ GADGET_ID_TIME_OR_STEPS, GADGET_ID_LEVEL_TIMELIMIT_UP,
+ -1,
+ options_time_or_steps,
+ &level.use_step_counter,
+ NULL, "(0 => no limit)", "time or step limit"
+ },
+
+ /* ---------- element settings: configure 1 (custom elements) ----------- */
+
+ {
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(3),
GADGET_ID_CUSTOM_ACCESS_TYPE, GADGET_ID_NONE,
-1,
options_access_type,
&custom_element.access_type,
- "player can", NULL, "type of access to this field"
+ NULL, NULL, "type of access to this field"
},
{
- -1, ED_SETTINGS_YPOS(1),
+ -1, ED_SETTINGS_YPOS(3),
GADGET_ID_CUSTOM_ACCESS_LAYER, GADGET_ID_CUSTOM_ACCESS_TYPE,
-1,
options_access_layer,
NULL, NULL, "layer of access for this field"
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(2),
+ -1, ED_SETTINGS_YPOS(3),
+ GADGET_ID_CUSTOM_ACCESS_PROTECTED, GADGET_ID_CUSTOM_ACCESS_LAYER,
+ -1,
+ options_access_protected,
+ &custom_element.access_protected,
+ NULL, NULL, "protected access for this field"
+ },
+ {
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(4),
+ GADGET_ID_CUSTOM_ACCESS_DIRECTION, GADGET_ID_NONE,
+ -1,
+ options_access_direction,
+ &custom_element.access_direction,
+ "from", NULL, "access direction for this field"
+ },
+ {
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(5),
GADGET_ID_CUSTOM_WALK_TO_ACTION, GADGET_ID_NONE,
-1,
options_walk_to_action,
&custom_element.walk_to_action,
NULL, NULL, "diggable/collectible/pushable"
},
+
+ /* ---------- element settings: configure 2 (custom elements) ----------- */
+
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(5),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(1),
GADGET_ID_CUSTOM_MOVE_PATTERN, GADGET_ID_NONE,
-1,
options_move_pattern,
&custom_element.move_pattern,
- "can move", NULL, "element move direction"
+ "can move", NULL, "element move pattern"
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(6),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(2),
GADGET_ID_CUSTOM_MOVE_DIRECTION, GADGET_ID_NONE,
-1,
options_move_direction,
"starts moving", NULL, "initial element move direction"
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(8),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(4),
GADGET_ID_CUSTOM_MOVE_STEPSIZE, GADGET_ID_NONE,
-1,
options_move_stepsize,
"move/fall speed", NULL, "speed of element movement"
},
{
- -1, ED_SETTINGS_YPOS(9),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(3),
+ GADGET_ID_CUSTOM_MOVE_LEAVE_TYPE, GADGET_ID_NONE,
+ -1,
+ options_move_leave_type,
+ &custom_element.move_leave_type,
+ "can dig: can", ":", "leave behind or change element"
+ },
+ {
+ -1, ED_SETTINGS_YPOS(7),
GADGET_ID_CUSTOM_SMASH_TARGETS, GADGET_ID_CUSTOM_CAN_SMASH,
-1,
options_smash_targets,
"can smash", NULL, "elements that can be smashed"
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(10),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(8),
GADGET_ID_CUSTOM_SLIPPERY_TYPE, GADGET_ID_NONE,
-1,
options_slippery_type,
"slippery", NULL, "where other elements fall down"
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(11),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(9),
GADGET_ID_CUSTOM_DEADLINESS, GADGET_ID_NONE,
-1,
options_deadliness,
"deadly when", NULL, "deadliness of element"
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(12),
- GADGET_ID_CUSTOM_CONSISTENCY, GADGET_ID_NONE,
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(10),
+ GADGET_ID_CUSTOM_EXPLOSION_TYPE, GADGET_ID_NONE,
-1,
- options_consistency,
- &custom_element.consistency,
- NULL, NULL, "consistency/destructibility"
+ options_explosion_type,
+ &custom_element.explosion_type,
+ "can explode", NULL, "explosion type"
},
/* ---------- element settings: advanced (custom elements) --------------- */
{
- ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(4),
+ ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(3),
GADGET_ID_CHANGE_TIME_UNITS, GADGET_ID_NONE,
-1,
options_time_units,
"delay time given in", NULL, "delay time units for change"
},
{
- ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(5),
+ ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(4),
GADGET_ID_CHANGE_DIRECT_ACTION, GADGET_ID_NONE,
-1,
options_change_direct_action,
NULL, NULL, "type of direct action"
},
{
- ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(6),
+ ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(5),
GADGET_ID_CHANGE_OTHER_ACTION, GADGET_ID_NONE,
-1,
options_change_other_action,
&custom_element_change.other_action,
NULL, "element:", "type of other element action"
},
+ {
+ ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(6),
+ GADGET_ID_CHANGE_SIDE, GADGET_ID_NONE,
+ -1,
+ options_change_trigger_side,
+ &custom_element_change.trigger_side,
+ "at", "side", "element side that causes change"
+ },
{
ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(7),
- GADGET_ID_CHANGE_SIDES, GADGET_ID_NONE,
+ GADGET_ID_CHANGE_PLAYER, GADGET_ID_NONE,
-1,
- options_change_sides,
- &custom_element_change.sides,
- "... at", NULL, "element side that causes change"
+ options_change_trigger_player,
+ &custom_element_change.trigger_player,
+ "player:", " ", "player that causes change"
+ },
+ {
+ ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(7),
+ GADGET_ID_CHANGE_PAGE, GADGET_ID_CHANGE_PLAYER,
+ -1,
+ options_change_trigger_page,
+ &custom_element_change.trigger_page,
+ "page:", NULL, "change page that causes change"
},
{
ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(10),
- GADGET_ID_CHANGE_POWER, GADGET_ID_NONE,
+ GADGET_ID_CHANGE_REPLACE_WHEN, GADGET_ID_NONE,
-1,
- options_change_power,
- &custom_element_change.power,
+ options_change_replace_when,
+ &custom_element_change.replace_when,
"replace when", NULL, "which elements can be replaced"
},
{
3,
options_change_page,
&custom_element.current_change_page,
- NULL, NULL, "element config page"
+ NULL, NULL, "element change page"
+ },
+
+ /* ---------- element settings: configure (group elements) --------------- */
+
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(6),
+ GADGET_ID_GROUP_CHOICE_MODE, GADGET_ID_NONE,
+ -1,
+ options_group_choice_mode,
+ &group_element_info.choice_mode,
+ "choice type:", NULL, "type of group element choice"
},
};
char *text_left, *text_right, *infotext;
} textbutton_info[ED_NUM_TEXTBUTTONS] =
{
+#if 1
+ {
+ ED_SETTINGS_XPOS(0), ED_COUNTER_YPOS(1),
+ GADGET_ID_PROPERTIES_INFO, GADGET_ID_NONE,
+ 8, "Info",
+ NULL, NULL, "Show information about element"
+ },
+ {
+ ED_SETTINGS_XPOS(0) + 124, ED_COUNTER_YPOS(1),
+ GADGET_ID_PROPERTIES_CONFIG, GADGET_ID_NONE,
+ 8, "Config",
+ NULL, NULL, "Configure element properties"
+ },
+ {
+ ED_SETTINGS_XPOS(0) + 124, ED_COUNTER_YPOS(1),
+ GADGET_ID_PROPERTIES_CONFIG_1, GADGET_ID_NONE,
+ 8, "Config 1",
+ NULL, NULL, "Configure custom element properties"
+ },
+ {
+ ED_SETTINGS_XPOS(0) + 248, ED_COUNTER_YPOS(1),
+ GADGET_ID_PROPERTIES_CONFIG_2, GADGET_ID_NONE,
+ 8, "Config 2",
+ NULL, NULL, "Configure custom element properties"
+ },
+ {
+ ED_SETTINGS_XPOS(0) + 372, ED_COUNTER_YPOS(1),
+ GADGET_ID_PROPERTIES_CHANGE, GADGET_ID_NONE,
+ 8, "Change",
+ NULL, NULL, "Custom element change configuration"
+ },
+#else
{
ED_SETTINGS_XPOS(0), ED_COUNTER_YPOS(1),
GADGET_ID_PROPERTIES_INFO, GADGET_ID_NONE,
},
{
ED_SETTINGS_XPOS(0) + 332, ED_COUNTER_YPOS(1),
- GADGET_ID_PROPERTIES_ADVANCED, GADGET_ID_NONE,
+ GADGET_ID_PROPERTIES_CHANGE, GADGET_ID_NONE,
11, "Advanced",
NULL, NULL, "Advanced element configuration"
},
+#endif
{
- -1, ED_SETTINGS_YPOS(13),
+ -1, ED_SETTINGS_YPOS(2),
GADGET_ID_SAVE_AS_TEMPLATE, GADGET_ID_CUSTOM_USE_TEMPLATE,
- -1, "Save as template",
- " ", NULL, "Save current settings as new template"
+ -1, "Save",
+ " ", "As Template", "Save current settings as new template"
},
{
-1, ED_SETTINGS_YPOS(14),
- GADGET_ID_ADD_CHANGE_PAGE, GADGET_ID_NEXT_CHANGE_PAGE,
+ GADGET_ID_ADD_CHANGE_PAGE, GADGET_ID_PASTE_CHANGE_PAGE,
-1, "New",
- " ", NULL, "Add new config page"
+ NULL, NULL, "Add new change page"
},
{
-1, ED_SETTINGS_YPOS(14),
GADGET_ID_DEL_CHANGE_PAGE, GADGET_ID_ADD_CHANGE_PAGE,
-1, "Delete",
- NULL, NULL, "Delete current config page"
+ NULL, NULL, "Delete current change page"
},
};
ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(14),
ED_BUTTON_COUNT_XSIZE, ED_BUTTON_COUNT_YSIZE,
GADGET_ID_PREV_CHANGE_PAGE, GADGET_ID_NONE,
- NULL, NULL, "select previous config page"
+ NULL, NULL, "select previous change page"
},
{
ED_BUTTON_PLUS_XPOS, ED_BUTTON_COUNT_YPOS,
-1, ED_SETTINGS_YPOS(14),
ED_BUTTON_COUNT_XSIZE, ED_BUTTON_COUNT_YSIZE,
GADGET_ID_NEXT_CHANGE_PAGE, GADGET_ID_SELECT_CHANGE_PAGE,
- NULL, "config page", "select next config page"
+ NULL, "change page", "select next change page"
+ },
+ {
+ ED_COPY_CHANGE_PAGE_XPOS, ED_COPY_CHANGE_PAGE_YPOS,
+ -1, ED_SETTINGS_YPOS(14),
+ ED_BUTTON_COUNT_XSIZE, ED_BUTTON_COUNT_YSIZE,
+ GADGET_ID_COPY_CHANGE_PAGE, GADGET_ID_NEXT_CHANGE_PAGE,
+ " ", NULL, "copy settings from this change page"
+ },
+ {
+ ED_PASTE_CHANGE_PAGE_XPOS, ED_PASTE_CHANGE_PAGE_YPOS,
+ -1, ED_SETTINGS_YPOS(14),
+ ED_BUTTON_COUNT_XSIZE, ED_BUTTON_COUNT_YSIZE,
+ GADGET_ID_PASTE_CHANGE_PAGE, GADGET_ID_COPY_CHANGE_PAGE,
+ NULL, NULL, "paste settings to this change page"
},
};
/* ---------- element settings: configure (various elements) ------------- */
{
- ED_SETTINGS_XPOS(0), 0, /* set at runtime */
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(0),
GADGET_ID_STICK_ELEMENT, GADGET_ID_NONE,
&stick_element_properties_window,
NULL,
"stick this screen to edit content","stick this screen to edit content"
},
{
- ED_SETTINGS_XPOS(0), ED_COUNTER_YPOS(4),
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(1),
GADGET_ID_EM_SLIPPERY_GEMS, GADGET_ID_NONE,
&level.em_slippery_gems,
NULL,
"slip down from certain flat walls","use EM style slipping behaviour"
},
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(1),
+ GADGET_ID_USE_SPRING_BUG, GADGET_ID_NONE,
+ &level.use_spring_bug,
+ NULL,
+ "use spring pushing bug", "use odd spring pushing behaviour"
+ },
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(0),
+ GADGET_ID_GROW_INTO_DIGGABLE, GADGET_ID_NONE,
+ &level.grow_into_diggable,
+ NULL,
+ "can grow into anything diggable", "grow into more than just sand"
+ },
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(1),
+ GADGET_ID_BLOCK_LAST_FIELD, GADGET_ID_NONE,
+ &level.block_last_field,
+ NULL,
+ "block last field when moving", "player blocks last field when moving"
+ },
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(1),
+ GADGET_ID_SP_BLOCK_LAST_FIELD, GADGET_ID_NONE,
+ &level.sp_block_last_field,
+ NULL,
+ "block last field when moving", "player blocks last field when moving"
+ },
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(2),
+ GADGET_ID_INSTANT_RELOCATION, GADGET_ID_NONE,
+ &level.instant_relocation,
+ NULL,
+ "no scrolling when relocating", "player gets relocated without delay"
+ },
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(3),
+ GADGET_ID_CAN_PASS_TO_WALKABLE, GADGET_ID_NONE,
+ &level.can_pass_to_walkable,
+ NULL,
+ "can pass to walkable element", "player can pass to empty or walkable"
+ },
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(0),
+ GADGET_ID_CAN_FALL_INTO_ACID, GADGET_ID_NONE,
+ &custom_element_properties[EP_CAN_MOVE_INTO_ACID],
+ NULL,
+ "can fall into acid (with gravity)","player can fall into acid pool"
+ },
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(0),
+ GADGET_ID_CAN_MOVE_INTO_ACID, GADGET_ID_NONE,
+ &custom_element_properties[EP_CAN_MOVE_INTO_ACID],
+ NULL,
+ "can move into acid", "element can move into acid pool"
+ },
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(1),
+ GADGET_ID_DONT_COLLIDE_WITH, GADGET_ID_NONE,
+ &custom_element_properties[EP_DONT_COLLIDE_WITH],
+ NULL,
+ "deadly when colliding with", "element is deadly when hitting player"
+ },
- /* ---------- element settings: configure (custom elements) ------------- */
+ /* ---------- element settings: configure 1 (custom elements) ----------- */
{
ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(1),
+ GADGET_ID_CUSTOM_USE_GRAPHIC, GADGET_ID_NONE,
+ &custom_element.use_gfx_element,
+#if 0
+ NULL, "use graphic/sound of element:", "use existing graphic and sound"
+#else
+ NULL, "use graphic of element:", "use existing element graphic"
+#endif
+ },
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(2),
+ GADGET_ID_CUSTOM_USE_TEMPLATE, GADGET_ID_NONE,
+ &level.use_custom_template,
+ NULL, "use template", "use template for custom properties"
+ },
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(3),
GADGET_ID_CUSTOM_ACCESSIBLE, GADGET_ID_NONE,
&custom_element_properties[EP_ACCESSIBLE],
NULL, NULL, "player can walk to or pass this field"
},
{
- ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(2),
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(10),
+ GADGET_ID_CUSTOM_GRAV_REACHABLE, GADGET_ID_NONE,
+ &custom_element_properties[EP_GRAVITY_REACHABLE],
+ NULL, "reachable despite gravity", "player can walk/dig despite gravity"
+ },
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(5),
GADGET_ID_CUSTOM_WALK_TO_OBJECT, GADGET_ID_NONE,
&custom_element_properties[EP_WALK_TO_OBJECT],
NULL, NULL, "player can dig/collect/push element"
},
{
- ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(5),
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(9),
+ GADGET_ID_CUSTOM_INDESTRUCTIBLE, GADGET_ID_NONE,
+ &custom_element_properties[EP_INDESTRUCTIBLE],
+ NULL, "indestructible", "element is indestructible"
+ },
+
+ /* ---------- element settings: configure 2 (custom elements) ----------- */
+
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(1),
GADGET_ID_CUSTOM_CAN_MOVE, GADGET_ID_NONE,
&custom_element_properties[EP_CAN_MOVE],
- NULL, NULL, "element can move in some direction"
+ NULL, NULL, "element can move with some pattern"
},
{
- ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(9),
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(7),
GADGET_ID_CUSTOM_CAN_FALL, GADGET_ID_NONE,
&custom_element_properties[EP_CAN_FALL],
NULL, "can fall", "element can fall down"
},
{
- -1, ED_SETTINGS_YPOS(9),
+ -1, ED_SETTINGS_YPOS(7),
GADGET_ID_CUSTOM_CAN_SMASH, GADGET_ID_CUSTOM_CAN_FALL,
&custom_element_properties[EP_CAN_SMASH],
" ", NULL, "element can smash other elements"
},
{
- ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(10),
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(8),
GADGET_ID_CUSTOM_SLIPPERY, GADGET_ID_NONE,
&custom_element_properties[EP_SLIPPERY],
NULL, NULL, "other elements can fall down from it"
},
{
- ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(11),
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(9),
GADGET_ID_CUSTOM_DEADLY, GADGET_ID_NONE,
&custom_element_properties[EP_DEADLY],
NULL, NULL, "element can kill the player"
},
{
- ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(12),
- GADGET_ID_CUSTOM_EXPLODE_RESULT, GADGET_ID_NONE,
- &custom_element_properties[EP_EXPLODE_RESULT],
- NULL, NULL, "set consistency/destructibility"
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(10),
+ GADGET_ID_CUSTOM_CAN_EXPLODE, GADGET_ID_NONE,
+ &custom_element_properties[EP_CAN_EXPLODE],
+ NULL, NULL, "element can explode"
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(13),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(11),
GADGET_ID_CUSTOM_EXPLODE_FIRE, GADGET_ID_NONE,
- &custom_element.can_explode_by_fire,
+ &custom_element_properties[EP_EXPLODES_BY_FIRE],
NULL, "by fire", "element can explode by fire/explosion"
},
{
- -1, ED_SETTINGS_YPOS(13),
+ -1, ED_SETTINGS_YPOS(11),
GADGET_ID_CUSTOM_EXPLODE_SMASH, GADGET_ID_CUSTOM_EXPLODE_FIRE,
- &custom_element.can_explode_smashed,
+ &custom_element_properties[EP_EXPLODES_SMASHED],
" ", "smashed", "element can explode when smashed"
},
{
- -1, ED_SETTINGS_YPOS(13),
+ -1, ED_SETTINGS_YPOS(11),
GADGET_ID_CUSTOM_EXPLODE_IMPACT, GADGET_ID_CUSTOM_EXPLODE_SMASH,
- &custom_element.can_explode_impact,
+ &custom_element_properties[EP_EXPLODES_IMPACT],
" ", "impact", "element can explode on impact"
},
{
ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(1),
- GADGET_ID_CUSTOM_USE_GRAPHIC, GADGET_ID_NONE,
- &custom_element.use_gfx_element,
- NULL, "use graphic of element:", "use graphic for custom element"
- },
- {
- ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(2),
GADGET_ID_CUSTOM_CAN_CHANGE, GADGET_ID_NONE,
&custom_element_change.can_change,
NULL, "element changes to:", "element can change to other element"
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(3),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(2),
GADGET_ID_CHANGE_DELAY, GADGET_ID_NONE,
&custom_element_change_events[CE_DELAY],
NULL, NULL, "element changes after delay"
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(5),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(4),
GADGET_ID_CHANGE_BY_DIRECT_ACT, GADGET_ID_NONE,
&custom_element_change_events[CE_BY_DIRECT_ACTION],
NULL, NULL, "element changes by direct action"
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(6),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(5),
GADGET_ID_CHANGE_BY_OTHER_ACT, GADGET_ID_NONE,
&custom_element_change_events[CE_BY_OTHER_ACTION],
NULL, NULL, "element changes by other element"
{
ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(9),
GADGET_ID_CHANGE_USE_CONTENT, GADGET_ID_NONE,
- &custom_element_change.use_content,
+ &custom_element_change.use_target_content,
NULL, "use extended change target:","element changes to more elements"
},
{
ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(11),
GADGET_ID_CHANGE_ONLY_COMPLETE, GADGET_ID_NONE,
- &custom_element_change.only_complete,
+ &custom_element_change.only_if_complete,
NULL, "replace all or nothing", "only replace when all can be changed"
},
{
ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(12),
GADGET_ID_CHANGE_USE_RANDOM, GADGET_ID_NONE,
- &custom_element_change.use_random_change,
+ &custom_element_change.use_random_replace,
NULL, NULL, "use percentage for random replace"
},
- {
- ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(13),
- GADGET_ID_CUSTOM_USE_TEMPLATE, GADGET_ID_NONE,
- &level.use_custom_template,
- NULL, "use template", "use template for custom properties"
- },
};
static struct
/* ---------- amoeba content --------------------------------------------- */
{
- ED_AREA_ELEM_CONTENT_XPOS, ED_AREA_ELEM_CONTENT_YPOS,
+ ED_AREA_1X1_SETTINGS_XPOS(0), ED_AREA_1X1_SETTINGS_YPOS(3),
1, 1,
GADGET_ID_AMOEBA_CONTENT, GADGET_ID_NONE,
- NULL, "content of amoeba", NULL
+ "content:", NULL, NULL
},
+ /* ---------- element settings: configure 1 (custom elements) ----------- */
+
/* ---------- custom graphic --------------------------------------------- */
{
- -1, ED_AREA_ELEM_CONTENT3_YPOS,
+ -1, ED_AREA_1X1_SETTINGS_YPOS(1),
1, 1,
GADGET_ID_CUSTOM_GRAPHIC, GADGET_ID_CUSTOM_USE_GRAPHIC,
NULL, NULL, NULL
},
+ /* ---------- element settings: configure 2 (custom elements) ----------- */
+
/* ---------- custom content (when exploding) ---------------------------- */
{
- ED_AREA_ELEM_CONTENT4_XPOS, ED_AREA_ELEM_CONTENT4_YPOS,
+ -1, ED_AREA_3X3_SETTINGS_YPOS(10),
3, 3,
GADGET_ID_CUSTOM_CONTENT, GADGET_ID_NONE, /* align three rows */
"content:", NULL, NULL
},
+ /* ---------- custom enter and leave element (when moving) --------------- */
+
+ {
+ ED_AREA_1X1_SETTINGS_XPOS(1), ED_AREA_1X1_SETTINGS_YPOS(3),
+ 1, 1,
+ GADGET_ID_CUSTOM_MOVE_ENTER, GADGET_ID_NONE,
+ "can dig:", " ", NULL
+ },
+ {
+ -1, ED_AREA_1X1_SETTINGS_YPOS(3),
+ 1, 1,
+ GADGET_ID_CUSTOM_MOVE_LEAVE, GADGET_ID_CUSTOM_MOVE_LEAVE_TYPE,
+ NULL, NULL, NULL
+ },
+
+ /* ---------- element settings: advanced (custom elements) --------------- */
+
/* ---------- custom change target --------------------------------------- */
{
- -1, ED_AREA_ELEM_CONTENT2_YPOS,
+ -1, ED_AREA_1X1_SETTINGS_YPOS(1),
1, 1,
GADGET_ID_CUSTOM_CHANGE_TARGET, GADGET_ID_CUSTOM_CAN_CHANGE,
NULL, "after/when:", NULL
/* ---------- custom change content (extended change target) ------------- */
{
- ED_AREA_ELEM_CONTENT6_XPOS, ED_AREA_ELEM_CONTENT6_YPOS,
+ -1, ED_AREA_3X3_SETTINGS_YPOS(10),
3, 3,
GADGET_ID_CUSTOM_CHANGE_CONTENT, GADGET_ID_NONE, /* align three rows */
NULL, NULL, NULL
/* ---------- custom change trigger (element causing change) ------------- */
{
- -1, ED_AREA_ELEM_CONTENT5_YPOS,
+ -1, ED_AREA_1X1_SETTINGS_YPOS(5),
1, 1,
GADGET_ID_CUSTOM_CHANGE_TRIGGER, GADGET_ID_CHANGE_OTHER_ACTION,
NULL, NULL, NULL
},
+ /* ---------- group element content -------------------------------------- */
+
+ {
+ ED_AREA_1X1_SETTINGS_XPOS(0), ED_AREA_1X1_SETTINGS_YPOS(4),
+ MAX_ELEMENTS_IN_GROUP, 1,
+ GADGET_ID_GROUP_CONTENT, GADGET_ID_NONE,
+ "content:", NULL, NULL
+ },
+
/* ---------- random background (for random painting) -------------------- */
{
- -1, ED_AREA_RANDOM_BACKGROUND_YPOS,
+ -1, ED_SETTINGS_YPOS(14),
1, 1,
GADGET_ID_RANDOM_BACKGROUND, GADGET_ID_RANDOM_RESTRICTED,
NULL, NULL, NULL
static void ModifyEditorCounter(int, int);
static void ModifyEditorCounterLimits(int, int, int);
static void ModifyEditorSelectbox(int, int);
+static void ModifyEditorDrawingArea(int, int, int);
static void ModifyEditorElementList();
static void RedrawDrawingElements();
static void DrawDrawingWindow();
static void DrawLevelInfoWindow();
static void DrawPropertiesWindow();
static void UpdateCustomElementGraphicGadgets();
-static boolean checkPropertiesConfig();
+static boolean checkPropertiesConfig(int);
static void CopyLevelToUndoBuffer(int);
static void HandleDrawingAreas(struct GadgetInfo *);
static void HandleCounterButtons(struct GadgetInfo *);
EL_BD_FIREFLY,
EL_MOLE_LEFT,
-#if 0
- EL_MAZE_RUNNER,
-#else
EL_EMPTY,
-#endif
EL_MOLE_RIGHT,
EL_PACMAN,
EL_SOKOBAN_OBJECT,
EL_SOKOBAN_FIELD_EMPTY,
EL_SOKOBAN_FIELD_FULL,
- EL_STEELWALL,
+ EL_SOKOBAN_FIELD_PLAYER,
};
static int *editor_hl_sokoban_ptr = editor_hl_sokoban;
static int *editor_el_sokoban_ptr = editor_el_sokoban;
static int num_editor_hl_custom_more = SIZEOF_ARRAY_INT(editor_hl_custom_more);
static int num_editor_el_custom_more = SIZEOF_ARRAY_INT(editor_el_custom_more);
+static int editor_hl_custom_special[] =
+{
+};
+
+static int editor_el_custom_special[] =
+{
+ EL_TRIGGER_ELEMENT,
+ EL_TRIGGER_PLAYER,
+ EL_EMPTY,
+ EL_EMPTY
+};
+static int *editor_hl_custom_special_ptr = editor_hl_custom_special;
+static int *editor_el_custom_special_ptr = editor_el_custom_special;
+static int num_editor_hl_custom_special = SIZEOF_ARRAY_INT(editor_hl_custom_special);
+static int num_editor_el_custom_special = SIZEOF_ARRAY_INT(editor_el_custom_special);
+
+static int editor_hl_group[] =
+{
+ EL_CHAR('G'),
+ EL_CHAR('R'),
+ EL_CHAR('O'),
+ EL_CHAR('U'),
+
+ EL_CHAR('P'),
+ EL_CHAR(' '),
+ EL_CHAR(' '),
+ EL_CHAR(' '),
+
+ EL_CHAR('E'),
+ EL_CHAR('L'),
+ EL_CHAR('E'),
+ EL_CHAR('M'),
+
+ EL_CHAR('E'),
+ EL_CHAR('N'),
+ EL_CHAR('T'),
+ EL_CHAR('S'),
+};
+
+static int editor_el_group[] =
+{
+ EL_GROUP_START + 0,
+ EL_GROUP_START + 1,
+ EL_GROUP_START + 2,
+ EL_GROUP_START + 3,
+
+ EL_GROUP_START + 4,
+ EL_GROUP_START + 5,
+ EL_GROUP_START + 6,
+ EL_GROUP_START + 7,
+
+ EL_GROUP_START + 8,
+ EL_GROUP_START + 9,
+ EL_GROUP_START + 10,
+ EL_GROUP_START + 11,
+
+ EL_GROUP_START + 12,
+ EL_GROUP_START + 13,
+ EL_GROUP_START + 14,
+ EL_GROUP_START + 15
+};
+static int *editor_hl_group_ptr = editor_hl_group;
+static int *editor_el_group_ptr = editor_el_group;
+static int num_editor_hl_group = SIZEOF_ARRAY_INT(editor_hl_group);
+static int num_editor_el_group = SIZEOF_ARRAY_INT(editor_el_group);
+
+static int editor_hl_group_more[] =
+{
+};
+
+static int editor_el_group_more[] =
+{
+ EL_GROUP_START + 16,
+ EL_GROUP_START + 17,
+ EL_GROUP_START + 18,
+ EL_GROUP_START + 19,
+
+ EL_GROUP_START + 20,
+ EL_GROUP_START + 21,
+ EL_GROUP_START + 22,
+ EL_GROUP_START + 23,
+
+ EL_GROUP_START + 24,
+ EL_GROUP_START + 25,
+ EL_GROUP_START + 26,
+ EL_GROUP_START + 27,
+
+ EL_GROUP_START + 28,
+ EL_GROUP_START + 29,
+ EL_GROUP_START + 30,
+ EL_GROUP_START + 31
+};
+static int *editor_hl_group_more_ptr = editor_hl_group_more;
+static int *editor_el_group_more_ptr = editor_el_group_more;
+static int num_editor_hl_group_more = SIZEOF_ARRAY_INT(editor_hl_group_more);
+static int num_editor_el_group_more = SIZEOF_ARRAY_INT(editor_el_group_more);
+
static int editor_hl_user_defined[] =
{
EL_CHAR('U'),
&editor_hl_custom_more_ptr, &num_editor_hl_custom_more,
&editor_el_custom_more_ptr, &num_editor_el_custom_more
},
+ {
+ &setup.editor.el_custom,
+ &editor_hl_custom_special_ptr, &num_editor_hl_custom_special,
+ &editor_el_custom_special_ptr, &num_editor_el_custom_special
+ },
+ {
+ &setup.editor.el_custom,
+ &editor_hl_group_ptr, &num_editor_hl_group,
+ &editor_el_group_ptr, &num_editor_el_group
+ },
+ {
+ &setup.editor.el_custom_more,
+ &editor_hl_group_more_ptr, &num_editor_hl_group_more,
+ &editor_el_group_more_ptr, &num_editor_el_group_more
+ },
{
&setup.editor.el_user_defined,
&editor_hl_user_defined_ptr, &num_editor_hl_user_defined,
}
};
+#if 0
+
+static struct
+{
+ short element;
+ short element_mapped;
+}
+forum_sketch_element_mapping[] =
+{
+ { EL_WALL_SLIPPERY, EL_WALL },
+ { EL_EXPANDABLE_WALL, EL_WALL },
+ { EL_EXPANDABLE_WALL_HORIZONTAL, EL_WALL },
+ { EL_EXPANDABLE_WALL_VERTICAL, EL_WALL },
+ { EL_EXPANDABLE_WALL_ANY, EL_WALL },
+ { EL_WALL_EMERALD, EL_WALL },
+ { EL_WALL_DIAMOND, EL_WALL },
+ { EL_WALL_BD_DIAMOND, EL_WALL },
+ { EL_WALL_EMERALD_YELLOW, EL_WALL },
+ { EL_WALL_EMERALD_RED, EL_WALL },
+ { EL_WALL_EMERALD_PURPLE, EL_WALL },
+ { EL_ACID_POOL_TOPLEFT, EL_WALL },
+ { EL_ACID_POOL_TOPRIGHT, EL_WALL },
+ { EL_ACID_POOL_BOTTOMLEFT, EL_WALL },
+ { EL_ACID_POOL_BOTTOM, EL_WALL },
+ { EL_ACID_POOL_BOTTOMRIGHT, EL_WALL },
+ { EL_BD_WALL, EL_WALL },
+
+ { EL_BD_ROCK, EL_ROCK },
+
+ { EL_SP_ZONK, EL_ROCK },
+ { EL_SP_BASE, EL_SAND },
+ { EL_SP_MURPHY, EL_PLAYER_1 },
+ { EL_SP_INFOTRON, EL_EMERALD },
+ { EL_SP_HARDWARE_GRAY, EL_STEELWALL },
+ { EL_SP_EXIT_CLOSED, EL_EXIT_OPEN },
+ { EL_SP_DISK_ORANGE, EL_BOMB },
+ { EL_SP_DISK_RED, EL_BOMB },
+ { EL_SP_DISK_YELLOW, EL_BOMB },
+ { EL_SP_PORT_RIGHT, EL_GATE_1_GRAY },
+ { EL_SP_PORT_DOWN, EL_GATE_1_GRAY },
+ { EL_SP_PORT_LEFT, EL_GATE_1_GRAY },
+ { EL_SP_PORT_UP, EL_GATE_1_GRAY },
+ { EL_SP_GRAVITY_PORT_RIGHT, EL_GATE_1_GRAY },
+ { EL_SP_GRAVITY_PORT_DOWN, EL_GATE_1_GRAY },
+ { EL_SP_GRAVITY_PORT_LEFT, EL_GATE_1_GRAY },
+ { EL_SP_GRAVITY_PORT_UP, EL_GATE_1_GRAY },
+ { EL_SP_PORT_VERTICAL, EL_GATE_1_GRAY },
+ { EL_SP_PORT_HORIZONTAL, EL_GATE_1_GRAY },
+ { EL_SP_PORT_ANY, EL_GATE_1_GRAY },
+ { EL_SP_SNIKSNAK, EL_BUG },
+ { EL_SP_ELECTRON, EL_SPACESHIP },
+ { EL_SP_CHIP_SINGLE, EL_WALL },
+ { EL_SP_CHIP_LEFT, EL_WALL },
+ { EL_SP_CHIP_RIGHT, EL_WALL },
+ { EL_SP_CHIP_TOP, EL_WALL },
+ { EL_SP_CHIP_BOTTOM, EL_WALL },
+ { EL_SP_HARDWARE_BASE_1, EL_STEELWALL },
+ { EL_SP_HARDWARE_GREEN, EL_STEELWALL },
+ { EL_SP_HARDWARE_BLUE, EL_STEELWALL },
+ { EL_SP_HARDWARE_RED, EL_STEELWALL },
+ { EL_SP_HARDWARE_YELLOW, EL_STEELWALL },
+ { EL_SP_HARDWARE_BASE_2, EL_STEELWALL },
+ { EL_SP_HARDWARE_BASE_3, EL_STEELWALL },
+ { EL_SP_HARDWARE_BASE_3, EL_STEELWALL },
+ { EL_SP_HARDWARE_BASE_4, EL_STEELWALL },
+ { EL_SP_HARDWARE_BASE_5, EL_STEELWALL },
+ { EL_SP_HARDWARE_BASE_6, EL_STEELWALL },
+
+ { EL_STEELWALL_SLIPPERY, EL_STEELWALL },
+
+ { EL_EXIT_CLOSED, EL_EXIT_OPEN },
+
+ { EL_DIAMOND, EL_EMERALD },
+ { EL_BD_DIAMOND, EL_EMERALD },
+ { EL_EMERALD_YELLOW, EL_EMERALD },
+ { EL_EMERALD_RED, EL_EMERALD },
+ { EL_EMERALD_PURPLE, EL_EMERALD },
+
+ { EL_AMOEBA_DEAD, EL_AMOEBA },
+ { EL_AMOEBA_DROP, EL_AMOEBA },
+ { EL_AMOEBA_WET, EL_AMOEBA },
+ { EL_AMOEBA_DRY, EL_AMOEBA },
+ { EL_AMOEBA_FULL, EL_AMOEBA },
+ { EL_BD_AMOEBA, EL_AMOEBA },
+ { EL_AMOEBA_TO_DIAMOND, EL_AMOEBA },
+
+ { EL_DYNAMITE_ACTIVE, EL_DYNAMITE },
+
+ { EL_GATE_2_GRAY, EL_GATE_1_GRAY },
+ { EL_GATE_3_GRAY, EL_GATE_1_GRAY },
+ { EL_GATE_4_GRAY, EL_GATE_1_GRAY },
+
+ { EL_EM_KEY_1, EL_KEY_1 },
+ { EL_EM_KEY_2, EL_KEY_2 },
+ { EL_EM_KEY_3, EL_KEY_3 },
+ { EL_EM_KEY_4, EL_KEY_4 },
+
+ { EL_EM_GATE_1, EL_GATE_1 },
+ { EL_EM_GATE_2, EL_GATE_2 },
+ { EL_EM_GATE_3, EL_GATE_3 },
+ { EL_EM_GATE_4, EL_GATE_4 },
+
+ { EL_EM_GATE_1_GRAY, EL_GATE_1_GRAY },
+ { EL_EM_GATE_2_GRAY, EL_GATE_1_GRAY },
+ { EL_EM_GATE_3_GRAY, EL_GATE_1_GRAY },
+ { EL_EM_GATE_4_GRAY, EL_GATE_1_GRAY },
+
+ { EL_INVISIBLE_SAND, EL_EMPTY },
+ { EL_INVISIBLE_WALL, EL_EMPTY },
+ { EL_INVISIBLE_STEELWALL, EL_EMPTY },
+
+ { EL_PACMAN, EL_YAMYAM },
+ { EL_DARK_YAMYAM, EL_YAMYAM },
+
+ { EL_BD_MAGIC_WALL, EL_MAGIC_WALL },
+
+ { EL_DYNABOMB_INCREASE_NUMBER, EL_BOMB },
+ { EL_DYNABOMB_INCREASE_SIZE, EL_BOMB },
+ { EL_DYNABOMB_INCREASE_POWER, EL_BOMB },
+ { EL_BLACK_ORB, EL_BOMB },
+ { EL_DX_SUPABOMB, EL_BOMB },
+
+ { EL_SOKOBAN_OBJECT, EL_KEY_1 },
+ { EL_SOKOBAN_FIELD_EMPTY, EL_GATE_1_GRAY },
+ { EL_SOKOBAN_FIELD_FULL, EL_GATE_1 },
+ { EL_SOKOBAN_FIELD_PLAYER, EL_PLAYER_1 },
+
+ { EL_BD_BUTTERFLY_RIGHT, EL_BD_BUTTERFLY },
+ { EL_BD_BUTTERFLY_UP, EL_BD_BUTTERFLY },
+ { EL_BD_BUTTERFLY_LEFT, EL_BD_BUTTERFLY },
+ { EL_BD_BUTTERFLY_DOWN, EL_BD_BUTTERFLY },
+
+ { EL_BD_FIREFLY_RIGHT, EL_BD_FIREFLY },
+ { EL_BD_FIREFLY_UP, EL_BD_FIREFLY },
+ { EL_BD_FIREFLY_LEFT, EL_BD_FIREFLY },
+ { EL_BD_FIREFLY_DOWN, EL_BD_FIREFLY },
+
+ { EL_PLAYER_2, EL_PLAYER_1 },
+ { EL_PLAYER_3, EL_PLAYER_1 },
+ { EL_PLAYER_4, EL_PLAYER_1 },
+
+ { EL_BUG_RIGHT, EL_BUG },
+ { EL_BUG_UP, EL_BUG },
+ { EL_BUG_LEFT, EL_BUG },
+ { EL_BUG_DOWN, EL_BUG },
+
+ { EL_SPACESHIP_RIGHT, EL_SPACESHIP },
+ { EL_SPACESHIP_UP, EL_SPACESHIP },
+ { EL_SPACESHIP_LEFT, EL_SPACESHIP },
+ { EL_SPACESHIP_DOWN, EL_SPACESHIP },
+
+ { EL_PACMAN_RIGHT, EL_YAMYAM },
+ { EL_PACMAN_UP, EL_YAMYAM },
+ { EL_PACMAN_LEFT, EL_YAMYAM },
+ { EL_PACMAN_DOWN, EL_YAMYAM },
+
+ { -1, -1 }
+};
+
+static struct
+{
+ short element;
+ char *element_string;
+}
+forum_sketch_element_strings[] =
+{
+ { EL_PLAYER_1, "p" },
+ { EL_EMPTY, "_" },
+ { EL_SAND, "s" },
+ { EL_ROCK, "b" },
+ { EL_EMERALD, "e" },
+ { EL_BUG, "u" },
+ { EL_SPACESHIP, "h" },
+ { EL_BD_FIREFLY, "f" },
+ { EL_BD_BUTTERFLY, "b" },
+ { EL_AMOEBA, "a" },
+ { EL_YAMYAM, "y" },
+ { EL_WALL, "w" },
+ { EL_STEELWALL, "t" },
+ { EL_MAGIC_WALL, "m" },
+ { EL_EXIT_OPEN, "x" },
+ { EL_DYNAMITE, "d" },
+ { EL_KEY_1, "1" },
+ { EL_KEY_2, "2" },
+ { EL_KEY_3, "3" },
+ { EL_KEY_4, "4" },
+ { EL_GATE_1, "5" },
+ { EL_GATE_2, "6" },
+ { EL_GATE_3, "7" },
+ { EL_GATE_4, "8" },
+ { EL_GATE_1_GRAY, "9" },
+ { EL_BOMB, "@" },
+ { EL_ROBOT, "r" },
+ { EL_ROBOT_WHEEL, "0" },
+ { EL_NUT, "n" },
+ { EL_CUSTOM_1, "c" },
+ { EL_CHAR_QUESTION, "?" },
+
+ { -1, NULL }
+};
+
+#endif
+
/*
-----------------------------------------------------------------------------
(input ? IMG_EDITOR_ELEMENT_BORDER_INPUT : IMG_EDITOR_ELEMENT_BORDER);
Bitmap *src_bitmap;
int src_x, src_y;
- int num_mini_tilex = width / MINI_TILEX + 1;
- int num_mini_tiley = width / MINI_TILEY + 1;
+ int num_mini_tilex = width / MINI_TILEX + 1;
+ int num_mini_tiley = height / MINI_TILEY + 1;
int x, y;
getMiniGraphicSource(border_graphic, &src_bitmap, &src_x, &src_y);
DrawMiniGraphicExt(drawto,
gi->x + x * MINI_TILEX, gi->y + y * MINI_TILEY,
el2edimg(custom_element.content[x][y]));
+ else if (id == ED_DRAWING_ID_CUSTOM_MOVE_ENTER)
+ DrawMiniGraphicExt(drawto, gi->x, gi->y,
+ el2edimg(custom_element.move_enter_element));
+ else if (id == ED_DRAWING_ID_CUSTOM_MOVE_LEAVE)
+ DrawMiniGraphicExt(drawto, gi->x, gi->y,
+ el2edimg(custom_element.move_leave_element));
else if (id == ED_DRAWING_ID_CUSTOM_CHANGE_TARGET)
DrawMiniGraphicExt(drawto, gi->x, gi->y,
el2edimg(custom_element_change.target_element));
for (x = 0; x < 3; x++)
DrawMiniGraphicExt(drawto,
gi->x + x * MINI_TILEX, gi->y + y * MINI_TILEY,
- el2edimg(custom_element_change.content[x][y]));
+ el2edimg(custom_element_change.target_content[x][y]));
else if (id == ED_DRAWING_ID_CUSTOM_CHANGE_TRIGGER)
DrawMiniGraphicExt(drawto, gi->x, gi->y,
el2edimg(custom_element_change.trigger_element));
+ else if (id == ED_DRAWING_ID_GROUP_CONTENT)
+ for (x = 0; x < group_element_info.num_elements; x++)
+ DrawMiniGraphicExt(drawto, gi->x + x * MINI_TILEX, gi->y,
+ el2edimg(group_element_info.element[x]));
else if (id >= ED_DRAWING_ID_ELEMENT_CONTENT_0 &&
id <= ED_DRAWING_ID_ELEMENT_CONTENT_7)
{
gd_xoffset = ED_CTRL1_BUTTONS_XPOS + x * ED_CTRL1_BUTTON_XSIZE;
gd_yoffset = ED_CTRL1_BUTTONS_YPOS + y * ED_CTRL1_BUTTON_YSIZE;
- width = ED_CTRL1_BUTTON_XSIZE;
+ width = ED_CTRL1_BUTTON_XSIZE;
height = ED_CTRL1_BUTTON_YSIZE;
gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
gd_xoffset = ED_CTRL2_BUTTONS_XPOS + x * ED_CTRL2_BUTTON_XSIZE;
gd_yoffset = ED_CTRL2_BUTTONS_YPOS + y * ED_CTRL2_BUTTON_YSIZE;
- width = ED_CTRL2_BUTTON_XSIZE;
+ width = ED_CTRL2_BUTTON_XSIZE;
height = ED_CTRL2_BUTTON_YSIZE;
gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL2_BUTTONS_GFX_YPOS + gd_yoffset;
gd_y2 = 0; /* no alternative graphic for these buttons */
}
- else
+ else if (id < ED_NUM_CTRL1_3_BUTTONS)
{
int x = (i - ED_NUM_CTRL1_2_BUTTONS) % ED_CTRL3_BUTTONS_HORIZ + 1;
int y = (i - ED_NUM_CTRL1_2_BUTTONS) / ED_CTRL3_BUTTONS_HORIZ;
gd_xoffset = ED_CTRL3_BUTTONS_XPOS + x * ED_CTRL3_BUTTON_XSIZE;
gd_yoffset = ED_CTRL3_BUTTONS_YPOS + y * ED_CTRL3_BUTTON_YSIZE;
- width = ED_CTRL3_BUTTON_XSIZE;
+ width = ED_CTRL3_BUTTON_XSIZE;
height = ED_CTRL3_BUTTON_YSIZE;
gd_x1 = DOOR_GFX_PAGEX6 + gd_xoffset;
gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL3_BUTTONS_GFX_YPOS + gd_yoffset;
gd_y2 = DOOR_GFX_PAGEY1 + ED_CTRL3_BUTTONS_ALT_GFX_YPOS + gd_yoffset;
}
+ else
+ {
+ int x = (i - ED_NUM_CTRL1_3_BUTTONS) % ED_CTRL4_BUTTONS_HORIZ;
+ int y = (i - ED_NUM_CTRL1_3_BUTTONS) / ED_CTRL4_BUTTONS_HORIZ + 3;
+
+ gd_xoffset = ED_CTRL4_BUTTONS_XPOS + x * ED_CTRL4_BUTTON_XSIZE;
+ gd_yoffset = ED_CTRL4_BUTTONS_YPOS + y * ED_CTRL4_BUTTON_YSIZE;
+ width = ED_CTRL4_BUTTON_XSIZE;
+ height = ED_CTRL4_BUTTON_YSIZE;
+
+ gd_x1 = DOOR_GFX_PAGEX6 + ED_CTRL4_BUTTONS_GFX_XPOS + gd_xoffset;
+ gd_x2 = DOOR_GFX_PAGEX5 + ED_CTRL4_BUTTONS_GFX_XPOS + gd_xoffset;
+ gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL4_BUTTONS_GFX_YPOS + gd_yoffset;
+ gd_y2 = 0; /* no alternative graphic for these buttons */
+ }
gi = CreateGadget(GDI_CUSTOM_ID, id,
GDI_CUSTOM_TYPE_ID, i,
GDI_NUMBER_VALUE, 0,
GDI_NUMBER_MIN, counterbutton_info[i].min_value,
GDI_NUMBER_MAX, counterbutton_info[i].max_value,
- GDI_TEXT_SIZE, 3,
+ GDI_TEXT_SIZE, 3, /* minimal counter text size */
GDI_TEXT_FONT, font_type,
GDI_TEXT_FONT_ACTIVE, font_type_active,
GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x, gd_y,
event_mask = GD_EVENT_RELEASED;
- if (id >= GADGET_ID_PROPERTIES_INFO && id <= GADGET_ID_PROPERTIES_ADVANCED)
+ if (id >= GADGET_ID_PROPERTIES_INFO && id <= GADGET_ID_PROPERTIES_CHANGE)
{
gd_x1 = DOOR_GFX_PAGEX4 + ED_TEXTBUTTON_TAB_XPOS;
gd_x2 = DOOR_GFX_PAGEX3 + ED_TEXTBUTTON_TAB_XPOS;
event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
- gd_x1 = DOOR_GFX_PAGEX4 + graphicbutton_info[i].gd_x;
- gd_x2 = DOOR_GFX_PAGEX3 + graphicbutton_info[i].gd_x;
- gd_y1 = DOOR_GFX_PAGEY1 + graphicbutton_info[i].gd_y;
- gd_y2 = gd_y1;
+ if (i <= ED_GRAPHICBUTTON_ID_NEXT_CHANGE_PAGE)
+ {
+ gd_x1 = DOOR_GFX_PAGEX4 + graphicbutton_info[i].gd_x;
+ gd_y1 = DOOR_GFX_PAGEY1 + graphicbutton_info[i].gd_y;
+ gd_x2 = DOOR_GFX_PAGEX3 + graphicbutton_info[i].gd_x;
+ gd_y2 = gd_y1;
+ }
+ else /* (i <= ED_GRAPHICBUTTON_ID_PASTE_CHANGE_PAGE) */
+ {
+ gd_x1 = DOOR_GFX_PAGEX6 + graphicbutton_info[i].gd_x;
+ gd_y1 = DOOR_GFX_PAGEY1 + graphicbutton_info[i].gd_y;
+ gd_x2 = gd_x1 - ED_BUTTON_COUNT_XSIZE;
+ gd_y2 = gd_y1;
+ }
/* determine horizontal position to the right of specified gadget */
if (graphicbutton_info[i].gadget_id_align != GADGET_ID_NONE)
static void MapCounterButtons(int id)
{
int gadget_id_down = counterbutton_info[id].gadget_id_down;
+ int gadget_id_text = counterbutton_info[id].gadget_id_text;
int gadget_id_up = counterbutton_info[id].gadget_id_up;
struct GadgetInfo *gi_down = level_editor_gadget[gadget_id_down];
+ struct GadgetInfo *gi_text = level_editor_gadget[gadget_id_text];
struct GadgetInfo *gi_up = level_editor_gadget[gadget_id_up];
#if 0
char infotext[MAX_OUTPUT_LINESIZE + 1];
int x_right = gi_up->x + gi_up->width + xoffset_right;
int y_above = gi_down->y - yoffset_above;
int x = gi_down->x;
- int y = gi_up->y + yoffset;
+ int y; /* set after gadget position was modified */
#endif
+ /* set position for "score" counter gadget */
+ if (id == ED_COUNTER_ID_ELEMENT_SCORE)
+ {
+ ModifyGadget(gi_down, GDI_Y, SY + counterbutton_info[id].y, GDI_END);
+ ModifyGadget(gi_text, GDI_Y, SY + counterbutton_info[id].y, GDI_END);
+ ModifyGadget(gi_up, GDI_Y, SY + counterbutton_info[id].y, GDI_END);
+ }
+
+ y = gi_up->y + yoffset;
+
if (counterbutton_info[id].text_above)
DrawText(x, y_above, counterbutton_info[id].text_above, FONT_TEXT_1);
ModifyEditorCounter(id, *counterbutton_info[id].value);
- MapGadget(level_editor_gadget[counterbutton_info[id].gadget_id_down]);
- MapGadget(level_editor_gadget[counterbutton_info[id].gadget_id_text]);
- MapGadget(level_editor_gadget[counterbutton_info[id].gadget_id_up]);
+ MapGadget(gi_down);
+ MapGadget(gi_text);
+ MapGadget(gi_up);
}
static void MapControlButtons()
int xoffset_left = getTextWidthForGadget(checkbutton_info[id].text_left);
int xoffset_right = ED_GADGET_TEXT_DISTANCE;
int yoffset = ED_BORDER_SIZE;
- int x_left = gi->x - xoffset_left;
- int x_right = gi->x + gi->width + xoffset_right;
- int y = gi->y + yoffset;
+ int x_left, x_right, y; /* set after gadget position was modified */
- /* special case needed for "sticky" gadget */
- ModifyGadget(gi, GDI_CHECKED, *checkbutton_info[id].value,
- GDI_Y, SY + checkbutton_info[id].y, GDI_END);
+ /* set position for gadgets with dynamically determined position */
+ if (checkbutton_info[id].x != -1) /* do not change dynamic positions */
+ ModifyGadget(gi, GDI_X, SX + checkbutton_info[id].x, GDI_END);
+ ModifyGadget(gi, GDI_Y, SY + checkbutton_info[id].y, GDI_END);
+
+ x_left = gi->x - xoffset_left;
+ x_right = gi->x + gi->width + xoffset_right;
y = gi->y + yoffset;
if (checkbutton_info[id].text_left)
if (checkbutton_info[id].text_right)
DrawText(x_right, y, checkbutton_info[id].text_right, FONT_TEXT_1);
+ ModifyGadget(gi, GDI_CHECKED, *checkbutton_info[id].value, GDI_END);
+
MapGadget(gi);
}
{
if (i == GADGET_ID_CUSTOM_COPY_FROM ||
i == GADGET_ID_CUSTOM_COPY_TO ||
- i == GADGET_ID_CUSTOM_EXCHANGE)
+ i == GADGET_ID_CUSTOM_EXCHANGE ||
+ i == GADGET_ID_CUSTOM_COPY ||
+ i == GADGET_ID_CUSTOM_PASTE)
{
if (map)
MapGadget(level_editor_gadget[i]);
static void UnmapDrawingArea(int id)
{
- UnmapGadget(level_editor_gadget[id]);
+ UnmapGadget(level_editor_gadget[drawingarea_info[id].gadget_id]);
}
static void UnmapLevelEditorWindowGadgets()
static void copy_custom_element_settings(int element_from, int element_to)
{
+#if 0
+ struct ElementInfo ei_to_old = element_info[element_to];
+ struct ElementInfo *ei_from = &element_info[element_from];
+ struct ElementInfo *ei_to = &element_info[element_to];
+ int i;
+
+ /* ---------- copy whole element structure ---------- */
+ *ei_to = *ei_from;
+
+ /* ---------- restore structure pointers which cannot be copied ---------- */
+ ei_to->token_name = ei_to_old.token_name;
+ ei_to->class_name = ei_to_old.class_name;
+ ei_to->editor_description = ei_to_old.editor_description;
+ ei_to->custom_description = ei_to_old.custom_description;
+ ei_to->change_page = ei_to_old.change_page;
+ ei_to->change = ei_to_old.change;
+ ei_to->group = ei_to_old.group;
+
+ /* ---------- copy element base properties ---------- */
+ Properties[element_to][EP_BITFIELD_BASE] =
+ Properties[element_from][EP_BITFIELD_BASE];
+
+ /* ---------- reinitialize and copy change pages ---------- */
+ setElementChangePages(ei_to, ei_to->num_change_pages);
+
+ for (i=0; i < ei_to->num_change_pages; i++)
+ ei_to->change_page[i] = ei_from->change_page[i];
+
+ /* ---------- copy group element info ---------- */
+ if (ei_from->group != NULL && ei_to->group != NULL) /* group or internal */
+ *ei_to->group = *ei_from->group;
+
+#else
+
struct ElementInfo *ei_from = &element_info[element_from];
struct ElementInfo *ei_to = &element_info[element_to];
int i, x, y;
for (i = 0; i < MAX_ELEMENT_NAME_LEN + 1; i++)
ei_to->description[i] = ei_from->description[i];
- /* ---------- copy element properties ---------- */
+ /* ---------- copy element base properties ---------- */
Properties[element_to][EP_BITFIELD_BASE] =
Properties[element_from][EP_BITFIELD_BASE];
ei_to->use_gfx_element = ei_from->use_gfx_element;
ei_to->gfx_element = ei_from->gfx_element;
+ ei_to->access_direction = ei_from->access_direction;
+
ei_to->collect_score = ei_from->collect_score;
ei_to->collect_count = ei_from->collect_count;
ei_to->push_delay_fixed = ei_from->push_delay_fixed;
ei_to->push_delay_random = ei_from->push_delay_random;
+ ei_to->drop_delay_fixed = ei_from->drop_delay_fixed;
+ ei_to->drop_delay_random = ei_from->drop_delay_random;
ei_to->move_delay_fixed = ei_from->move_delay_fixed;
ei_to->move_delay_random = ei_from->move_delay_random;
ei_to->move_direction_initial = ei_from->move_direction_initial;
ei_to->move_stepsize = ei_from->move_stepsize;
+ ei_to->move_enter_element = ei_from->move_enter_element;
+ ei_to->move_leave_element = ei_from->move_leave_element;
+ ei_to->move_leave_type = ei_from->move_leave_type;
+
ei_to->slippery_type = ei_from->slippery_type;
for (y = 0; y < 3; y++)
- for (x = 0; x < 3; x++)
- ei_to->content[x][y] = ei_from->content[x][y];
-
- ei_to->num_change_pages = ei_from->num_change_pages;
- setElementChangePages(ei_to, ei_to->num_change_pages);
-
- for (i=0; i < ei_to->num_change_pages; i++)
- {
- struct ElementChangeInfo *change_to = &ei_to->change_page[i];
- struct ElementChangeInfo *change_from = &ei_from->change_page[i];
-
- /* always start with reliable default values */
- setElementChangeInfoToDefaults(change_to);
-
- change_to->events = change_from->events;
-
- change_to->target_element = change_from->target_element;
+ for (x = 0; x < 3; x++)
+ ei_to->content[x][y] = ei_from->content[x][y];
- change_to->delay_fixed = change_from->delay_fixed;
- change_to->delay_random = change_from->delay_random;
- change_to->delay_frames = change_from->delay_frames;
+ ei_to->explosion_type = ei_from->explosion_type;
+ ei_to->explosion_delay = ei_from->explosion_delay;
+ ei_to->ignition_delay = ei_from->ignition_delay;
- change_to->trigger_element = change_from->trigger_element;
+ /* ---------- reinitialize and copy change pages ---------- */
- change_to->explode = change_from->explode;
- change_to->use_content = change_from->use_content;
- change_to->only_complete = change_from->only_complete;
- change_to->use_random_change = change_from->use_random_change;
+ ei_to->num_change_pages = ei_from->num_change_pages;
+ ei_to->current_change_page = ei_from->current_change_page;
- change_to->random = change_from->random;
- change_to->power = change_from->power;
+ setElementChangePages(ei_to, ei_to->num_change_pages);
- for (y = 0; y < 3; y++)
- for (x = 0; x < 3; x++)
- change_to->content[x][y] = change_from->content[x][y];
+ for (i=0; i < ei_to->num_change_pages; i++)
+ ei_to->change_page[i] = ei_from->change_page[i];
- change_to->can_change = change_from->can_change;
+ /* ---------- copy group element info ---------- */
+ if (ei_from->group != NULL && ei_to->group != NULL) /* group or internal */
+ *ei_to->group = *ei_from->group;
- change_to->sides = change_from->sides;
- }
+#endif
/* mark this custom element as modified */
ei_to->modified_settings = TRUE;
if (ei->content[x][y] == element_from)
ei->content[x][y] = element_to;
- for (j=0; j < ei->num_change_pages; j++)
+ for (j = 0; j < ei->num_change_pages; j++)
{
struct ElementChangeInfo *change = &ei->change_page[j];
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- if (change->content[x][y] == element_from)
- change->content[x][y] = element_to;
+ if (change->target_content[x][y] == element_from)
+ change->target_content[x][y] = element_to;
}
+
+ if (ei->group != NULL) /* group or internal */
+ for (j = 0; j < MAX_ELEMENTS_IN_GROUP; j++)
+ if (ei->group->element[j] == element_from)
+ ei->group->element[j] = element_to;
}
}
Feld[x][y] = element_to;
}
-static void CopyCustomElement(int element_old, int element_new, int copy_mode)
+static boolean CopyCustomElement(int element_old, int element_new,
+ int copy_mode)
{
+ if (copy_mode == GADGET_ID_CUSTOM_COPY)
+ {
+ element_new = (IS_CUSTOM_ELEMENT(element_old) ?
+ EL_INTERNAL_CLIPBOARD_CUSTOM : EL_INTERNAL_CLIPBOARD_GROUP);
+ copy_mode = GADGET_ID_CUSTOM_COPY_TO;
+ }
+ else if (copy_mode == GADGET_ID_CUSTOM_PASTE)
+ {
+ element_old = (IS_CUSTOM_ELEMENT(element_new) ?
+ EL_INTERNAL_CLIPBOARD_CUSTOM : EL_INTERNAL_CLIPBOARD_GROUP);
+ copy_mode = GADGET_ID_CUSTOM_COPY_TO;
+ }
+ else if (IS_CUSTOM_ELEMENT(element_old) && !IS_CUSTOM_ELEMENT(element_new))
+ {
+ Request("Please choose custom element !", REQ_CONFIRM);
+
+ return FALSE;
+ }
+ else if (IS_GROUP_ELEMENT(element_old) && !IS_GROUP_ELEMENT(element_new))
+ {
+ Request("Please choose group element !", REQ_CONFIRM);
+
+ return FALSE;
+ }
+
if (copy_mode == GADGET_ID_CUSTOM_COPY_FROM)
{
copy_custom_element_settings(element_new, element_old);
}
else if (copy_mode == GADGET_ID_CUSTOM_EXCHANGE)
{
- copy_custom_element_settings(element_old, EL_DUMMY);
+ copy_custom_element_settings(element_old, EL_INTERNAL_DUMMY);
copy_custom_element_settings(element_new, element_old);
- copy_custom_element_settings(EL_DUMMY, element_new);
+ copy_custom_element_settings(EL_INTERNAL_DUMMY, element_new);
- replace_custom_element_in_settings(element_old, EL_DUMMY);
+ replace_custom_element_in_settings(element_old, EL_INTERNAL_DUMMY);
replace_custom_element_in_settings(element_new, element_old);
- replace_custom_element_in_settings(EL_DUMMY, element_new);
+ replace_custom_element_in_settings(EL_INTERNAL_DUMMY, element_new);
- replace_custom_element_in_playfield(element_old, EL_DUMMY);
+ replace_custom_element_in_playfield(element_old, EL_INTERNAL_DUMMY);
replace_custom_element_in_playfield(element_new, element_old);
- replace_custom_element_in_playfield(EL_DUMMY, element_new);
+ replace_custom_element_in_playfield(EL_INTERNAL_DUMMY, element_new);
}
UpdateCustomElementGraphicGadgets();
DrawPropertiesWindow();
+
+ return TRUE;
}
static void CopyCustomElementPropertiesToEditor(int element)
IS_ACCESSIBLE_INSIDE(element) ? EP_ACCESSIBLE_INSIDE :
IS_ACCESSIBLE_UNDER(element) ? EP_ACCESSIBLE_UNDER :
custom_element.access_layer);
+ custom_element.access_protected =
+ (IS_PROTECTED(element) ? 1 : 0);
custom_element_properties[EP_ACCESSIBLE] =
(IS_ACCESSIBLE_OVER(element) ||
IS_ACCESSIBLE_INSIDE(element) ||
(IS_DIGGABLE(element) ? EP_DIGGABLE :
IS_COLLECTIBLE_ONLY(element) ? EP_COLLECTIBLE_ONLY :
IS_DROPPABLE(element) ? EP_DROPPABLE :
+ IS_THROWABLE(element) ? EP_THROWABLE :
IS_PUSHABLE(element) ? EP_PUSHABLE :
custom_element.walk_to_action);
custom_element_properties[EP_WALK_TO_OBJECT] =
(IS_DIGGABLE(element) ||
IS_COLLECTIBLE_ONLY(element) ||
IS_DROPPABLE(element) ||
+ IS_THROWABLE(element) ||
IS_PUSHABLE(element));
/* set smash targets selectbox help value */
DONT_COLLIDE_WITH(element) ||
DONT_RUN_INTO(element));
- /* set consistency selectbox help value */
- custom_element.consistency =
- (IS_INDESTRUCTIBLE(element) ? EP_INDESTRUCTIBLE :
+#if 0
+ /* set explosion type selectbox help value */
+ custom_element.explosion_type =
+ (
+#if 0
+ IS_INDESTRUCTIBLE(element) ? EP_INDESTRUCTIBLE :
+#endif
CAN_EXPLODE_1X1(element) ? EP_CAN_EXPLODE_1X1 :
CAN_EXPLODE_3X3(element) ? EP_CAN_EXPLODE_3X3 :
- custom_element.consistency);
- custom_element_properties[EP_EXPLODE_RESULT] =
- (IS_INDESTRUCTIBLE(element) ||
+ CAN_EXPLODE_CROSS(element) ? EP_CAN_EXPLODE_CROSS :
+ custom_element.explosion_type);
+ custom_element_properties[EP_CAN_EXPLODE_AT_ALL] =
+ (
+#if 0
+ IS_INDESTRUCTIBLE(element) ||
+#endif
CAN_EXPLODE_1X1(element) ||
- CAN_EXPLODE_3X3(element));
+ CAN_EXPLODE_3X3(element) ||
+ CAN_EXPLODE_CROSS(element));
+#endif
+#if 0
/* special case: sub-settings dependent from main setting */
+#if 0
+ custom_element.can_explode_by_fire = CAN_EXPLODE_BY_FIRE(element);
+ custom_element.can_explode_smashed = CAN_EXPLODE_SMASHED(element);
+ custom_element.can_explode_impact = CAN_EXPLODE_IMPACT(element);
+#else
if (CAN_EXPLODE_BY_FIRE(element))
custom_element.can_explode_by_fire = TRUE;
if (CAN_EXPLODE_SMASHED(element))
custom_element.can_explode_smashed = TRUE;
if (CAN_EXPLODE_IMPACT(element))
custom_element.can_explode_impact = TRUE;
+#endif
+#endif
/* ---------- element settings: advanced (custom elements) --------------- */
HAS_CHANGE_EVENT(element, CE_LEFT_BY_PLAYER) ? CE_LEFT_BY_PLAYER :
HAS_CHANGE_EVENT(element, CE_DROPPED_BY_PLAYER) ? CE_DROPPED_BY_PLAYER :
HAS_CHANGE_EVENT(element, CE_SWITCHED) ? CE_SWITCHED :
- HAS_CHANGE_EVENT(element, CE_COLLISION_ACTIVE) ? CE_COLLISION_ACTIVE :
- HAS_CHANGE_EVENT(element, CE_COLLISION_PASSIVE) ? CE_COLLISION_PASSIVE :
+ HAS_CHANGE_EVENT(element, CE_HITTING_SOMETHING) ? CE_HITTING_SOMETHING :
+ HAS_CHANGE_EVENT(element, CE_HIT_BY_SOMETHING) ? CE_HIT_BY_SOMETHING :
+ HAS_CHANGE_EVENT(element, CE_BLOCKED) ? CE_BLOCKED :
HAS_CHANGE_EVENT(element, CE_IMPACT) ? CE_IMPACT :
HAS_CHANGE_EVENT(element, CE_SMASHED) ? CE_SMASHED :
custom_element_change.direct_action);
HAS_CHANGE_EVENT(element, CE_OTHER_GETS_COLLECTED) ? CE_OTHER_GETS_COLLECTED :
HAS_CHANGE_EVENT(element, CE_OTHER_GETS_DROPPED) ? CE_OTHER_GETS_DROPPED :
HAS_CHANGE_EVENT(element, CE_OTHER_IS_TOUCHING) ? CE_OTHER_IS_TOUCHING :
- HAS_CHANGE_EVENT(element, CE_OTHER_IS_COLL_ACTIVE) ? CE_OTHER_IS_COLL_ACTIVE :
- HAS_CHANGE_EVENT(element, CE_OTHER_IS_COLL_PASSIVE) ? CE_OTHER_IS_COLL_PASSIVE :
+ HAS_CHANGE_EVENT(element, CE_OTHER_IS_HITTING) ? CE_OTHER_IS_HITTING :
+ HAS_CHANGE_EVENT(element, CE_OTHER_GETS_HIT) ? CE_OTHER_GETS_HIT :
HAS_CHANGE_EVENT(element, CE_OTHER_IS_SWITCHING) ? CE_OTHER_IS_SWITCHING :
HAS_CHANGE_EVENT(element, CE_OTHER_IS_CHANGING) ? CE_OTHER_IS_CHANGING :
HAS_CHANGE_EVENT(element, CE_OTHER_IS_EXPLODING) ? CE_OTHER_IS_EXPLODING :
custom_element_change.other_action);
}
+static void CopyGroupElementPropertiesToEditor(int element)
+{
+ group_element_info = *element_info[element].group;
+ custom_element = element_info[element]; /* needed for description */
+}
+
+static void CopyClassicElementPropertiesToEditor(int element)
+{
+#if 1
+ if (ELEM_IS_PLAYER(element) || COULD_MOVE_INTO_ACID(element))
+ custom_element_properties[EP_CAN_MOVE_INTO_ACID] =
+ getMoveIntoAcidProperty(&level, element);
+
+ if (MAYBE_DONT_COLLIDE_WITH(element))
+ custom_element_properties[EP_DONT_COLLIDE_WITH] =
+ getDontCollideWithProperty(&level, element);
+#else
+
+ if (COULD_MOVE_INTO_ACID(element))
+ {
+ int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID);
+
+ if (bit_nr > -1)
+ custom_element_properties[EP_CAN_MOVE_INTO_ACID] =
+ ((level.can_move_into_acid_bits & (1 << bit_nr)) != 0);
+ }
+#endif
+}
+
+static void CopyElementPropertiesToEditor(int element)
+{
+ if (IS_CUSTOM_ELEMENT(element))
+ CopyCustomElementPropertiesToEditor(element);
+ else if (IS_GROUP_ELEMENT(element))
+ CopyGroupElementPropertiesToEditor(element);
+ else
+ CopyClassicElementPropertiesToEditor(element);
+}
+
static void CopyCustomElementPropertiesToGame(int element)
{
int i;
int access_type_and_layer;
+#if 0
+ boolean can_explode;
+#endif
/* mark that this custom element has been modified */
custom_element.modified_settings = TRUE;
(custom_element.access_layer - EP_ACCESSIBLE_OVER));
custom_element_properties[access_type_and_layer] =
custom_element_properties[EP_ACCESSIBLE];
+ custom_element_properties[EP_PROTECTED] =
+ (custom_element.access_protected != 0 &&
+ custom_element_properties[EP_ACCESSIBLE]);
/* set walk-to-object property from checkbox and selectbox */
custom_element_properties[EP_DIGGABLE] = FALSE;
custom_element_properties[EP_COLLECTIBLE_ONLY] = FALSE;
custom_element_properties[EP_DROPPABLE] = FALSE;
+ custom_element_properties[EP_THROWABLE] = FALSE;
custom_element_properties[EP_PUSHABLE] = FALSE;
custom_element_properties[custom_element.walk_to_action] =
custom_element_properties[EP_WALK_TO_OBJECT];
custom_element_properties[custom_element.deadliness] =
custom_element_properties[EP_DEADLY];
- /* set consistency property from checkbox and selectbox */
+#if 0
+ /* set explosion type property from checkbox and selectbox */
+#if 0
custom_element_properties[EP_INDESTRUCTIBLE] = FALSE;
+#endif
custom_element_properties[EP_CAN_EXPLODE_1X1] = FALSE;
custom_element_properties[EP_CAN_EXPLODE_3X3] = FALSE;
+ custom_element_properties[EP_CAN_EXPLODE_CROSS] = FALSE;
custom_element_properties[EP_CAN_EXPLODE_BY_FIRE] = FALSE;
custom_element_properties[EP_CAN_EXPLODE_SMASHED] = FALSE;
custom_element_properties[EP_CAN_EXPLODE_IMPACT] = FALSE;
- custom_element_properties[custom_element.consistency] =
- custom_element_properties[EP_EXPLODE_RESULT];
+ custom_element_properties[custom_element.explosion_type] =
+ custom_element_properties[EP_CAN_EXPLODE_AT_ALL];
+#endif
+#if 0
/* special case: sub-settings dependent from main setting */
- if (custom_element_properties[EP_CAN_EXPLODE_3X3] ||
- custom_element_properties[EP_CAN_EXPLODE_1X1])
+#if 0
+ can_explode = (custom_element_properties[EP_CAN_EXPLODE_1X1] ||
+ custom_element_properties[EP_CAN_EXPLODE_3X3] ||
+ custom_element_properties[EP_CAN_EXPLODE_CROSS]);
+ custom_element_properties[EP_CAN_EXPLODE_BY_FIRE] =
+ (can_explode && custom_element.can_explode_by_fire);
+ custom_element_properties[EP_CAN_EXPLODE_SMASHED] =
+ (can_explode && custom_element.can_explode_smashed);
+ custom_element_properties[EP_CAN_EXPLODE_IMPACT] =
+ (can_explode && custom_element.can_explode_impact);
+#else
+ if (custom_element_properties[EP_CAN_EXPLODE_1X1] ||
+ custom_element_properties[EP_CAN_EXPLODE_3X3] ||
+ custom_element_properties[EP_CAN_EXPLODE_CROSS])
{
custom_element_properties[EP_CAN_EXPLODE_BY_FIRE] =
custom_element.can_explode_by_fire;
custom_element_properties[EP_CAN_EXPLODE_IMPACT] =
custom_element.can_explode_impact;
}
+#endif
+#endif
/* ---------- element settings: advanced (custom elements) --------------- */
custom_element_change_events[CE_LEFT_BY_PLAYER] = FALSE;
custom_element_change_events[CE_DROPPED_BY_PLAYER] = FALSE;
custom_element_change_events[CE_SWITCHED] = FALSE;
- custom_element_change_events[CE_COLLISION_ACTIVE] = FALSE;
- custom_element_change_events[CE_COLLISION_PASSIVE] = FALSE;
+ custom_element_change_events[CE_HITTING_SOMETHING] = FALSE;
+ custom_element_change_events[CE_HIT_BY_SOMETHING] = FALSE;
+ custom_element_change_events[CE_BLOCKED] = FALSE;
custom_element_change_events[CE_IMPACT] = FALSE;
custom_element_change_events[CE_SMASHED] = FALSE;
custom_element_change_events[custom_element_change.direct_action] =
custom_element_change_events[CE_OTHER_GETS_COLLECTED] = FALSE;
custom_element_change_events[CE_OTHER_GETS_DROPPED] = FALSE;
custom_element_change_events[CE_OTHER_IS_TOUCHING] = FALSE;
- custom_element_change_events[CE_OTHER_IS_COLL_ACTIVE] = FALSE;
- custom_element_change_events[CE_OTHER_IS_COLL_PASSIVE] = FALSE;
+ custom_element_change_events[CE_OTHER_IS_HITTING] = FALSE;
+ custom_element_change_events[CE_OTHER_GETS_HIT] = FALSE;
custom_element_change_events[CE_OTHER_IS_SWITCHING] = FALSE;
custom_element_change_events[CE_OTHER_IS_CHANGING] = FALSE;
custom_element_change_events[CE_OTHER_IS_EXPLODING] = FALSE;
custom_element_change = *element_info[element].change;
}
+static void CopyGroupElementPropertiesToGame(int element)
+{
+ element_info[element] = custom_element;
+ *element_info[element].group = group_element_info;
+
+ /* mark that this group element has been modified */
+ element_info[element].modified_settings = TRUE;
+}
+
+static void CopyClassicElementPropertiesToGame(int element)
+{
+#if 1
+ if (ELEM_IS_PLAYER(element) || COULD_MOVE_INTO_ACID(element))
+ setMoveIntoAcidProperty(&level, element,
+ custom_element_properties[EP_CAN_MOVE_INTO_ACID]);
+
+ if (MAYBE_DONT_COLLIDE_WITH(element))
+ setDontCollideWithProperty(&level, element,
+ custom_element_properties[EP_DONT_COLLIDE_WITH]);
+#else
+
+ if (COULD_MOVE_INTO_ACID(element))
+ {
+ int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID);
+
+ if (bit_nr > -1)
+ {
+ level.can_move_into_acid_bits &= ~(1 << bit_nr);
+
+ if (custom_element_properties[EP_CAN_MOVE_INTO_ACID])
+ level.can_move_into_acid_bits |= (1 << bit_nr);
+ }
+ }
+#endif
+}
+
+static void CopyElementPropertiesToGame(int element)
+{
+ if (IS_CUSTOM_ELEMENT(element))
+ CopyCustomElementPropertiesToGame(element);
+ else if (IS_GROUP_ELEMENT(element))
+ CopyGroupElementPropertiesToGame(element);
+ else
+ CopyClassicElementPropertiesToGame(element);
+}
+
void DrawLevelEd()
{
CloseDoor(DOOR_CLOSE_ALL);
redraw_mask |= REDRAW_ALL;
- ReinitializeElementListButtons(); /* only needed after setup changes */
+ ReinitializeElementListButtons(); /* custom element may look different */
#if 0
ModifyEditorElementList(); /* may be needed for custom elements */
#endif
ModifyGadget(gi, GDI_SELECTBOX_INDEX, new_index_value, GDI_END);
}
+static void ModifyEditorDrawingArea(int drawingarea_id, int xsize, int ysize)
+{
+ int gadget_id = drawingarea_info[drawingarea_id].gadget_id;
+ struct GadgetInfo *gi = level_editor_gadget[gadget_id];
+
+ ModifyGadget(gi, GDI_AREA_SIZE, xsize, ysize, GDI_END);
+}
+
static void ModifyEditorElementList()
{
int i;
for (i = ED_COUNTER_ID_LEVEL_FIRST; i <= ED_COUNTER_ID_LEVEL_LAST; i++)
MapCounterButtons(i);
+ /* draw selectbox gadgets */
+ for (i = ED_SELECTBOX_ID_LEVEL_FIRST; i <= ED_SELECTBOX_ID_LEVEL_LAST; i++)
+ MapSelectboxGadget(i);
+
/* draw checkbutton gadgets */
for (i=ED_CHECKBUTTON_ID_LEVEL_FIRST; i <= ED_CHECKBUTTON_ID_LEVEL_LAST; i++)
MapCheckbuttonGadget(i);
int id = ED_DRAWING_ID_CUSTOM_CONTENT;
struct GadgetInfo *gi = level_editor_gadget[drawingarea_info[id].gadget_id];
int x1 = right_gadget_border[GADGET_ID_CUSTOM_DEADLINESS];
- int x2 = right_gadget_border[GADGET_ID_CUSTOM_CONSISTENCY];
+ int x2 = right_gadget_border[GADGET_ID_CUSTOM_EXPLOSION_TYPE];
int x3 = right_gadget_border[GADGET_ID_CUSTOM_EXPLODE_IMPACT];
int xoffset = ED_DRAWINGAREA_TEXT_DISTANCE;
int id = ED_DRAWING_ID_CUSTOM_CHANGE_CONTENT;
struct GadgetInfo *gi = level_editor_gadget[drawingarea_info[id].gadget_id];
int x1 = right_gadget_border[GADGET_ID_CHANGE_USE_CONTENT];
- int x2 = right_gadget_border[GADGET_ID_CHANGE_POWER];
+ int x2 = right_gadget_border[GADGET_ID_CHANGE_REPLACE_WHEN];
int x3 = right_gadget_border[GADGET_ID_CHANGE_ONLY_COMPLETE];
int xoffset = ED_DRAWINGAREA_TEXT_DISTANCE;
DrawBackground(SX + drawingarea_info[id].x - MINI_TILEX / 2,
SY + drawingarea_info[id].y - MINI_TILEY / 2,
4 * MINI_TILEX,
- 4 * MINI_TILEX + ED_GADGET_TEXT_DISTANCE + font_height);
+ 4 * MINI_TILEY + ED_GADGET_TEXT_DISTANCE + font_height);
}
}
DrawText(x, y + 2 * MINI_TILEY, "smashed", FONT_TEXT_1);
}
+static void DrawGroupElementArea(int element)
+{
+ int num_elements = group_element_info.num_elements;
+ int id = ED_DRAWING_ID_GROUP_CONTENT;
+ int sx = SX + drawingarea_info[id].x - MINI_TILEX / 2;
+ int sy = SY + drawingarea_info[id].y - MINI_TILEY / 2;
+ int xsize = MAX_ELEMENTS_IN_GROUP;
+ int ysize = 1;
+
+ if (drawingarea_info[id].text_left != NULL)
+ sx += getTextWidthForDrawingArea(drawingarea_info[id].text_left);
+
+ UnmapDrawingArea(id);
+
+ ModifyEditorDrawingArea(id, num_elements, 1);
+
+ /* delete content areas in case of reducing number of them */
+ DrawBackground(sx, sy, (xsize + 1) * MINI_TILEX, (ysize + 1) * MINI_TILEY);
+
+ MapDrawingArea(id);
+}
+
static void DrawEnvelopeTextArea(int envelope_nr)
{
int id = ED_TEXTAREA_ID_ENVELOPE_INFO;
Pixel tab_color = GetPixel(gd->bitmap, gd_x, gd_y);
int id_first = ED_TEXTBUTTON_ID_PROPERTIES_INFO;
int id_last = ED_TEXTBUTTON_ID_PROPERTIES_CONFIG;
+ int max_tabs = 4;
int i;
/* draw additional "advanced" tabulator for custom elements */
if (IS_CUSTOM_ELEMENT(properties_element))
- id_last = ED_TEXTBUTTON_ID_PROPERTIES_ADVANCED;
+ id_last = ED_TEXTBUTTON_ID_PROPERTIES_CHANGE;
for (i = id_first; i <= id_last; i++)
{
struct GadgetInfo *gi = level_editor_gadget[gadget_id];
boolean active = (i != edit_mode_properties);
+ /* use "config 1" and "config 2" instead of "config" */
+ if (i == ED_TEXTBUTTON_ID_PROPERTIES_CONFIG &&
+ IS_CUSTOM_ELEMENT(properties_element))
+ continue;
+
/* draw background line below tabulator button */
ClearRectangleOnBackground(drawto, gi->x, gi->y + gi->height, gi->width,1);
/* draw little border line below tabulator buttons */
if (tab_color != BLACK_PIXEL) /* black => transparent */
FillRectangle(drawto, gd_gi->x, gd_gi->y + gd_gi->height + 1,
- 3 * gd_gi->width + 2 * ED_GADGET_DISTANCE,
+ max_tabs * gd_gi->width + (max_tabs -1) * ED_GADGET_DISTANCE,
ED_GADGET_DISTANCE, tab_color);
}
{ EP_PASSABLE_OVER, "- player can pass over it" },
{ EP_PASSABLE_INSIDE, "- player can pass through it" },
{ EP_PASSABLE_UNDER, "- player can pass under it" },
+ { EP_PROTECTED, "- player is protected by it" },
{ EP_DIGGABLE, "- can be digged away" },
{ EP_COLLECTIBLE, "- can be collected" },
{ EP_DROPPABLE, "- can be dropped after collecting" },
+ { EP_THROWABLE, "- can be thrown after collecting" },
{ EP_PUSHABLE, "- can be pushed" },
- { EP_CAN_MOVE, "- can move" },
{ EP_CAN_FALL, "- can fall" },
+ { EP_CAN_MOVE, "- can move" },
{ EP_CAN_SMASH_PLAYER, "- can smash player" },
#if 0
#endif
{ EP_CAN_SMASH_EVERYTHING, "- can smash everything smashable" },
- { EP_SLIPPERY, "- slippery for falling objects" },
+ { EP_SLIPPERY, "- slippery for falling elements" },
{ EP_EM_SLIPPERY_WALL, "- slippery for some gems (EM style)" },
{ EP_DONT_RUN_INTO, "- deadly when running into" },
/* pre-defined properties */
{ EP_CAN_PASS_MAGIC_WALL, "- can pass magic walls" },
+ { EP_SWITCHABLE, "- can be switched" },
{ EP_HAS_CONTENT, "- can contain other elements" },
{ -1, NULL }
"[Custom Element %d]", properties_element - EL_CUSTOM_START + 1);
screen_line++;
}
+ else if (IS_GROUP_ELEMENT(properties_element))
+ {
+ DrawTextF(pad_x, pad_y + screen_line++ * font2_height, FONT_TEXT_3,
+ "[Group Element %d]", properties_element - EL_GROUP_START + 1);
+ screen_line++;
+ }
#endif
/* ----- print number of elements / percentage of this element in level */
{ EL_DIAMOND, &level.score[SC_DIAMOND], TEXT_COLLECTING },
{ EL_CRYSTAL, &level.score[SC_CRYSTAL], TEXT_COLLECTING },
{ EL_PEARL, &level.score[SC_PEARL], TEXT_COLLECTING },
+ { EL_BUG, &level.score[SC_BUG], TEXT_SMASHING },
{ EL_BUG_RIGHT, &level.score[SC_BUG], TEXT_SMASHING },
{ EL_BUG_UP, &level.score[SC_BUG], TEXT_SMASHING },
{ EL_BUG_LEFT, &level.score[SC_BUG], TEXT_SMASHING },
{ EL_BUG_DOWN, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BD_BUTTERFLY, &level.score[SC_BUG], TEXT_SMASHING },
{ EL_BD_BUTTERFLY_RIGHT,&level.score[SC_BUG], TEXT_SMASHING },
{ EL_BD_BUTTERFLY_UP, &level.score[SC_BUG], TEXT_SMASHING },
{ EL_BD_BUTTERFLY_LEFT, &level.score[SC_BUG], TEXT_SMASHING },
{ EL_BD_BUTTERFLY_DOWN, &level.score[SC_BUG], TEXT_SMASHING },
{ EL_SP_ELECTRON, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_SPACESHIP, &level.score[SC_SPACESHIP], TEXT_SMASHING },
{ EL_SPACESHIP_RIGHT, &level.score[SC_SPACESHIP], TEXT_SMASHING },
{ EL_SPACESHIP_UP, &level.score[SC_SPACESHIP], TEXT_SMASHING },
{ EL_SPACESHIP_LEFT, &level.score[SC_SPACESHIP], TEXT_SMASHING },
{ EL_SPACESHIP_DOWN, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_BD_FIREFLY, &level.score[SC_SPACESHIP], TEXT_SMASHING },
{ EL_BD_FIREFLY_RIGHT,&level.score[SC_SPACESHIP], TEXT_SMASHING },
{ EL_BD_FIREFLY_UP, &level.score[SC_SPACESHIP], TEXT_SMASHING },
{ EL_BD_FIREFLY_LEFT, &level.score[SC_SPACESHIP], TEXT_SMASHING },
{ EL_YAMYAM, &level.score[SC_YAMYAM], TEXT_SMASHING },
{ EL_DARK_YAMYAM, &level.score[SC_YAMYAM], TEXT_SMASHING },
{ EL_ROBOT, &level.score[SC_ROBOT], TEXT_SMASHING },
+ { EL_PACMAN, &level.score[SC_PACMAN], TEXT_SMASHING },
{ EL_PACMAN_RIGHT, &level.score[SC_PACMAN], TEXT_SMASHING },
{ EL_PACMAN_UP, &level.score[SC_PACMAN], TEXT_SMASHING },
{ EL_PACMAN_LEFT, &level.score[SC_PACMAN], TEXT_SMASHING },
{ -1, NULL, NULL }
};
-static boolean checkPropertiesConfig()
+static boolean checkPropertiesConfig(int element)
{
int i;
- if (IS_GEM(properties_element) ||
- IS_CUSTOM_ELEMENT(properties_element) ||
- IS_ENVELOPE(properties_element) ||
- HAS_CONTENT(properties_element))
+ if (IS_GEM(element) ||
+ IS_CUSTOM_ELEMENT(element) ||
+ IS_GROUP_ELEMENT(element) ||
+ IS_ENVELOPE(element) ||
+ ELEM_IS_PLAYER(element) ||
+ HAS_CONTENT(element) ||
+ CAN_GROW(element) ||
+ COULD_MOVE_INTO_ACID(element) ||
+ MAYBE_DONT_COLLIDE_WITH(element))
return TRUE;
else
for (i = 0; elements_with_counter[i].element != -1; i++)
- if (elements_with_counter[i].element == properties_element)
+ if (elements_with_counter[i].element == element)
return TRUE;
return FALSE;
{
int i;
- if (!checkPropertiesConfig())
+ if (!checkPropertiesConfig(properties_element))
{
PrintInfoText("No configuration options available.", FONT_TEXT_1, 0);
{
int counter_id = ED_COUNTER_ID_ELEMENT_SCORE;
+ counterbutton_info[counter_id].y =
+ ED_SETTINGS_YPOS((HAS_CONTENT(properties_element) ? 1 : 0) +
+ (CAN_GROW(properties_element) ? 1 : 0) +
+ (COULD_MOVE_INTO_ACID(properties_element) ? 1 : 0) +
+ (MAYBE_DONT_COLLIDE_WITH(properties_element) ? 1 :0));
+
counterbutton_info[counter_id].value = elements_with_counter[i].value;
counterbutton_info[counter_id].text_right= elements_with_counter[i].text;
+
MapCounterButtons(counter_id);
break;
if (HAS_CONTENT(properties_element))
{
/* draw stickybutton gadget */
- i = ED_CHECKBUTTON_ID_STICK_ELEMENT;
- checkbutton_info[i].y = ED_COUNTER_YPOS(4);
- MapCheckbuttonGadget(i);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_STICK_ELEMENT);
if (IS_AMOEBOID(properties_element))
MapDrawingArea(ED_DRAWING_ID_AMOEBA_CONTENT);
DrawElementContentAreas();
}
+ if (ELEM_IS_PLAYER(properties_element))
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID);
+ MapCheckbuttonGadget(properties_element == EL_SP_MURPHY ?
+ ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD :
+ ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_INSTANT_RELOCATION);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_PASS_TO_WALKABLE);
+ }
+
if (IS_GEM(properties_element))
MapCheckbuttonGadget(ED_CHECKBUTTON_ID_EM_SLIPPERY_GEMS);
+ if (COULD_MOVE_INTO_ACID(properties_element) &&
+ !ELEM_IS_PLAYER(properties_element) &&
+ (!IS_CUSTOM_ELEMENT(properties_element) ||
+ edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_2))
+ {
+ /* set position for checkbutton for "can move into acid" */
+ checkbutton_info[ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID].x =
+ ED_SETTINGS_XPOS(IS_CUSTOM_ELEMENT(properties_element) ? 1 : 0);
+ checkbutton_info[ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID].y =
+ ED_SETTINGS_YPOS(IS_CUSTOM_ELEMENT(properties_element) ? 6 :
+ HAS_CONTENT(properties_element) ? 1 : 0);
+
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID);
+ }
+
+ if (MAYBE_DONT_COLLIDE_WITH(properties_element))
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH);
+
+ if (properties_element == EL_SPRING)
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_SPRING_BUG);
+
+ if (CAN_GROW(properties_element))
+ {
+ checkbutton_info[ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE].y =
+ ED_SETTINGS_YPOS(HAS_CONTENT(properties_element) ? 1 : 0);
+
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE);
+ }
+
if (IS_ENVELOPE(properties_element))
{
int counter1_id = ED_COUNTER_ID_ENVELOPE_XSIZE;
if (IS_CUSTOM_ELEMENT(properties_element))
{
/* draw stickybutton gadget */
- i = ED_CHECKBUTTON_ID_STICK_ELEMENT;
- checkbutton_info[i].y = ED_SETTINGS_YPOS(0);
- MapCheckbuttonGadget(i);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_STICK_ELEMENT);
+
+ if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_1)
+ {
+ /* draw checkbutton gadgets */
+ for (i = ED_CHECKBUTTON_ID_CUSTOM1_FIRST;
+ i <= ED_CHECKBUTTON_ID_CUSTOM1_LAST; i++)
+ MapCheckbuttonGadget(i);
+
+ /* draw counter gadgets */
+ for (i = ED_COUNTER_ID_CUSTOM1_FIRST;
+ i <= ED_COUNTER_ID_CUSTOM1_LAST; i++)
+ MapCounterButtons(i);
+
+ /* draw selectbox gadgets */
+ for (i = ED_SELECTBOX_ID_CUSTOM1_FIRST;
+ i <= ED_SELECTBOX_ID_CUSTOM1_LAST; i++)
+ MapSelectboxGadget(i);
+
+ /* draw textbutton gadgets */
+ MapTextbuttonGadget(ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE);
+
+ /* draw text input gadgets */
+ MapTextInputGadget(ED_TEXTINPUT_ID_ELEMENT_NAME);
+
+ /* draw drawing area gadgets */
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_GRAPHIC);
+ }
+ else if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_2)
+ {
+ /* draw checkbutton gadgets */
+ for (i = ED_CHECKBUTTON_ID_CUSTOM2_FIRST;
+ i <= ED_CHECKBUTTON_ID_CUSTOM2_LAST; i++)
+ MapCheckbuttonGadget(i);
+
+ /* draw counter gadgets */
+ for (i = ED_COUNTER_ID_CUSTOM2_FIRST;
+ i <= ED_COUNTER_ID_CUSTOM2_LAST; i++)
+ MapCounterButtons(i);
+
+ /* draw selectbox gadgets */
+ for (i = ED_SELECTBOX_ID_CUSTOM2_FIRST;
+ i <= ED_SELECTBOX_ID_CUSTOM2_LAST; i++)
+ MapSelectboxGadget(i);
+
+ /* draw drawing area gadgets */
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_MOVE_ENTER);
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_MOVE_LEAVE);
+ DrawCustomContentArea();
+ }
+ }
+ else if (IS_GROUP_ELEMENT(properties_element))
+ {
+ /* draw stickybutton gadget */
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_STICK_ELEMENT);
/* draw checkbutton gadgets */
- for (i = ED_CHECKBUTTON_ID_CUSTOM_FIRST;
- i <= ED_CHECKBUTTON_ID_CUSTOM_LAST; i++)
- MapCheckbuttonGadget(i);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE);
/* draw counter gadgets */
- for (i = ED_COUNTER_ID_CUSTOM_FIRST; i <= ED_COUNTER_ID_CUSTOM_LAST; i++)
- MapCounterButtons(i);
+ MapCounterButtons(ED_COUNTER_ID_GROUP_CONTENT);
/* draw selectbox gadgets */
- for (i=ED_SELECTBOX_ID_CUSTOM_FIRST; i <= ED_SELECTBOX_ID_CUSTOM_LAST; i++)
- MapSelectboxGadget(i);
+ MapSelectboxGadget(ED_SELECTBOX_ID_GROUP_CHOICE_MODE);
+
+ /* draw textbutton gadgets */
+ MapTextbuttonGadget(ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE);
/* draw drawing area gadgets */
- DrawCustomContentArea();
+ DrawGroupElementArea(properties_element);
/* draw text input gadgets */
MapTextInputGadget(ED_TEXTINPUT_ID_ELEMENT_NAME);
+
+ /* draw drawing area gadgets */
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_GRAPHIC);
}
}
-static void DrawPropertiesAdvancedDrawingAreas()
+static void DrawPropertiesChangeDrawingAreas()
{
- MapDrawingArea(ED_DRAWING_ID_CUSTOM_GRAPHIC);
- MapDrawingArea(ED_DRAWING_ID_CUSTOM_CHANGE_TARGET);
- MapDrawingArea(ED_DRAWING_ID_CUSTOM_CHANGE_TRIGGER);
+ if (IS_CUSTOM_ELEMENT(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_CHANGE_TARGET);
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_CHANGE_TRIGGER);
- DrawCustomChangeContentArea();
+ DrawCustomChangeContentArea();
+ }
redraw_mask |= REDRAW_FIELD;
}
-static void DrawPropertiesAdvanced()
+static void DrawPropertiesChange()
{
int i;
/* draw stickybutton gadget */
- i = ED_CHECKBUTTON_ID_STICK_ELEMENT;
- checkbutton_info[i].y = ED_SETTINGS_YPOS(0);
- MapCheckbuttonGadget(i);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_STICK_ELEMENT);
/* draw checkbutton gadgets */
for (i = ED_CHECKBUTTON_ID_CHANGE_FIRST;
MapCheckbuttonGadget(i);
/* draw counter gadgets */
- for (i = ED_COUNTER_ID_CHANGE_FIRST; i <= ED_COUNTER_ID_CHANGE_LAST; i++)
+ for (i = ED_COUNTER_ID_CHANGE_FIRST;
+ i <= ED_COUNTER_ID_CHANGE_LAST; i++)
MapCounterButtons(i);
/* draw selectbox gadgets */
- for (i = ED_SELECTBOX_ID_CHANGE_FIRST; i <= ED_SELECTBOX_ID_CHANGE_LAST; i++)
+ for (i = ED_SELECTBOX_ID_CHANGE_FIRST;
+ i <= ED_SELECTBOX_ID_CHANGE_LAST; i++)
MapSelectboxGadget(i);
/* draw textbutton gadgets */
- for (i=ED_TEXTBUTTON_ID_CHANGE_FIRST; i <= ED_TEXTBUTTON_ID_CHANGE_LAST; i++)
+ for (i = ED_TEXTBUTTON_ID_CHANGE_FIRST;
+ i <= ED_TEXTBUTTON_ID_CHANGE_LAST; i++)
MapTextbuttonGadget(i);
/* draw graphicbutton gadgets */
MapGraphicbuttonGadget(i);
/* draw drawing area gadgets */
- DrawPropertiesAdvancedDrawingAreas();
+ DrawPropertiesChangeDrawingAreas();
}
static void DrawElementName(int x, int y, int element)
stick_element_properties_window = FALSE;
/* make sure that previous properties edit mode exists for this element */
- if (edit_mode_properties == ED_MODE_PROPERTIES_ADVANCED &&
+ if (edit_mode_properties > ED_MODE_PROPERTIES_CONFIG &&
!IS_CUSTOM_ELEMENT(properties_element))
edit_mode_properties = ED_MODE_PROPERTIES_CONFIG;
- if (IS_CUSTOM_ELEMENT(properties_element))
- CopyCustomElementPropertiesToEditor(properties_element);
+ if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG &&
+ IS_CUSTOM_ELEMENT(properties_element))
+ edit_mode_properties = ED_MODE_PROPERTIES_CONFIG_1;
+
+ CopyElementPropertiesToEditor(properties_element);
UnmapLevelEditorWindowGadgets();
UnmapLevelEditorToolboxDrawingGadgets();
UnmapLevelEditorToolboxCustomGadgets();
- if (IS_CUSTOM_ELEMENT(properties_element))
+ if (IS_CUSTOM_ELEMENT(properties_element) ||
+ IS_GROUP_ELEMENT(properties_element))
MapLevelEditorToolboxCustomGadgets();
SetMainBackgroundImage(IMG_BACKGROUND_EDITOR);
FrameCounter = 0; /* restart animation frame counter */
- DrawElementName((xstart + 3) * MINI_TILEX, (ystart + 1) * MINI_TILEY,
+ DrawElementName((xstart + 3) * MINI_TILEX + 1, (ystart + 1) * MINI_TILEY + 1,
properties_element);
DrawPropertiesTabulatorGadgets();
if (edit_mode_properties == ED_MODE_PROPERTIES_INFO)
DrawPropertiesInfo();
- else if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG)
+ else if (edit_mode_properties == ED_MODE_PROPERTIES_CHANGE)
+ DrawPropertiesChange();
+ else /* (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG[_1|_2]) */
DrawPropertiesConfig();
- else /* edit_mode_properties == ED_MODE_PROPERTIES_ADVANCED */
- DrawPropertiesAdvanced();
}
static void UpdateCustomElementGraphicGadgets()
{
+ int i;
+
ModifyEditorElementList();
RedrawDrawingElements();
- if (edit_mode == ED_MODE_PROPERTIES &&
- edit_mode_properties == ED_MODE_PROPERTIES_ADVANCED)
- DrawPropertiesAdvancedDrawingAreas();
+ /* force redraw of all mapped drawing area gadgets */
+ for (i = 0; i < ED_NUM_DRAWING_AREAS; i++)
+ {
+ struct GadgetInfo *gi = level_editor_gadget[drawingarea_info[i].gadget_id];
+
+ if (gi->mapped)
+ MapDrawingArea(i);
+ }
}
static void DrawLineElement(int sx, int sy, int element, boolean change_level)
#define CB_BRUSH_TO_CURSOR 1
#define CB_BRUSH_TO_LEVEL 2
#define CB_DELETE_OLD_CURSOR 3
+#define CB_DUMP_BRUSH 4
static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y,
int button, int mode)
int new_element = BUTTON_ELEMENT(button);
int x, y;
+ if (mode == CB_DUMP_BRUSH)
+ {
+ if (!draw_with_brush)
+ {
+ Error(ERR_WARN, "no brush selected");
+
+ return;
+ }
+
+ for (y = 0; y < brush_height; y++)
+ {
+ for (x = 0; x < brush_width; x++)
+ {
+ int element = brush_buffer[x][y];
+ int element_mapped = element;
+
+#if 0
+ char *element_string = "?";
+ int k;
+
+ for (k = 0; forum_sketch_element_mapping[k].element != -1; k++)
+ {
+ if (forum_sketch_element_mapping[k].element == element)
+ {
+ element_mapped = forum_sketch_element_mapping[k].element_mapped;
+ break;
+ }
+ }
+
+ if (IS_CUSTOM_ELEMENT(element))
+ element_mapped = EL_CUSTOM_1;
+
+ for (k = 0; forum_sketch_element_strings[k].element != -1; k++)
+ {
+ if (forum_sketch_element_strings[k].element == element_mapped)
+ {
+ element_string = forum_sketch_element_strings[k].element_string;
+ break;
+ }
+ }
+
+ printf("`%s", element_string);
+
+#else
+
+ if (IS_CUSTOM_ELEMENT(element))
+ element_mapped = EL_CUSTOM_START;
+ else if (element > EL_ENVELOPE_4)
+ element_mapped = EL_CHAR_QUESTION; /* change to EL_UNKNOWN ... */
+
+ printf("`%03d", element_mapped);
+#endif
+ }
+
+ printf("\n");
+ }
+
+ return;
+ }
+
if (mode == CB_DELETE_OLD_CURSOR && !delete_old_brush)
return;
CopyBrushExt(0, 0, 0, 0, 0, CB_DELETE_OLD_CURSOR);
}
+void DumpBrush()
+{
+ CopyBrushExt(0, 0, 0, 0, 0, CB_DUMP_BRUSH);
+}
+
static void FloodFill(int from_x, int from_y, int fill_element)
{
int i,x,y;
new_element = GFX_ELEMENT(new_element);
custom_element.gfx_element = new_element;
- CopyCustomElementPropertiesToGame(properties_element);
+ CopyElementPropertiesToGame(properties_element);
UpdateCustomElementGraphicGadgets();
CopyCustomElementPropertiesToGame(properties_element);
}
+ else if (id == GADGET_ID_CUSTOM_MOVE_ENTER)
+ {
+ custom_element.move_enter_element = new_element;
+
+ CopyCustomElementPropertiesToGame(properties_element);
+ }
+ else if (id == GADGET_ID_CUSTOM_MOVE_LEAVE)
+ {
+ custom_element.move_leave_element = new_element;
+
+ CopyCustomElementPropertiesToGame(properties_element);
+ }
else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET)
{
custom_element_change.target_element = new_element;
}
else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
{
- custom_element_change.content[sx][sy] = new_element;
+ custom_element_change.target_content[sx][sy] = new_element;
CopyCustomElementPropertiesToGame(properties_element);
}
CopyCustomElementPropertiesToGame(properties_element);
}
+ else if (id == GADGET_ID_GROUP_CONTENT)
+ {
+ group_element_info.element[sx] = new_element;
+
+ CopyGroupElementPropertiesToGame(properties_element);
+ }
else if (id == GADGET_ID_RANDOM_BACKGROUND)
random_placement_background_element = new_element;
else if (id >= GADGET_ID_ELEMENT_CONTENT_0 &&
PickDrawingElement(button, custom_element.gfx_element);
else if (id == GADGET_ID_CUSTOM_CONTENT)
PickDrawingElement(button, custom_element.content[sx][sy]);
+ else if (id == GADGET_ID_CUSTOM_MOVE_ENTER)
+ PickDrawingElement(button, custom_element.move_enter_element);
+ else if (id == GADGET_ID_CUSTOM_MOVE_LEAVE)
+ PickDrawingElement(button, custom_element.move_leave_element);
else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET)
PickDrawingElement(button, custom_element_change.target_element);
else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
- PickDrawingElement(button, custom_element_change.content[sx][sy]);
+ PickDrawingElement(button, custom_element_change.target_content[sx][sy]);
else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER)
PickDrawingElement(button, custom_element_change.trigger_element);
+ else if (id == GADGET_ID_GROUP_CONTENT)
+ PickDrawingElement(button, group_element_info.element[sx]);
else if (id == GADGET_ID_RANDOM_BACKGROUND)
PickDrawingElement(button, random_placement_background_element);
else if (id >= GADGET_ID_ELEMENT_CONTENT_0 &&
DrawElementContentAreas();
break;
+ case ED_COUNTER_ID_GROUP_CONTENT:
+ DrawGroupElementArea(properties_element);
+ CopyGroupElementPropertiesToGame(properties_element);
+ break;
+
case ED_COUNTER_ID_ENVELOPE_XSIZE:
case ED_COUNTER_ID_ENVELOPE_YSIZE:
DrawEnvelopeTextArea(-1);
counter_id <= ED_COUNTER_ID_CUSTOM_LAST) ||
(counter_id >= ED_COUNTER_ID_CHANGE_FIRST &&
counter_id <= ED_COUNTER_ID_CHANGE_LAST))
- CopyCustomElementPropertiesToGame(properties_element);
+ CopyElementPropertiesToGame(properties_element);
}
static void HandleTextInputGadgets(struct GadgetInfo *gi)
if (type_id == ED_TEXTINPUT_ID_ELEMENT_NAME)
{
- CopyCustomElementPropertiesToGame(properties_element);
+ CopyElementPropertiesToGame(properties_element);
ModifyEditorElementList(); /* update changed button info text */
}
else if ((type_id >= ED_SELECTBOX_ID_CUSTOM_FIRST &&
type_id <= ED_SELECTBOX_ID_CUSTOM_LAST) ||
(type_id >= ED_SELECTBOX_ID_CHANGE_FIRST &&
- type_id <= ED_SELECTBOX_ID_CHANGE_LAST))
- CopyCustomElementPropertiesToGame(properties_element);
+ type_id <= ED_SELECTBOX_ID_CHANGE_LAST) ||
+ (type_id == ED_SELECTBOX_ID_GROUP_CHOICE_MODE))
+ CopyElementPropertiesToGame(properties_element);
}
static void HandleTextbuttonGadgets(struct GadgetInfo *gi)
}
else if (type_id == ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE)
{
- boolean new_template = (!LevelFileExists(-1));
+ char *template_filename = getDefaultLevelFilename(-1);
+ boolean new_template = !fileExists(template_filename);
if (new_template ||
Request("Save this template and kill the old ?", REQ_ASK))
DrawPropertiesWindow();
}
+ else if (type_id == ED_GRAPHICBUTTON_ID_COPY_CHANGE_PAGE ||
+ type_id == ED_GRAPHICBUTTON_ID_PASTE_CHANGE_PAGE)
+ {
+ struct ElementInfo *ei = &element_info[properties_element];
+ int current_change_page = ei->current_change_page;
+
+ if (type_id == ED_GRAPHICBUTTON_ID_COPY_CHANGE_PAGE)
+ element_info[EL_INTERNAL_CLIPBOARD_CHANGE].change_page[0] =
+ ei->change_page[current_change_page];
+ else if (type_id == ED_GRAPHICBUTTON_ID_PASTE_CHANGE_PAGE)
+ ei->change_page[current_change_page] =
+ element_info[EL_INTERNAL_CLIPBOARD_CHANGE].change_page[0];
+
+ DrawPropertiesWindow();
+ }
}
static void HandleRadiobuttons(struct GadgetInfo *gi)
*checkbutton_info[type_id].value ^= TRUE;
- if ((type_id >= ED_CHECKBUTTON_ID_CUSTOM_FIRST &&
- type_id <= ED_CHECKBUTTON_ID_CUSTOM_LAST) ||
- (type_id >= ED_CHECKBUTTON_ID_CHANGE_FIRST &&
- type_id <= ED_CHECKBUTTON_ID_CHANGE_LAST &&
+ if (type_id == ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID ||
+ type_id == ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID ||
+ type_id == ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH ||
+ (((type_id >= ED_CHECKBUTTON_ID_CUSTOM_FIRST &&
+ type_id <= ED_CHECKBUTTON_ID_CUSTOM_LAST) ||
+ (type_id >= ED_CHECKBUTTON_ID_CHANGE_FIRST &&
+ type_id <= ED_CHECKBUTTON_ID_CHANGE_LAST)) &&
type_id != ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE))
{
- CopyCustomElementPropertiesToGame(properties_element);
+ CopyElementPropertiesToGame(properties_element);
}
if (type_id == ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC)
}
else if (type_id == ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE)
{
- if (level.use_custom_template && !LevelFileExists(-1))
+ char *template_filename = getDefaultLevelFilename(-1);
+
+ if (level.use_custom_template && !fileExists(template_filename))
{
Request("No level template found !", REQ_CONFIRM);
edit_mode = ED_MODE_DRAWING;
}
+ /* element copy mode active, but no element button pressed => deactivate */
+ if (last_custom_copy_mode != -1 && id < ED_NUM_CTRL_BUTTONS)
+ last_custom_copy_mode = -1;
+
switch (id)
{
case GADGET_ID_SCROLL_LEFT:
last_drawing_function = drawing_function;
break;
+ case GADGET_ID_CUSTOM_COPY:
+ CopyCustomElement(properties_element, -1, id);
+ break;
+
+ case GADGET_ID_CUSTOM_PASTE:
+ CopyCustomElement(-1, properties_element, id);
+ break;
+
case GADGET_ID_UNDO:
if (undo_buffer_steps == 0)
{
Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
else
{
- boolean new_level = (!LevelFileExists(level_nr));
+ char *level_filename = getDefaultLevelFilename(level_nr);
+ boolean new_level = !fileExists(level_filename);
if (new_level ||
Request("Save this level and kill the old ?", REQ_ASK))
if (last_custom_copy_mode != -1)
{
- CopyCustomElement(properties_element, new_element,
- last_custom_copy_mode);
-
- ClickOnGadget(level_editor_gadget[last_drawing_function],
- MB_LEFTBUTTON);
+ if (CopyCustomElement(properties_element, new_element,
+ last_custom_copy_mode))
+ {
+ ClickOnGadget(level_editor_gadget[last_drawing_function],
+ MB_LEFTBUTTON);
- last_custom_copy_mode = -1;
+ last_custom_copy_mode = -1;
+ }
break;
}
{
RequestExitLevelEditor(setup.ask_on_escape);
}
- else
+ else if (edit_mode == ED_MODE_INFO)
+ {
+ HandleControlButtons(level_editor_gadget[GADGET_ID_INFO]);
+ }
+ else if (edit_mode == ED_MODE_PROPERTIES)
+ {
+ HandleControlButtons(level_editor_gadget[GADGET_ID_PROPERTIES]);
+ }
+ else /* should never happen */
{
DrawDrawingWindow();
edit_mode = ED_MODE_DRAWING;
static void HandleDrawingAreaInfo(struct GadgetInfo *gi)
{
static int start_lx, start_ly;
- char *infotext;
int id = gi->custom_id;
int sx = gi->event.x;
int sy = gi->event.y;
int max_sx = gi->drawing.area_xsize - 1;
int max_sy = gi->drawing.area_ysize - 1;
int actual_drawing_function = drawing_function;
+ int max_infotext_len = getMaxInfoTextLength();
+ char infotext[MAX_OUTPUT_LINESIZE + 1];
+ char *text;
+
+ infotext[0] = '\0'; /* start with empty info text */
/* pressed Control key: simulate picking element */
if (GetKeyModState() & KMOD_Control)
switch (actual_drawing_function)
{
case GADGET_ID_SINGLE_ITEMS:
- infotext = "Drawing single items";
+ text = "Drawing single items";
break;
case GADGET_ID_CONNECTED_ITEMS:
- infotext = "Drawing connected items";
+ text = "Drawing connected items";
break;
case GADGET_ID_LINE:
- infotext = "Drawing line";
+ text = "Drawing line";
break;
case GADGET_ID_ARC:
- infotext = "Drawing arc";
+ text = "Drawing arc";
break;
case GADGET_ID_TEXT:
- infotext = "Setting text cursor";
+ text = "Setting text cursor";
break;
case GADGET_ID_RECTANGLE:
- infotext = "Drawing rectangle";
+ text = "Drawing rectangle";
break;
case GADGET_ID_FILLED_BOX:
- infotext = "Drawing filled box";
+ text = "Drawing filled box";
break;
case GADGET_ID_FLOOD_FILL:
- infotext = "Flood fill";
+ text = "Flood fill";
break;
case GADGET_ID_GRAB_BRUSH:
- infotext = "Grabbing brush";
+ text = "Grabbing brush";
break;
case GADGET_ID_PICK_ELEMENT:
- infotext = "Picking element";
+ text = "Picking element";
break;
default:
- infotext = "Drawing position";
+ text = "Drawing position";
break;
}
+#if 1
+ if (actual_drawing_function == GADGET_ID_PICK_ELEMENT)
+ sprintf(infotext, "%s: %d, %d", text, lx, ly);
+ else
+ sprintf(infotext, "%s: %d, %d", text,
+ ABS(lx - start_lx) + 1, ABS(ly - start_ly) + 1);
+#else
if (actual_drawing_function == GADGET_ID_PICK_ELEMENT)
DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
"%s: %d, %d", infotext, lx, ly);
DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
"%s: %d, %d", infotext,
ABS(lx - start_lx) + 1, ABS(ly - start_ly) + 1);
+#endif
}
+#if 1
+ else if (actual_drawing_function == GADGET_ID_PICK_ELEMENT)
+ strncpy(infotext, getElementInfoText(Feld[lx][ly]), max_infotext_len);
+ else
+ sprintf(infotext, "Level position: %d, %d", lx, ly);
+#else
else if (actual_drawing_function == GADGET_ID_PICK_ELEMENT)
DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
"%s", getElementInfoText(Feld[lx][ly]));
else
DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
"Level position: %d, %d", lx, ly);
+#endif
}
/* misuse this function to draw brush cursor, if needed */
}
else if (actual_drawing_function == GADGET_ID_PICK_ELEMENT)
{
+ int element = EL_EMPTY;
+
if (id == GADGET_ID_AMOEBA_CONTENT)
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
- getElementInfoText(level.amoeba_content));
+ element = level.amoeba_content;
else if (id == GADGET_ID_CUSTOM_GRAPHIC)
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
- getElementInfoText(custom_element.gfx_element));
+ element = custom_element.gfx_element;
else if (id == GADGET_ID_CUSTOM_CONTENT)
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
- getElementInfoText(custom_element.content[sx][sy]));
+ element = custom_element.content[sx][sy];
+ else if (id == GADGET_ID_CUSTOM_MOVE_ENTER)
+ element = custom_element.move_enter_element;
+ else if (id == GADGET_ID_CUSTOM_MOVE_LEAVE)
+ element = custom_element.move_leave_element;
else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET)
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
- getElementInfoText(custom_element_change.target_element));
+ element = custom_element_change.target_element;
else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
- getElementInfoText(custom_element_change.content[sx][sy]));
+ element = custom_element_change.target_content[sx][sy];
else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER)
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
- getElementInfoText(custom_element_change.trigger_element));
+ element = custom_element_change.trigger_element;
+ else if (id == GADGET_ID_GROUP_CONTENT)
+ element = group_element_info.element[sx];
else if (id == GADGET_ID_RANDOM_BACKGROUND)
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
- getElementInfoText(random_placement_background_element));
+ element = random_placement_background_element;
else if (id >= GADGET_ID_ELEMENT_CONTENT_0 &&
id <= GADGET_ID_ELEMENT_CONTENT_7)
- {
- int i = id - GADGET_ID_ELEMENT_CONTENT_0;
+ element = level.yamyam_content[id - GADGET_ID_ELEMENT_CONTENT_0][sx][sy];
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
- getElementInfoText(level.yamyam_content[i][sx][sy]));
- }
+ strncpy(infotext, getElementInfoText(element), max_infotext_len);
}
else
{
if (id == GADGET_ID_AMOEBA_CONTENT)
- DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
- "Amoeba content");
+ strcpy(infotext, "Amoeba content");
else if (id == GADGET_ID_CUSTOM_GRAPHIC)
- DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
- "Custom graphic element");
+ strcpy(infotext, "Custom graphic element");
else if (id == GADGET_ID_CUSTOM_CONTENT)
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
- "Custom element content position: %d, %d", sx, sy);
+ sprintf(infotext, "Custom element content position: %d, %d", sx, sy);
+ else if (id == GADGET_ID_CUSTOM_MOVE_ENTER)
+ strcpy(infotext, "Element that can be digged/collected");
+ else if (id == GADGET_ID_CUSTOM_MOVE_LEAVE)
+ strcpy(infotext, "Element that will be left behind");
else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET)
- DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
- "New element after change");
+ strcpy(infotext, "New element after change");
else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
- DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
- "New extended elements after change");
+ strcpy(infotext, "New extended elements after change");
else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER)
- DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
- "Other element triggering change");
+ strcpy(infotext, "Other element triggering change");
+ else if (id == GADGET_ID_GROUP_CONTENT)
+ sprintf(infotext, "Group element position: %d", sx + 1);
else if (id == GADGET_ID_RANDOM_BACKGROUND)
- DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
- "Random placement background");
+ strcpy(infotext, "Random placement background");
else if (id >= GADGET_ID_ELEMENT_CONTENT_0 &&
id <= GADGET_ID_ELEMENT_CONTENT_7)
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
- "Content area %d position: %d, %d",
- id - GADGET_ID_ELEMENT_CONTENT_0 + 1, sx, sy);
+ sprintf(infotext, "Content area %d position: %d, %d",
+ id - GADGET_ID_ELEMENT_CONTENT_0 + 1, sx, sy);
}
+
+ infotext[max_infotext_len] = '\0';
+
+ if (strlen(infotext) > 0)
+ DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, infotext);
}
void RequestExitLevelEditor(boolean ask_if_level_has_changed)
void RequestExitLevelEditor(boolean);
void PrintEditorElementList();
+void DumpBrush();
+
#endif
{
Event event;
- if (NextValidEvent(&event))
+ while (NextValidEvent(&event))
{
switch(event.type)
{
else
{
/* when playing, display a special mouse pointer inside the playfield */
- if (game_status == GAME_MODE_PLAYING)
+ if (game_status == GAME_MODE_PLAYING && !tape.pausing)
{
if (!playfield_cursor_set && cursor_inside_playfield &&
DelayReached(&playfield_cursor_delay, 1000))
case GAME_MODE_PLAYING:
#ifdef DEBUG
- if (button == MB_RELEASED)
- {
- if (IN_GFX_SCREEN(mx, my))
- {
- int sx = (mx - SX) / TILEX;
- int sy = (my - SY) / TILEY;
- int x = LEVELX(sx);
- int y = LEVELY(sy);
-
- printf("INFO: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
-
- if (!IN_LEV_FIELD(x, y))
- break;
-
- printf(" Feld[%d][%d] == %d ('%s')\n", x,y, Feld[x][y],
- element_info[Feld[x][y]].token_name);
- printf(" Back[%d][%d] == %d\n", x,y, Back[x][y]);
- printf(" Store[%d][%d] == %d\n", x,y, Store[x][y]);
- printf(" Store2[%d][%d] == %d\n", x,y, Store2[x][y]);
- printf(" StorePlayer[%d][%d] == %d\n", x,y, StorePlayer[x][y]);
- printf(" MovPos[%d][%d] == %d\n", x,y, MovPos[x][y]);
- printf(" MovDir[%d][%d] == %d\n", x,y, MovDir[x][y]);
- printf(" MovDelay[%d][%d] == %d\n", x,y, MovDelay[x][y]);
- printf(" ChangeDelay[%d][%d] == %d\n", x,y, ChangeDelay[x][y]);
- printf(" GfxElement[%d][%d] == %d\n", x,y, GfxElement[x][y]);
- printf(" GfxAction[%d][%d] == %d\n", x,y, GfxAction[x][y]);
- printf(" GfxFrame[%d][%d] == %d\n", x,y, GfxFrame[x][y]);
- printf("\n");
- }
- }
+ if (button == MB_PRESSED && !motion_status && IN_GFX_SCREEN(mx, my))
+ DumpTile(LEVELX((mx - SX) / TILEX), LEVELY((my - SY) / TILEY));
#endif
break;
#define MAX_CHEAT_INPUT_LEN 32
-static void HandleKeysCheating(Key key)
+static void HandleKeysSpecial(Key key)
{
static char cheat_input[2 * MAX_CHEAT_INPUT_LEN + 1] = "";
char letter = getCharFromKey(key);
printf("::: '%s' [%d]\n", cheat_input, cheat_input_len);
#endif
-#if 1
- if (is_string_suffix(cheat_input, ":insert solution tape"))
- InsertSolutionTape();
-#else
- if (is_string_suffix(cheat_input, ":ist"))
- InsertSolutionTape();
-#endif
-
+ if (game_status == GAME_MODE_MAIN)
+ {
+ if (is_string_suffix(cheat_input, ":insert-solution-tape") ||
+ is_string_suffix(cheat_input, ":ist"))
+ {
+ InsertSolutionTape();
+ }
+ else if (is_string_suffix(cheat_input, ":reload-graphics") ||
+ is_string_suffix(cheat_input, ":rg"))
+ {
+ ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS);
+ DrawMainMenu();
+ }
+ else if (is_string_suffix(cheat_input, ":reload-sounds") ||
+ is_string_suffix(cheat_input, ":rs"))
+ {
+ ReloadCustomArtwork(1 << ARTWORK_TYPE_SOUNDS);
+ DrawMainMenu();
+ }
+ else if (is_string_suffix(cheat_input, ":reload-music") ||
+ is_string_suffix(cheat_input, ":rm"))
+ {
+ ReloadCustomArtwork(1 << ARTWORK_TYPE_MUSIC);
+ DrawMainMenu();
+ }
+ else if (is_string_suffix(cheat_input, ":reload-artwork") ||
+ is_string_suffix(cheat_input, ":ra"))
+ {
+ ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS |
+ 1 << ARTWORK_TYPE_SOUNDS |
+ 1 << ARTWORK_TYPE_MUSIC);
+ DrawMainMenu();
+ }
+ else if (is_string_suffix(cheat_input, ":dump-level") ||
+ is_string_suffix(cheat_input, ":dl"))
+ {
+ DumpLevel(&level);
+ }
+ else if (is_string_suffix(cheat_input, ":dump-tape") ||
+ is_string_suffix(cheat_input, ":dt"))
+ {
+ DumpTape(&tape);
+ }
+ }
+ else if (game_status == GAME_MODE_PLAYING)
+ {
#ifdef DEBUG
- else if (is_string_suffix(cheat_input, ":dump tape"))
- DumpTape(&tape);
- else if (is_string_suffix(cheat_input, ".q"))
- for (i = 0; i < MAX_INVENTORY_SIZE; i++)
- if (local_player->inventory_size < MAX_INVENTORY_SIZE)
- local_player->inventory_element[local_player->inventory_size++] =
- EL_DYNAMITE;
+ if (is_string_suffix(cheat_input, ".q"))
+ for (i = 0; i < MAX_INVENTORY_SIZE; i++)
+ if (local_player->inventory_size < MAX_INVENTORY_SIZE)
+ local_player->inventory_element[local_player->inventory_size++] =
+ EL_DYNAMITE;
#endif
+ }
+ else if (game_status == GAME_MODE_EDITOR)
+ {
+ if (is_string_suffix(cheat_input, ":dump-brush") ||
+ is_string_suffix(cheat_input, ":DB"))
+ {
+ DumpBrush();
+ }
+ }
}
void HandleKey(Key key, int key_status)
{ &custom_key.up, DEFAULT_KEY_UP, JOY_UP },
{ &custom_key.down, DEFAULT_KEY_DOWN, JOY_DOWN },
{ &custom_key.snap, DEFAULT_KEY_SNAP, JOY_BUTTON_1 },
- { &custom_key.bomb, DEFAULT_KEY_BOMB, JOY_BUTTON_2 }
+ { &custom_key.drop, DEFAULT_KEY_DROP, JOY_BUTTON_2 }
};
if (game_status == GAME_MODE_PLAYING)
{
/* only needed for single-step tape recording mode */
static boolean clear_button_2[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
- static boolean bomb_placed[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
+ static boolean element_dropped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
int pnr;
for (pnr = 0; pnr < MAX_PLAYERS; pnr++)
if (key_action & KEY_MOTION)
{
if (stored_player[pnr].action & KEY_BUTTON_2)
- bomb_placed[pnr] = TRUE;
+ element_dropped[pnr] = TRUE;
}
}
else if (key_status == KEY_RELEASED &&
(key_action & KEY_BUTTON_2))
{
- if (!bomb_placed[pnr])
+ if (!element_dropped[pnr])
{
TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
clear_button_2[pnr] = TRUE;
}
- bomb_placed[pnr] = FALSE;
+ element_dropped[pnr] = FALSE;
}
}
else if (tape.recording && tape.pausing && (key_action & KEY_ACTION))
if (key_status == KEY_RELEASED)
return;
- if ((key == KSYM_Return || key == setup.shortcut.toggle_pause) &&
- game_status == GAME_MODE_PLAYING && AllPlayersGone)
+ if (game_status == GAME_MODE_PLAYING && AllPlayersGone &&
+ (key == KSYM_Return || key == setup.shortcut.toggle_pause))
{
CloseDoor(DOOR_CLOSE_1);
game_status = GAME_MODE_MAIN;
DrawMainMenu();
+
+ return;
+ }
+
+ if (game_status == GAME_MODE_MAIN && key == setup.shortcut.toggle_pause)
+ {
+ if (setup.autorecord)
+ TapeStartRecording();
+
+#if defined(NETWORK_AVALIABLE)
+ if (options.network)
+ SendToServer_StartPlaying();
+ else
+#endif
+ {
+ game_status = GAME_MODE_PLAYING;
+ StopAnimation();
+ InitGame();
+ }
+
return;
}
- /* special key shortcuts */
if (game_status == GAME_MODE_MAIN || game_status == GAME_MODE_PLAYING)
{
if (key == setup.shortcut.save_game)
TapeQuickLoad();
else if (key == setup.shortcut.toggle_pause)
TapeTogglePause(TAPE_TOGGLE_MANUAL);
-
- HandleKeysCheating(key);
}
+ HandleKeysSpecial(key);
+
if (HandleGadgetsKeyInput(key))
{
if (key != KSYM_Escape) /* always allow ESC key to be handled */
case GAME_MODE_INFO:
switch(key)
{
+ case KSYM_space:
case KSYM_Return:
if (game_status == GAME_MODE_MAIN)
HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
case GAME_MODE_SCORES:
switch(key)
{
+ case KSYM_space:
case KSYM_Return:
case KSYM_Escape:
game_status = GAME_MODE_MAIN;
return;
}
-#if defined(PLATFORM_UNIX)
+#if defined(NETWORK_AVALIABLE)
if (options.network)
HandleNetworking();
#endif
#define CHUNK_SIZE_NONE -1 /* do not write chunk size */
#define FILE_VERS_CHUNK_SIZE 8 /* size of file version chunk */
#define LEVEL_HEADER_SIZE 80 /* size of level file header */
-#define LEVEL_HEADER_UNUSED 13 /* unused level header bytes */
+#define LEVEL_HEADER_UNUSED 1 /* unused level header bytes */
#define LEVEL_CHUNK_CNT2_SIZE 160 /* size of level CNT2 chunk */
#define LEVEL_CHUNK_CNT2_UNUSED 11 /* unused CNT2 chunk bytes */
#define LEVEL_CHUNK_CNT3_HEADER 16 /* size of level CNT3 header */
#define LEVEL_CHUNK_CNT3_UNUSED 10 /* unused CNT3 chunk bytes */
#define LEVEL_CPART_CUS3_SIZE 134 /* size of CUS3 chunk part */
#define LEVEL_CPART_CUS3_UNUSED 15 /* unused CUS3 bytes / part */
+#define LEVEL_CHUNK_GRP1_SIZE 74 /* size of level GRP1 chunk */
#define TAPE_HEADER_SIZE 20 /* size of tape file header */
#define TAPE_HEADER_UNUSED 3 /* unused tape header bytes */
+#define LEVEL_CHUNK_CNT3_SIZE(x) (LEVEL_CHUNK_CNT3_HEADER + (x))
#define LEVEL_CHUNK_CUS3_SIZE(x) (2 + (x) * LEVEL_CPART_CUS3_SIZE)
#define LEVEL_CHUNK_CUS4_SIZE(x) (48 + 48 + (x) * 48)
#define TAPE_COOKIE_TMPL "ROCKSNDIAMONDS_TAPE_FILE_VERSION_x.x"
#define SCORE_COOKIE "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.2"
+/* values for level file type identifier */
+#define LEVEL_FILE_TYPE_UNKNOWN 0
+#define LEVEL_FILE_TYPE_RND 1
+#define LEVEL_FILE_TYPE_BD 2
+#define LEVEL_FILE_TYPE_EM 3
+#define LEVEL_FILE_TYPE_SP 4
+#define LEVEL_FILE_TYPE_DX 5
+#define LEVEL_FILE_TYPE_SB 6
+#define LEVEL_FILE_TYPE_DC 7
+
+#define LEVEL_FILE_TYPE_RND_PACKED (10 + LEVEL_FILE_TYPE_RND)
+#define LEVEL_FILE_TYPE_EM_PACKED (10 + LEVEL_FILE_TYPE_EM)
+
+#define IS_SINGLE_LEVEL_FILE(x) (x < 10)
+#define IS_PACKED_LEVEL_FILE(x) (x > 10)
+
/* ========================================================================= */
/* level file functions */
change->can_change = FALSE;
change->events = CE_BITMASK_DEFAULT;
- change->sides = CH_SIDE_ANY;
+
+ change->trigger_player = CH_PLAYER_ANY;
+ change->trigger_side = CH_SIDE_ANY;
+ change->trigger_page = CH_PAGE_ANY;
change->target_element = EL_EMPTY_SPACE;
change->trigger_element = EL_EMPTY_SPACE;
change->explode = FALSE;
- change->use_content = FALSE;
- change->only_complete = FALSE;
- change->use_random_change = FALSE;
- change->random = 100;
- change->power = CP_NON_DESTRUCTIVE;
+ change->use_target_content = FALSE;
+ change->only_if_complete = FALSE;
+ change->use_random_replace = FALSE;
+ change->random_percentage = 100;
+ change->replace_when = CP_WHEN_EMPTY;
for (x = 0; x < 3; x++)
for (y = 0; y < 3; y++)
- change->content[x][y] = EL_EMPTY_SPACE;
+ change->target_content[x][y] = EL_EMPTY_SPACE;
change->direct_action = 0;
change->other_action = 0;
static void setLevelInfoToDefaults(struct LevelInfo *level)
{
+ static boolean clipboard_elements_initialized = FALSE;
+
int i, j, x, y;
level->file_version = FILE_VERSION_ACTUAL;
level->time = 100;
level->gems_needed = 0;
+
level->amoeba_speed = 10;
+
level->time_magic_wall = 10;
level->time_wheel = 10;
level->time_light = 10;
level->time_timegate = 10;
+
level->amoeba_content = EL_DIAMOND;
+
level->double_speed = FALSE;
level->initial_gravity = FALSE;
level->em_slippery_gems = FALSE;
+ level->block_last_field = FALSE;
+ level->sp_block_last_field = TRUE;
+ level->instant_relocation = FALSE;
+ level->can_pass_to_walkable = FALSE;
+ level->grow_into_diggable = TRUE;
+
+ level->can_move_into_acid_bits = ~0; /* everything can move into acid */
+ level->dont_collide_with_bits = ~0; /* always deadly when colliding */
+
+ level->use_spring_bug = FALSE;
+ level->use_step_counter = FALSE;
level->use_custom_template = FALSE;
for (i = 0; i < MAX_NUM_ELEMENTS; i++)
{
- setElementChangePages(&element_info[i], 1);
- setElementChangeInfoToDefaults(element_info[i].change);
- }
+ int element = i;
- for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
- {
- int element = EL_CUSTOM_START + i;
+ /* never initialize clipboard elements after the very first time */
+ if (IS_CLIPBOARD_ELEMENT(element) && clipboard_elements_initialized)
+ continue;
- for (j = 0; j < MAX_ELEMENT_NAME_LEN + 1; j++)
- element_info[element].description[j] = '\0';
- if (element_info[element].custom_description != NULL)
- strncpy(element_info[element].description,
- element_info[element].custom_description, MAX_ELEMENT_NAME_LEN);
- else
- strcpy(element_info[element].description,
- element_info[element].editor_description);
+ setElementChangePages(&element_info[element], 1);
+ setElementChangeInfoToDefaults(element_info[element].change);
- element_info[element].use_gfx_element = FALSE;
- element_info[element].gfx_element = EL_EMPTY_SPACE;
+ if (IS_CUSTOM_ELEMENT(element) ||
+ IS_GROUP_ELEMENT(element) ||
+ IS_INTERNAL_ELEMENT(element))
+ {
+ for (j = 0; j < MAX_ELEMENT_NAME_LEN + 1; j++)
+ element_info[element].description[j] = '\0';
- element_info[element].collect_score = 10; /* special default */
- element_info[element].collect_count = 1; /* special default */
+ if (element_info[element].custom_description != NULL)
+ strncpy(element_info[element].description,
+ element_info[element].custom_description,MAX_ELEMENT_NAME_LEN);
+ else
+ strcpy(element_info[element].description,
+ element_info[element].editor_description);
- element_info[element].push_delay_fixed = -1; /* initialize later */
- element_info[element].push_delay_random = -1; /* initialize later */
- element_info[element].move_delay_fixed = 0;
- element_info[element].move_delay_random = 0;
+ element_info[element].use_gfx_element = FALSE;
+ element_info[element].gfx_element = EL_EMPTY_SPACE;
- element_info[element].move_pattern = MV_ALL_DIRECTIONS;
- element_info[element].move_direction_initial = MV_NO_MOVING;
- element_info[element].move_stepsize = TILEX / 8;
+ element_info[element].modified_settings = FALSE;
+ }
- element_info[element].slippery_type = SLIPPERY_ANY_RANDOM;
+ if (IS_CUSTOM_ELEMENT(element) ||
+ IS_INTERNAL_ELEMENT(element))
+ {
+ element_info[element].access_direction = MV_ALL_DIRECTIONS;
- for (x = 0; x < 3; x++)
- for (y = 0; y < 3; y++)
- element_info[element].content[x][y] = EL_EMPTY_SPACE;
+ element_info[element].collect_score = 10; /* special default */
+ element_info[element].collect_count = 1; /* special default */
+
+ element_info[element].push_delay_fixed = -1; /* initialize later */
+ element_info[element].push_delay_random = -1; /* initialize later */
+ element_info[element].drop_delay_fixed = 0;
+ element_info[element].drop_delay_random = 0;
+ element_info[element].move_delay_fixed = 0;
+ element_info[element].move_delay_random = 0;
+
+ element_info[element].move_pattern = MV_ALL_DIRECTIONS;
+ element_info[element].move_direction_initial = MV_START_AUTOMATIC;
+ element_info[element].move_stepsize = TILEX / 8;
+
+ element_info[element].move_enter_element = EL_EMPTY_SPACE;
+ element_info[element].move_leave_element = EL_EMPTY_SPACE;
+ element_info[element].move_leave_type = LEAVE_TYPE_UNLIMITED;
+
+ element_info[element].slippery_type = SLIPPERY_ANY_RANDOM;
- element_info[element].access_type = 0;
- element_info[element].access_layer = 0;
- element_info[element].walk_to_action = 0;
- element_info[element].smash_targets = 0;
- element_info[element].deadliness = 0;
- element_info[element].consistency = 0;
+ element_info[element].explosion_type = EXPLODES_3X3;
+ element_info[element].explosion_delay = 16;
+ element_info[element].ignition_delay = 8;
- element_info[element].can_explode_by_fire = FALSE;
- element_info[element].can_explode_smashed = FALSE;
- element_info[element].can_explode_impact = FALSE;
+ for (x = 0; x < 3; x++)
+ for (y = 0; y < 3; y++)
+ element_info[element].content[x][y] = EL_EMPTY_SPACE;
+
+ element_info[element].access_type = 0;
+ element_info[element].access_layer = 0;
+ element_info[element].access_protected = 0;
+ element_info[element].walk_to_action = 0;
+ element_info[element].smash_targets = 0;
+ element_info[element].deadliness = 0;
+
+ element_info[element].can_explode_by_fire = FALSE;
+ element_info[element].can_explode_smashed = FALSE;
+ element_info[element].can_explode_impact = FALSE;
+
+ element_info[element].current_change_page = 0;
+
+ /* start with no properties at all */
+ for (j = 0; j < NUM_EP_BITFIELDS; j++)
+ Properties[element][j] = EP_BITMASK_DEFAULT;
+
+ /* now set default properties */
+ SET_PROPERTY(element, EP_CAN_MOVE_INTO_ACID, TRUE);
+ }
+
+ if (IS_GROUP_ELEMENT(element) ||
+ IS_INTERNAL_ELEMENT(element))
+ {
+ /* initialize memory for list of elements in group */
+ if (element_info[element].group == NULL)
+ element_info[element].group =
+ checked_malloc(sizeof(struct ElementGroupInfo));
- element_info[element].current_change_page = 0;
+ for (j = 0; j < MAX_ELEMENTS_IN_GROUP; j++)
+ element_info[element].group->element[j] = EL_EMPTY_SPACE;
- /* start with no properties at all */
- for (j = 0; j < NUM_EP_BITFIELDS; j++)
- Properties[element][j] = EP_BITMASK_DEFAULT;
+ /* default: only one element in group */
+ element_info[element].group->num_elements = 1;
- element_info[element].modified_settings = FALSE;
+ element_info[element].group->choice_mode = ANIM_RANDOM;
+ }
}
+ clipboard_elements_initialized = TRUE;
+
BorderElement = EL_STEELWALL;
- level->no_level_file = FALSE;
+ level->no_valid_file = FALSE;
if (leveldir_current == NULL) /* only when dumping level */
return;
}
}
+static void setFileInfoToDefaults(struct LevelFileInfo *level_file_info)
+{
+ level_file_info->nr = 0;
+ level_file_info->type = LEVEL_FILE_TYPE_UNKNOWN;
+ level_file_info->packed = FALSE;
+ level_file_info->basename = NULL;
+ level_file_info->filename = NULL;
+}
+
static void ActivateLevelTemplate()
{
/* Currently there is no special action needed to activate the template
level data, while all other variables do not change. */
}
-boolean LevelFileExists(int level_nr)
+static char *getLevelFilenameFromBasename(char *basename)
+{
+ static char *filename = NULL;
+
+ checked_free(filename);
+
+ filename = getPath2(getCurrentLevelDir(), basename);
+
+ return filename;
+}
+
+static int getFileTypeFromBasename(char *basename)
+{
+ static char *filename = NULL;
+ struct stat file_status;
+
+ /* ---------- try to determine file type from filename ---------- */
+
+ /* check for typical filename of a Supaplex level package file */
+ if (strlen(basename) == 10 && (strncmp(basename, "levels.d", 8) == 0 ||
+ strncmp(basename, "LEVELS.D", 8) == 0))
+ return LEVEL_FILE_TYPE_SP;
+
+ /* ---------- try to determine file type from filesize ---------- */
+
+ checked_free(filename);
+ filename = getPath2(getCurrentLevelDir(), basename);
+
+ if (stat(filename, &file_status) == 0)
+ {
+ /* check for typical filesize of a Supaplex level package file */
+ if (file_status.st_size == 170496)
+ return LEVEL_FILE_TYPE_SP;
+ }
+
+ return LEVEL_FILE_TYPE_UNKNOWN;
+}
+
+static char *getSingleLevelBasename(int nr, int type)
+{
+ static char basename[MAX_FILENAME_LEN];
+ char *level_filename = getStringCopy(leveldir_current->level_filename);
+
+ if (level_filename == NULL)
+ level_filename = getStringCat2("%03d.", LEVELFILE_EXTENSION);
+
+ switch (type)
+ {
+ case LEVEL_FILE_TYPE_RND:
+ if (nr < 0)
+ sprintf(basename, "template.%s", LEVELFILE_EXTENSION);
+ else
+ sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION);
+ break;
+
+ case LEVEL_FILE_TYPE_EM:
+ sprintf(basename, "%d", nr);
+ break;
+
+ case LEVEL_FILE_TYPE_UNKNOWN:
+ default:
+ sprintf(basename, level_filename, nr);
+ break;
+ }
+
+ free(level_filename);
+
+ return basename;
+}
+
+static char *getPackedLevelBasename(int type)
+{
+ static char basename[MAX_FILENAME_LEN];
+ char *directory = getCurrentLevelDir();
+ DIR *dir;
+ struct dirent *dir_entry;
+
+ strcpy(basename, UNDEFINED_FILENAME); /* default: undefined file */
+
+ if ((dir = opendir(directory)) == NULL)
+ {
+ Error(ERR_WARN, "cannot read current level directory '%s'", directory);
+
+ return basename;
+ }
+
+ while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
+ {
+ char *entry_basename = dir_entry->d_name;
+ int entry_type = getFileTypeFromBasename(entry_basename);
+
+ if (entry_type != LEVEL_FILE_TYPE_UNKNOWN) /* found valid level package */
+ {
+ if (type == LEVEL_FILE_TYPE_UNKNOWN ||
+ type == entry_type)
+ {
+ strcpy(basename, entry_basename);
+
+ break;
+ }
+ }
+ }
+
+ closedir(dir);
+
+ return basename;
+}
+
+static char *getSingleLevelFilename(int nr, int type)
+{
+ return getLevelFilenameFromBasename(getSingleLevelBasename(nr, type));
+}
+
+#if 0
+static char *getPackedLevelFilename(int type)
+{
+ return getLevelFilenameFromBasename(getPackedLevelBasename(type));
+}
+#endif
+
+char *getDefaultLevelFilename(int nr)
+{
+ return getSingleLevelFilename(nr, LEVEL_FILE_TYPE_RND);
+}
+
+static void setLevelFileInfo_SingleLevelFilename(struct LevelFileInfo *lfi,
+ int type)
+{
+ lfi->type = type;
+ lfi->packed = FALSE;
+ lfi->basename = getSingleLevelBasename(lfi->nr, lfi->type);
+ lfi->filename = getLevelFilenameFromBasename(lfi->basename);
+}
+
+static void setLevelFileInfo_PackedLevelFilename(struct LevelFileInfo *lfi,
+ int type)
+{
+ lfi->type = type;
+ lfi->packed = TRUE;
+ lfi->basename = getPackedLevelBasename(lfi->type);
+ lfi->filename = getLevelFilenameFromBasename(lfi->basename);
+}
+
+static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi)
+{
+ /* special case: level number is negative => check for level template file */
+ if (lfi->nr < 0)
+ {
+ setLevelFileInfo_SingleLevelFilename(lfi, LEVEL_FILE_TYPE_RND);
+
+ return;
+ }
+
+ if (leveldir_current->level_filename != NULL)
+ {
+ /* check for file name/pattern specified in "levelinfo.conf" */
+ setLevelFileInfo_SingleLevelFilename(lfi, LEVEL_FILE_TYPE_UNKNOWN);
+ if (fileExists(lfi->filename))
+ return;
+ }
+
+ /* check for native Rocks'n'Diamonds level file */
+ setLevelFileInfo_SingleLevelFilename(lfi, LEVEL_FILE_TYPE_RND);
+ if (fileExists(lfi->filename))
+ return;
+
+ /* check for classic Emerald Mine level file */
+ setLevelFileInfo_SingleLevelFilename(lfi, LEVEL_FILE_TYPE_EM);
+ if (fileExists(lfi->filename))
+ return;
+
+ /* check for various packed level file formats */
+ setLevelFileInfo_PackedLevelFilename(lfi, LEVEL_FILE_TYPE_UNKNOWN);
+ if (fileExists(lfi->filename))
+ return;
+
+ /* no known level file found -- try to use default values */
+ setLevelFileInfo_SingleLevelFilename(lfi, LEVEL_FILE_TYPE_UNKNOWN);
+}
+
+static void determineLevelFileInfo_Filetype(struct LevelFileInfo *lfi)
{
- char *filename = getLevelFilename(level_nr);
+ if (lfi->type == LEVEL_FILE_TYPE_UNKNOWN)
+ lfi->type = getFileTypeFromBasename(lfi->basename);
+}
+
+static struct LevelFileInfo *getLevelFileInfo(int nr)
+{
+ static struct LevelFileInfo level_file_info;
+
+ /* always start with reliable default values */
+ setFileInfoToDefaults(&level_file_info);
+
+ level_file_info.nr = nr; /* set requested level number */
+
+ determineLevelFileInfo_Filename(&level_file_info);
+ determineLevelFileInfo_Filetype(&level_file_info);
- return (access(filename, F_OK) == 0);
+ return &level_file_info;
}
-static int checkLevelElement(int element)
+
+/* ------------------------------------------------------------------------- */
+/* functions for loading R'n'D level */
+/* ------------------------------------------------------------------------- */
+
+int getMappedElement(int element)
{
- /* map some (historic, now obsolete) elements */
+ /* remap some (historic, now obsolete) elements */
#if 1
switch (element)
{
Error(ERR_WARN, "invalid level element %d", element);
- element = EL_CHAR_QUESTION;
+ element = EL_UNKNOWN;
}
break;
}
{
Error(ERR_WARN, "invalid level element %d", element);
- element = EL_CHAR_QUESTION;
+ element = EL_UNKNOWN;
}
else if (element == EL_PLAYER_OBSOLETE)
element = EL_PLAYER_1;
return element;
}
+int getMappedElementByVersion(int element, int game_version)
+{
+ /* remap some elements due to certain game version */
+
+ if (game_version <= VERSION_IDENT(2,2,0,0))
+ {
+ /* map game font elements */
+ element = (element == EL_CHAR('[') ? EL_CHAR_AUMLAUT :
+ element == EL_CHAR('\\') ? EL_CHAR_OUMLAUT :
+ element == EL_CHAR(']') ? EL_CHAR_UUMLAUT :
+ element == EL_CHAR('^') ? EL_CHAR_COPYRIGHT : element);
+ }
+
+ if (game_version < VERSION_IDENT(3,0,0,0))
+ {
+ /* map Supaplex gravity tube elements */
+ element = (element == EL_SP_GRAVITY_PORT_LEFT ? EL_SP_PORT_LEFT :
+ element == EL_SP_GRAVITY_PORT_RIGHT ? EL_SP_PORT_RIGHT :
+ element == EL_SP_GRAVITY_PORT_UP ? EL_SP_PORT_UP :
+ element == EL_SP_GRAVITY_PORT_DOWN ? EL_SP_PORT_DOWN :
+ element);
+ }
+
+ return element;
+}
+
static int LoadLevel_VERS(FILE *file, int chunk_size, struct LevelInfo *level)
{
level->file_version = getFileVersion(file);
for (i = 0; i < STD_ELEMENT_CONTENTS; i++)
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- level->yamyam_content[i][x][y] = checkLevelElement(getFile8Bit(file));
+ level->yamyam_content[i][x][y] = getMappedElement(getFile8Bit(file));
level->amoeba_speed = getFile8Bit(file);
level->time_magic_wall = getFile8Bit(file);
level->time_wheel = getFile8Bit(file);
- level->amoeba_content = checkLevelElement(getFile8Bit(file));
+ level->amoeba_content = getMappedElement(getFile8Bit(file));
level->double_speed = (getFile8Bit(file) == 1 ? TRUE : FALSE);
level->initial_gravity = (getFile8Bit(file) == 1 ? TRUE : FALSE);
level->encoding_16bit_field = (getFile8Bit(file) == 1 ? TRUE : FALSE);
level->use_custom_template = (getFile8Bit(file) == 1 ? TRUE : FALSE);
+ level->block_last_field = (getFile8Bit(file) == 1 ? TRUE : FALSE);
+ level->sp_block_last_field = (getFile8Bit(file) == 1 ? TRUE : FALSE);
+ level->can_move_into_acid_bits = getFile32BitBE(file);
+ level->dont_collide_with_bits = getFile8Bit(file);
+
+ level->use_spring_bug = (getFile8Bit(file) == 1 ? TRUE : FALSE);
+ level->use_step_counter = (getFile8Bit(file) == 1 ? TRUE : FALSE);
+
+ level->instant_relocation = (getFile8Bit(file) == 1 ? TRUE : FALSE);
+ level->can_pass_to_walkable = (getFile8Bit(file) == 1 ? TRUE : FALSE);
+ level->grow_into_diggable = (getFile8Bit(file) == 1 ? TRUE : FALSE);
+
ReadUnusedBytesFromFile(file, LEVEL_HEADER_UNUSED);
return chunk_size;
for (y = 0; y < level->fieldy; y++)
for (x = 0; x < level->fieldx; x++)
level->field[x][y] =
- checkLevelElement(level->encoding_16bit_field ? getFile16BitBE(file) :
- getFile8Bit(file));
+ getMappedElement(level->encoding_16bit_field ? getFile16BitBE(file) :
+ getFile8Bit(file));
return chunk_size;
}
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
level->yamyam_content[i][x][y] =
- checkLevelElement(level->encoding_16bit_field ?
- getFile16BitBE(file) : getFile8Bit(file));
+ getMappedElement(level->encoding_16bit_field ?
+ getFile16BitBE(file) : getFile8Bit(file));
return chunk_size;
}
int num_contents, content_xsize, content_ysize;
int content_array[MAX_ELEMENT_CONTENTS][3][3];
- element = checkLevelElement(getFile16BitBE(file));
+ element = getMappedElement(getFile16BitBE(file));
num_contents = getFile8Bit(file);
content_xsize = getFile8Bit(file);
content_ysize = getFile8Bit(file);
for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- content_array[i][x][y] = checkLevelElement(getFile16BitBE(file));
+ content_array[i][x][y] = getMappedElement(getFile16BitBE(file));
/* correct invalid number of content fields -- should never happen */
if (num_contents < 1 || num_contents > MAX_ELEMENT_CONTENTS)
int envelope_len;
int chunk_size_expected;
- element = checkLevelElement(getFile16BitBE(file));
+ element = getMappedElement(getFile16BitBE(file));
if (!IS_ENVELOPE(element))
element = EL_ENVELOPE_1;
ReadUnusedBytesFromFile(file, LEVEL_CHUNK_CNT3_UNUSED);
- chunk_size_expected = LEVEL_CHUNK_CNT3_HEADER + envelope_len;
-
+ chunk_size_expected = LEVEL_CHUNK_CNT3_SIZE(envelope_len);
if (chunk_size_expected != chunk_size)
{
ReadUnusedBytesFromFile(file, chunk_size - LEVEL_CHUNK_CNT3_HEADER);
{
Error(ERR_WARN, "invalid custom element number %d", element);
- element = EL_DUMMY;
+ element = EL_INTERNAL_DUMMY;
}
for (j = 0; j < MAX_ELEMENT_NAME_LEN; j++)
element_info[element].use_gfx_element = getFile8Bit(file);
element_info[element].gfx_element =
- checkLevelElement(getFile16BitBE(file));
+ getMappedElement(getFile16BitBE(file));
element_info[element].collect_score = getFile8Bit(file);
element_info[element].collect_count = getFile8Bit(file);
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
element_info[element].content[x][y] =
- checkLevelElement(getFile16BitBE(file));
+ getMappedElement(getFile16BitBE(file));
element_info[element].change->events = getFile32BitBE(file);
element_info[element].change->target_element =
- checkLevelElement(getFile16BitBE(file));
+ getMappedElement(getFile16BitBE(file));
element_info[element].change->delay_fixed = getFile16BitBE(file);
element_info[element].change->delay_random = getFile16BitBE(file);
element_info[element].change->delay_frames = getFile16BitBE(file);
element_info[element].change->trigger_element =
- checkLevelElement(getFile16BitBE(file));
+ getMappedElement(getFile16BitBE(file));
element_info[element].change->explode = getFile8Bit(file);
- element_info[element].change->use_content = getFile8Bit(file);
- element_info[element].change->only_complete = getFile8Bit(file);
- element_info[element].change->use_random_change = getFile8Bit(file);
+ element_info[element].change->use_target_content = getFile8Bit(file);
+ element_info[element].change->only_if_complete = getFile8Bit(file);
+ element_info[element].change->use_random_replace = getFile8Bit(file);
- element_info[element].change->random = getFile8Bit(file);
- element_info[element].change->power = getFile8Bit(file);
+ element_info[element].change->random_percentage = getFile8Bit(file);
+ element_info[element].change->replace_when = getFile8Bit(file);
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- element_info[element].change->content[x][y] =
- checkLevelElement(getFile16BitBE(file));
+ element_info[element].change->target_content[x][y] =
+ getMappedElement(getFile16BitBE(file));
element_info[element].slippery_type = getFile8Bit(file);
{
Error(ERR_WARN, "invalid custom element number %d", element);
- element = EL_DUMMY;
+ ReadUnusedBytesFromFile(file, chunk_size - 2);
+ return chunk_size;
}
ei = &element_info[element];
/* read custom property values */
ei->use_gfx_element = getFile8Bit(file);
- ei->gfx_element = checkLevelElement(getFile16BitBE(file));
+ ei->gfx_element = getMappedElement(getFile16BitBE(file));
ei->collect_score = getFile8Bit(file);
ei->collect_count = getFile8Bit(file);
- ei->push_delay_fixed = getFile16BitBE(file);
- ei->push_delay_random = getFile16BitBE(file);
+ ei->drop_delay_fixed = getFile8Bit(file);
+ ei->push_delay_fixed = getFile8Bit(file);
+ ei->drop_delay_random = getFile8Bit(file);
+ ei->push_delay_random = getFile8Bit(file);
ei->move_delay_fixed = getFile16BitBE(file);
ei->move_delay_random = getFile16BitBE(file);
+ /* bits 0 - 15 of "move_pattern" ... */
ei->move_pattern = getFile16BitBE(file);
ei->move_direction_initial = getFile8Bit(file);
ei->move_stepsize = getFile8Bit(file);
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- ei->content[x][y] = checkLevelElement(getFile16BitBE(file));
+ ei->content[x][y] = getMappedElement(getFile16BitBE(file));
+
+ ei->move_enter_element = getMappedElement(getFile16BitBE(file));
+ ei->move_leave_element = getMappedElement(getFile16BitBE(file));
+ ei->move_leave_type = getFile8Bit(file);
+
+ /* ... bits 16 - 31 of "move_pattern" (not nice, but downward compatible) */
+ ei->move_pattern |= (getFile16BitBE(file) << 16);
+
+ ei->access_direction = getFile8Bit(file);
+
+ ei->explosion_delay = getFile8Bit(file);
+ ei->ignition_delay = getFile8Bit(file);
+ ei->explosion_type = getFile8Bit(file);
/* some free bytes for future custom property values and padding */
- ReadUnusedBytesFromFile(file, 12);
+ ReadUnusedBytesFromFile(file, 1);
/* read change property values */
change->events = getFile32BitBE(file);
- change->target_element = checkLevelElement(getFile16BitBE(file));
+ change->target_element = getMappedElement(getFile16BitBE(file));
change->delay_fixed = getFile16BitBE(file);
change->delay_random = getFile16BitBE(file);
change->delay_frames = getFile16BitBE(file);
- change->trigger_element = checkLevelElement(getFile16BitBE(file));
+ change->trigger_element = getMappedElement(getFile16BitBE(file));
change->explode = getFile8Bit(file);
- change->use_content = getFile8Bit(file);
- change->only_complete = getFile8Bit(file);
- change->use_random_change = getFile8Bit(file);
+ change->use_target_content = getFile8Bit(file);
+ change->only_if_complete = getFile8Bit(file);
+ change->use_random_replace = getFile8Bit(file);
- change->random = getFile8Bit(file);
- change->power = getFile8Bit(file);
+ change->random_percentage = getFile8Bit(file);
+ change->replace_when = getFile8Bit(file);
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- change->content[x][y] = checkLevelElement(getFile16BitBE(file));
+ change->target_content[x][y] = getMappedElement(getFile16BitBE(file));
change->can_change = getFile8Bit(file);
- change->sides = getFile8Bit(file);
+ change->trigger_side = getFile8Bit(file);
+
+#if 1
+ change->trigger_player = getFile8Bit(file);
+ change->trigger_page = getFile8Bit(file);
+
+ change->trigger_page = (change->trigger_page == CH_PAGE_ANY_FILE ?
+ CH_PAGE_ANY : (1 << change->trigger_page));
+
+ /* some free bytes for future change property values and padding */
+ ReadUnusedBytesFromFile(file, 6);
- if (change->sides == CH_SIDE_NONE) /* correct empty sides field */
- change->sides = CH_SIDE_ANY;
+#else
/* some free bytes for future change property values and padding */
ReadUnusedBytesFromFile(file, 8);
+#endif
}
/* mark this custom element as modified */
return chunk_size;
}
-void LoadLevelFromFilename(struct LevelInfo *level, char *filename)
+static int LoadLevel_GRP1(FILE *file, int chunk_size, struct LevelInfo *level)
{
+ struct ElementInfo *ei;
+ struct ElementGroupInfo *group;
+ int element;
+ int i;
+
+ element = getFile16BitBE(file);
+
+ if (!IS_GROUP_ELEMENT(element))
+ {
+ Error(ERR_WARN, "invalid group element number %d", element);
+
+ ReadUnusedBytesFromFile(file, chunk_size - 2);
+ return chunk_size;
+ }
+
+ ei = &element_info[element];
+
+ for (i = 0; i < MAX_ELEMENT_NAME_LEN; i++)
+ ei->description[i] = getFile8Bit(file);
+ ei->description[MAX_ELEMENT_NAME_LEN] = 0;
+
+ group = element_info[element].group;
+
+ group->num_elements = getFile8Bit(file);
+
+ ei->use_gfx_element = getFile8Bit(file);
+ ei->gfx_element = getMappedElement(getFile16BitBE(file));
+
+ group->choice_mode = getFile8Bit(file);
+
+ /* some free bytes for future values and padding */
+ ReadUnusedBytesFromFile(file, 3);
+
+ for (i = 0; i < MAX_ELEMENTS_IN_GROUP; i++)
+ group->element[i] = getMappedElement(getFile16BitBE(file));
+
+ /* mark this group element as modified */
+ element_info[element].modified_settings = TRUE;
+
+ return chunk_size;
+}
+
+static void LoadLevelFromFileInfo_RND(struct LevelInfo *level,
+ struct LevelFileInfo *level_file_info)
+{
+ char *filename = level_file_info->filename;
char cookie[MAX_LINE_LEN];
char chunk_name[CHUNK_ID_LEN + 1];
int chunk_size;
FILE *file;
- /* always start with reliable default values */
- setLevelInfoToDefaults(level);
-
if (!(file = fopen(filename, MODE_READ)))
{
- level->no_level_file = TRUE;
+ level->no_valid_file = TRUE;
if (level != &level_template)
- Error(ERR_WARN, "cannot read level '%s' - creating new level", filename);
+ Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
return;
}
getFileChunkBE(file, chunk_name, NULL);
if (strcmp(chunk_name, "CAVE") != 0)
{
+ level->no_valid_file = TRUE;
+
Error(ERR_WARN, "unknown format of level file '%s'", filename);
fclose(file);
return;
if (!checkCookieString(cookie, LEVEL_COOKIE_TMPL))
{
+ level->no_valid_file = TRUE;
+
Error(ERR_WARN, "unknown format of level file '%s'", filename);
fclose(file);
return;
if ((level->file_version = getFileVersionFromCookieString(cookie)) == -1)
{
+ level->no_valid_file = TRUE;
+
Error(ERR_WARN, "unsupported version of level file '%s'", filename);
fclose(file);
return;
}
chunk_info[] =
{
- { "VERS", FILE_VERS_CHUNK_SIZE, LoadLevel_VERS },
- { "HEAD", LEVEL_HEADER_SIZE, LoadLevel_HEAD },
- { "AUTH", MAX_LEVEL_AUTHOR_LEN, LoadLevel_AUTH },
- { "BODY", -1, LoadLevel_BODY },
- { "CONT", -1, LoadLevel_CONT },
- { "CNT2", LEVEL_CHUNK_CNT2_SIZE, LoadLevel_CNT2 },
- { "CNT3", -1, LoadLevel_CNT3 },
- { "CUS1", -1, LoadLevel_CUS1 },
- { "CUS2", -1, LoadLevel_CUS2 },
- { "CUS3", -1, LoadLevel_CUS3 },
- { "CUS4", -1, LoadLevel_CUS4 },
- { NULL, 0, NULL }
- };
+ { "VERS", FILE_VERS_CHUNK_SIZE, LoadLevel_VERS },
+ { "HEAD", LEVEL_HEADER_SIZE, LoadLevel_HEAD },
+ { "AUTH", MAX_LEVEL_AUTHOR_LEN, LoadLevel_AUTH },
+ { "BODY", -1, LoadLevel_BODY },
+ { "CONT", -1, LoadLevel_CONT },
+ { "CNT2", LEVEL_CHUNK_CNT2_SIZE, LoadLevel_CNT2 },
+ { "CNT3", -1, LoadLevel_CNT3 },
+ { "CUS1", -1, LoadLevel_CUS1 },
+ { "CUS2", -1, LoadLevel_CUS2 },
+ { "CUS3", -1, LoadLevel_CUS3 },
+ { "CUS4", -1, LoadLevel_CUS4 },
+ { "GRP1", -1, LoadLevel_GRP1 },
+ { NULL, 0, NULL }
+ };
+
+ while (getFileChunkBE(file, chunk_name, &chunk_size))
+ {
+ int i = 0;
+
+ while (chunk_info[i].name != NULL &&
+ strcmp(chunk_name, chunk_info[i].name) != 0)
+ i++;
+
+ if (chunk_info[i].name == NULL)
+ {
+ Error(ERR_WARN, "unknown chunk '%s' in level file '%s'",
+ chunk_name, filename);
+ ReadUnusedBytesFromFile(file, chunk_size);
+ }
+ else if (chunk_info[i].size != -1 &&
+ chunk_info[i].size != chunk_size)
+ {
+ Error(ERR_WARN, "wrong size (%d) of chunk '%s' in level file '%s'",
+ chunk_size, chunk_name, filename);
+ ReadUnusedBytesFromFile(file, chunk_size);
+ }
+ else
+ {
+ /* call function to load this level chunk */
+ int chunk_size_expected =
+ (chunk_info[i].loader)(file, chunk_size, level);
+
+ /* the size of some chunks cannot be checked before reading other
+ chunks first (like "HEAD" and "BODY") that contain some header
+ information, so check them here */
+ if (chunk_size_expected != chunk_size)
+ {
+ Error(ERR_WARN, "wrong size (%d) of chunk '%s' in level file '%s'",
+ chunk_size, chunk_name, filename);
+ }
+ }
+ }
+ }
+
+ fclose(file);
+}
+
+/* ------------------------------------------------------------------------- */
+/* functions for loading EM level */
+/* ------------------------------------------------------------------------- */
+
+static int map_em_element_yam(int element)
+{
+ switch (element)
+ {
+ case 0x00: return EL_EMPTY;
+ case 0x01: return EL_EMERALD;
+ case 0x02: return EL_DIAMOND;
+ case 0x03: return EL_ROCK;
+ case 0x04: return EL_ROBOT;
+ case 0x05: return EL_SPACESHIP_UP;
+ case 0x06: return EL_BOMB;
+ case 0x07: return EL_BUG_UP;
+ case 0x08: return EL_AMOEBA_DROP;
+ case 0x09: return EL_NUT;
+ case 0x0a: return EL_YAMYAM;
+ case 0x0b: return EL_QUICKSAND_FULL;
+ case 0x0c: return EL_SAND;
+ case 0x0d: return EL_WALL_SLIPPERY;
+ case 0x0e: return EL_STEELWALL;
+ case 0x0f: return EL_WALL;
+ case 0x10: return EL_EM_KEY_1;
+ case 0x11: return EL_EM_KEY_2;
+ case 0x12: return EL_EM_KEY_4;
+ case 0x13: return EL_EM_KEY_3;
+ case 0x14: return EL_MAGIC_WALL;
+ case 0x15: return EL_ROBOT_WHEEL;
+ case 0x16: return EL_DYNAMITE;
+
+ case 0x17: return EL_EM_KEY_1; /* EMC */
+ case 0x18: return EL_BUG_UP; /* EMC */
+ case 0x1a: return EL_DIAMOND; /* EMC */
+ case 0x1b: return EL_EMERALD; /* EMC */
+ case 0x25: return EL_NUT; /* EMC */
+ case 0x80: return EL_EMPTY; /* EMC */
+ case 0x85: return EL_EM_KEY_1; /* EMC */
+ case 0x86: return EL_EM_KEY_2; /* EMC */
+ case 0x87: return EL_EM_KEY_4; /* EMC */
+ case 0x88: return EL_EM_KEY_3; /* EMC */
+ case 0x94: return EL_QUICKSAND_EMPTY; /* EMC */
+ case 0x9a: return EL_AMOEBA_WET; /* EMC */
+ case 0xaf: return EL_DYNAMITE; /* EMC */
+ case 0xbd: return EL_SAND; /* EMC */
+
+ default:
+ Error(ERR_WARN, "invalid level element %d", element);
+ return EL_UNKNOWN;
+ }
+}
+
+static int map_em_element_field(int element)
+{
+ if (element >= 0xc8 && element <= 0xe1)
+ return EL_CHAR_A + (element - 0xc8);
+ else if (element >= 0xe2 && element <= 0xeb)
+ return EL_CHAR_0 + (element - 0xe2);
+
+ switch (element)
+ {
+ case 0x00: return EL_ROCK;
+ case 0x01: return EL_ROCK; /* EMC */
+ case 0x02: return EL_DIAMOND;
+ case 0x03: return EL_DIAMOND;
+ case 0x04: return EL_ROBOT;
+ case 0x05: return EL_ROBOT; /* EMC */
+ case 0x06: return EL_EMPTY_SPACE; /* EMC */
+ case 0x07: return EL_EMPTY_SPACE; /* EMC */
+ case 0x08: return EL_SPACESHIP_UP;
+ case 0x09: return EL_SPACESHIP_RIGHT;
+ case 0x0a: return EL_SPACESHIP_DOWN;
+ case 0x0b: return EL_SPACESHIP_LEFT;
+ case 0x0c: return EL_SPACESHIP_UP;
+ case 0x0d: return EL_SPACESHIP_RIGHT;
+ case 0x0e: return EL_SPACESHIP_DOWN;
+ case 0x0f: return EL_SPACESHIP_LEFT;
+
+ case 0x10: return EL_BOMB;
+ case 0x11: return EL_BOMB; /* EMC */
+ case 0x12: return EL_EMERALD;
+ case 0x13: return EL_EMERALD;
+ case 0x14: return EL_BUG_UP;
+ case 0x15: return EL_BUG_RIGHT;
+ case 0x16: return EL_BUG_DOWN;
+ case 0x17: return EL_BUG_LEFT;
+ case 0x18: return EL_BUG_UP;
+ case 0x19: return EL_BUG_RIGHT;
+ case 0x1a: return EL_BUG_DOWN;
+ case 0x1b: return EL_BUG_LEFT;
+ case 0x1c: return EL_AMOEBA_DROP;
+ case 0x1d: return EL_AMOEBA_DROP; /* EMC */
+ case 0x1e: return EL_AMOEBA_DROP; /* EMC */
+ case 0x1f: return EL_AMOEBA_DROP; /* EMC */
+
+ case 0x20: return EL_ROCK;
+ case 0x21: return EL_BOMB; /* EMC */
+ case 0x22: return EL_DIAMOND; /* EMC */
+ case 0x23: return EL_EMERALD; /* EMC */
+ case 0x24: return EL_MAGIC_WALL;
+ case 0x25: return EL_NUT;
+ case 0x26: return EL_NUT; /* EMC */
+ case 0x27: return EL_NUT; /* EMC */
+
+ /* looks like magic wheel, but is _always_ activated */
+ case 0x28: return EL_ROBOT_WHEEL; /* EMC */
+
+ case 0x29: return EL_YAMYAM; /* up */
+ case 0x2a: return EL_YAMYAM; /* down */
+ case 0x2b: return EL_YAMYAM; /* left */ /* EMC */
+ case 0x2c: return EL_YAMYAM; /* right */ /* EMC */
+ case 0x2d: return EL_QUICKSAND_FULL;
+ case 0x2e: return EL_EMPTY_SPACE; /* EMC */
+ case 0x2f: return EL_EMPTY_SPACE; /* EMC */
+
+ case 0x30: return EL_EMPTY_SPACE; /* EMC */
+ case 0x31: return EL_SAND; /* EMC */
+ case 0x32: return EL_SAND; /* EMC */
+ case 0x33: return EL_SAND; /* EMC */
+ case 0x34: return EL_QUICKSAND_FULL; /* EMC */
+ case 0x35: return EL_QUICKSAND_FULL; /* EMC */
+ case 0x36: return EL_QUICKSAND_FULL; /* EMC */
+ case 0x37: return EL_SAND; /* EMC */
+ case 0x38: return EL_ROCK; /* EMC */
+ case 0x39: return EL_EXPANDABLE_WALL_HORIZONTAL; /* EMC */
+ case 0x3a: return EL_EXPANDABLE_WALL_VERTICAL; /* EMC */
+ case 0x3b: return EL_DYNAMITE_ACTIVE; /* 1 */
+ case 0x3c: return EL_DYNAMITE_ACTIVE; /* 2 */
+ case 0x3d: return EL_DYNAMITE_ACTIVE; /* 3 */
+ case 0x3e: return EL_DYNAMITE_ACTIVE; /* 4 */
+ case 0x3f: return EL_ACID_POOL_BOTTOM;
+
+ case 0x40: return EL_EXIT_OPEN; /* 1 */
+ case 0x41: return EL_EXIT_OPEN; /* 2 */
+ case 0x42: return EL_EXIT_OPEN; /* 3 */
+ case 0x43: return EL_BALLOON; /* EMC */
+ case 0x44: return EL_UNKNOWN; /* EMC ("plant") */
+ case 0x45: return EL_SPRING; /* EMC */
+ case 0x46: return EL_SPRING; /* falling */ /* EMC */
+ case 0x47: return EL_SPRING; /* left */ /* EMC */
+ case 0x48: return EL_SPRING; /* right */ /* EMC */
+ case 0x49: return EL_UNKNOWN; /* EMC ("ball 1") */
+ case 0x4a: return EL_UNKNOWN; /* EMC ("ball 2") */
+ case 0x4b: return EL_UNKNOWN; /* EMC ("android") */
+ case 0x4c: return EL_EMPTY_SPACE; /* EMC */
+ case 0x4d: return EL_UNKNOWN; /* EMC ("android") */
+ case 0x4e: return EL_INVISIBLE_WALL; /* EMC (? "android") */
+ case 0x4f: return EL_UNKNOWN; /* EMC ("android") */
+
+ case 0x50: return EL_UNKNOWN; /* EMC ("android") */
+ case 0x51: return EL_UNKNOWN; /* EMC ("android") */
+ case 0x52: return EL_UNKNOWN; /* EMC ("android") */
+ case 0x53: return EL_UNKNOWN; /* EMC ("android") */
+ case 0x54: return EL_UNKNOWN; /* EMC ("android") */
+ case 0x55: return EL_EMPTY_SPACE; /* EMC */
+ case 0x56: return EL_EMPTY_SPACE; /* EMC */
+ case 0x57: return EL_EMPTY_SPACE; /* EMC */
+ case 0x58: return EL_EMPTY_SPACE; /* EMC */
+ case 0x59: return EL_EMPTY_SPACE; /* EMC */
+ case 0x5a: return EL_EMPTY_SPACE; /* EMC */
+ case 0x5b: return EL_EMPTY_SPACE; /* EMC */
+ case 0x5c: return EL_EMPTY_SPACE; /* EMC */
+ case 0x5d: return EL_EMPTY_SPACE; /* EMC */
+ case 0x5e: return EL_EMPTY_SPACE; /* EMC */
+ case 0x5f: return EL_EMPTY_SPACE; /* EMC */
+
+ case 0x60: return EL_EMPTY_SPACE; /* EMC */
+ case 0x61: return EL_EMPTY_SPACE; /* EMC */
+ case 0x62: return EL_EMPTY_SPACE; /* EMC */
+ case 0x63: return EL_SPRING; /* left */ /* EMC */
+ case 0x64: return EL_SPRING; /* right */ /* EMC */
+ case 0x65: return EL_ACID; /* 1 */ /* EMC */
+ case 0x66: return EL_ACID; /* 2 */ /* EMC */
+ case 0x67: return EL_ACID; /* 3 */ /* EMC */
+ case 0x68: return EL_ACID; /* 4 */ /* EMC */
+ case 0x69: return EL_ACID; /* 5 */ /* EMC */
+ case 0x6a: return EL_ACID; /* 6 */ /* EMC */
+ case 0x6b: return EL_ACID; /* 7 */ /* EMC */
+ case 0x6c: return EL_ACID; /* 8 */ /* EMC */
+ case 0x6d: return EL_EMPTY_SPACE; /* EMC */
+ case 0x6e: return EL_EMPTY_SPACE; /* EMC */
+ case 0x6f: return EL_EMPTY_SPACE; /* EMC */
+
+ case 0x70: return EL_EMPTY_SPACE; /* EMC */
+ case 0x71: return EL_EMPTY_SPACE; /* EMC */
+ case 0x72: return EL_NUT; /* left */ /* EMC */
+ case 0x73: return EL_SAND; /* EMC (? "nut") */
+ case 0x74: return EL_STEELWALL;
+ case 0x75: return EL_EMPTY_SPACE; /* EMC */
+ case 0x76: return EL_EMPTY_SPACE; /* EMC */
+ case 0x77: return EL_BOMB; /* left */ /* EMC */
+ case 0x78: return EL_BOMB; /* right */ /* EMC */
+ case 0x79: return EL_ROCK; /* left */ /* EMC */
+ case 0x7a: return EL_ROCK; /* right */ /* EMC */
+ case 0x7b: return EL_ACID; /* (? EMC "blank") */
+ case 0x7c: return EL_EMPTY_SPACE; /* EMC */
+ case 0x7d: return EL_EMPTY_SPACE; /* EMC */
+ case 0x7e: return EL_EMPTY_SPACE; /* EMC */
+ case 0x7f: return EL_EMPTY_SPACE; /* EMC */
+
+ case 0x80: return EL_EMPTY;
+ case 0x81: return EL_WALL_SLIPPERY;
+ case 0x82: return EL_SAND;
+ case 0x83: return EL_STEELWALL;
+ case 0x84: return EL_WALL;
+ case 0x85: return EL_EM_KEY_1;
+ case 0x86: return EL_EM_KEY_2;
+ case 0x87: return EL_EM_KEY_4;
+ case 0x88: return EL_EM_KEY_3;
+ case 0x89: return EL_EM_GATE_1;
+ case 0x8a: return EL_EM_GATE_2;
+ case 0x8b: return EL_EM_GATE_4;
+ case 0x8c: return EL_EM_GATE_3;
+ case 0x8d: return EL_INVISIBLE_WALL; /* EMC (? "dripper") */
+ case 0x8e: return EL_EM_GATE_1_GRAY;
+ case 0x8f: return EL_EM_GATE_2_GRAY;
+
+ case 0x90: return EL_EM_GATE_4_GRAY;
+ case 0x91: return EL_EM_GATE_3_GRAY;
+ case 0x92: return EL_MAGIC_WALL;
+ case 0x93: return EL_ROBOT_WHEEL;
+ case 0x94: return EL_QUICKSAND_EMPTY; /* (? EMC "sand") */
+ case 0x95: return EL_ACID_POOL_TOPLEFT;
+ case 0x96: return EL_ACID_POOL_TOPRIGHT;
+ case 0x97: return EL_ACID_POOL_BOTTOMLEFT;
+ case 0x98: return EL_ACID_POOL_BOTTOMRIGHT;
+ case 0x99: return EL_ACID; /* (? EMC "fake blank") */
+ case 0x9a: return EL_AMOEBA_DEAD; /* 1 */
+ case 0x9b: return EL_AMOEBA_DEAD; /* 2 */
+ case 0x9c: return EL_AMOEBA_DEAD; /* 3 */
+ case 0x9d: return EL_AMOEBA_DEAD; /* 4 */
+ case 0x9e: return EL_EXIT_CLOSED;
+ case 0x9f: return EL_CHAR_LESS; /* arrow left */
+
+ /* looks like normal sand, but behaves like wall */
+ case 0xa0: return EL_UNKNOWN; /* EMC ("fake grass") */
+ case 0xa1: return EL_UNKNOWN; /* EMC ("lenses") */
+ case 0xa2: return EL_UNKNOWN; /* EMC ("magnify") */
+ case 0xa3: return EL_UNKNOWN; /* EMC ("fake blank") */
+ case 0xa4: return EL_UNKNOWN; /* EMC ("fake grass") */
+ case 0xa5: return EL_UNKNOWN; /* EMC ("switch") */
+ case 0xa6: return EL_UNKNOWN; /* EMC ("switch") */
+ case 0xa7: return EL_EMPTY_SPACE; /* EMC */
+ case 0xa8: return EL_EMC_WALL_1; /* EMC ("decor 8") */
+ case 0xa9: return EL_EMC_WALL_2; /* EMC ("decor 9") */
+ case 0xaa: return EL_EMC_WALL_3; /* EMC ("decor 10") */
+ case 0xab: return EL_EMC_WALL_7; /* EMC ("decor 5") */
+ case 0xac: return EL_CHAR_COMMA; /* EMC */
+ case 0xad: return EL_CHAR_QUOTEDBL; /* EMC */
+ case 0xae: return EL_CHAR_MINUS; /* EMC */
+ case 0xaf: return EL_DYNAMITE;
+
+ case 0xb0: return EL_EMC_STEELWALL_1; /* EMC ("steel 3") */
+ case 0xb1: return EL_EMC_WALL_8; /* EMC ("decor 6") */
+ case 0xb2: return EL_UNKNOWN; /* EMC ("decor 7") */
+ case 0xb3: return EL_STEELWALL; /* 2 */ /* EMC */
+ case 0xb4: return EL_WALL_SLIPPERY; /* 2 */ /* EMC */
+ case 0xb5: return EL_EMC_WALL_6; /* EMC ("decor 2") */
+ case 0xb6: return EL_EMC_WALL_5; /* EMC ("decor 4") */
+ case 0xb7: return EL_EMC_WALL_4; /* EMC ("decor 3") */
+ case 0xb8: return EL_BALLOON_SWITCH_ANY; /* EMC */
+ case 0xb9: return EL_BALLOON_SWITCH_RIGHT; /* EMC */
+ case 0xba: return EL_BALLOON_SWITCH_DOWN; /* EMC */
+ case 0xbb: return EL_BALLOON_SWITCH_LEFT; /* EMC */
+ case 0xbc: return EL_BALLOON_SWITCH_UP; /* EMC */
+ case 0xbd: return EL_SAND; /* EMC ("dirt") */
+ case 0xbe: return EL_UNKNOWN; /* EMC ("plant") */
+ case 0xbf: return EL_UNKNOWN; /* EMC ("key 5") */
+
+ case 0xc0: return EL_UNKNOWN; /* EMC ("key 6") */
+ case 0xc1: return EL_UNKNOWN; /* EMC ("key 7") */
+ case 0xc2: return EL_UNKNOWN; /* EMC ("key 8") */
+ case 0xc3: return EL_UNKNOWN; /* EMC ("door 5") */
+ case 0xc4: return EL_UNKNOWN; /* EMC ("door 6") */
+ case 0xc5: return EL_UNKNOWN; /* EMC ("door 7") */
+ case 0xc6: return EL_UNKNOWN; /* EMC ("door 8") */
+ case 0xc7: return EL_UNKNOWN; /* EMC ("bumper") */
+
+ /* characters: see above */
+
+ case 0xec: return EL_CHAR_PERIOD;
+ case 0xed: return EL_CHAR_EXCLAM;
+ case 0xee: return EL_CHAR_COLON;
+ case 0xef: return EL_CHAR_QUESTION;
+
+ case 0xf0: return EL_CHAR_GREATER; /* arrow right */
+ case 0xf1: return EL_CHAR_COPYRIGHT; /* EMC: "decor 1" */
+ case 0xf2: return EL_UNKNOWN; /* EMC ("fake door 5") */
+ case 0xf3: return EL_UNKNOWN; /* EMC ("fake door 6") */
+ case 0xf4: return EL_UNKNOWN; /* EMC ("fake door 7") */
+ case 0xf5: return EL_UNKNOWN; /* EMC ("fake door 8") */
+ case 0xf6: return EL_EMPTY_SPACE; /* EMC */
+ case 0xf7: return EL_EMPTY_SPACE; /* EMC */
+
+ case 0xf8: return EL_EMPTY_SPACE; /* EMC */
+ case 0xf9: return EL_EMPTY_SPACE; /* EMC */
+ case 0xfa: return EL_EMPTY_SPACE; /* EMC */
+ case 0xfb: return EL_EMPTY_SPACE; /* EMC */
+ case 0xfc: return EL_EMPTY_SPACE; /* EMC */
+ case 0xfd: return EL_EMPTY_SPACE; /* EMC */
+
+ case 0xfe: return EL_PLAYER_1; /* EMC: "blank" */
+ case 0xff: return EL_PLAYER_2; /* EMC: "blank" */
+
+ default:
+ /* should never happen (all 8-bit value cases should be handled) */
+ Error(ERR_WARN, "invalid level element %d", element);
+ return EL_UNKNOWN;
+ }
+}
+
+#define EM_LEVEL_SIZE 2106
+#define EM_LEVEL_XSIZE 64
+#define EM_LEVEL_YSIZE 32
+
+static void LoadLevelFromFileInfo_EM(struct LevelInfo *level,
+ struct LevelFileInfo *level_file_info)
+{
+ char *filename = level_file_info->filename;
+ FILE *file;
+ unsigned char leveldata[EM_LEVEL_SIZE];
+ unsigned char *header = &leveldata[EM_LEVEL_XSIZE * EM_LEVEL_YSIZE];
+ unsigned char code0 = 0x65;
+ unsigned char code1 = 0x11;
+ boolean level_is_crypted = FALSE;
+ int nr = level_file_info->nr;
+ int i, x, y;
+
+ if (!(file = fopen(filename, MODE_READ)))
+ {
+ level->no_valid_file = TRUE;
+
+ Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
+
+ return;
+ }
+
+ for(i = 0; i < EM_LEVEL_SIZE; i++)
+ leveldata[i] = fgetc(file);
+
+ fclose(file);
+
+ /* check if level data is crypted by testing against known starting bytes
+ of the few existing crypted level files (from Emerald Mine 1 + 2) */
+
+ if ((leveldata[0] == 0xf1 ||
+ leveldata[0] == 0xf5) && leveldata[2] == 0xe7 && leveldata[3] == 0xee)
+ {
+ level_is_crypted = TRUE;
+
+ if (leveldata[0] == 0xf5) /* error in crypted Emerald Mine 2 levels */
+ leveldata[0] = 0xf1;
+ }
+
+ if (level_is_crypted) /* decode crypted level data */
+ {
+ for(i = 0; i < EM_LEVEL_SIZE; i++)
+ {
+ leveldata[i] ^= code0;
+ leveldata[i] -= code1;
+
+ code0 = (code0 + 7) & 0xff;
+ }
+ }
+
+ level->fieldx = EM_LEVEL_XSIZE;
+ level->fieldy = EM_LEVEL_YSIZE;
+
+ level->time = header[46] * 10;
+ level->gems_needed = header[47];
+
+ /* The original Emerald Mine levels have their level number stored
+ at the second byte of the level file...
+ Do not trust this information at other level files, e.g. EMC,
+ but correct it anyway (normally the first row is completely
+ steel wall, so the correction does not hurt anyway). */
+
+ if (leveldata[1] == nr)
+ leveldata[1] = leveldata[2]; /* correct level number field */
+
+ sprintf(level->name, "Level %d", nr); /* set level name */
+
+ level->score[SC_EMERALD] = header[36];
+ level->score[SC_DIAMOND] = header[37];
+ level->score[SC_ROBOT] = header[38];
+ level->score[SC_SPACESHIP] = header[39];
+ level->score[SC_BUG] = header[40];
+ level->score[SC_YAMYAM] = header[41];
+ level->score[SC_NUT] = header[42];
+ level->score[SC_DYNAMITE] = header[43];
+ level->score[SC_TIME_BONUS] = header[44];
+
+ level->num_yamyam_contents = 4;
+
+ for(i = 0; i < level->num_yamyam_contents; i++)
+ for(y = 0; y < 3; y++)
+ for(x = 0; x < 3; x++)
+ level->yamyam_content[i][x][y] =
+ map_em_element_yam(header[i * 9 + y * 3 + x]);
+
+ level->amoeba_speed = (header[52] * 256 + header[53]) % 256;
+ level->time_magic_wall = (header[54] * 256 + header[55]) * 16 / 100;
+ level->time_wheel = (header[56] * 256 + header[57]) * 16 / 100;
+ level->amoeba_content = EL_DIAMOND;
+
+ for (y = 0; y < level->fieldy; y++) for (x = 0; x < level->fieldx; x++)
+ {
+ int new_element = map_em_element_field(leveldata[y * EM_LEVEL_XSIZE + x]);
+
+ if (new_element == EL_AMOEBA_DEAD && level->amoeba_speed)
+ new_element = EL_AMOEBA_WET;
+
+ level->field[x][y] = new_element;
+ }
+
+ x = (header[48] * 256 + header[49]) % EM_LEVEL_XSIZE;
+ y = (header[48] * 256 + header[49]) / EM_LEVEL_XSIZE;
+ level->field[x][y] = EL_PLAYER_1;
+
+ x = (header[50] * 256 + header[51]) % EM_LEVEL_XSIZE;
+ y = (header[50] * 256 + header[51]) / EM_LEVEL_XSIZE;
+ level->field[x][y] = EL_PLAYER_2;
+}
+
+/* ------------------------------------------------------------------------- */
+/* functions for loading SP level */
+/* ------------------------------------------------------------------------- */
+
+#define NUM_SUPAPLEX_LEVELS_PER_PACKAGE 111
+#define SP_LEVEL_SIZE 1536
+#define SP_LEVEL_XSIZE 60
+#define SP_LEVEL_YSIZE 24
+#define SP_LEVEL_NAME_LEN 23
+
+static void LoadLevelFromFileStream_SP(FILE *file, struct LevelInfo *level,
+ int nr)
+{
+ int num_special_ports;
+ int i, x, y;
+
+ /* for details of the Supaplex level format, see Herman Perk's Supaplex
+ documentation file "SPFIX63.DOC" from his Supaplex "SpeedFix" package */
+
+ /* read level body (width * height == 60 * 24 tiles == 1440 bytes) */
+ for (y = 0; y < SP_LEVEL_YSIZE; y++)
+ {
+ for (x = 0; x < SP_LEVEL_XSIZE; x++)
+ {
+ int element_old = fgetc(file);
+ int element_new;
+
+ if (element_old <= 0x27)
+ element_new = getMappedElement(EL_SP_START + element_old);
+ else if (element_old == 0x28)
+ element_new = EL_INVISIBLE_WALL;
+ else
+ {
+ Error(ERR_WARN, "in level %d, at position %d, %d:", nr, x, y);
+ Error(ERR_WARN, "invalid level element %d", element_old);
+
+ element_new = EL_UNKNOWN;
+ }
+
+ level->field[x][y] = element_new;
+ }
+ }
+
+ ReadUnusedBytesFromFile(file, 4); /* (not used by Supaplex engine) */
+
+ /* initial gravity: 1 == "on", anything else (0) == "off" */
+ level->initial_gravity = (fgetc(file) == 1 ? TRUE : FALSE);
+
+ ReadUnusedBytesFromFile(file, 1); /* (not used by Supaplex engine) */
+
+ /* level title in uppercase letters, padded with dashes ("-") (23 bytes) */
+ for (i = 0; i < SP_LEVEL_NAME_LEN; i++)
+ level->name[i] = fgetc(file);
+ level->name[SP_LEVEL_NAME_LEN] = '\0';
+
+ /* initial "freeze zonks": 2 == "on", anything else (0, 1) == "off" */
+ ReadUnusedBytesFromFile(file, 1); /* (not used by R'n'D engine) */
+
+ /* number of infotrons needed; 0 means that Supaplex will count the total
+ amount of infotrons in the level and use the low byte of that number
+ (a multiple of 256 infotrons will result in "0 infotrons needed"!) */
+ level->gems_needed = fgetc(file);
+
+ /* number of special ("gravity") port entries below (maximum 10 allowed) */
+ num_special_ports = fgetc(file);
+
+ /* database of properties of up to 10 special ports (6 bytes per port) */
+ for (i = 0; i < 10; i++)
+ {
+ int port_location, port_x, port_y, port_element;
+ int gravity;
+
+ /* high and low byte of the location of a special port; if (x, y) are the
+ coordinates of a port in the field and (0, 0) is the top-left corner,
+ the 16 bit value here calculates as 2 * (x + (y * 60)) (this is twice
+ of what may be expected: Supaplex works with a game field in memory
+ which is 2 bytes per tile) */
+ port_location = getFile16BitBE(file);
+
+ /* change gravity: 1 == "turn on", anything else (0) == "turn off" */
+ gravity = fgetc(file);
+
+ /* "freeze zonks": 2 == "turn on", anything else (0, 1) == "turn off" */
+ ReadUnusedBytesFromFile(file, 1); /* (not used by R'n'D engine) */
+
+ /* "freeze enemies": 1 == "turn on", anything else (0) == "turn off" */
+ ReadUnusedBytesFromFile(file, 1); /* (not used by R'n'D engine) */
+
+ ReadUnusedBytesFromFile(file, 1); /* (not used by Supaplex engine) */
+
+ if (i >= num_special_ports)
+ continue;
+
+ port_x = (port_location / 2) % SP_LEVEL_XSIZE;
+ port_y = (port_location / 2) / SP_LEVEL_XSIZE;
+
+ if (port_x < 0 || port_x >= SP_LEVEL_XSIZE ||
+ port_y < 0 || port_y >= SP_LEVEL_YSIZE)
+ {
+ Error(ERR_WARN, "special port position (%d, %d) out of bounds",
+ port_x, port_y);
+
+ continue;
+ }
+
+ port_element = level->field[port_x][port_y];
+
+ if (port_element < EL_SP_GRAVITY_PORT_RIGHT ||
+ port_element > EL_SP_GRAVITY_PORT_UP)
+ {
+ Error(ERR_WARN, "no special port at position (%d, %d)", port_x, port_y);
+
+ continue;
+ }
+
+ /* change previous (wrong) gravity inverting special port to either
+ gravity enabling special port or gravity disabling special port */
+ level->field[port_x][port_y] +=
+ (gravity == 1 ? EL_SP_GRAVITY_ON_PORT_RIGHT :
+ EL_SP_GRAVITY_OFF_PORT_RIGHT) - EL_SP_GRAVITY_PORT_RIGHT;
+ }
+
+ ReadUnusedBytesFromFile(file, 4); /* (not used by Supaplex engine) */
+
+ /* change special gravity ports without database entries to normal ports */
+ for (y = 0; y < SP_LEVEL_YSIZE; y++)
+ for (x = 0; x < SP_LEVEL_XSIZE; x++)
+ if (level->field[x][y] >= EL_SP_GRAVITY_PORT_RIGHT &&
+ level->field[x][y] <= EL_SP_GRAVITY_PORT_UP)
+ level->field[x][y] += EL_SP_PORT_RIGHT - EL_SP_GRAVITY_PORT_RIGHT;
+
+ /* auto-determine number of infotrons if it was stored as "0" -- see above */
+ if (level->gems_needed == 0)
+ {
+ for (y = 0; y < SP_LEVEL_YSIZE; y++)
+ for (x = 0; x < SP_LEVEL_XSIZE; x++)
+ if (level->field[x][y] == EL_SP_INFOTRON)
+ level->gems_needed++;
+
+ level->gems_needed &= 0xff; /* only use low byte -- see above */
+ }
+
+ level->fieldx = SP_LEVEL_XSIZE;
+ level->fieldy = SP_LEVEL_YSIZE;
+
+ level->time = 0; /* no time limit */
+ level->amoeba_speed = 0;
+ level->time_magic_wall = 0;
+ level->time_wheel = 0;
+ level->amoeba_content = EL_EMPTY;
+
+ for(i = 0; i < LEVEL_SCORE_ELEMENTS; i++)
+ level->score[i] = 0; /* !!! CORRECT THIS !!! */
+
+ /* there are no yamyams in supaplex levels */
+ for(i = 0; i < level->num_yamyam_contents; i++)
+ for(y = 0; y < 3; y++)
+ for(x = 0; x < 3; x++)
+ level->yamyam_content[i][x][y] = EL_EMPTY;
+}
+
+static void LoadLevelFromFileInfo_SP(struct LevelInfo *level,
+ struct LevelFileInfo *level_file_info)
+{
+ char *filename = level_file_info->filename;
+ FILE *file;
+ int nr = level_file_info->nr - leveldir_current->first_level;
+ int i, l, x, y;
+ char name_first, name_last;
+ struct LevelInfo multipart_level;
+ int multipart_xpos, multipart_ypos;
+ boolean is_multipart_level;
+ boolean is_first_part;
+ boolean reading_multipart_level = FALSE;
+ boolean use_empty_level = FALSE;
+
+ if (!(file = fopen(filename, MODE_READ)))
+ {
+ level->no_valid_file = TRUE;
+
+ Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
+
+ return;
+ }
+
+ /* position file stream to the requested level inside the level package */
+ if (fseek(file, nr * SP_LEVEL_SIZE, SEEK_SET) != 0)
+ {
+ level->no_valid_file = TRUE;
+
+ Error(ERR_WARN, "cannot fseek level '%s' -- using empty level", filename);
+
+ return;
+ }
+
+ /* there exist Supaplex level package files with multi-part levels which
+ can be detected as follows: instead of leading and trailing dashes ('-')
+ to pad the level name, they have leading and trailing numbers which are
+ the x and y coordinations of the current part of the multi-part level;
+ if there are '?' characters instead of numbers on the left or right side
+ of the level name, the multi-part level consists of only horizontal or
+ vertical parts */
+
+ for (l = nr; l < NUM_SUPAPLEX_LEVELS_PER_PACKAGE; l++)
+ {
+ LoadLevelFromFileStream_SP(file, level, l);
+
+ /* check if this level is a part of a bigger multi-part level */
+
+ name_first = level->name[0];
+ name_last = level->name[SP_LEVEL_NAME_LEN - 1];
+
+ is_multipart_level =
+ ((name_first == '?' || (name_first >= '0' && name_first <= '9')) &&
+ (name_last == '?' || (name_last >= '0' && name_last <= '9')));
+
+ is_first_part =
+ ((name_first == '?' || name_first == '1') &&
+ (name_last == '?' || name_last == '1'));
+
+ /* correct leading multipart level meta information in level name */
+ for (i = 0; i < SP_LEVEL_NAME_LEN && level->name[i] == name_first; i++)
+ level->name[i] = '-';
+
+ /* correct trailing multipart level meta information in level name */
+ for (i = SP_LEVEL_NAME_LEN - 1; i>=0 && level->name[i] == name_last; i--)
+ level->name[i] = '-';
+
+ /* ---------- check for normal single level ---------- */
+
+ if (!reading_multipart_level && !is_multipart_level)
+ {
+ /* the current level is simply a normal single-part level, and we are
+ not reading a multi-part level yet, so return the level as it is */
+
+ break;
+ }
+
+ /* ---------- check for empty level (unused multi-part) ---------- */
+
+ if (!reading_multipart_level && is_multipart_level && !is_first_part)
+ {
+ /* this is a part of a multi-part level, but not the first part
+ (and we are not already reading parts of a multi-part level);
+ in this case, use an empty level instead of the single part */
+
+ use_empty_level = TRUE;
+
+ break;
+ }
+
+ /* ---------- check for finished multi-part level ---------- */
+
+ if (reading_multipart_level &&
+ (!is_multipart_level ||
+ strcmp(level->name, multipart_level.name) != 0))
+ {
+ /* we are already reading parts of a multi-part level, but this level is
+ either not a multi-part level, or a part of a different multi-part
+ level; in both cases, the multi-part level seems to be complete */
+
+ break;
+ }
+
+ /* ---------- here we have one part of a multi-part level ---------- */
+
+ reading_multipart_level = TRUE;
+
+ if (is_first_part) /* start with first part of new multi-part level */
+ {
+ /* copy level info structure from first part */
+ multipart_level = *level;
- while (getFileChunkBE(file, chunk_name, &chunk_size))
+ /* clear playfield of new multi-part level */
+ for (y = 0; y < MAX_LEV_FIELDY; y++)
+ for (x = 0; x < MAX_LEV_FIELDX; x++)
+ multipart_level.field[x][y] = EL_EMPTY;
+ }
+
+ if (name_first == '?')
+ name_first = '1';
+ if (name_last == '?')
+ name_last = '1';
+
+ multipart_xpos = (int)(name_first - '0');
+ multipart_ypos = (int)(name_last - '0');
+
+#if 0
+ printf("----------> part (%d/%d) of multi-part level '%s'\n",
+ multipart_xpos, multipart_ypos, multipart_level.name);
+#endif
+
+ if (multipart_xpos * SP_LEVEL_XSIZE > MAX_LEV_FIELDX ||
+ multipart_ypos * SP_LEVEL_YSIZE > MAX_LEV_FIELDY)
{
- int i = 0;
+ Error(ERR_WARN, "multi-part level is too big -- ignoring part of it");
- while (chunk_info[i].name != NULL &&
- strcmp(chunk_name, chunk_info[i].name) != 0)
- i++;
+ break;
+ }
- if (chunk_info[i].name == NULL)
- {
- Error(ERR_WARN, "unknown chunk '%s' in level file '%s'",
- chunk_name, filename);
- ReadUnusedBytesFromFile(file, chunk_size);
- }
- else if (chunk_info[i].size != -1 &&
- chunk_info[i].size != chunk_size)
- {
- Error(ERR_WARN, "wrong size (%d) of chunk '%s' in level file '%s'",
- chunk_size, chunk_name, filename);
- ReadUnusedBytesFromFile(file, chunk_size);
- }
- else
+ multipart_level.fieldx = MAX(multipart_level.fieldx,
+ multipart_xpos * SP_LEVEL_XSIZE);
+ multipart_level.fieldy = MAX(multipart_level.fieldy,
+ multipart_ypos * SP_LEVEL_YSIZE);
+
+ /* copy level part at the right position of multi-part level */
+ for (y = 0; y < SP_LEVEL_YSIZE; y++)
+ {
+ for (x = 0; x < SP_LEVEL_XSIZE; x++)
{
- /* call function to load this level chunk */
- int chunk_size_expected =
- (chunk_info[i].loader)(file, chunk_size, level);
+ int start_x = (multipart_xpos - 1) * SP_LEVEL_XSIZE;
+ int start_y = (multipart_ypos - 1) * SP_LEVEL_YSIZE;
- /* the size of some chunks cannot be checked before reading other
- chunks first (like "HEAD" and "BODY") that contain some header
- information, so check them here */
- if (chunk_size_expected != chunk_size)
- {
- Error(ERR_WARN, "wrong size (%d) of chunk '%s' in level file '%s'",
- chunk_size, chunk_name, filename);
- }
+ multipart_level.field[start_x + x][start_y + y] = level->field[x][y];
}
}
}
fclose(file);
+
+ if (use_empty_level)
+ {
+ setLevelInfoToDefaults(level);
+
+ level->fieldx = SP_LEVEL_XSIZE;
+ level->fieldy = SP_LEVEL_YSIZE;
+
+ for (y = 0; y < SP_LEVEL_YSIZE; y++)
+ for (x = 0; x < SP_LEVEL_XSIZE; x++)
+ level->field[x][y] = EL_EMPTY;
+
+ strcpy(level->name, "-------- EMPTY --------");
+
+ Error(ERR_WARN, "single part of multi-part level -- using empty level");
+ }
+
+ if (reading_multipart_level)
+ *level = multipart_level;
+}
+
+/* ------------------------------------------------------------------------- */
+/* functions for loading generic level */
+/* ------------------------------------------------------------------------- */
+
+void LoadLevelFromFileInfo(struct LevelInfo *level,
+ struct LevelFileInfo *level_file_info)
+{
+ /* always start with reliable default values */
+ setLevelInfoToDefaults(level);
+
+ switch (level_file_info->type)
+ {
+ case LEVEL_FILE_TYPE_RND:
+ LoadLevelFromFileInfo_RND(level, level_file_info);
+ break;
+
+ case LEVEL_FILE_TYPE_EM:
+ LoadLevelFromFileInfo_EM(level, level_file_info);
+ break;
+
+ case LEVEL_FILE_TYPE_SP:
+ LoadLevelFromFileInfo_SP(level, level_file_info);
+ break;
+
+ default:
+ LoadLevelFromFileInfo_RND(level, level_file_info);
+ break;
+ }
+}
+
+void LoadLevelFromFilename(struct LevelInfo *level, char *filename)
+{
+ static struct LevelFileInfo level_file_info;
+
+ /* always start with reliable default values */
+ setFileInfoToDefaults(&level_file_info);
+
+ level_file_info.nr = 0; /* unknown level number */
+ level_file_info.type = LEVEL_FILE_TYPE_RND; /* no others supported yet */
+ level_file_info.filename = filename;
+
+ LoadLevelFromFileInfo(level, &level_file_info);
}
static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
pre-2.0 levels, where the game version is still taken from the
file format version used to store the level -- see above). */
+#if 1
+ /* player was faster than enemies in 1.0.0 and before */
+ if (level->file_version == FILE_VERSION_1_0)
+ level->double_speed = TRUE;
+#else
/* do some special adjustments to support older level versions */
if (level->file_version == FILE_VERSION_1_0)
{
/* player was faster than monsters in (pre-)1.0 levels */
level->double_speed = TRUE;
}
+#endif
- /* Default behaviour for EM style gems was "slippery" only in 2.0.1 */
+ /* default behaviour for EM style gems was "slippery" only in 2.0.1 */
if (level->game_version == VERSION_IDENT(2,0,1,0))
level->em_slippery_gems = TRUE;
+
+ if (level->game_version < VERSION_IDENT(2,2,0,0))
+ level->use_spring_bug = TRUE;
+
+ if (level->game_version < VERSION_IDENT(3,1,0,0))
+ {
+ int i, j;
+
+ level->can_move_into_acid_bits = 0; /* nothing can move into acid */
+ level->dont_collide_with_bits = 0; /* nothing is deadly when colliding */
+
+ setMoveIntoAcidProperty(level, EL_ROBOT, TRUE);
+ setMoveIntoAcidProperty(level, EL_SATELLITE, TRUE);
+ setMoveIntoAcidProperty(level, EL_PENGUIN, TRUE);
+ setMoveIntoAcidProperty(level, EL_BALLOON, TRUE);
+
+ for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+ SET_PROPERTY(EL_CUSTOM_START + i, EP_CAN_MOVE_INTO_ACID, TRUE);
+
+ for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ int element = EL_CUSTOM_START + i;
+ struct ElementInfo *ei = &element_info[element];
+
+ for (j = 0; j < ei->num_change_pages; j++)
+ {
+ struct ElementChangeInfo *change = &ei->change_page[j];
+
+ change->trigger_player = CH_PLAYER_ANY;
+ change->trigger_page = CH_PAGE_ANY;
+ }
+ }
+ }
}
else
{
static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
{
- int i, j;
+ int i, j, x, y;
/* map custom element change events that have changed in newer versions
(these following values were accidentally changed in version 3.0.1) */
}
/* order of checking and copying events to be mapped is important */
- for (j = CE_OTHER_GETS_COLLECTED; j >= CE_COLLISION_ACTIVE; j--)
+ for (j = CE_OTHER_GETS_COLLECTED; j >= CE_HITTING_SOMETHING; j--)
{
if (HAS_CHANGE_EVENT(element, j - 1))
{
}
}
+ /* correct custom element values (for old levels without these options) */
+ for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ int element = EL_CUSTOM_START + i;
+ struct ElementInfo *ei = &element_info[element];
+
+ if (ei->access_direction == MV_NO_MOVING)
+ ei->access_direction = MV_ALL_DIRECTIONS;
+
+ for (j = 0; j < ei->num_change_pages; j++)
+ {
+ struct ElementChangeInfo *change = &ei->change_page[j];
+
+ if (change->trigger_side == CH_SIDE_NONE)
+ change->trigger_side = CH_SIDE_ANY;
+ }
+ }
+
+ /* initialize "can_explode" field for old levels which did not store this */
+ if (level->game_version <= VERSION_IDENT(3,1,0,0))
+ {
+ for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ int element = EL_CUSTOM_START + i;
+
+ if (EXPLODES_1X1_OLD(element))
+ element_info[element].explosion_type = EXPLODES_1X1;
+
+ SET_PROPERTY(element, EP_CAN_EXPLODE, (EXPLODES_BY_FIRE(element) ||
+ EXPLODES_SMASHED(element) ||
+ EXPLODES_IMPACT(element)));
+ }
+ }
+
#if 0
/* set default push delay values (corrected since version 3.0.7-1) */
if (level->game_version < VERSION_IDENT(3,0,7,1))
}
#endif
+ /* map elements that have changed in newer versions */
+ level->amoeba_content = getMappedElementByVersion(level->amoeba_content,
+ level->game_version);
+ for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
+ for (x = 0; x < 3; x++)
+ for (y = 0; y < 3; y++)
+ level->yamyam_content[i][x][y] =
+ getMappedElementByVersion(level->yamyam_content[i][x][y],
+ level->game_version);
+
/* initialize element properties for level editor etc. */
InitElementPropertiesEngine(level->game_version);
}
{
int element = level->field[x][y];
+#if 1
+ element = getMappedElementByVersion(element, level->game_version);
+#else
if (level->game_version <= VERSION_IDENT(2,2,0,0))
{
/* map game font elements */
element == EL_SP_GRAVITY_PORT_DOWN ? EL_SP_PORT_DOWN :
element);
}
+#endif
level->field[x][y] = element;
}
SetBorderElement();
}
-void LoadLevelTemplate(int level_nr)
+void LoadLevelTemplate(int nr)
{
- char *filename = getLevelFilename(level_nr);
+#if 1
+ struct LevelFileInfo *level_file_info = getLevelFileInfo(nr);
+ char *filename = level_file_info->filename;
+
+ LoadLevelFromFileInfo(&level_template, level_file_info);
+#else
+ char *filename = getDefaultLevelFilename(nr);
- LoadLevelFromFilename(&level_template, filename);
+ LoadLevelFromFilename_RND(&level_template, filename);
+#endif
LoadLevel_InitVersion(&level, filename);
LoadLevel_InitElements(&level, filename);
ActivateLevelTemplate();
}
-void LoadLevel(int level_nr)
+void LoadLevel(int nr)
{
- char *filename = getLevelFilename(level_nr);
+#if 1
+ struct LevelFileInfo *level_file_info = getLevelFileInfo(nr);
+ char *filename = level_file_info->filename;
+
+ LoadLevelFromFileInfo(&level, level_file_info);
+#else
+ char *filename = getLevelFilename(nr);
- LoadLevelFromFilename(&level, filename);
+ LoadLevelFromFilename_RND(&level, filename);
+#endif
if (level.use_custom_template)
LoadLevelTemplate(-1);
putFile8Bit(file, (level->use_custom_template ? 1 : 0));
+ putFile8Bit(file, (level->block_last_field ? 1 : 0));
+ putFile8Bit(file, (level->sp_block_last_field ? 1 : 0));
+ putFile32BitBE(file, level->can_move_into_acid_bits);
+ putFile8Bit(file, level->dont_collide_with_bits);
+
+ putFile8Bit(file, (level->use_spring_bug ? 1 : 0));
+ putFile8Bit(file, (level->use_step_counter ? 1 : 0));
+
+ putFile8Bit(file, (level->instant_relocation ? 1 : 0));
+ putFile8Bit(file, (level->can_pass_to_walkable ? 1 : 0));
+ putFile8Bit(file, (level->grow_into_diggable ? 1 : 0));
+
WriteUnusedBytesToFile(file, LEVEL_HEADER_UNUSED);
}
putFile16BitBE(file, element_info[element].change->trigger_element);
putFile8Bit(file, element_info[element].change->explode);
- putFile8Bit(file, element_info[element].change->use_content);
- putFile8Bit(file, element_info[element].change->only_complete);
- putFile8Bit(file, element_info[element].change->use_random_change);
+ putFile8Bit(file, element_info[element].change->use_target_content);
+ putFile8Bit(file, element_info[element].change->only_if_complete);
+ putFile8Bit(file, element_info[element].change->use_random_replace);
- putFile8Bit(file, element_info[element].change->random);
- putFile8Bit(file, element_info[element].change->power);
+ putFile8Bit(file, element_info[element].change->random_percentage);
+ putFile8Bit(file, element_info[element].change->replace_when);
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
putFile8Bit(file, ei->collect_score);
putFile8Bit(file, ei->collect_count);
- putFile16BitBE(file, ei->push_delay_fixed);
- putFile16BitBE(file, ei->push_delay_random);
+ putFile8Bit(file, ei->drop_delay_fixed);
+ putFile8Bit(file, ei->push_delay_fixed);
+ putFile8Bit(file, ei->drop_delay_random);
+ putFile8Bit(file, ei->push_delay_random);
putFile16BitBE(file, ei->move_delay_fixed);
putFile16BitBE(file, ei->move_delay_random);
- putFile16BitBE(file, ei->move_pattern);
+ /* bits 0 - 15 of "move_pattern" ... */
+ putFile16BitBE(file, ei->move_pattern & 0xffff);
putFile8Bit(file, ei->move_direction_initial);
putFile8Bit(file, ei->move_stepsize);
for (x = 0; x < 3; x++)
putFile16BitBE(file, ei->content[x][y]);
+ putFile16BitBE(file, ei->move_enter_element);
+ putFile16BitBE(file, ei->move_leave_element);
+ putFile8Bit(file, ei->move_leave_type);
+
+ /* ... bits 16 - 31 of "move_pattern" (not nice, but downward compatible) */
+ putFile16BitBE(file, (ei->move_pattern >> 16) & 0xffff);
+
+ putFile8Bit(file, ei->access_direction);
+
+ putFile8Bit(file, ei->explosion_delay);
+ putFile8Bit(file, ei->ignition_delay);
+ putFile8Bit(file, ei->explosion_type);
+
/* some free bytes for future custom property values and padding */
- WriteUnusedBytesToFile(file, 12);
+ WriteUnusedBytesToFile(file, 1);
/* write change property values */
putFile16BitBE(file, change->trigger_element);
putFile8Bit(file, change->explode);
- putFile8Bit(file, change->use_content);
- putFile8Bit(file, change->only_complete);
- putFile8Bit(file, change->use_random_change);
+ putFile8Bit(file, change->use_target_content);
+ putFile8Bit(file, change->only_if_complete);
+ putFile8Bit(file, change->use_random_replace);
- putFile8Bit(file, change->random);
- putFile8Bit(file, change->power);
+ putFile8Bit(file, change->random_percentage);
+ putFile8Bit(file, change->replace_when);
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- putFile16BitBE(file, change->content[x][y]);
+ putFile16BitBE(file, change->target_content[x][y]);
putFile8Bit(file, change->can_change);
- putFile8Bit(file, change->sides);
+ putFile8Bit(file, change->trigger_side);
+
+#if 1
+ putFile8Bit(file, change->trigger_player);
+ putFile8Bit(file, (change->trigger_page == CH_PAGE_ANY ? CH_PAGE_ANY_FILE :
+ log_2(change->trigger_page)));
+
+ /* some free bytes for future change property values and padding */
+ WriteUnusedBytesToFile(file, 6);
+
+#else
/* some free bytes for future change property values and padding */
WriteUnusedBytesToFile(file, 8);
+#endif
}
}
+static void SaveLevel_GRP1(FILE *file, struct LevelInfo *level, int element)
+{
+ struct ElementInfo *ei = &element_info[element];
+ struct ElementGroupInfo *group = ei->group;
+ int i;
+
+ putFile16BitBE(file, element);
+
+ for (i = 0; i < MAX_ELEMENT_NAME_LEN; i++)
+ putFile8Bit(file, ei->description[i]);
+
+ putFile8Bit(file, group->num_elements);
+
+ putFile8Bit(file, ei->use_gfx_element);
+ putFile16BitBE(file, ei->gfx_element);
+
+ putFile8Bit(file, group->choice_mode);
+
+ /* some free bytes for future values and padding */
+ WriteUnusedBytesToFile(file, 3);
+
+ for (i = 0; i < MAX_ELEMENTS_IN_GROUP; i++)
+ putFile16BitBE(file, group->element[i]);
+}
+
static void SaveLevelFromFilename(struct LevelInfo *level, char *filename)
{
int body_chunk_size;
{
int envelope_len = strlen(level->envelope_text[i]) + 1;
- putFileChunkBE(file, "CNT3", LEVEL_CHUNK_CNT3_HEADER + envelope_len);
+ putFileChunkBE(file, "CNT3", LEVEL_CHUNK_CNT3_SIZE(envelope_len));
SaveLevel_CNT3(file, level, EL_ENVELOPE_1 + i);
}
}
}
}
+ /* check for non-default group elements (unless using template level) */
+ if (!level->use_custom_template)
+ {
+ for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
+ {
+ int element = EL_GROUP_START + i;
+
+ if (element_info[element].modified_settings)
+ {
+ putFileChunkBE(file, "GRP1", LEVEL_CHUNK_GRP1_SIZE);
+ SaveLevel_GRP1(file, level, element);
+ }
+ }
+ }
+
fclose(file);
SetFilePermissions(filename, PERMS_PRIVATE);
}
-void SaveLevel(int level_nr)
+void SaveLevel(int nr)
{
- char *filename = getLevelFilename(level_nr);
+ char *filename = getDefaultLevelFilename(nr);
SaveLevelFromFilename(&level, filename);
}
void SaveLevelTemplate()
{
- char *filename = getLevelFilename(-1);
+ char *filename = getDefaultLevelFilename(-1);
SaveLevelFromFilename(&level, filename);
}
void DumpLevel(struct LevelInfo *level)
{
+ if (level->no_valid_file)
+ {
+ Error(ERR_WARN, "cannot dump -- no valid level file found");
+
+ return;
+ }
+
printf_line("-", 79);
printf("Level xxx (file version %08d, game version %08d)\n",
level->file_version, level->game_version);
printf_line("-", 79);
- printf("Level Author: '%s'\n", level->author);
- printf("Level Title: '%s'\n", level->name);
+ printf("Level author: '%s'\n", level->author);
+ printf("Level title: '%s'\n", level->name);
printf("\n");
- printf("Playfield Size: %d x %d\n", level->fieldx, level->fieldy);
+ printf("Playfield size: %d x %d\n", level->fieldx, level->fieldy);
printf("\n");
- printf("Level Time: %d seconds\n", level->time);
+ printf("Level time: %d seconds\n", level->time);
printf("Gems needed: %d\n", level->gems_needed);
printf("\n");
- printf("Time for Magic Wall: %d seconds\n", level->time_magic_wall);
- printf("Time for Wheel: %d seconds\n", level->time_wheel);
- printf("Time for Light: %d seconds\n", level->time_light);
- printf("Time for Timegate: %d seconds\n", level->time_timegate);
+ printf("Time for magic wall: %d seconds\n", level->time_magic_wall);
+ printf("Time for wheel: %d seconds\n", level->time_wheel);
+ printf("Time for light: %d seconds\n", level->time_light);
+ printf("Time for timegate: %d seconds\n", level->time_timegate);
printf("\n");
- printf("Amoeba Speed: %d\n", level->amoeba_speed);
+ printf("Amoeba speed: %d\n", level->amoeba_speed);
printf("\n");
- printf("Gravity: %s\n", (level->initial_gravity ? "yes" : "no"));
- printf("Double Speed Movement: %s\n", (level->double_speed ? "yes" : "no"));
- printf("EM style slippery gems: %s\n", (level->em_slippery_gems ? "yes" : "no"));
+ printf("Initial gravity: %s\n", (level->initial_gravity ? "yes" : "no"));
+ printf("Double speed movement: %s\n", (level->double_speed ? "yes" : "no"));
+ printf("EM style slippery gems: %s\n", (level->em_slippery_gems ? "yes" : "no"));
+ printf("Player blocks last field: %s\n", (level->block_last_field ? "yes" : "no"));
+ printf("SP player blocks last field: %s\n", (level->sp_block_last_field ? "yes" : "no"));
+ printf("use spring bug: %s\n", (level->use_spring_bug ? "yes" : "no"));
+ printf("use step counter: %s\n", (level->use_step_counter ? "yes" : "no"));
printf_line("-", 79);
}
tape.recording = FALSE;
tape.playing = FALSE;
tape.pausing = FALSE;
+
+ tape.no_valid_file = FALSE;
}
static int LoadTape_VERS(FILE *file, int chunk_size, struct TapeInfo *tape)
setTapeInfoToDefaults();
if (!(file = fopen(filename, MODE_READ)))
+ {
+ tape.no_valid_file = TRUE;
+
+#if 0
+ Error(ERR_WARN, "cannot read tape '%s' -- using empty tape", filename);
+#endif
+
return;
+ }
getFileChunkBE(file, chunk_name, NULL);
if (strcmp(chunk_name, "RND1") == 0)
getFileChunkBE(file, chunk_name, NULL);
if (strcmp(chunk_name, "TAPE") != 0)
{
+ tape.no_valid_file = TRUE;
+
Error(ERR_WARN, "unknown format of tape file '%s'", filename);
fclose(file);
return;
if (!checkCookieString(cookie, TAPE_COOKIE_TMPL))
{
+ tape.no_valid_file = TRUE;
+
Error(ERR_WARN, "unknown format of tape file '%s'", filename);
fclose(file);
return;
if ((tape.file_version = getFileVersionFromCookieString(cookie)) == -1)
{
+ tape.no_valid_file = TRUE;
+
Error(ERR_WARN, "unsupported version of tape file '%s'", filename);
fclose(file);
return;
#endif
}
-void LoadTape(int level_nr)
+void LoadTape(int nr)
{
- char *filename = getTapeFilename(level_nr);
+ char *filename = getTapeFilename(nr);
LoadTapeFromFilename(filename);
}
-void LoadSolutionTape(int level_nr)
+void LoadSolutionTape(int nr)
{
- char *filename = getSolutionTapeFilename(level_nr);
+ char *filename = getSolutionTapeFilename(nr);
LoadTapeFromFilename(filename);
}
}
}
-void SaveTape(int level_nr)
+void SaveTape(int nr)
{
- char *filename = getTapeFilename(level_nr);
+ char *filename = getTapeFilename(nr);
FILE *file;
boolean new_tape = TRUE;
int num_participating_players = 0;
int body_chunk_size;
int i;
- InitTapeDirectory(leveldir_current->filename);
+ InitTapeDirectory(leveldir_current->subdir);
/* if a tape still exists, ask to overwrite it */
if (access(filename, F_OK) == 0)
{
int i, j;
+#if 1
+ if (tape->no_valid_file)
+ {
+ Error(ERR_WARN, "cannot dump -- no valid tape file found");
+
+ return;
+ }
+#else
if (TAPE_IS_EMPTY(*tape))
{
Error(ERR_WARN, "no tape available for level %d", tape->level_nr);
+
return;
}
+#endif
printf_line("-", 79);
printf("Tape of Level %03d (file version %08d, game version %08d)\n",
/* score file functions */
/* ========================================================================= */
-void LoadScore(int level_nr)
+void LoadScore(int nr)
{
int i;
- char *filename = getScoreFilename(level_nr);
+ char *filename = getScoreFilename(nr);
char cookie[MAX_LINE_LEN];
char line[MAX_LINE_LEN];
char *line_ptr;
fclose(file);
}
-void SaveScore(int level_nr)
+void SaveScore(int nr)
{
int i;
- char *filename = getScoreFilename(level_nr);
+ char *filename = getScoreFilename(nr);
FILE *file;
- InitScoreDirectory(leveldir_current->filename);
+ InitScoreDirectory(leveldir_current->subdir);
if (!(file = fopen(filename, MODE_WRITE)))
{
- Error(ERR_WARN, "cannot save score for level %d", level_nr);
+ Error(ERR_WARN, "cannot save score for level %d", nr);
return;
}
#define SETUP_TOKEN_PLAYER_JOY_YMIDDLE 6
#define SETUP_TOKEN_PLAYER_JOY_YLOWER 7
#define SETUP_TOKEN_PLAYER_JOY_SNAP 8
-#define SETUP_TOKEN_PLAYER_JOY_BOMB 9
+#define SETUP_TOKEN_PLAYER_JOY_DROP 9
#define SETUP_TOKEN_PLAYER_KEY_LEFT 10
#define SETUP_TOKEN_PLAYER_KEY_RIGHT 11
#define SETUP_TOKEN_PLAYER_KEY_UP 12
#define SETUP_TOKEN_PLAYER_KEY_DOWN 13
#define SETUP_TOKEN_PLAYER_KEY_SNAP 14
-#define SETUP_TOKEN_PLAYER_KEY_BOMB 15
+#define SETUP_TOKEN_PLAYER_KEY_DROP 15
#define NUM_PLAYER_SETUP_TOKENS 16
{ TYPE_INTEGER, &sii.joy.ymiddle, ".joy.ymiddle" },
{ TYPE_INTEGER, &sii.joy.ylower, ".joy.ylower" },
{ TYPE_INTEGER, &sii.joy.snap, ".joy.snap_field" },
- { TYPE_INTEGER, &sii.joy.bomb, ".joy.place_bomb" },
+ { TYPE_INTEGER, &sii.joy.drop, ".joy.place_bomb" },
{ TYPE_KEY_X11, &sii.key.left, ".key.move_left" },
{ TYPE_KEY_X11, &sii.key.right, ".key.move_right" },
{ TYPE_KEY_X11, &sii.key.up, ".key.move_up" },
{ TYPE_KEY_X11, &sii.key.down, ".key.move_down" },
{ TYPE_KEY_X11, &sii.key.snap, ".key.snap_field" },
- { TYPE_KEY_X11, &sii.key.bomb, ".key.place_bomb" }
+ { TYPE_KEY_X11, &sii.key.drop, ".key.place_bomb" }
};
static struct TokenInfo system_setup_tokens[] =
si->input[i].joy.ymiddle = JOYSTICK_YMIDDLE;
si->input[i].joy.ylower = JOYSTICK_YLOWER;
si->input[i].joy.snap = (i == 0 ? JOY_BUTTON_1 : 0);
- si->input[i].joy.bomb = (i == 0 ? JOY_BUTTON_2 : 0);
+ si->input[i].joy.drop = (i == 0 ? JOY_BUTTON_2 : 0);
si->input[i].key.left = (i == 0 ? DEFAULT_KEY_LEFT : KSYM_UNDEFINED);
si->input[i].key.right = (i == 0 ? DEFAULT_KEY_RIGHT : KSYM_UNDEFINED);
si->input[i].key.up = (i == 0 ? DEFAULT_KEY_UP : KSYM_UNDEFINED);
si->input[i].key.down = (i == 0 ? DEFAULT_KEY_DOWN : KSYM_UNDEFINED);
si->input[i].key.snap = (i == 0 ? DEFAULT_KEY_SNAP : KSYM_UNDEFINED);
- si->input[i].key.bomb = (i == 0 ? DEFAULT_KEY_BOMB : KSYM_UNDEFINED);
+ si->input[i].key.drop = (i == 0 ? DEFAULT_KEY_DROP : KSYM_UNDEFINED);
}
si->system.sdl_audiodriver = getStringCopy(ARG_DEFAULT);
boolean music_already_used = FALSE;
int i;
+ /* skip all music files that are configured in music config file */
for (i = 0; i < num_music; i++)
{
music = getMusicListEntry(i);
END_HASH_ITERATION(hash, itr)
#endif
}
+
+
+/* ------------------------------------------------------------------------- *
+ * convert levels
+ * ------------------------------------------------------------------------- */
+
+#define MAX_NUM_CONVERT_LEVELS 1000
+
+void ConvertLevels()
+{
+ static LevelDirTree *convert_leveldir = NULL;
+ static int convert_level_nr = -1;
+ static int num_levels_handled = 0;
+ static int num_levels_converted = 0;
+ static boolean levels_failed[MAX_NUM_CONVERT_LEVELS];
+ int i;
+
+ convert_leveldir = getTreeInfoFromIdentifier(leveldir_first,
+ global.convert_leveldir);
+
+ if (convert_leveldir == NULL)
+ Error(ERR_EXIT, "no such level identifier: '%s'",
+ global.convert_leveldir);
+
+ leveldir_current = convert_leveldir;
+
+ if (global.convert_level_nr != -1)
+ {
+ convert_leveldir->first_level = global.convert_level_nr;
+ convert_leveldir->last_level = global.convert_level_nr;
+ }
+
+ convert_level_nr = convert_leveldir->first_level;
+
+ printf_line("=", 79);
+ printf("Converting levels\n");
+ printf_line("-", 79);
+ printf("Level series identifier: '%s'\n", convert_leveldir->identifier);
+ printf("Level series name: '%s'\n", convert_leveldir->name);
+ printf("Level series author: '%s'\n", convert_leveldir->author);
+ printf("Number of levels: %d\n", convert_leveldir->levels);
+ printf_line("=", 79);
+ printf("\n");
+
+ for (i = 0; i < MAX_NUM_CONVERT_LEVELS; i++)
+ levels_failed[i] = FALSE;
+
+ while (convert_level_nr <= convert_leveldir->last_level)
+ {
+ char *level_filename;
+ boolean new_level;
+
+ level_nr = convert_level_nr++;
+
+ printf("Level %03d: ", level_nr);
+
+ LoadLevel(level_nr);
+ if (level.no_valid_file)
+ {
+ printf("(no level)\n");
+ continue;
+ }
+
+ printf("converting level ... ");
+
+ level_filename = getDefaultLevelFilename(level_nr);
+ new_level = !fileExists(level_filename);
+
+ if (new_level)
+ {
+ SaveLevel(level_nr);
+
+ num_levels_converted++;
+
+ printf("converted.\n");
+ }
+ else
+ {
+ if (level_nr >= 0 && level_nr < MAX_NUM_CONVERT_LEVELS)
+ levels_failed[level_nr] = TRUE;
+
+ printf("NOT CONVERTED -- LEVEL ALREADY EXISTS.\n");
+ }
+
+ num_levels_handled++;
+ }
+
+ printf("\n");
+ printf_line("=", 79);
+ printf("Number of levels handled: %d\n", num_levels_handled);
+ printf("Number of levels converted: %d (%d%%)\n", num_levels_converted,
+ (num_levels_handled ?
+ num_levels_converted * 100 / num_levels_handled : 0));
+ printf_line("-", 79);
+ printf("Summary (for automatic parsing by scripts):\n");
+ printf("LEVELDIR '%s', CONVERTED %d/%d (%d%%)",
+ convert_leveldir->identifier, num_levels_converted,
+ num_levels_handled,
+ (num_levels_handled ?
+ num_levels_converted * 100 / num_levels_handled : 0));
+
+ if (num_levels_handled != num_levels_converted)
+ {
+ printf(", FAILED:");
+ for (i = 0; i < MAX_NUM_CONVERT_LEVELS; i++)
+ if (levels_failed[i])
+ printf(" %03d", i);
+ }
+
+ printf("\n");
+ printf_line("=", 79);
+
+ CloseAllAndExit(0);
+}
void setElementChangePages(struct ElementInfo *, int);
void setElementChangeInfoToDefaults(struct ElementChangeInfo *);
-boolean LevelFileExists(int);
+char *getDefaultLevelFilename(int);
+
void LoadLevelFromFilename(struct LevelInfo *, char *);
void LoadLevel(int);
void LoadLevelTemplate(int);
void LoadHelpAnimInfo();
void LoadHelpTextInfo();
+void ConvertLevels(void);
+
#endif /* FILES_H */
/* for Explode() */
#define EX_PHASE_START 0
-#define EX_NO_EXPLOSION 0
-#define EX_NORMAL 1
-#define EX_CENTER 2
-#define EX_BORDER 3
+#define EX_TYPE_NONE 0
+#define EX_TYPE_NORMAL (1 << 0)
+#define EX_TYPE_CENTER (1 << 1)
+#define EX_TYPE_BORDER (1 << 2)
+#define EX_TYPE_CROSS (1 << 3)
+#define EX_TYPE_SINGLE_TILE (EX_TYPE_CENTER | EX_TYPE_BORDER)
/* special positions in the game control window (relative to control window) */
#define XX_LEVEL 37
#define YY_KEYS 123
#define XX_SCORE 15
#define YY_SCORE 159
-#define XX_TIME 29
+#define XX_TIME1 29
+#define XX_TIME2 30
#define YY_TIME 194
/* special positions in the game control window (relative to main window) */
#define DY_KEYS (DY + YY_KEYS)
#define DX_SCORE (DX + XX_SCORE)
#define DY_SCORE (DY + YY_SCORE)
-#define DX_TIME (DX + XX_TIME)
+#define DX_TIME1 (DX + XX_TIME1)
+#define DX_TIME2 (DX + XX_TIME2)
#define DY_TIME (DY + YY_TIME)
/* values for initial player move delay (initial delay counter value) */
/* values for other actions */
#define MOVE_STEPSIZE_NORMAL (TILEX / MOVE_DELAY_NORMAL_SPEED)
+#define GET_DX_FROM_DIR(d) ((d) == MV_LEFT ? -1 : (d) == MV_RIGHT ? 1 : 0)
+#define GET_DY_FROM_DIR(d) ((d) == MV_UP ? -1 : (d) == MV_DOWN ? 1 : 0)
+
#define INIT_GFX_RANDOM() (SimpleRND(1000000))
#define GET_NEW_PUSH_DELAY(e) ( (element_info[e].push_delay_fixed) + \
RND(element_info[e].push_delay_random))
+#define GET_NEW_DROP_DELAY(e) ( (element_info[e].drop_delay_fixed) + \
+ RND(element_info[e].drop_delay_random))
#define GET_NEW_MOVE_DELAY(e) ( (element_info[e].move_delay_fixed) + \
RND(element_info[e].move_delay_random))
#define GET_MAX_MOVE_DELAY(e) ( (element_info[e].move_delay_fixed) + \
(element_info[e].move_delay_random))
-#define ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, condition) \
+#define GET_TARGET_ELEMENT(e, ch) \
+ ((e) == EL_TRIGGER_ELEMENT ? (ch)->actual_trigger_element : \
+ (e) == EL_TRIGGER_PLAYER ? (ch)->actual_trigger_player : (e))
+
+#define GET_VALID_PLAYER_ELEMENT(e) \
+ ((e) >= EL_PLAYER_1 && (e) <= EL_PLAYER_4 ? (e) : EL_PLAYER_1)
+
+#define CAN_GROW_INTO(e) \
+ ((e) == EL_SAND || (IS_DIGGABLE(e) && level.grow_into_diggable))
+
+#define ELEMENT_CAN_ENTER_FIELD_BASE_X(x, y, condition) \
+ (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
+ (condition)))
+
+#define ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, condition) \
+ (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
+ (CAN_MOVE_INTO_ACID(e) && \
+ Feld[x][y] == EL_ACID) || \
+ (condition)))
+
+#define ELEMENT_CAN_ENTER_FIELD_BASE_3(e, x, y, condition) \
+ (IN_LEV_FIELD(x, y) && (IS_FREE_OR_PLAYER(x, y) || \
+ (CAN_MOVE_INTO_ACID(e) && \
+ Feld[x][y] == EL_ACID) || \
+ (condition)))
+
+#define ELEMENT_CAN_ENTER_FIELD_BASE_4(e, x, y, condition) \
(IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
(condition) || \
+ (CAN_MOVE_INTO_ACID(e) && \
+ Feld[x][y] == EL_ACID) || \
(DONT_COLLIDE_WITH(e) && \
- IS_FREE_OR_PLAYER(x, y))))
+ IS_PLAYER(x, y) && \
+ !PLAYER_ENEMY_PROTECTED(x, y))))
-#define ELEMENT_CAN_ENTER_FIELD_GENERIC_2(x, y, condition) \
+#if 0
+#define ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, condition) \
(IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
- (condition)))
+ (condition) || \
+ (DONT_COLLIDE_WITH(e) && \
+ IS_PLAYER(x, y) && \
+ !PLAYER_ENEMY_PROTECTED(x, y))))
+#endif
#define ELEMENT_CAN_ENTER_FIELD(e, x, y) \
- ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, 0)
+ ELEMENT_CAN_ENTER_FIELD_BASE_4(e, x, y, 0)
+
+#if 1
+#define SATELLITE_CAN_ENTER_FIELD(x, y) \
+ ELEMENT_CAN_ENTER_FIELD_BASE_2(EL_SATELLITE, x, y, 0)
+#else
+#define SATELLITE_CAN_ENTER_FIELD(x, y) \
+ ELEMENT_CAN_ENTER_FIELD_BASE_X(x, y, Feld[x][y] == EL_ACID)
+#endif
+
+#if 0
+#define ENEMY_CAN_ENTER_FIELD(e, x, y) (IN_LEV_FIELD(x, y) && IS_FREE(x, y))
+#endif
+
+#define ENEMY_CAN_ENTER_FIELD(e, x, y) \
+ ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, 0)
+
+#if 1
+
+#define YAMYAM_CAN_ENTER_FIELD(e, x, y) \
+ ELEMENT_CAN_ENTER_FIELD_BASE_3(e, x, y, Feld[x][y] == EL_DIAMOND)
+
+#define DARK_YAMYAM_CAN_ENTER_FIELD(e, x, y) \
+ ELEMENT_CAN_ENTER_FIELD_BASE_3(e, x,y, IS_FOOD_DARK_YAMYAM(Feld[x][y]))
-#define ELEMENT_CAN_ENTER_FIELD_OR_ACID(e, x, y) \
- ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, (Feld[x][y] == EL_ACID))
+#define PACMAN_CAN_ENTER_FIELD(e, x, y) \
+ ELEMENT_CAN_ENTER_FIELD_BASE_3(e, x, y, IS_AMOEBOID(Feld[x][y]))
-#define ELEMENT_CAN_ENTER_FIELD_OR_ACID_2(x, y) \
- ELEMENT_CAN_ENTER_FIELD_GENERIC_2(x, y, (Feld[x][y] == EL_ACID))
+#define PIG_CAN_ENTER_FIELD(e, x, y) \
+ ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, IS_FOOD_PIG(Feld[x][y]))
-#define ENEMY_CAN_ENTER_FIELD(x, y) (IN_LEV_FIELD(x, y) && IS_FREE(x, y))
+#define PENGUIN_CAN_ENTER_FIELD(e, x, y) \
+ ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, (Feld[x][y] == EL_EXIT_OPEN ||\
+ IS_FOOD_PENGUIN(Feld[x][y])))
+#define DRAGON_CAN_ENTER_FIELD(e, x, y) \
+ ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, 0)
-#define YAMYAM_CAN_ENTER_FIELD(x, y) \
+#define MOLE_CAN_ENTER_FIELD(e, x, y, condition) \
+ ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, (condition))
+
+#define SPRING_CAN_ENTER_FIELD(e, x, y) \
+ ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, 0)
+
+#else
+
+#define YAMYAM_CAN_ENTER_FIELD(e, x, y) \
(IN_LEV_FIELD(x, y) && (IS_FREE_OR_PLAYER(x, y) || \
+ (CAN_MOVE_INTO_ACID(e) && \
+ Feld[x][y] == EL_ACID) || \
Feld[x][y] == EL_DIAMOND))
-#define DARK_YAMYAM_CAN_ENTER_FIELD(x, y) \
+#define DARK_YAMYAM_CAN_ENTER_FIELD(e, x, y) \
(IN_LEV_FIELD(x, y) && (IS_FREE_OR_PLAYER(x, y) || \
+ (CAN_MOVE_INTO_ACID(e) && \
+ Feld[x][y] == EL_ACID) || \
IS_FOOD_DARK_YAMYAM(Feld[x][y])))
-#define PACMAN_CAN_ENTER_FIELD(x, y) \
+#define PACMAN_CAN_ENTER_FIELD(e, x, y) \
(IN_LEV_FIELD(x, y) && (IS_FREE_OR_PLAYER(x, y) || \
+ (CAN_MOVE_INTO_ACID(e) && \
+ Feld[x][y] == EL_ACID) || \
IS_AMOEBOID(Feld[x][y])))
-#define PIG_CAN_ENTER_FIELD(x, y) \
+#define PIG_CAN_ENTER_FIELD(e, x, y) \
(IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
+ (CAN_MOVE_INTO_ACID(e) && \
+ Feld[x][y] == EL_ACID) || \
IS_FOOD_PIG(Feld[x][y])))
-#define PENGUIN_CAN_ENTER_FIELD(x, y) \
+#define PENGUIN_CAN_ENTER_FIELD(e, x, y) \
(IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
+ (CAN_MOVE_INTO_ACID(e) && \
+ Feld[x][y] == EL_ACID) || \
IS_FOOD_PENGUIN(Feld[x][y]) || \
- Feld[x][y] == EL_EXIT_OPEN || \
- Feld[x][y] == EL_ACID))
+ Feld[x][y] == EL_EXIT_OPEN))
-#define MAZE_RUNNER_CAN_ENTER_FIELD(x, y) \
+#define DRAGON_CAN_ENTER_FIELD(e, x, y) \
(IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
- IS_FOOD_DARK_YAMYAM(Feld[x][y])))
+ (CAN_MOVE_INTO_ACID(e) && \
+ Feld[x][y] == EL_ACID)))
+
+#define MOLE_CAN_ENTER_FIELD(e, x, y, condition) \
+ (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
+ (CAN_MOVE_INTO_ACID(e) && \
+ Feld[x][y] == EL_ACID) || \
+ (condition)))
+
+#define SPRING_CAN_ENTER_FIELD(e, x, y) \
+ (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
+ (CAN_MOVE_INTO_ACID(e) && \
+ Feld[x][y] == EL_ACID)))
+
+#endif
+
+#define GROUP_NR(e) ((e) - EL_GROUP_START)
+#define MOVE_ENTER_EL(e) (element_info[e].move_enter_element)
+#define IS_IN_GROUP(e, nr) (element_info[e].in_group[nr] == TRUE)
+#define IS_IN_GROUP_EL(e, ge) (IS_IN_GROUP(e, (ge) - EL_GROUP_START))
+
+#define IS_EQUAL_OR_IN_GROUP(e, ge) \
+ (IS_GROUP_ELEMENT(ge) ? IS_IN_GROUP(e, GROUP_NR(ge)) : (e) == (ge))
+
+#if 0
+#define CE_ENTER_FIELD_COND(e, x, y) \
+ (!IS_PLAYER(x, y) && \
+ (Feld[x][y] == EL_ACID || \
+ IS_EQUAL_OR_IN_GROUP(Feld[x][y], MOVE_ENTER_EL(e))))
+#else
+#define CE_ENTER_FIELD_COND(e, x, y) \
+ (!IS_PLAYER(x, y) && \
+ IS_EQUAL_OR_IN_GROUP(Feld[x][y], MOVE_ENTER_EL(e)))
+#endif
-#define MOLE_CAN_ENTER_FIELD(x, y, condition) \
- (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || (condition)))
+#define CUSTOM_ELEMENT_CAN_ENTER_FIELD(e, x, y) \
+ ELEMENT_CAN_ENTER_FIELD_BASE_4(e, x, y, CE_ENTER_FIELD_COND(e, x, y))
#define IN_LEV_FIELD_AND_IS_FREE(x, y) (IN_LEV_FIELD(x, y) && IS_FREE(x, y))
#define IN_LEV_FIELD_AND_NOT_FREE(x, y) (IN_LEV_FIELD(x, y) && !IS_FREE(x, y))
+#define ACCESS_FROM(e, d) (element_info[e].access_direction &(d))
+#define IS_WALKABLE_FROM(e, d) (IS_WALKABLE(e) && ACCESS_FROM(e, d))
+#define IS_PASSABLE_FROM(e, d) (IS_PASSABLE(e) && ACCESS_FROM(e, d))
+#define IS_ACCESSIBLE_FROM(e, d) (IS_ACCESSIBLE(e) && ACCESS_FROM(e, d))
+
/* game button identifiers */
#define GAME_CTRL_ID_STOP 0
#define GAME_CTRL_ID_PAUSE 1
static void ScrollPlayer(struct PlayerInfo *, int);
static void ScrollScreen(struct PlayerInfo *, int);
+int DigField(struct PlayerInfo *, int, int, int, int, int, int, int);
+
static void InitBeltMovement(void);
static void CloseAllOpenTimegates(void);
static void CheckGravityMovement(struct PlayerInfo *);
-static void KillHeroUnlessProtected(int, int);
+static void CheckGravityMovementWhenNotMoving(struct PlayerInfo *);
+static void KillHeroUnlessEnemyProtected(int, int);
+static void KillHeroUnlessExplosionProtected(int, int);
static void TestIfPlayerTouchesCustomElement(int, int);
static void TestIfElementTouchesCustomElement(int, int);
+static void TestIfElementHitsCustomElement(int, int, int);
+#if 0
+static void TestIfElementSmashesCustomElement(int, int, int);
+#endif
static void ChangeElement(int, int, int);
-static boolean CheckTriggeredElementSideChange(int, int, int, int, int);
-static boolean CheckTriggeredElementChange(int, int, int, int);
-static boolean CheckElementSideChange(int, int, int, int, int, int);
-static boolean CheckElementChange(int, int, int, int);
+
+static boolean CheckTriggeredElementChangeExt(int, int, int, int, int,int,int);
+#define CheckTriggeredElementChange(x, y, e, ev) \
+ CheckTriggeredElementChangeExt(x, y, e, ev, CH_PLAYER_ANY, \
+ CH_SIDE_ANY, -1)
+#define CheckTriggeredElementChangeByPlayer(x, y, e, ev, p, s) \
+ CheckTriggeredElementChangeExt(x, y, e, ev, p, s, -1)
+#define CheckTriggeredElementChangeBySide(x, y, e, ev, s) \
+ CheckTriggeredElementChangeExt(x, y, e, ev, CH_PLAYER_ANY, s, -1)
+#define CheckTriggeredElementChangeByPage(x, y, e, ev, p) \
+ CheckTriggeredElementChangeExt(x, y, e, ev, CH_PLAYER_ANY, \
+ CH_SIDE_ANY, p)
+
+static boolean CheckElementChangeExt(int, int, int, int, int, int, int, int);
+#define CheckElementChange(x, y, e, te, ev) \
+ CheckElementChangeExt(x, y, e, te, ev, CH_PLAYER_ANY, CH_SIDE_ANY, -1)
+#define CheckElementChangeByPlayer(x, y, e, ev, p, s) \
+ CheckElementChangeExt(x, y, e, EL_EMPTY, ev, p, s, CH_PAGE_ANY)
+#define CheckElementChangeBySide(x, y, e, te, ev, s) \
+ CheckElementChangeExt(x, y, e, te, ev, CH_PLAYER_ANY, s, CH_PAGE_ANY)
+#define CheckElementChangeByPage(x, y, e, te, ev, p) \
+ CheckElementChangeExt(x, y, e, te, ev, CH_PLAYER_ANY, CH_SIDE_ANY, p)
static void PlayLevelSound(int, int, int);
static void PlayLevelSoundNearest(int, int, int);
{ EL_UNDEFINED, 0 },
};
+struct
+{
+ int element;
+ int direction;
+}
+access_direction_list[] =
+{
+ { EL_TUBE_ANY, MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN },
+ { EL_TUBE_VERTICAL, MV_UP | MV_DOWN },
+ { EL_TUBE_HORIZONTAL, MV_LEFT | MV_RIGHT },
+ { EL_TUBE_VERTICAL_LEFT, MV_LEFT | MV_UP | MV_DOWN },
+ { EL_TUBE_VERTICAL_RIGHT, MV_RIGHT | MV_UP | MV_DOWN },
+ { EL_TUBE_HORIZONTAL_UP, MV_LEFT | MV_RIGHT | MV_UP },
+ { EL_TUBE_HORIZONTAL_DOWN, MV_LEFT | MV_RIGHT | MV_DOWN },
+ { EL_TUBE_LEFT_UP, MV_LEFT | MV_UP },
+ { EL_TUBE_LEFT_DOWN, MV_LEFT | MV_DOWN },
+ { EL_TUBE_RIGHT_UP, MV_RIGHT | MV_UP },
+ { EL_TUBE_RIGHT_DOWN, MV_RIGHT | MV_DOWN },
+
+ { EL_SP_PORT_LEFT, MV_RIGHT },
+ { EL_SP_PORT_RIGHT, MV_LEFT },
+ { EL_SP_PORT_UP, MV_DOWN },
+ { EL_SP_PORT_DOWN, MV_UP },
+ { EL_SP_PORT_HORIZONTAL, MV_LEFT | MV_RIGHT },
+ { EL_SP_PORT_VERTICAL, MV_UP | MV_DOWN },
+ { EL_SP_PORT_ANY, MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN },
+ { EL_SP_GRAVITY_PORT_LEFT, MV_RIGHT },
+ { EL_SP_GRAVITY_PORT_RIGHT, MV_LEFT },
+ { EL_SP_GRAVITY_PORT_UP, MV_DOWN },
+ { EL_SP_GRAVITY_PORT_DOWN, MV_UP },
+ { EL_SP_GRAVITY_ON_PORT_LEFT, MV_RIGHT },
+ { EL_SP_GRAVITY_ON_PORT_RIGHT, MV_LEFT },
+ { EL_SP_GRAVITY_ON_PORT_UP, MV_DOWN },
+ { EL_SP_GRAVITY_ON_PORT_DOWN, MV_UP },
+ { EL_SP_GRAVITY_OFF_PORT_LEFT, MV_RIGHT },
+ { EL_SP_GRAVITY_OFF_PORT_RIGHT, MV_LEFT },
+ { EL_SP_GRAVITY_OFF_PORT_UP, MV_DOWN },
+ { EL_SP_GRAVITY_OFF_PORT_DOWN, MV_UP },
+
+ { EL_UNDEFINED, MV_NO_MOVING }
+};
+
static unsigned long trigger_events[MAX_NUM_ELEMENTS];
#define IS_AUTO_CHANGING(e) (element_info[e].change_events & \
player->present = TRUE;
+ player->block_last_field = (element == EL_SP_MURPHY ?
+ level.sp_block_last_field :
+ level.block_last_field);
+
if (!options.network || player->connected)
{
player->active = TRUE;
}
Feld[x][y] = EL_EMPTY;
+
player->jx = player->last_jx = x;
player->jy = player->last_jy = y;
}
InitPlayerField(x, y, element, init_game);
break;
+ case EL_SOKOBAN_FIELD_PLAYER:
+ element = Feld[x][y] = EL_PLAYER_1;
+ InitField(x, y, init_game);
+
+ element = Feld[x][y] = EL_SOKOBAN_FIELD_EMPTY;
+ InitField(x, y, init_game);
+ break;
+
+ case EL_SOKOBAN_FIELD_EMPTY:
+ local_player->sokobanfields_still_needed++;
+ break;
+
case EL_STONEBLOCK:
if (x < lev_fieldx-1 && Feld[x+1][y] == EL_ACID)
Feld[x][y] = EL_ACID_POOL_TOPLEFT;
break;
case EL_DYNAMITE_ACTIVE:
+ case EL_SP_DISK_RED_ACTIVE:
+ case EL_DYNABOMB_PLAYER_1_ACTIVE:
+ case EL_DYNABOMB_PLAYER_2_ACTIVE:
+ case EL_DYNABOMB_PLAYER_3_ACTIVE:
+ case EL_DYNABOMB_PLAYER_4_ACTIVE:
MovDelay[x][y] = 96;
break;
local_player->lights_still_needed++;
break;
- case EL_SOKOBAN_FIELD_EMPTY:
- local_player->sokobanfields_still_needed++;
- break;
-
case EL_PENGUIN:
local_player->friends_still_needed++;
break;
default:
if (IS_CUSTOM_ELEMENT(element) && CAN_MOVE(element))
InitMovDir(x, y);
+ else if (IS_GROUP_ELEMENT(element))
+ {
+ struct ElementGroupInfo *group = element_info[element].group;
+ int last_anim_random_frame = gfx.anim_random_frame;
+ int element_pos;
+
+ if (group->choice_mode == ANIM_RANDOM)
+ gfx.anim_random_frame = RND(group->num_elements_resolved);
+
+ element_pos = getAnimationFrame(group->num_elements_resolved, 1,
+ group->choice_mode, 0,
+ group->choice_pos);
+
+ if (group->choice_mode == ANIM_RANDOM)
+ gfx.anim_random_frame = last_anim_random_frame;
+
+ group->choice_pos++;
+
+ Feld[x][y] = group->element_resolved[element_pos];
+
+ InitField(x, y, init_game);
+ }
break;
}
}
+static inline void InitField_WithBug1(int x, int y, boolean init_game)
+{
+ InitField(x, y, init_game);
+
+ /* not needed to call InitMovDir() -- already done by InitField()! */
+ if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
+ CAN_MOVE(Feld[x][y]))
+ InitMovDir(x, y);
+}
+
+static inline void InitField_WithBug2(int x, int y, boolean init_game)
+{
+ int old_element = Feld[x][y];
+
+ InitField(x, y, init_game);
+
+ /* not needed to call InitMovDir() -- already done by InitField()! */
+ if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
+ CAN_MOVE(old_element) &&
+ (old_element < EL_MOLE_LEFT || old_element > EL_MOLE_DOWN))
+ InitMovDir(x, y);
+
+ /* this case is in fact a combination of not less than three bugs:
+ first, it calls InitMovDir() for elements that can move, although this is
+ already done by InitField(); then, it checks the element that was at this
+ field _before_ the call to InitField() (which can change it); lastly, it
+ was not called for "mole with direction" elements, which were treated as
+ "cannot move" due to (fixed) wrong element initialization in "src/init.c"
+ */
+}
+
+inline void DrawGameValue_Emeralds(int value)
+{
+ DrawText(DX_EMERALDS, DY_EMERALDS, int2str(value, 3), FONT_TEXT_2);
+}
+
+inline void DrawGameValue_Dynamite(int value)
+{
+ DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(value, 3), FONT_TEXT_2);
+}
+
+inline void DrawGameValue_Keys(struct PlayerInfo *player)
+{
+ int i;
+
+ for (i = 0; i < MAX_KEYS; i++)
+ if (player->key[i])
+ DrawMiniGraphicExt(drawto, DX_KEYS + i * MINI_TILEX, DY_KEYS,
+ el2edimg(EL_KEY_1 + i));
+}
+
+inline void DrawGameValue_Score(int value)
+{
+ DrawText(DX_SCORE, DY_SCORE, int2str(value, 5), FONT_TEXT_2);
+}
+
+inline void DrawGameValue_Time(int value)
+{
+ if (value < 1000)
+ DrawText(DX_TIME1, DY_TIME, int2str(value, 3), FONT_TEXT_2);
+ else
+ DrawText(DX_TIME2, DY_TIME, int2str(value, 4), FONT_LEVEL_NUMBER);
+}
+
+inline void DrawGameValue_Level(int value)
+{
+ if (level_nr < 100)
+ DrawText(DX_LEVEL, DY_LEVEL, int2str(value, 2), FONT_TEXT_2);
+ else
+ {
+ /* misuse area for displaying emeralds to draw bigger level number */
+ DrawTextExt(drawto, DX_EMERALDS, DY_EMERALDS,
+ int2str(value, 3), FONT_LEVEL_NUMBER, BLIT_OPAQUE);
+
+ /* now copy it to the area for displaying level number */
+ BlitBitmap(drawto, drawto,
+ DX_EMERALDS, DY_EMERALDS + 1,
+ getFontWidth(FONT_LEVEL_NUMBER) * 3,
+ getFontHeight(FONT_LEVEL_NUMBER) - 1,
+ DX_LEVEL - 1, DY_LEVEL + 1);
+
+ /* restore the area for displaying emeralds */
+ DrawGameValue_Emeralds(local_player->gems_still_needed);
+
+ /* yes, this is all really ugly :-) */
+ }
+}
+
void DrawGameDoorValues()
{
- int i, j;
+ int i;
+
+ DrawGameValue_Level(level_nr);
for (i = 0; i < MAX_PLAYERS; i++)
- for (j = 0; j < 4; j++)
- if (stored_player[i].key[j])
- DrawMiniGraphicExt(drawto, DX_KEYS + j * MINI_TILEX, DY_KEYS,
- el2edimg(EL_KEY_1 + j));
+ DrawGameValue_Keys(&stored_player[i]);
+
+ DrawGameValue_Emeralds(local_player->gems_still_needed);
+ DrawGameValue_Dynamite(local_player->inventory_size);
+ DrawGameValue_Score(local_player->score);
+ DrawGameValue_Time(TimeLeft);
+}
+
+static void resolve_group_element(int group_element, int recursion_depth)
+{
+ static int group_nr;
+ static struct ElementGroupInfo *group;
+ struct ElementGroupInfo *actual_group = element_info[group_element].group;
+ int i;
+
+ if (recursion_depth > NUM_GROUP_ELEMENTS) /* recursion too deep */
+ {
+ Error(ERR_WARN, "recursion too deep when resolving group element %d",
+ group_element - EL_GROUP_START + 1);
+
+ /* replace element which caused too deep recursion by question mark */
+ group->element_resolved[group->num_elements_resolved++] = EL_UNKNOWN;
+
+ return;
+ }
- DrawText(DX + XX_EMERALDS, DY + YY_EMERALDS,
- int2str(local_player->gems_still_needed, 3), FONT_TEXT_2);
- DrawText(DX + XX_DYNAMITE, DY + YY_DYNAMITE,
- int2str(local_player->inventory_size, 3), FONT_TEXT_2);
- DrawText(DX + XX_SCORE, DY + YY_SCORE,
- int2str(local_player->score, 5), FONT_TEXT_2);
- DrawText(DX + XX_TIME, DY + YY_TIME,
- int2str(TimeLeft, 3), FONT_TEXT_2);
+ if (recursion_depth == 0) /* initialization */
+ {
+ group = element_info[group_element].group;
+ group_nr = group_element - EL_GROUP_START;
+
+ group->num_elements_resolved = 0;
+ group->choice_pos = 0;
+ }
+
+ for (i = 0; i < actual_group->num_elements; i++)
+ {
+ int element = actual_group->element[i];
+
+ if (group->num_elements_resolved == NUM_FILE_ELEMENTS)
+ break;
+
+ if (IS_GROUP_ELEMENT(element))
+ resolve_group_element(element, recursion_depth + 1);
+ else
+ {
+ group->element_resolved[group->num_elements_resolved++] = element;
+ element_info[element].in_group[group_nr] = TRUE;
+ }
+ }
+
+#if 0
+ if (recursion_depth == 0 && group_element <= EL_GROUP_4)
+ {
+ printf("::: group %d: %d resolved elements\n",
+ group_element - EL_GROUP_START, group->num_elements_resolved);
+ for (i = 0; i < group->num_elements_resolved; i++)
+ printf("::: - %d ['%s']\n", group->element_resolved[i],
+ element_info[group->element_resolved[i]].token_name);
+ }
+#endif
}
printf(" => game.engine_version == %06d\n", game.engine_version);
#endif
+ /* ---------- recursively resolve group elements ------------------------- */
+
+ for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+ for (j = 0; j < NUM_GROUP_ELEMENTS; j++)
+ element_info[i].in_group[j] = FALSE;
+
+ for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
+ resolve_group_element(EL_GROUP_START + i, 0);
+
/* ---------- initialize player's initial move delay --------------------- */
/* dynamically adjust player properties according to game engine version */
ei->change->post_change_function = ch_delay->post_change_function;
ei->change_events |= CH_EVENT_BIT(CE_DELAY);
+
+#if 1
+ SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE, TRUE);
+#endif
}
#if 1
}
#endif
+ /* ---------- initialize run-time trigger player and element ------------- */
+
+ for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i];
+
+ for (j = 0; j < ei->num_change_pages; j++)
+ {
+ ei->change_page[j].actual_trigger_element = EL_EMPTY;
+ ei->change_page[j].actual_trigger_player = EL_PLAYER_1;
+ }
+ }
+
/* ---------- initialize trigger events ---------------------------------- */
/* initialize trigger events information */
{
int trigger_element = ei->change_page[j].trigger_element;
- trigger_events[trigger_element] |= ei->change_page[j].events;
+ if (IS_GROUP_ELEMENT(trigger_element))
+ {
+ struct ElementGroupInfo *group = element_info[trigger_element].group;
+
+ for (k = 0; k < group->num_elements_resolved; k++)
+ trigger_events[group->element_resolved[k]]
+ |= ei->change_page[j].events;
+ }
+ else
+ trigger_events[trigger_element] |= ei->change_page[j].events;
}
}
}
element_info[e].push_delay_random = push_delay_list[i].push_delay_random;
}
+ /* set push delay value for Supaplex elements for newer engine versions */
+ if (game.engine_version >= VERSION_IDENT(3,1,0,0))
+ {
+ for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+ {
+ if (IS_SP_ELEMENT(i))
+ {
+ element_info[i].push_delay_fixed = 6; /* just enough to escape ... */
+ element_info[i].push_delay_random = 0; /* ... from falling zonk */
+ }
+ }
+ }
+
/* ---------- initialize move stepsize ----------------------------------- */
/* initialize move stepsize values to default */
element_info[e].move_stepsize = move_stepsize_list[i].move_stepsize;
}
+#if 0
+ /* ---------- initialize move dig/leave ---------------------------------- */
+
+ for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+ {
+ element_info[i].can_leave_element = FALSE;
+ element_info[i].can_leave_element_last = FALSE;
+ }
+#endif
+
/* ---------- initialize gem count --------------------------------------- */
/* initialize gem count values for each element */
for (i = 0; collect_count_list[i].element != EL_UNDEFINED; i++)
element_info[collect_count_list[i].element].collect_count =
collect_count_list[i].count;
+
+ /* ---------- initialize access direction -------------------------------- */
+
+ /* initialize access direction values to default (access from every side) */
+ for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+ if (!IS_CUSTOM_ELEMENT(i))
+ element_info[i].access_direction = MV_ALL_DIRECTIONS;
+
+ /* set access direction value for certain elements from pre-defined list */
+ for (i = 0; access_direction_list[i].element != EL_UNDEFINED; i++)
+ element_info[access_direction_list[i].element].access_direction =
+ access_direction_list[i].direction;
}
struct PlayerInfo *player = &stored_player[i];
player->index_nr = i;
+ player->index_bit = (1 << i);
player->element_nr = EL_PLAYER_1 + i;
player->present = FALSE;
player->lights_still_needed = 0;
player->friends_still_needed = 0;
- for (j = 0; j < 4; j++)
+ for (j = 0; j < MAX_KEYS; j++)
player->key[j] = FALSE;
player->dynabomb_count = 0;
player->use_murphy_graphic = FALSE;
+ player->block_last_field = FALSE;
+ player->can_fall_into_acid = CAN_MOVE_INTO_ACID(player->element_nr);
+
player->actual_frame_counter = 0;
player->step_counter = 0;
player->is_waiting = FALSE;
player->is_moving = FALSE;
+ player->is_auto_moving = FALSE;
player->is_digging = FALSE;
player->is_snapping = FALSE;
player->is_collecting = FALSE;
player->is_pushing = FALSE;
player->is_switching = FALSE;
+ player->is_dropping = FALSE;
player->is_bored = FALSE;
player->is_sleeping = FALSE;
player->move_delay = game.initial_move_delay;
player->move_delay_value = game.initial_move_delay_value;
+ player->move_delay_reset_counter = 0;
+
player->push_delay = 0;
player->push_delay_value = game.initial_push_delay_value;
+ player->drop_delay = 0;
+
player->last_jx = player->last_jy = 0;
player->jx = player->jy = 0;
player->shield_normal_time_left = 0;
player->shield_deadly_time_left = 0;
+ player->inventory_infinite_element = EL_UNDEFINED;
player->inventory_size = 0;
- DigField(player, 0, 0, 0, 0, DF_NO_PUSH);
+ DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH);
SnapField(player, 0, 0);
player->LevelSolved = FALSE;
network_player_action_received = FALSE;
-#if defined(PLATFORM_UNIX)
+#if defined(NETWORK_AVALIABLE)
/* initial null action */
if (network_playing)
SendToServer_MovePlayer(MV_NO_MOVING);
TimeFrames = 0;
TimePlayed = 0;
TimeLeft = level.time;
+ TapeTime = 0;
ScreenMovDir = MV_NO_MOVING;
ScreenMovPos = 0;
game.envelope_active = FALSE;
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_BELTS; i++)
{
game.belt_dir[i] = MV_NO_MOVING;
game.belt_dir_nr[i] = 3; /* not moving, next moving left */
AmoebaNr[x][y] = 0;
WasJustMoving[x][y] = 0;
WasJustFalling[x][y] = 0;
+ CheckCollision[x][y] = 0;
Stop[x][y] = FALSE;
Pushed[x][y] = FALSE;
ChangeEvent[x][y] = CE_BITMASK_DEFAULT;
ExplodePhase[x][y] = 0;
- ExplodeField[x][y] = EX_NO_EXPLOSION;
+ ExplodeDelay[x][y] = 0;
+ ExplodeField[x][y] = EX_TYPE_NONE;
RunnerVisit[x][y] = 0;
PlayerVisit[x][y] = 0;
emulate_sb ? EMU_SOKOBAN :
emulate_sp ? EMU_SUPAPLEX : EMU_NONE);
+ /* initialize explosion and ignition delay */
+ for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+ {
+ if (!IS_CUSTOM_ELEMENT(i))
+ {
+ int num_phase = 8;
+ int delay = (((IS_SP_ELEMENT(i) && i != EL_EMPTY_SPACE) &&
+ game.engine_version >= VERSION_IDENT(3,1,0,0)) ||
+ game.emulation == EMU_SUPAPLEX ? 3 : 2);
+ int last_phase = (num_phase + 1) * delay;
+ int half_phase = (num_phase / 2) * delay;
+
+ element_info[i].explosion_delay = last_phase - 1;
+ element_info[i].ignition_delay = half_phase;
+
+#if 0
+ if (i == EL_BLACK_ORB)
+ element_info[i].ignition_delay = 0;
+#else
+ if (i == EL_BLACK_ORB)
+ element_info[i].ignition_delay = 1;
+#endif
+ }
+
+#if 0
+ if (element_info[i].explosion_delay < 1) /* !!! check again !!! */
+ element_info[i].explosion_delay = 1;
+
+ if (element_info[i].ignition_delay < 1) /* !!! check again !!! */
+ element_info[i].ignition_delay = 1;
+#endif
+ }
+
/* correct non-moving belts to start moving left */
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_BELTS; i++)
if (game.belt_dir[i] == MV_NO_MOVING)
game.belt_dir_nr[i] = 3; /* not moving, next moving left */
{
player->present = TRUE;
player->active = TRUE;
+
some_player->present = FALSE;
+ some_player->active = FALSE;
+
+#if 0
+ player->element_nr = some_player->element_nr;
+#endif
StorePlayer[jx][jy] = player->element_nr;
player->jx = player->last_jx = jx;
if (tape.playing)
{
- /* when playing a tape, eliminate all players who do not participate */
+ /* when playing a tape, eliminate all players which do not participate */
for (i = 0; i < MAX_PLAYERS; i++)
{
int jx = player->jx, jy = player->jy;
player->active = FALSE;
+ player->present = FALSE;
+
StorePlayer[jx][jy] = 0;
Feld[jx][jy] = EL_EMPTY;
}
for (i = 0; i < element_info[element].num_change_pages; i++)
{
- content = element_info[element].change_page[i].content[xx][yy];
+ content= element_info[element].change_page[i].target_content[xx][yy];
is_player = ELEM_IS_PLAYER(content);
if (is_player && (found_rating < 1 || element < found_element))
BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
- if (level_nr < 100)
- DrawText(DX + XX_LEVEL, DY + YY_LEVEL, int2str(level_nr, 2), FONT_TEXT_2);
- else
- {
- DrawTextExt(drawto, DX + XX_EMERALDS, DY + YY_EMERALDS,
- int2str(level_nr, 3), FONT_LEVEL_NUMBER, BLIT_OPAQUE);
- BlitBitmap(drawto, drawto,
- DX + XX_EMERALDS, DY + YY_EMERALDS + 1,
- getFontWidth(FONT_LEVEL_NUMBER) * 3,
- getFontHeight(FONT_LEVEL_NUMBER) - 1,
- DX + XX_LEVEL - 1, DY + YY_LEVEL + 1);
- }
-
DrawGameDoorValues();
UnmapGameButtons();
if (options.debug)
{
- for (i = 0; i < 4; i++)
+ for (i = 0; i < MAX_PLAYERS; i++)
printf("Player %d %sactive.\n",
i + 1, (stored_player[i].active ? "" : "not "));
}
default:
if (IS_CUSTOM_ELEMENT(element))
{
- if (element_info[element].move_direction_initial != MV_NO_MOVING)
- MovDir[x][y] = element_info[element].move_direction_initial;
- else if (element_info[element].move_pattern == MV_ALL_DIRECTIONS ||
- element_info[element].move_pattern == MV_TURNING_LEFT ||
- element_info[element].move_pattern == MV_TURNING_RIGHT)
+ struct ElementInfo *ei = &element_info[element];
+ int move_direction_initial = ei->move_direction_initial;
+ int move_pattern = ei->move_pattern;
+
+ if (move_direction_initial == MV_START_PREVIOUS)
+ {
+ if (MovDir[x][y] != MV_NO_MOVING)
+ return;
+
+ move_direction_initial = MV_START_AUTOMATIC;
+ }
+
+ if (move_direction_initial == MV_START_RANDOM)
+ MovDir[x][y] = 1 << RND(4);
+ else if (move_direction_initial & MV_ANY_DIRECTION)
+ MovDir[x][y] = move_direction_initial;
+ else if (move_pattern == MV_ALL_DIRECTIONS ||
+ move_pattern == MV_TURNING_LEFT ||
+ move_pattern == MV_TURNING_RIGHT ||
+ move_pattern == MV_TURNING_LEFT_RIGHT ||
+ move_pattern == MV_TURNING_RIGHT_LEFT ||
+ move_pattern == MV_TURNING_RANDOM)
MovDir[x][y] = 1 << RND(4);
- else if (element_info[element].move_pattern == MV_HORIZONTAL)
+ else if (move_pattern == MV_HORIZONTAL)
MovDir[x][y] = (RND(2) ? MV_LEFT : MV_RIGHT);
- else if (element_info[element].move_pattern == MV_VERTICAL)
+ else if (move_pattern == MV_VERTICAL)
MovDir[x][y] = (RND(2) ? MV_UP : MV_DOWN);
- else if (element_info[element].move_pattern & MV_ANY_DIRECTION)
+ else if (move_pattern & MV_ANY_DIRECTION)
MovDir[x][y] = element_info[element].move_pattern;
- else if (element_info[element].move_pattern == MV_ALONG_LEFT_SIDE ||
- element_info[element].move_pattern == MV_ALONG_RIGHT_SIDE)
+ else if (move_pattern == MV_ALONG_LEFT_SIDE ||
+ move_pattern == MV_ALONG_RIGHT_SIDE)
{
- for (i = 0; i < 4; i++)
+#if 1
+ /* use random direction as default start direction */
+ if (game.engine_version >= VERSION_IDENT(3,1,0,0))
+ MovDir[x][y] = 1 << RND(4);
+#endif
+
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
int x1 = x + xy[i][0];
int y1 = y + xy[i][1];
if (!IN_LEV_FIELD(x1, y1) || !IS_FREE(x1, y1))
{
- if (element_info[element].move_pattern == MV_ALONG_RIGHT_SIDE)
+ if (move_pattern == MV_ALONG_RIGHT_SIDE)
MovDir[x][y] = direction[0][i];
else
MovDir[x][y] = direction[1][i];
element != EL_BD_FIREFLY)
break;
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
int x1 = x + xy[i][0];
int y1 = y + xy[i][1];
TimeLeft -= 10;
else
TimeLeft--;
- DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2);
+
+ DrawGameValue_Time(TimeLeft);
+
BackToFront();
if (!tape.playing)
TimePlayed += 10;
else
TimePlayed++;
- DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FONT_TEXT_2);
+
+ DrawGameValue_Time(TimePlayed);
+
BackToFront();
if (!tape.playing)
ChangePage[x][y] = -1;
Pushed[x][y] = FALSE;
+#if 0
+ ExplodeField[x][y] = EX_TYPE_NONE;
+#endif
+
GfxElement[x][y] = EL_UNDEFINED;
GfxAction[x][y] = ACTION_DEFAULT;
GfxDir[x][y] = MV_NO_MOVING;
if (IS_MOVING(x, y))
{
Moving2Blocked(x, y, &newx, &newy);
+#if 0
if (Feld[newx][newy] != EL_BLOCKED)
return;
- }
- else if (element == EL_BLOCKED)
- {
+#else
+ if (Feld[newx][newy] != EL_BLOCKED)
+ {
+ /* element is moving, but target field is not free (blocked), but
+ already occupied by something different (example: acid pool);
+ in this case, only remove the moving field, but not the target */
+
+ RemoveField(oldx, oldy);
+
+ Store[oldx][oldy] = Store2[oldx][oldy] = 0;
+
+ DrawLevelField(oldx, oldy);
+
+ return;
+ }
+#endif
+ }
+ else if (element == EL_BLOCKED)
+ {
Blocked2Moving(x, y, &oldx, &oldy);
if (!IS_MOVING(oldx, oldy))
return;
Bang(x, y);
}
-void RelocatePlayer(int x, int y, int element)
+void DrawRelocatePlayer(struct PlayerInfo *player)
{
- struct PlayerInfo *player = &stored_player[element - EL_PLAYER_1];
+ boolean ffwd_delay = (tape.playing && tape.fast_forward);
+ boolean no_delay = (tape.warp_forward);
+ int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
+ int wait_delay_value = (no_delay ? 0 : frame_delay_value);
+ int jx = player->jx;
+ int jy = player->jy;
+ if (level.instant_relocation)
+ {
#if 1
- RemoveField(x, y); /* temporarily remove newly placed player */
- DrawLevelField(x, y);
-#endif
+ int offset = (setup.scroll_delay ? 3 : 0);
- if (player->present)
- {
- while (player->MovPos)
+ if (!IN_VIS_FIELD(SCREENX(jx), SCREENY(jy)))
{
- ScrollPlayer(player, SCROLL_GO_ON);
- ScrollScreen(NULL, SCROLL_GO_ON);
- FrameCounter++;
+ scroll_x = (local_player->jx < SBX_Left + MIDPOSX ? SBX_Left :
+ local_player->jx > SBX_Right + MIDPOSX ? SBX_Right :
+ local_player->jx - MIDPOSX);
- DrawPlayer(player);
+ scroll_y = (local_player->jy < SBY_Upper + MIDPOSY ? SBY_Upper :
+ local_player->jy > SBY_Lower + MIDPOSY ? SBY_Lower :
+ local_player->jy - MIDPOSY);
+ }
+ else
+ {
+ if ((player->MovDir == MV_LEFT && scroll_x > jx - MIDPOSX + offset) ||
+ (player->MovDir == MV_RIGHT && scroll_x < jx - MIDPOSX - offset))
+ scroll_x = jx - MIDPOSX + (scroll_x < jx-MIDPOSX ? -offset : +offset);
- BackToFront();
- Delay(GAME_FRAME_DELAY);
+ if ((player->MovDir == MV_UP && scroll_y > jy - MIDPOSY + offset) ||
+ (player->MovDir == MV_DOWN && scroll_y < jy - MIDPOSY - offset))
+ scroll_y = jy - MIDPOSY + (scroll_y < jy-MIDPOSY ? -offset : +offset);
+
+ /* don't scroll over playfield boundaries */
+ if (scroll_x < SBX_Left || scroll_x > SBX_Right)
+ scroll_x = (scroll_x < SBX_Left ? SBX_Left : SBX_Right);
+
+ /* don't scroll over playfield boundaries */
+ if (scroll_y < SBY_Upper || scroll_y > SBY_Lower)
+ scroll_y = (scroll_y < SBY_Upper ? SBY_Upper : SBY_Lower);
}
+#else
+ scroll_x += (local_player->jx - old_jx);
+ scroll_y += (local_player->jy - old_jy);
- DrawPlayer(player); /* needed here only to cleanup last field */
- DrawLevelField(player->jx, player->jy); /* remove player graphic */
+ /* don't scroll over playfield boundaries */
+ if (scroll_x < SBX_Left || scroll_x > SBX_Right)
+ scroll_x = (scroll_x < SBX_Left ? SBX_Left : SBX_Right);
- player->is_moving = FALSE;
+ /* don't scroll over playfield boundaries */
+ if (scroll_y < SBY_Upper || scroll_y > SBY_Lower)
+ scroll_y = (scroll_y < SBY_Upper ? SBY_Upper : SBY_Lower);
+#endif
+
+ RedrawPlayfield(TRUE, 0,0,0,0);
}
+ else
+ {
+#if 1
+#if 0
+ int offset = (setup.scroll_delay ? 3 : 0);
+#endif
+ int scroll_xx = -999, scroll_yy = -999;
- Feld[x][y] = element;
- InitPlayerField(x, y, element, TRUE);
+ ScrollScreen(NULL, SCROLL_GO_ON); /* scroll last frame to full tile */
- if (player == local_player)
- {
+ while (scroll_xx != scroll_x || scroll_yy != scroll_y)
+ {
+ int dx = 0, dy = 0;
+ int fx = FX, fy = FY;
+
+ scroll_xx = (local_player->jx < SBX_Left + MIDPOSX ? SBX_Left :
+ local_player->jx > SBX_Right + MIDPOSX ? SBX_Right :
+ local_player->jx - MIDPOSX);
+
+ scroll_yy = (local_player->jy < SBY_Upper + MIDPOSY ? SBY_Upper :
+ local_player->jy > SBY_Lower + MIDPOSY ? SBY_Lower :
+ local_player->jy - MIDPOSY);
+
+ dx = (scroll_xx < scroll_x ? +1 : scroll_xx > scroll_x ? -1 : 0);
+ dy = (scroll_yy < scroll_y ? +1 : scroll_yy > scroll_y ? -1 : 0);
+
+#if 1
+ if (dx == 0 && dy == 0) /* no scrolling needed at all */
+ break;
+#else
+ if (scroll_xx == scroll_x && scroll_yy == scroll_y)
+ break;
+#endif
+
+ scroll_x -= dx;
+ scroll_y -= dy;
+
+ fx += dx * TILEX / 2;
+ fy += dy * TILEY / 2;
+
+ ScrollLevel(dx, dy);
+ DrawAllPlayers();
+
+ /* scroll in two steps of half tile size to make things smoother */
+ BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
+ FlushDisplay();
+ Delay(wait_delay_value);
+
+ /* scroll second step to align at full tile size */
+ BackToFront();
+ Delay(wait_delay_value);
+ }
+#else
int scroll_xx = -999, scroll_yy = -999;
+ ScrollScreen(NULL, SCROLL_GO_ON); /* scroll last frame to full tile */
+
while (scroll_xx != scroll_x || scroll_yy != scroll_y)
{
int dx = 0, dy = 0;
dx = (scroll_xx < scroll_x ? +1 : scroll_xx > scroll_x ? -1 : 0);
dy = (scroll_yy < scroll_y ? +1 : scroll_yy > scroll_y ? -1 : 0);
+#if 1
+ if (dx == 0 && dy == 0) /* no scrolling needed at all */
+ break;
+#else
+ if (scroll_xx == scroll_x && scroll_yy == scroll_y)
+ break;
+#endif
+
scroll_x -= dx;
scroll_y -= dy;
/* scroll in two steps of half tile size to make things smoother */
BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
FlushDisplay();
- Delay(GAME_FRAME_DELAY);
+ Delay(wait_delay_value);
/* scroll second step to align at full tile size */
BackToFront();
- Delay(GAME_FRAME_DELAY);
+ Delay(wait_delay_value);
+ }
+#endif
+
+ DrawPlayer(player);
+ BackToFront();
+ Delay(wait_delay_value);
+ }
+}
+
+void RelocatePlayer(int jx, int jy, int el_player_raw)
+{
+#if 1
+ int el_player = GET_VALID_PLAYER_ELEMENT(el_player_raw);
+#else
+ int el_player = (el_player_raw == EL_SP_MURPHY ? EL_PLAYER_1 :el_player_raw);
+#endif
+ struct PlayerInfo *player = &stored_player[el_player - EL_PLAYER_1];
+ boolean ffwd_delay = (tape.playing && tape.fast_forward);
+ boolean no_delay = (tape.warp_forward);
+ int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
+ int wait_delay_value = (no_delay ? 0 : frame_delay_value);
+ int old_jx = player->jx;
+ int old_jy = player->jy;
+ int old_element = Feld[old_jx][old_jy];
+ int element = Feld[jx][jy];
+ boolean player_relocated = (old_jx != jx || old_jy != jy);
+
+ int move_dir_horiz = (jx < old_jx ? MV_LEFT : jx > old_jx ? MV_RIGHT : 0);
+ int move_dir_vert = (jy < old_jy ? MV_UP : jy > old_jy ? MV_DOWN : 0);
+#if 1
+ int enter_side_horiz = MV_DIR_OPPOSITE(move_dir_horiz);
+ int enter_side_vert = MV_DIR_OPPOSITE(move_dir_vert);
+ int leave_side_horiz = move_dir_horiz;
+ int leave_side_vert = move_dir_vert;
+#else
+ static int trigger_sides[4][2] =
+ {
+ /* enter side leave side */
+ { CH_SIDE_RIGHT, CH_SIDE_LEFT }, /* moving left */
+ { CH_SIDE_LEFT, CH_SIDE_RIGHT }, /* moving right */
+ { CH_SIDE_BOTTOM, CH_SIDE_TOP }, /* moving up */
+ { CH_SIDE_TOP, CH_SIDE_BOTTOM } /* moving down */
+ };
+ int enter_side_horiz = trigger_sides[MV_DIR_BIT(move_dir_horiz)][0];
+ int enter_side_vert = trigger_sides[MV_DIR_BIT(move_dir_vert)][0];
+ int leave_side_horiz = trigger_sides[MV_DIR_BIT(move_dir_horiz)][1];
+ int leave_side_vert = trigger_sides[MV_DIR_BIT(move_dir_vert)][1];
+#endif
+ int enter_side = enter_side_horiz | enter_side_vert;
+ int leave_side = leave_side_horiz | leave_side_vert;
+
+ if (player->GameOver) /* do not reanimate dead player */
+ return;
+
+ if (!player_relocated) /* no need to relocate the player */
+ return;
+
+ if (IS_PLAYER(jx, jy)) /* player already placed at new position */
+ {
+ RemoveField(jx, jy); /* temporarily remove newly placed player */
+ DrawLevelField(jx, jy);
+ }
+
+ if (player->present)
+ {
+ while (player->MovPos)
+ {
+ ScrollPlayer(player, SCROLL_GO_ON);
+ ScrollScreen(NULL, SCROLL_GO_ON);
+ FrameCounter++;
+
+ DrawPlayer(player);
+
+ BackToFront();
+ Delay(wait_delay_value);
}
+
+ DrawPlayer(player); /* needed here only to cleanup last field */
+ DrawLevelField(player->jx, player->jy); /* remove player graphic */
+
+ player->is_moving = FALSE;
+ }
+
+#if 1
+ if (IS_CUSTOM_ELEMENT(old_element))
+ CheckElementChangeByPlayer(old_jx, old_jy, old_element,
+ CE_LEFT_BY_PLAYER,
+ player->index_bit, leave_side);
+
+ CheckTriggeredElementChangeByPlayer(old_jx, old_jy, old_element,
+ CE_OTHER_GETS_LEFT,
+ player->index_bit, leave_side);
+#endif
+
+ Feld[jx][jy] = el_player;
+ InitPlayerField(jx, jy, el_player, TRUE);
+
+ if (!ELEM_IS_PLAYER(element)) /* player may be set on walkable element */
+ {
+ Feld[jx][jy] = element;
+ InitField(jx, jy, FALSE);
}
+
+#if 1
+ if (player == local_player) /* only visually relocate local player */
+ DrawRelocatePlayer(player);
+#endif
+
+#if 1
+ TestIfHeroTouchesBadThing(jx, jy);
+ TestIfPlayerTouchesCustomElement(jx, jy);
+#endif
+
+#if 0
+ printf("::: %d,%d: %d\n", jx, jy-1, Changed[jx][jy-1]);
+#endif
+
+#if 0
+#if 0
+ /* needed to allow change of walkable custom element by entering player */
+ if (!(Changed[jx][jy] & CH_EVENT_BIT(CE_ENTERED_BY_PLAYER)))
+ Changed[jx][jy] = 0; /* allow another change (but prevent loop) */
+#else
+ /* needed to allow change of walkable custom element by entering player */
+ Changed[jx][jy] = 0; /* allow another change */
+#endif
+#endif
+
+#if 0
+ printf("::: player entering %d, %d from %s ...\n", jx, jy,
+ enter_side == MV_LEFT ? "left" :
+ enter_side == MV_RIGHT ? "right" :
+ enter_side == MV_UP ? "top" :
+ enter_side == MV_DOWN ? "bottom" : "oops! no idea!");
+#endif
+
+#if 1
+ if (IS_CUSTOM_ELEMENT(element))
+ CheckElementChangeByPlayer(jx, jy, element, CE_ENTERED_BY_PLAYER,
+ player->index_bit, enter_side);
+
+ CheckTriggeredElementChangeByPlayer(jx, jy, element,
+ CE_OTHER_GETS_ENTERED,
+ player->index_bit, enter_side);
+#endif
}
void Explode(int ex, int ey, int phase, int mode)
{
int x, y;
+#if 0
int num_phase = 9;
+#endif
+
+ /* !!! eliminate this variable !!! */
int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
+
+#if 1
+ int last_phase;
+#else
int last_phase = num_phase * delay;
int half_phase = (num_phase / 2) * delay;
int first_phase_after_start = EX_PHASE_START + 1;
+#endif
+ int border_element;
if (game.explosions_delayed)
{
{
int center_element = Feld[ex][ey];
+#if 0
+ printf("::: start explosion %d,%d [%d]\n", ex, ey, FrameCounter);
+#endif
+
#if 0
/* --- This is only really needed (and now handled) in "Impact()". --- */
/* do not explode moving elements that left the explode field in time */
if (game.engine_version >= VERSION_IDENT(2,2,0,7) &&
- center_element == EL_EMPTY && (mode == EX_NORMAL || mode == EX_CENTER))
+ center_element == EL_EMPTY &&
+ (mode == EX_TYPE_NORMAL || mode == EX_TYPE_CENTER))
return;
#endif
- if (mode == EX_NORMAL || mode == EX_CENTER)
+ if (mode == EX_TYPE_NORMAL || mode == EX_TYPE_CENTER)
PlayLevelSoundAction(ex, ey, ACTION_EXPLODING);
/* remove things displayed in background while burning dynamite */
Feld[ex][ey] = center_element;
}
+#if 1
+
+#if 1
+ last_phase = element_info[center_element].explosion_delay + 1;
+#else
+ last_phase = element_info[center_element].explosion_delay;
+#endif
+
+#if 0
+ printf("::: %d -> %d\n", center_element, last_phase);
+#endif
+#endif
+
for (y = ey - 1; y <= ey + 1; y++) for (x = ex - 1; x <= ex + 1; x++)
{
int xx = x - ex + 1;
int yy = y - ey + 1;
int element;
+#if 1
+#if 1
if (!IN_LEV_FIELD(x, y) ||
- ((mode != EX_NORMAL || center_element == EL_AMOEBA_TO_DIAMOND) &&
+ (mode & EX_TYPE_SINGLE_TILE && (x != ex || y != ey)) ||
+ (mode == EX_TYPE_CROSS && (x != ex && y != ey)))
+ continue;
+#else
+ if (!IN_LEV_FIELD(x, y) ||
+ (mode != EX_TYPE_NORMAL && (x != ex || y != ey)))
+ continue;
+#endif
+#else
+ if (!IN_LEV_FIELD(x, y) ||
+ ((mode != EX_TYPE_NORMAL ||
+ center_element == EL_AMOEBA_TO_DIAMOND) &&
(x != ex || y != ey)))
continue;
+#endif
element = Feld[x][y];
continue;
#else
/* indestructible elements can only explode in center (but not flames) */
+#if 1
+ if ((IS_EXPLOSION_PROOF(element) && (x != ex || y != ey ||
+ mode == EX_TYPE_BORDER)) ||
+ element == EL_FLAMES)
+ continue;
+#else
if ((IS_EXPLOSION_PROOF(element) && (x != ex || y != ey)) ||
element == EL_FLAMES)
continue;
#endif
+#endif
#else
if ((IS_INDESTRUCTIBLE(element) &&
continue;
#endif
+#if 1
+ if (IS_PLAYER(x, y) && SHIELD_ON(PLAYERINFO(x, y)) &&
+ (game.engine_version < VERSION_IDENT(3,1,0,0) ||
+ (x == ex && y == ey && mode != EX_TYPE_BORDER)))
+#else
if (IS_PLAYER(x, y) && SHIELD_ON(PLAYERINFO(x, y)))
+#endif
{
if (IS_ACTIVE_BOMB(element))
{
/* re-activate things under the bomb like gate or penguin */
+#if 1
+ Feld[x][y] = (Back[x][y] ? Back[x][y] : EL_EMPTY);
+ Back[x][y] = 0;
+#else
Feld[x][y] = (Store[x][y] ? Store[x][y] : EL_EMPTY);
Store[x][y] = 0;
+#endif
+
+#if 0
+ printf("::: %d,%d: %d %s [%d, %d]\n", x, y, Feld[x][y],
+ element_info[Feld[x][y]].token_name,
+ Store[x][y], Store2[x][y]);
+#endif
}
continue;
#if 0
if (IS_INDESTRUCTIBLE(element))
Back[x][y] = element;
+#else
+#if 1
+#if 1
+ if (IS_WALKABLE(element) && IS_INDESTRUCTIBLE(element) &&
+ (x != ex || y != ey || mode == EX_TYPE_BORDER))
+ Back[x][y] = element;
+#else
+ if (IS_WALKABLE(element) && IS_INDESTRUCTIBLE(element) &&
+ (x != ex || y != ey))
+ Back[x][y] = element;
+#endif
#else
if (IS_WALKABLE(element) && IS_INDESTRUCTIBLE(element))
Back[x][y] = element;
+#endif
#endif
/* ignite explodable elements reached by other explosion */
RemoveField(x, y);
#endif
- if (IS_PLAYER(ex, ey) && !PLAYER_PROTECTED(ex, ey))
+ if (IS_PLAYER(ex, ey) && !PLAYER_EXPLOSION_PROTECTED(ex, ey))
{
switch(StorePlayer[ex][ey])
{
case EL_PLAYER_2:
- Store[x][y] = EL_EMERALD_RED;
+ Store[x][y] = EL_PLAYER_IS_EXPLODING_2;
break;
case EL_PLAYER_3:
- Store[x][y] = EL_EMERALD;
+ Store[x][y] = EL_PLAYER_IS_EXPLODING_3;
break;
case EL_PLAYER_4:
- Store[x][y] = EL_EMERALD_PURPLE;
+ Store[x][y] = EL_PLAYER_IS_EXPLODING_4;
break;
case EL_PLAYER_1:
default:
- Store[x][y] = EL_EMERALD_YELLOW;
+ Store[x][y] = EL_PLAYER_IS_EXPLODING_1;
break;
}
+#if 1
+ if (PLAYERINFO(ex, ey)->use_murphy_graphic)
+ Store[x][y] = EL_EMPTY;
+#else
if (game.emulation == EMU_SUPAPLEX)
Store[x][y] = EL_EMPTY;
+#endif
}
else if (center_element == EL_MOLE)
Store[x][y] = EL_EMERALD_RED;
else
Store[x][y] = EL_EMPTY;
- if (x != ex || y != ey ||
- center_element == EL_AMOEBA_TO_DIAMOND || mode == EX_BORDER)
+ if (x != ex || y != ey || mode == EX_TYPE_BORDER ||
+ center_element == EL_AMOEBA_TO_DIAMOND)
Store2[x][y] = element;
+#if 0
+ printf("::: %d,%d: %d %s\n", x, y, Store2[x][y],
+ element_info[Store2[x][y]].token_name);
+#endif
+
#if 0
if (AmoebaNr[x][y] &&
(element == EL_AMOEBA_FULL ||
#endif
ExplodePhase[x][y] = 1;
+#if 1
+ ExplodeDelay[x][y] = last_phase;
+#endif
+
+#if 0
+#if 1
+ GfxFrame[x][y] = 0; /* animation does not start until next frame */
+#else
+ GfxFrame[x][y] = -1; /* animation does not start until next frame */
+#endif
+#endif
+
Stop[x][y] = TRUE;
}
game.yamyam_content_nr =
(game.yamyam_content_nr + 1) % level.num_yamyam_contents;
+#if 0
+ printf("::: %d,%d: %d %s [%d]\n", ex + 1, ey, Feld[ex + 1][ey],
+ element_info[Feld[ex + 1][ey]].token_name, Store2[ex + 1][ey]);
+#endif
+
return;
}
x = ex;
y = ey;
+#if 1
+ if (phase == 1)
+ GfxFrame[x][y] = 0; /* restart explosion animation */
+#endif
+
+#if 0
+ printf(":X: phase == %d [%d]\n", phase, GfxFrame[x][y]);
+#endif
+
+#if 1
+ last_phase = ExplodeDelay[x][y];
+#endif
+
ExplodePhase[x][y] = (phase < last_phase ? phase + 1 : 0);
#ifdef DEBUG
- /* activate this even in non-DEBUG version until cause for crash in
- getGraphicAnimationFrame() (see below) is found and eliminated */
+ /* activate this even in non-DEBUG version until cause for crash in
+ getGraphicAnimationFrame() (see below) is found and eliminated */
+#endif
+#if 1
+
+ if (GfxElement[x][y] == EL_UNDEFINED)
+ {
+ printf("\n\n");
+ printf("Explode(): x = %d, y = %d: GfxElement == EL_UNDEFINED\n", x, y);
+ printf("Explode(): This should never happen!\n");
+ printf("\n\n");
+
+ GfxElement[x][y] = EL_EMPTY;
+ }
+#endif
+
+#if 1
+
+ border_element = Store2[x][y];
+#if 1
+ if (IS_PLAYER(x, y) && !PLAYER_EXPLOSION_PROTECTED(x, y))
+ border_element = StorePlayer[x][y];
+#else
+ if (IS_PLAYER(x, y))
+ border_element = StorePlayer[x][y];
+#endif
+
+#if 0
+ printf("::: %d,%d: %d %s [%d]\n", x, y, border_element,
+ element_info[border_element].token_name, Store2[x][y]);
+#endif
+
+#if 0
+ printf("::: phase == %d\n", phase);
+#endif
+
+ if (phase == element_info[border_element].ignition_delay ||
+ phase == last_phase)
+ {
+ boolean border_explosion = FALSE;
+
+#if 1
+#if 1
+ if (IS_PLAYER(x, y) && PLAYERINFO(x, y)->present &&
+ !PLAYER_EXPLOSION_PROTECTED(x, y))
+#else
+ if (IS_PLAYER(x, y) && PLAYERINFO(x, y)->present)
+#endif
+#else
+ if (IS_PLAYER(x, y))
+#endif
+ {
+ KillHeroUnlessExplosionProtected(x, y);
+ border_explosion = TRUE;
+
+#if 0
+ if (phase == last_phase)
+ printf("::: IS_PLAYER\n");
+#endif
+ }
+ else if (CAN_EXPLODE_BY_EXPLOSION(border_element))
+ {
+#if 0
+ printf("::: %d,%d: %d %s\n", x, y, border_element,
+ element_info[border_element].token_name);
+#endif
+
+ Feld[x][y] = Store2[x][y];
+ Store2[x][y] = 0;
+ Bang(x, y);
+ border_explosion = TRUE;
+
+#if 0
+ if (phase == last_phase)
+ printf("::: CAN_EXPLODE_BY_EXPLOSION\n");
#endif
-#if 1
+ }
+ else if (border_element == EL_AMOEBA_TO_DIAMOND)
+ {
+ AmoebeUmwandeln(x, y);
+ Store2[x][y] = 0;
+ border_explosion = TRUE;
- if (GfxElement[x][y] == EL_UNDEFINED)
- {
- printf("\n\n");
- printf("Explode(): x = %d, y = %d: GfxElement == EL_UNDEFINED\n", x, y);
- printf("Explode(): This should never happen!\n");
- printf("\n\n");
+#if 0
+ if (phase == last_phase)
+ printf("::: EL_AMOEBA_TO_DIAMOND [%d, %d] [%d]\n",
+ element_info[border_element].explosion_delay,
+ element_info[border_element].ignition_delay,
+ phase);
+#endif
+ }
- GfxElement[x][y] = EL_EMPTY;
- }
+#if 1
+ /* if an element just explodes due to another explosion (chain-reaction),
+ do not immediately end the new explosion when it was the last frame of
+ the explosion (as it would be done in the following "if"-statement!) */
+ if (border_explosion && phase == last_phase)
+ return;
#endif
+ }
+
+#else
if (phase == first_phase_after_start)
{
int element = Store2[x][y];
if (IS_PLAYER(x, y))
- KillHeroUnlessProtected(x, y);
- else if (CAN_EXPLODE_BY_FIRE(element))
+ KillHeroUnlessExplosionProtected(x, y);
+ else if (CAN_EXPLODE_BY_EXPLOSION(element))
{
Feld[x][y] = Store2[x][y];
Store2[x][y] = 0;
else if (element == EL_AMOEBA_TO_DIAMOND)
AmoebeUmwandeln(x, y);
}
+#endif
if (phase == last_phase)
{
int element;
+#if 0
+ printf("::: done: phase == %d\n", phase);
+#endif
+
+#if 0
+ printf("::: explosion %d,%d done [%d]\n", x, y, FrameCounter);
+#endif
+
element = Feld[x][y] = Store[x][y];
Store[x][y] = Store2[x][y] = 0;
GfxElement[x][y] = EL_UNDEFINED;
+ /* player can escape from explosions and might therefore be still alive */
+ if (element >= EL_PLAYER_IS_EXPLODING_1 &&
+ element <= EL_PLAYER_IS_EXPLODING_4)
+ Feld[x][y] = (stored_player[element - EL_PLAYER_IS_EXPLODING_1].active ?
+ EL_EMPTY :
+ element == EL_PLAYER_IS_EXPLODING_1 ? EL_EMERALD_YELLOW :
+ element == EL_PLAYER_IS_EXPLODING_2 ? EL_EMERALD_RED :
+ element == EL_PLAYER_IS_EXPLODING_3 ? EL_EMERALD :
+ EL_EMERALD_PURPLE);
+
+ /* restore probably existing indestructible background element */
if (Back[x][y] && IS_INDESTRUCTIBLE(Back[x][y]))
element = Feld[x][y] = Back[x][y];
Back[x][y] = 0;
ChangeDelay[x][y] = 0;
ChangePage[x][y] = -1;
+#if 1
+ InitField_WithBug2(x, y, FALSE);
+#else
InitField(x, y, FALSE);
+#if 1
+ /* !!! not needed !!! */
+#if 1
+ if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
+ CAN_MOVE(Feld[x][y]) && Feld[x][y] != EL_MOLE)
+ InitMovDir(x, y);
+#else
if (CAN_MOVE(element))
InitMovDir(x, y);
+#endif
+#endif
+#endif
DrawLevelField(x, y);
TestIfElementTouchesCustomElement(x, y);
if (GFX_CRUMBLED(element))
DrawLevelFieldCrumbledSandNeighbours(x, y);
- if (IS_PLAYER(x, y) && !PLAYERINFO(x,y)->present)
+ if (IS_PLAYER(x, y) && !PLAYERINFO(x, y)->present)
StorePlayer[x][y] = 0;
if (ELEM_IS_PLAYER(element))
RelocatePlayer(x, y, element);
}
+#if 1
+ else if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
+#else
else if (phase >= delay && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
+#endif
{
#if 1
int graphic = el_act2img(GfxElement[x][y], ACTION_EXPLODING);
stored == EL_SP_INFOTRON ? IMG_SP_EXPLOSION_INFOTRON :
IMG_SP_EXPLOSION);
#endif
+#if 1
+ int frame = getGraphicAnimationFrame(graphic, GfxFrame[x][y]);
+#else
int frame = getGraphicAnimationFrame(graphic, phase - delay);
+#endif
+
+#if 0
+ printf("::: phase == %d [%d]\n", phase, GfxFrame[x][y]);
+#endif
+
+#if 0
+ printf("::: %d / %d [%d - %d]\n",
+ GfxFrame[x][y], phase - delay, phase, delay);
+#endif
+
+#if 0
+ printf("::: %d ['%s'] -> %d\n", GfxElement[x][y],
+ element_info[GfxElement[x][y]].token_name,
+ graphic);
+#endif
if (phase == delay)
DrawLevelFieldCrumbledSand(x, y);
void DynaExplode(int ex, int ey)
{
int i, j;
+ int dynabomb_element = Feld[ex][ey];
int dynabomb_size = 1;
boolean dynabomb_xl = FALSE;
struct PlayerInfo *player;
{ 0, +1 }
};
- if (IS_ACTIVE_BOMB(Feld[ex][ey]))
+ if (IS_ACTIVE_BOMB(dynabomb_element))
{
- player = &stored_player[Feld[ex][ey] - EL_DYNABOMB_PLAYER_1_ACTIVE];
+ player = &stored_player[dynabomb_element - EL_DYNABOMB_PLAYER_1_ACTIVE];
dynabomb_size = player->dynabomb_size;
dynabomb_xl = player->dynabomb_xl;
player->dynabombs_left++;
}
- Explode(ex, ey, EX_PHASE_START, EX_CENTER);
+ Explode(ex, ey, EX_PHASE_START, EX_TYPE_CENTER);
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
for (j = 1; j <= dynabomb_size; j++)
{
- int x = ex + j * xy[i % 4][0];
- int y = ey + j * xy[i % 4][1];
+ int x = ex + j * xy[i][0];
+ int y = ey + j * xy[i][1];
int element;
if (!IN_LEV_FIELD(x, y) || IS_INDESTRUCTIBLE(Feld[x][y]))
if (element == EL_EXPLOSION && IS_ACTIVE_BOMB(Store2[x][y]))
continue;
- Explode(x, y, EX_PHASE_START, EX_BORDER);
+ Explode(x, y, EX_PHASE_START, EX_TYPE_BORDER);
+#if 1
+#if 1
+ if (element != EL_EMPTY && element != EL_EXPLOSION &&
+ !IS_DIGGABLE(element) && !dynabomb_xl)
+ break;
+#else
+ if (element != EL_EMPTY && element != EL_EXPLOSION &&
+ !CAN_GROW_INTO(element) && !dynabomb_xl)
+ break;
+#endif
+#else
/* !!! extend EL_SAND to anything diggable (but maybe not SP_BASE) !!! */
- if (element != EL_EMPTY &&
- element != EL_SAND &&
- element != EL_EXPLOSION &&
- !dynabomb_xl)
+ if (element != EL_EMPTY && element != EL_EXPLOSION &&
+ element != EL_SAND && !dynabomb_xl)
break;
+#endif
}
}
}
#endif
#if 1
- if (IS_PLAYER(x, y) && !PLAYER_PROTECTED(x, y))
+ if (IS_PLAYER(x, y) && !PLAYER_EXPLOSION_PROTECTED(x, y))
#else
if (IS_PLAYER(x, y))
#endif
case EL_PACMAN:
case EL_MOLE:
RaiseScoreElement(element);
- Explode(x, y, EX_PHASE_START, EX_NORMAL);
+ Explode(x, y, EX_PHASE_START, EX_TYPE_NORMAL);
break;
case EL_DYNABOMB_PLAYER_1_ACTIVE:
case EL_DYNABOMB_PLAYER_2_ACTIVE:
case EL_PENGUIN:
case EL_LAMP:
case EL_LAMP_ACTIVE:
+#if 1
+ case EL_AMOEBA_TO_DIAMOND:
+#endif
if (IS_PLAYER(x, y))
- Explode(x, y, EX_PHASE_START, EX_NORMAL);
+ Explode(x, y, EX_PHASE_START, EX_TYPE_NORMAL);
else
- Explode(x, y, EX_PHASE_START, EX_CENTER);
+ Explode(x, y, EX_PHASE_START, EX_TYPE_CENTER);
break;
default:
- if (CAN_EXPLODE_1X1(element))
- Explode(x, y, EX_PHASE_START, EX_CENTER);
+#if 1
+ if (element_info[element].explosion_type == EXPLODES_CROSS)
+#else
+ if (CAN_EXPLODE_CROSS(element))
+#endif
+#if 1
+ Explode(x, y, EX_PHASE_START, EX_TYPE_CROSS);
+#else
+ DynaExplode(x, y);
+#endif
+#if 1
+ else if (element_info[element].explosion_type == EXPLODES_1X1)
+#else
+ else if (CAN_EXPLODE_1X1(element))
+#endif
+ Explode(x, y, EX_PHASE_START, EX_TYPE_CENTER);
else
- Explode(x, y, EX_PHASE_START, EX_NORMAL);
+ Explode(x, y, EX_PHASE_START, EX_TYPE_NORMAL);
break;
}
void SplashAcid(int x, int y)
{
+#if 1
+ if (IN_LEV_FIELD(x - 1, y - 1) && IS_FREE(x - 1, y - 1) &&
+ (!IN_LEV_FIELD(x - 1, y - 2) ||
+ !CAN_FALL(MovingOrBlocked2Element(x - 1, y - 2))))
+ Feld[x - 1][y - 1] = EL_ACID_SPLASH_LEFT;
+
+ if (IN_LEV_FIELD(x + 1, y - 1) && IS_FREE(x + 1, y - 1) &&
+ (!IN_LEV_FIELD(x + 1, y - 2) ||
+ !CAN_FALL(MovingOrBlocked2Element(x + 1, y - 2))))
+ Feld[x + 1][y - 1] = EL_ACID_SPLASH_RIGHT;
+
+ PlayLevelSound(x, y, SND_ACID_SPLASHING);
+#else
+ /* input: position of element entering acid (obsolete) */
+
int element = Feld[x][y];
+ if (!IN_LEV_FIELD(x, y + 1) || Feld[x][y + 1] != EL_ACID)
+ return;
+
if (element != EL_ACID_SPLASH_LEFT &&
element != EL_ACID_SPLASH_RIGHT)
{
PlayLevelSound(x, y, SND_ACID_SPLASHING);
- if (IN_LEV_FIELD(x-1, y) && IS_FREE(x-1, y) &&
- (!IN_LEV_FIELD(x-1, y-1) ||
- !CAN_FALL(MovingOrBlocked2Element(x-1, y-1))))
- Feld[x-1][y] = EL_ACID_SPLASH_LEFT;
+ if (IN_LEV_FIELD(x - 1, y) && IS_FREE(x - 1, y) &&
+ (!IN_LEV_FIELD(x - 1, y - 1) ||
+ !CAN_FALL(MovingOrBlocked2Element(x - 1, y - 1))))
+ Feld[x - 1][y] = EL_ACID_SPLASH_LEFT;
- if (IN_LEV_FIELD(x+1, y) && IS_FREE(x+1, y) &&
- (!IN_LEV_FIELD(x+1, y-1) ||
- !CAN_FALL(MovingOrBlocked2Element(x+1, y-1))))
- Feld[x+1][y] = EL_ACID_SPLASH_RIGHT;
+ if (IN_LEV_FIELD(x + 1, y) && IS_FREE(x + 1, y) &&
+ (!IN_LEV_FIELD(x + 1, y - 1) ||
+ !CAN_FALL(MovingOrBlocked2Element(x + 1, y - 1))))
+ Feld[x + 1][y] = EL_ACID_SPLASH_RIGHT;
}
+#endif
}
static void InitBeltMovement()
int x, y, i, j;
/* set frame order for belt animation graphic according to belt direction */
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_BELTS; i++)
{
int belt_nr = i;
- for (j = 0; j < 3; j++)
+ for (j = 0; j < NUM_BELT_PARTS; j++)
{
int element = belt_base_active_element[belt_nr] + j;
int graphic = el2img(element);
{
int element = Feld[x][y];
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_BELTS; i++)
{
if (IS_BELT(element) && game.belt_dir[i] != MV_NO_MOVING)
{
belt_dir_nr = 1;
/* set frame order for belt animation graphic according to belt direction */
- for (i = 0; i < 3; i++)
+ for (i = 0; i < NUM_BELT_PARTS; i++)
{
int element = belt_base_active_element[belt_nr] + i;
int graphic = el2img(element);
/* special values for move stepsize for spring and things on conveyor belt */
if (horiz_move)
{
+#if 0
+ if (element == EL_SPRING)
+ step = sign * MOVE_STEPSIZE_NORMAL * 2;
+ else if (CAN_FALL(element) && !CAN_MOVE(element) &&
+ y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
+ step = sign * MOVE_STEPSIZE_NORMAL / 2;
+#else
if (CAN_FALL(element) &&
y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
step = sign * MOVE_STEPSIZE_NORMAL / 2;
else if (element == EL_SPRING)
step = sign * MOVE_STEPSIZE_NORMAL * 2;
+#endif
}
return step;
boolean object_hit = FALSE;
boolean impact = (lastline || object_hit);
int element = Feld[x][y];
- int smashed = EL_UNDEFINED;
+ int smashed = EL_STEELWALL;
if (!lastline) /* check if element below was hit */
{
MovDir[x][y + 1] != MV_DOWN ||
MovPos[x][y + 1] <= TILEY / 2));
+#if 0
+ object_hit = !IS_FREE(x, y + 1);
+#endif
+
/* do not smash moving elements that left the smashed field in time */
if (game.engine_version >= VERSION_IDENT(2,2,0,7) && IS_MOVING(x, y + 1) &&
ABS(MovPos[x][y + 1] + getElementMoveStepsize(x, y + 1)) >= TILEX)
if (!lastline && smashed == EL_ACID) /* element falls into acid */
{
- SplashAcid(x, y);
+ SplashAcid(x, y + 1);
return;
}
+ /* !!! not sufficient for all cases -- see EL_PEARL below !!! */
/* only reset graphic animation if graphic really changes after impact */
if (impact &&
el_act_dir2img(element, GfxAction[x][y], MV_DOWN) != el2img(element))
}
else if (impact && element == EL_PEARL)
{
+ ResetGfxAnimation(x, y);
+
Feld[x][y] = EL_PEARL_BREAKING;
PlayLevelSound(x, y, SND_PEARL_BREAKING);
return;
}
- else if (impact && CheckElementChange(x, y, element, CE_IMPACT))
+ else if (impact && CheckElementChange(x, y, element, smashed, CE_IMPACT))
{
PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT);
if (impact && element == EL_AMOEBA_DROP)
{
if (object_hit && IS_PLAYER(x, y + 1))
- KillHeroUnlessProtected(x, y + 1);
+ KillHeroUnlessEnemyProtected(x, y + 1);
else if (object_hit && smashed == EL_PENGUIN)
Bang(x, y + 1);
else
{
if (CAN_SMASH_PLAYER(element))
{
- KillHeroUnlessProtected(x, y + 1);
+ KillHeroUnlessEnemyProtected(x, y + 1);
return;
}
}
return;
}
}
- else if ((element == EL_SP_INFOTRON ||
- element == EL_SP_ZONK) &&
- (smashed == EL_SP_SNIKSNAK ||
- smashed == EL_SP_ELECTRON ||
- smashed == EL_SP_DISK_ORANGE))
+ else if (((element == EL_SP_INFOTRON ||
+ element == EL_SP_ZONK) &&
+ (smashed == EL_SP_SNIKSNAK ||
+ smashed == EL_SP_ELECTRON ||
+ smashed == EL_SP_DISK_ORANGE)) ||
+ (element == EL_SP_INFOTRON &&
+ smashed == EL_SP_DISK_YELLOW))
{
Bang(x, y + 1);
return;
}
else if (smashed == EL_PEARL)
{
+ ResetGfxAnimation(x, y);
+
Feld[x][y + 1] = EL_PEARL_BREAKING;
PlayLevelSound(x, y, SND_PEARL_BREAKING);
return;
}
else
{
- CheckElementChange(x, y + 1, smashed, CE_SMASHED);
+#if 0
+ TestIfElementSmashesCustomElement(x, y, MV_DOWN);
+#endif
+
+ CheckElementChange(x, y + 1, smashed, element, CE_SMASHED);
- CheckTriggeredElementSideChange(x, y + 1, smashed, CH_SIDE_TOP,
- CE_OTHER_IS_SWITCHING);
- CheckElementSideChange(x, y + 1, smashed, CH_SIDE_TOP,
- CE_SWITCHED, -1);
+#if 1
+ /* !!! TEST ONLY !!! */
+ CheckElementChangeBySide(x, y + 1, smashed, element,
+ CE_SWITCHED, CH_SIDE_TOP);
+ CheckTriggeredElementChangeBySide(x, y + 1, smashed,
+ CE_OTHER_IS_SWITCHING,CH_SIDE_TOP);
+#else
+ CheckTriggeredElementChangeBySide(x, y + 1, smashed,
+ CE_OTHER_IS_SWITCHING,CH_SIDE_TOP);
+ CheckElementChangeBySide(x, y + 1, smashed, element,
+ CE_SWITCHED, CH_SIDE_TOP);
+#endif
}
}
else
{
- CheckElementChange(x, y + 1, smashed, CE_SMASHED);
+ CheckElementChange(x, y + 1, smashed, element, CE_SMASHED);
}
}
}
{
TestIfBadThingTouchesOtherBadThing(x, y);
- if (ENEMY_CAN_ENTER_FIELD(right_x, right_y))
+ if (ENEMY_CAN_ENTER_FIELD(element, right_x, right_y))
MovDir[x][y] = right_dir;
- else if (!ENEMY_CAN_ENTER_FIELD(move_x, move_y))
+ else if (!ENEMY_CAN_ENTER_FIELD(element, move_x, move_y))
MovDir[x][y] = left_dir;
if (element == EL_BUG && MovDir[x][y] != old_move_dir)
else if (element == EL_BD_BUTTERFLY) /* && MovDir[x][y] == left_dir) */
MovDelay[x][y] = 1;
}
+#if 0
else if (element == EL_SPACESHIP || element == EL_BD_FIREFLY ||
element == EL_SP_SNIKSNAK || element == EL_SP_ELECTRON)
{
TestIfBadThingTouchesOtherBadThing(x, y);
- if (ENEMY_CAN_ENTER_FIELD(left_x, left_y))
+ if (ENEMY_CAN_ENTER_FIELD(element, left_x, left_y))
MovDir[x][y] = left_dir;
- else if (!ENEMY_CAN_ENTER_FIELD(move_x, move_y))
+ else if (!ENEMY_CAN_ENTER_FIELD(element, move_x, move_y))
MovDir[x][y] = right_dir;
if ((element == EL_SPACESHIP ||
else if (element == EL_BD_FIREFLY) /* && MovDir[x][y] == right_dir) */
MovDelay[x][y] = 1;
}
+#else
+ else if (element == EL_SPACESHIP || element == EL_BD_FIREFLY)
+ {
+ TestIfBadThingTouchesOtherBadThing(x, y);
+
+ if (ENEMY_CAN_ENTER_FIELD(element, left_x, left_y))
+ MovDir[x][y] = left_dir;
+ else if (!ENEMY_CAN_ENTER_FIELD(element, move_x, move_y))
+ MovDir[x][y] = right_dir;
+
+ if (element == EL_SPACESHIP && MovDir[x][y] != old_move_dir)
+ MovDelay[x][y] = 9;
+ else if (element == EL_BD_FIREFLY) /* && MovDir[x][y] == right_dir) */
+ MovDelay[x][y] = 1;
+ }
+ else if (element == EL_SP_SNIKSNAK || element == EL_SP_ELECTRON)
+ {
+ TestIfBadThingTouchesOtherBadThing(x, y);
+
+ if (ELEMENT_CAN_ENTER_FIELD_BASE_4(element, left_x, left_y, 0))
+ MovDir[x][y] = left_dir;
+ else if (!ELEMENT_CAN_ENTER_FIELD_BASE_4(element, move_x, move_y, 0))
+ MovDir[x][y] = right_dir;
+
+ if (MovDir[x][y] != old_move_dir)
+ MovDelay[x][y] = 9;
+ }
+#endif
else if (element == EL_YAMYAM)
{
- boolean can_turn_left = YAMYAM_CAN_ENTER_FIELD(left_x, left_y);
- boolean can_turn_right = YAMYAM_CAN_ENTER_FIELD(right_x, right_y);
+ boolean can_turn_left = YAMYAM_CAN_ENTER_FIELD(element, left_x, left_y);
+ boolean can_turn_right = YAMYAM_CAN_ENTER_FIELD(element, right_x, right_y);
if (can_turn_left && can_turn_right)
MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
}
else if (element == EL_DARK_YAMYAM)
{
- boolean can_turn_left = DARK_YAMYAM_CAN_ENTER_FIELD(left_x, left_y);
- boolean can_turn_right = DARK_YAMYAM_CAN_ENTER_FIELD(right_x, right_y);
+ boolean can_turn_left = DARK_YAMYAM_CAN_ENTER_FIELD(element,
+ left_x, left_y);
+ boolean can_turn_right = DARK_YAMYAM_CAN_ENTER_FIELD(element,
+ right_x, right_y);
if (can_turn_left && can_turn_right)
MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
}
else if (element == EL_PACMAN)
{
- boolean can_turn_left = PACMAN_CAN_ENTER_FIELD(left_x, left_y);
- boolean can_turn_right = PACMAN_CAN_ENTER_FIELD(right_x, right_y);
+ boolean can_turn_left = PACMAN_CAN_ENTER_FIELD(element, left_x, left_y);
+ boolean can_turn_right = PACMAN_CAN_ENTER_FIELD(element, right_x, right_y);
if (can_turn_left && can_turn_right)
MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
}
else if (element == EL_PIG)
{
- boolean can_turn_left = PIG_CAN_ENTER_FIELD(left_x, left_y);
- boolean can_turn_right = PIG_CAN_ENTER_FIELD(right_x, right_y);
- boolean can_move_on = PIG_CAN_ENTER_FIELD(move_x, move_y);
+ boolean can_turn_left = PIG_CAN_ENTER_FIELD(element, left_x, left_y);
+ boolean can_turn_right = PIG_CAN_ENTER_FIELD(element, right_x, right_y);
+ boolean can_move_on = PIG_CAN_ENTER_FIELD(element, move_x, move_y);
boolean should_turn_left, should_turn_right, should_move_on;
int rnd_value = 24;
int rnd = RND(rnd_value);
}
else if (element == EL_DRAGON)
{
- boolean can_turn_left = IN_LEV_FIELD_AND_IS_FREE(left_x, left_y);
- boolean can_turn_right = IN_LEV_FIELD_AND_IS_FREE(right_x, right_y);
- boolean can_move_on = IN_LEV_FIELD_AND_IS_FREE(move_x, move_y);
+ boolean can_turn_left = DRAGON_CAN_ENTER_FIELD(element, left_x, left_y);
+ boolean can_turn_right = DRAGON_CAN_ENTER_FIELD(element, right_x, right_y);
+ boolean can_move_on = DRAGON_CAN_ENTER_FIELD(element, move_x, move_y);
int rnd_value = 24;
int rnd = RND(rnd_value);
else if (element == EL_MOLE)
{
boolean can_move_on =
- (MOLE_CAN_ENTER_FIELD(move_x, move_y,
+ (MOLE_CAN_ENTER_FIELD(element, move_x, move_y,
IS_AMOEBOID(Feld[move_x][move_y]) ||
Feld[move_x][move_y] == EL_AMOEBA_SHRINKING));
if (!can_move_on)
{
boolean can_turn_left =
- (MOLE_CAN_ENTER_FIELD(left_x, left_y,
+ (MOLE_CAN_ENTER_FIELD(element, left_x, left_y,
IS_AMOEBOID(Feld[left_x][left_y])));
boolean can_turn_right =
- (MOLE_CAN_ENTER_FIELD(right_x, right_y,
+ (MOLE_CAN_ENTER_FIELD(element, right_x, right_y,
IS_AMOEBOID(Feld[right_x][right_y])));
if (can_turn_left && can_turn_right)
}
else if (element == EL_SPRING)
{
+#if 0
if (MovDir[x][y] & MV_HORIZONTAL &&
- (!IN_LEV_FIELD_AND_IS_FREE(move_x, move_y) ||
- IN_LEV_FIELD_AND_IS_FREE(x, y + 1)))
+ !SPRING_CAN_ENTER_FIELD(element, move_x, move_y))
MovDir[x][y] = MV_NO_MOVING;
+#else
+ if (MovDir[x][y] & MV_HORIZONTAL &&
+ (!SPRING_CAN_ENTER_FIELD(element, move_x, move_y) ||
+ SPRING_CAN_ENTER_FIELD(element, x, y + 1)))
+ MovDir[x][y] = MV_NO_MOVING;
+#endif
MovDelay[x][y] = 0;
}
}
}
+#if 1
+ if (element == EL_ROBOT && ZX >= 0 && ZY >= 0 &&
+ (Feld[ZX][ZY] == EL_ROBOT_WHEEL_ACTIVE ||
+ game.engine_version < VERSION_IDENT(3,1,0,0)))
+#else
if (element == EL_ROBOT && ZX >= 0 && ZY >= 0)
+#endif
{
attr_x = ZX;
attr_y = ZY;
{ 0, +1 }
};
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
- int ex = x + xy[i % 4][0];
- int ey = y + xy[i % 4][1];
+ int ex = x + xy[i][0];
+ int ey = y + xy[i][1];
if (IN_LEV_FIELD(ex, ey) && Feld[ex][ey] == EL_EXIT_OPEN)
{
new_move_dir & (first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
Moving2Blocked(x, y, &newx, &newy);
- if (PENGUIN_CAN_ENTER_FIELD(newx, newy))
+ if (PENGUIN_CAN_ENTER_FIELD(EL_PENGUIN, newx, newy))
return;
MovDir[x][y] =
new_move_dir & (!first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
Moving2Blocked(x, y, &newx, &newy);
- if (PENGUIN_CAN_ENTER_FIELD(newx, newy))
+ if (PENGUIN_CAN_ENTER_FIELD(EL_PENGUIN, newx, newy))
return;
MovDir[x][y] = old_move_dir;
new_move_dir & (first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
Moving2Blocked(x, y, &newx, &newy);
- if (ELEMENT_CAN_ENTER_FIELD_OR_ACID_2(newx, newy))
+ if (SATELLITE_CAN_ENTER_FIELD(newx, newy))
return;
MovDir[x][y] =
new_move_dir & (!first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
Moving2Blocked(x, y, &newx, &newy);
- if (ELEMENT_CAN_ENTER_FIELD_OR_ACID_2(newx, newy))
+ if (SATELLITE_CAN_ENTER_FIELD(newx, newy))
return;
MovDir[x][y] = old_move_dir;
}
}
}
- else if (move_pattern == MV_ALL_DIRECTIONS ||
- move_pattern == MV_TURNING_LEFT ||
- move_pattern == MV_TURNING_RIGHT)
+ else if (move_pattern == MV_TURNING_LEFT ||
+ move_pattern == MV_TURNING_RIGHT ||
+ move_pattern == MV_TURNING_LEFT_RIGHT ||
+ move_pattern == MV_TURNING_RIGHT_LEFT ||
+ move_pattern == MV_TURNING_RANDOM ||
+ move_pattern == MV_ALL_DIRECTIONS)
{
- boolean can_turn_left = ELEMENT_CAN_ENTER_FIELD(element, left_x, left_y);
- boolean can_turn_right = ELEMENT_CAN_ENTER_FIELD(element, right_x,right_y);
+ boolean can_turn_left =
+ CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, left_x, left_y);
+ boolean can_turn_right =
+ CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, right_x,right_y);
if (move_pattern == MV_TURNING_LEFT)
MovDir[x][y] = left_dir;
else if (move_pattern == MV_TURNING_RIGHT)
MovDir[x][y] = right_dir;
+ else if (move_pattern == MV_TURNING_LEFT_RIGHT)
+ MovDir[x][y] = (can_turn_left || !can_turn_right ? left_dir : right_dir);
+ else if (move_pattern == MV_TURNING_RIGHT_LEFT)
+ MovDir[x][y] = (can_turn_right || !can_turn_left ? right_dir : left_dir);
+ else if (move_pattern == MV_TURNING_RANDOM)
+ MovDir[x][y] = (can_turn_left && !can_turn_right ? left_dir :
+ can_turn_right && !can_turn_left ? right_dir :
+ RND(2) ? left_dir : right_dir);
else if (can_turn_left && can_turn_right)
MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
else if (can_turn_left)
}
else if (move_pattern == MV_ALONG_LEFT_SIDE)
{
- if (ELEMENT_CAN_ENTER_FIELD(element, left_x, left_y))
+ if (CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, left_x, left_y))
MovDir[x][y] = left_dir;
- else if (!ELEMENT_CAN_ENTER_FIELD(element, move_x, move_y))
+ else if (!CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, move_x, move_y))
MovDir[x][y] = right_dir;
if (MovDir[x][y] != old_move_dir)
}
else if (move_pattern == MV_ALONG_RIGHT_SIDE)
{
- if (ELEMENT_CAN_ENTER_FIELD(element, right_x, right_y))
+ if (CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, right_x, right_y))
MovDir[x][y] = right_dir;
- else if (!ELEMENT_CAN_ENTER_FIELD(element, move_x, move_y))
+ else if (!CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, move_x, move_y))
MovDir[x][y] = left_dir;
if (MovDir[x][y] != old_move_dir)
new_move_dir & (first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
Moving2Blocked(x, y, &newx, &newy);
- if (ELEMENT_CAN_ENTER_FIELD_OR_ACID(element, newx, newy))
+ if (CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, newx, newy))
return;
MovDir[x][y] =
new_move_dir & (!first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
Moving2Blocked(x, y, &newx, &newy);
- if (ELEMENT_CAN_ENTER_FIELD_OR_ACID(element, newx, newy))
+ if (CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, newx, newy))
return;
MovDir[x][y] = old_move_dir;
}
}
- else if (move_pattern == MV_WHEN_PUSHED)
+ else if (move_pattern == MV_WHEN_PUSHED ||
+ move_pattern == MV_WHEN_DROPPED)
{
- if (!IN_LEV_FIELD_AND_IS_FREE(move_x, move_y))
+ if (!CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, move_x, move_y))
MovDir[x][y] = MV_NO_MOVING;
MovDelay[x][y] = 0;
}
- else if (move_pattern & MV_MAZE_RUNNER_STYLE ||
- element == EL_MAZE_RUNNER)
+ else if (move_pattern & MV_MAZE_RUNNER_STYLE)
{
static int test_xy[7][2] =
{
int start_test = RND(4);
int i;
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
int move_dir = test_dir[start_test + i];
int move_dir_preference;
break;
}
- if (!MAZE_RUNNER_CAN_ENTER_FIELD(xx, yy))
+ if (!CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, xx, yy))
continue;
move_dir_preference = -1 * RunnerVisit[xx][yy];
void StartMoving(int x, int y)
{
+#if 0
boolean use_spring_bug = (game.engine_version < VERSION_IDENT(2,2,0,0));
+#endif
boolean started_moving = FALSE; /* some elements can fall _and_ move */
int element = Feld[x][y];
if (CAN_FALL(element) && y < lev_fieldy - 1)
{
- if ((x > 0 && IS_PLAYER(x - 1, y)) ||
- (x < lev_fieldx-1 && IS_PLAYER(x + 1, y)))
+ if ((x > 0 && IS_PLAYER(x - 1, y)) ||
+ (x < lev_fieldx - 1 && IS_PLAYER(x + 1, y)))
if (JustBeingPushed(x, y))
return;
else if (CAN_FALL(element) && Feld[x][y + 1] == EL_ACID)
#endif
{
- SplashAcid(x, y);
+ SplashAcid(x, y + 1);
InitMovingField(x, y, MV_DOWN);
started_moving = TRUE;
#endif
}
#if 1
- else if ((game.engine_version < VERSION_IDENT(2,2,0,7) &&
- CAN_SMASH(element) && WasJustMoving[x][y] && !Pushed[x][y + 1] &&
- (Feld[x][y + 1] == EL_BLOCKED)) ||
+ else if ((game.engine_version >= VERSION_IDENT(3,1,0,0) &&
+ CheckCollision[x][y] && !IS_FREE(x, y + 1)) ||
+
(game.engine_version >= VERSION_IDENT(3,0,7,0) &&
CAN_SMASH(element) && WasJustFalling[x][y] &&
- (Feld[x][y + 1] == EL_BLOCKED || IS_PLAYER(x, y + 1))))
+ (Feld[x][y + 1] == EL_BLOCKED || IS_PLAYER(x, y + 1))) ||
+
+ (game.engine_version < VERSION_IDENT(2,2,0,7) &&
+ CAN_SMASH(element) && WasJustMoving[x][y] && !Pushed[x][y + 1] &&
+ (Feld[x][y + 1] == EL_BLOCKED)))
#else
#if 1
element; also, the case of the player being the element to smash was
simply not covered here... :-/ ) */
+#if 0
+ WasJustMoving[x][y] = 0;
+ WasJustFalling[x][y] = 0;
+#endif
+
+ CheckCollision[x][y] = 0;
+
Impact(x, y);
}
- else if (IS_FREE(x, y + 1) && element == EL_SPRING && use_spring_bug)
+ else if (IS_FREE(x, y + 1) && element == EL_SPRING && level.use_spring_bug)
{
if (MovDir[x][y] == MV_NO_MOVING)
{
started_moving = TRUE;
}
}
+#if 0
+ else if (IS_BELT_ACTIVE(Feld[x][y + 1]) && !CAN_MOVE(element))
+#else
else if (IS_BELT_ACTIVE(Feld[x][y + 1]))
+#endif
{
boolean left_is_free = (x > 0 && IS_FREE(x - 1, y));
boolean right_is_free = (x < lev_fieldx - 1 && IS_FREE(x + 1, y));
if ((belt_dir == MV_LEFT && left_is_free) ||
(belt_dir == MV_RIGHT && right_is_free))
{
+#if 1
+ int nextx = (belt_dir == MV_LEFT ? x - 1 : x + 1);
+#endif
+
InitMovingField(x, y, belt_dir);
started_moving = TRUE;
+#if 1
+ Pushed[x][y] = TRUE;
+ Pushed[nextx][y] = TRUE;
+#endif
+
GfxAction[x][y] = ACTION_DEFAULT;
}
+ else
+ {
+ MovDir[x][y] = 0; /* if element was moving, stop it */
+ }
}
}
/* not "else if" because of elements that can fall and move (EL_SPRING) */
+#if 0
+ if (CAN_MOVE(element) && !started_moving && MovDir[x][y] != MV_NO_MOVING)
+#else
if (CAN_MOVE(element) && !started_moving)
+#endif
{
int move_pattern = element_info[element].move_pattern;
int newx, newy;
+#if 0
+#if DEBUG
+ if (MovDir[x][y] == MV_NO_MOVING)
+ {
+ printf("StartMoving(): %d,%d: element %d ['%s'] not moving\n",
+ x, y, element, element_info[element].token_name);
+ printf("StartMoving(): This should never happen!\n");
+ }
+#endif
+#endif
+
+ Moving2Blocked(x, y, &newx, &newy);
+
#if 1
if (IS_PUSHABLE(element) && JustBeingPushed(x, y))
return;
return;
#endif
+#if 1
+
+#if 1
+ if (game.engine_version >= VERSION_IDENT(3,1,0,0) &&
+ CheckCollision[x][y] && !IN_LEV_FIELD_AND_IS_FREE(newx, newy))
+#else
+ if (game.engine_version >= VERSION_IDENT(3,1,0,0) &&
+ WasJustMoving[x][y] && IN_LEV_FIELD(newx, newy) &&
+ (Feld[newx][newy] == EL_BLOCKED || IS_PLAYER(newx, newy)))
+#endif
+ {
+#if 0
+ printf("::: element %d '%s' WasJustMoving %d [%d, %d, %d, %d]\n",
+ element, element_info[element].token_name,
+ WasJustMoving[x][y],
+ HAS_ANY_CHANGE_EVENT(element, CE_HITTING_SOMETHING),
+ HAS_ANY_CHANGE_EVENT(element, CE_HIT_BY_SOMETHING),
+ HAS_ANY_CHANGE_EVENT(element, CE_OTHER_IS_HITTING),
+ HAS_ANY_CHANGE_EVENT(element, CE_OTHER_GETS_HIT));
+#endif
+
+#if 1
+ WasJustMoving[x][y] = 0;
+#endif
+
+ CheckCollision[x][y] = 0;
+
+ TestIfElementHitsCustomElement(x, y, MovDir[x][y]);
+
+#if 0
+ if (Feld[x][y] != element) /* element has changed */
+ {
+ element = Feld[x][y];
+ move_pattern = element_info[element].move_pattern;
+
+ if (!CAN_MOVE(element))
+ return;
+ }
+#else
+ if (Feld[x][y] != element) /* element has changed */
+ return;
+#endif
+ }
+#endif
+
#if 0
#if 0
if (element == EL_SPRING && MovDir[x][y] == MV_DOWN)
element != EL_PACMAN &&
!(move_pattern & MV_ANY_DIRECTION) &&
move_pattern != MV_TURNING_LEFT &&
- move_pattern != MV_TURNING_RIGHT)
+ move_pattern != MV_TURNING_RIGHT &&
+ move_pattern != MV_TURNING_LEFT_RIGHT &&
+ move_pattern != MV_TURNING_RIGHT_LEFT &&
+ move_pattern != MV_TURNING_RANDOM)
{
TurnRound(x, y);
{
int flamed = MovingOrBlocked2Element(xx, yy);
- if (IS_CLASSIC_ENEMY(flamed) || CAN_EXPLODE_BY_FIRE(flamed))
+ /* !!! */
+#if 0
+ if (IS_CLASSIC_ENEMY(flamed) || CAN_EXPLODE_BY_DRAGONFIRE(flamed))
+ Bang(xx, yy);
+ else if (IS_MOVING(xx, yy) || IS_BLOCKED(xx, yy))
+ RemoveMovingField(xx, yy);
+ else
+ RemoveField(xx, yy);
+#else
+ if (IS_CLASSIC_ENEMY(flamed) || CAN_EXPLODE_BY_DRAGONFIRE(flamed))
Bang(xx, yy);
else
RemoveMovingField(xx, yy);
+#endif
+#if 0
+ if (ChangeDelay[xx][yy])
+ printf("::: !!! [%d]\n", (IS_MOVING(xx, yy) ||
+ Feld[xx][yy] == EL_BLOCKED));
+#endif
+
+#if 1
+ ChangeDelay[xx][yy] = 0;
+#endif
Feld[xx][yy] = EL_FLAMES;
if (IN_SCR_FIELD(sx, sy))
{
if (DONT_COLLIDE_WITH(element) &&
IN_LEV_FIELD(newx, newy) && IS_PLAYER(newx, newy) &&
- !PLAYER_PROTECTED(newx, newy))
+ !PLAYER_ENEMY_PROTECTED(newx, newy))
{
#if 1
TestIfBadThingRunsIntoHero(x, y, MovDir[x][y]);
+
return;
#else
/* player killed by element which is deadly when colliding with */
#endif
}
+#if 1
+#if 1
+ else if (CAN_MOVE_INTO_ACID(element) &&
+ IN_LEV_FIELD(newx, newy) && Feld[newx][newy] == EL_ACID &&
+ (MovDir[x][y] == MV_DOWN ||
+ game.engine_version >= VERSION_IDENT(3,1,0,0)))
+#else
+ else if (CAN_MOVE_INTO_ACID(element) && MovDir[x][y] == MV_DOWN &&
+ IN_LEV_FIELD(newx, newy) && Feld[newx][newy] == EL_ACID)
+#endif
+#else
+
else if ((element == EL_PENGUIN ||
element == EL_ROBOT ||
element == EL_SATELLITE ||
IS_CUSTOM_ELEMENT(element)) &&
IN_LEV_FIELD(newx, newy) &&
MovDir[x][y] == MV_DOWN && Feld[newx][newy] == EL_ACID)
+#endif
{
- SplashAcid(x, y);
+ SplashAcid(newx, newy);
Store[x][y] = EL_ACID;
}
else if (element == EL_PENGUIN && IN_LEV_FIELD(newx, newy))
{
if (Feld[newx][newy] == EL_EXIT_OPEN)
{
+#if 1
+ RemoveField(x, y);
+ DrawLevelField(x, y);
+#else
Feld[x][y] = EL_EMPTY;
DrawLevelField(x, y);
+#endif
PlayLevelSound(newx, newy, SND_PENGUIN_PASSING);
if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
}
else if (IS_FOOD_PENGUIN(Feld[newx][newy]))
{
- if (DigField(local_player, newx, newy, 0, 0, DF_DIG) == MF_MOVING)
+ if (DigField(local_player, x, y, newx, newy, 0,0, DF_DIG) == MF_MOVING)
DrawLevelField(newx, newy);
else
GfxDir[x][y] = MovDir[x][y] = MV_NO_MOVING;
DrawPlayerField(x, y);
else
DrawLevelField(x, y);
+
return;
}
}
DrawPlayerField(x, y);
else
DrawLevelField(x, y);
+
return;
}
}
- else if ((move_pattern & MV_MAZE_RUNNER_STYLE ||
- element == EL_MAZE_RUNNER) && IN_LEV_FIELD(newx, newy))
+
+#if 1
+
+ /*
+ else if (move_pattern & MV_MAZE_RUNNER_STYLE && IN_LEV_FIELD(newx, newy))
+ */
+
+ else if (IS_CUSTOM_ELEMENT(element) &&
+ CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, newx, newy)
+
+#if 0
+ &&
+ !IS_FREE(newx, newy)
+#endif
+
+)
{
- if (IS_FOOD_DARK_YAMYAM(Feld[newx][newy]))
+ int new_element = Feld[newx][newy];
+
+#if 0
+ printf("::: '%s' digs '%s' [%d]\n",
+ element_info[element].token_name,
+ element_info[Feld[newx][newy]].token_name,
+ StorePlayer[newx][newy]);
+#endif
+
+ if (!IS_FREE(newx, newy))
{
+ int action = (IS_DIGGABLE(new_element) ? ACTION_DIGGING :
+ IS_COLLECTIBLE(new_element) ? ACTION_COLLECTING :
+ ACTION_BREAKING);
+
+ /* no element can dig solid indestructible elements */
+ if (IS_INDESTRUCTIBLE(new_element) &&
+ !IS_DIGGABLE(new_element) &&
+ !IS_COLLECTIBLE(new_element))
+ return;
+
+ if (AmoebaNr[newx][newy] &&
+ (new_element == EL_AMOEBA_FULL ||
+ new_element == EL_BD_AMOEBA ||
+ new_element == EL_AMOEBA_GROWING))
+ {
+ AmoebaCnt[AmoebaNr[newx][newy]]--;
+ AmoebaCnt2[AmoebaNr[newx][newy]]--;
+ }
+
if (IS_MOVING(newx, newy))
RemoveMovingField(newx, newy);
else
{
- Feld[newx][newy] = EL_EMPTY;
+ RemoveField(newx, newy);
DrawLevelField(newx, newy);
}
- PlayLevelSound(x, y, SND_DARK_YAMYAM_DIGGING);
+ /* if digged element was about to explode, prevent the explosion */
+ ExplodeField[newx][newy] = EX_TYPE_NONE;
+
+ PlayLevelSoundAction(x, y, action);
}
- else if (!IS_FREE(newx, newy))
- {
-#if 0
- if (IS_PLAYER(x, y))
- DrawPlayerField(x, y);
- else
- DrawLevelField(x, y);
+
+#if 1
+#if 1
+ Store[newx][newy] = EL_EMPTY;
+ if (IS_EQUAL_OR_IN_GROUP(new_element, MOVE_ENTER_EL(element)))
+ Store[newx][newy] = element_info[element].move_leave_element;
+#else
+ Store[newx][newy] = EL_EMPTY;
+ if (IS_EQUAL_OR_IN_GROUP(new_element, MOVE_ENTER_EL(element)) ||
+ element_info[element].move_leave_type == LEAVE_TYPE_UNLIMITED)
+ Store[newx][newy] = element_info[element].move_leave_element;
+#endif
+#else
+ if (IS_EQUAL_OR_IN_GROUP(new_element, MOVE_ENTER_EL(element)))
+ element_info[element].can_leave_element = TRUE;
#endif
- return;
- }
- RunnerVisit[x][y] = FrameCounter;
- PlayerVisit[x][y] /= 8; /* expire player visit path */
+ if (move_pattern & MV_MAZE_RUNNER_STYLE)
+ {
+ RunnerVisit[x][y] = FrameCounter;
+ PlayerVisit[x][y] /= 8; /* expire player visit path */
+ }
}
+
+#endif
+
else if (element == EL_DRAGON && IN_LEV_FIELD(newx, newy))
{
if (!IS_FREE(newx, newy))
MovDelay[x][y] = 50;
+ /* !!! */
+#if 0
+ RemoveField(newx, newy);
+#endif
Feld[newx][newy] = EL_FLAMES;
if (IN_LEV_FIELD(newx1, newy1) && Feld[newx1][newy1] == EL_EMPTY)
+ {
+#if 0
+ RemoveField(newx1, newy1);
+#endif
Feld[newx1][newy1] = EL_FLAMES;
+ }
if (IN_LEV_FIELD(newx2, newy2) && Feld[newx2][newy2] == EL_EMPTY)
+ {
+#if 0
+ RemoveField(newx2, newy2);
+#endif
Feld[newx2][newy2] = EL_FLAMES;
+ }
return;
}
AmoebaCnt[AmoebaNr[newx][newy]]--;
}
+#if 0
+ /* !!! test !!! */
+ if (IS_MOVING(newx, newy) || IS_BLOCKED(newx, newy))
+#else
if (IS_MOVING(newx, newy))
+#endif
+ {
RemoveMovingField(newx, newy);
+ }
else
{
Feld[newx][newy] = EL_EMPTY;
DrawLevelField(x, y);
MovDelay[newx][newy] = 0; /* start amoeba shrinking delay */
+
return; /* wait for shrinking amoeba */
}
else /* element == EL_PACMAN */
TurnRound(x, y);
+#if 0
+ if (move_pattern & MV_ANY_DIRECTION &&
+ move_pattern == MovDir[x][y])
+ {
+ int blocking_element =
+ (IN_LEV_FIELD(newx, newy) ? Feld[newx][newy] : BorderElement);
+
+#if 0
+ printf("::: '%s' is blocked by '%s'! [%d,%d -> %d,%d]\n",
+ element_info[element].token_name,
+ element_info[blocking_element].token_name,
+ x, y, newx, newy);
+#endif
+
+ CheckElementChangeBySide(x, y, element, blocking_element, CE_BLOCKED,
+ MovDir[x][y]);
+
+ element = Feld[x][y]; /* element might have changed */
+ }
+#endif
+
#if 1
if (GFX_ELEMENT(element) != EL_SAND) /* !!! FIX THIS (crumble) !!! */
DrawLevelElementAnimation(x, y, element);
void ContinueMoving(int x, int y)
{
int element = Feld[x][y];
+ int stored = Store[x][y];
+ struct ElementInfo *ei = &element_info[element];
int direction = MovDir[x][y];
int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
int newx = x + dx, newy = y + dy;
+#if 0
int nextx = newx + dx, nexty = newy + dy;
- boolean pushed = Pushed[x][y];
+#endif
+#if 1
+ boolean pushed_by_player = (Pushed[x][y] && IS_PLAYER(x, y));
+ boolean pushed_by_conveyor = (Pushed[x][y] && !IS_PLAYER(x, y));
+#else
+ boolean pushed_by_player = Pushed[x][y];
+#endif
MovPos[x][y] += getElementMoveStepsize(x, y);
- if (pushed) /* special case: moving object pushed by player */
+#if 0
+ if (pushed_by_player && IS_PLAYER(x, y))
+ {
+ /* special case: moving object pushed by player */
+ MovPos[x][y] = SIGN(MovPos[x][y]) * (TILEX - ABS(PLAYERINFO(x,y)->MovPos));
+ }
+#else
+ if (pushed_by_player) /* special case: moving object pushed by player */
MovPos[x][y] = SIGN(MovPos[x][y]) * (TILEX - ABS(PLAYERINFO(x,y)->MovPos));
+#endif
if (ABS(MovPos[x][y]) < TILEX)
{
Feld[newx][newy] = element;
MovPos[x][y] = 0; /* force "not moving" for "crumbled sand" */
- if (element == EL_MOLE)
+#if 1
+ if (Store[x][y] == EL_ACID) /* element is moving into acid pool */
+ {
+ element = Feld[newx][newy] = EL_ACID;
+ }
+#endif
+ else if (element == EL_MOLE)
{
Feld[x][y] = EL_SAND;
Back[x][y] = Back[newx][newy] = 0;
}
+#if 0
else if (Store[x][y] == EL_ACID)
{
element = Feld[newx][newy] = EL_ACID;
}
+#endif
+#if 0
+ else if (IS_CUSTOM_ELEMENT(element) && !IS_PLAYER(x, y) &&
+ ei->move_leave_element != EL_EMPTY &&
+ (ei->move_leave_type == LEAVE_TYPE_UNLIMITED ||
+ Store[x][y] != EL_EMPTY))
+ {
+ /* some elements can leave other elements behind after moving */
+
+ Feld[x][y] = ei->move_leave_element;
+ InitField(x, y, FALSE);
+
+ if (GFX_CRUMBLED(Feld[x][y]))
+ DrawLevelFieldCrumbledSandNeighbours(x, y);
+ }
+#endif
- Store[x][y] = 0;
+ Store[x][y] = EL_EMPTY;
MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
MovDelay[newx][newy] = 0;
- /* copy element change control values to new field */
- ChangeDelay[newx][newy] = ChangeDelay[x][y];
- ChangePage[newx][newy] = ChangePage[x][y];
- Changed[newx][newy] = Changed[x][y];
- ChangeEvent[newx][newy] = ChangeEvent[x][y];
+ if (CAN_CHANGE(element))
+ {
+ /* copy element change control values to new field */
+ ChangeDelay[newx][newy] = ChangeDelay[x][y];
+ ChangePage[newx][newy] = ChangePage[x][y];
+ Changed[newx][newy] = Changed[x][y];
+ ChangeEvent[newx][newy] = ChangeEvent[x][y];
+ }
ChangeDelay[x][y] = 0;
ChangePage[x][y] = -1;
ResetGfxAnimation(x, y); /* reset animation values for old field */
+#if 1
+ /* some elements can leave other elements behind after moving */
+#if 1
+ if (IS_CUSTOM_ELEMENT(element) && ei->move_leave_element != EL_EMPTY &&
+ (ei->move_leave_type == LEAVE_TYPE_UNLIMITED || stored != EL_EMPTY) &&
+ (!IS_PLAYER(x, y) || IS_WALKABLE(ei->move_leave_element)))
+#else
+ if (IS_CUSTOM_ELEMENT(element) && ei->move_leave_element != EL_EMPTY &&
+ (ei->move_leave_type == LEAVE_TYPE_UNLIMITED || stored != EL_EMPTY) &&
+ !IS_PLAYER(x, y))
+#endif
+ {
+ int move_leave_element = ei->move_leave_element;
+
+ Feld[x][y] = move_leave_element;
+ InitField(x, y, FALSE);
+
+ if (GFX_CRUMBLED(Feld[x][y]))
+ DrawLevelFieldCrumbledSandNeighbours(x, y);
+
+ if (ELEM_IS_PLAYER(move_leave_element))
+ RelocatePlayer(x, y, move_leave_element);
+ }
+#endif
+
+#if 0
+ /* some elements can leave other elements behind after moving */
+ if (IS_CUSTOM_ELEMENT(element) && !IS_PLAYER(x, y) &&
+ ei->move_leave_element != EL_EMPTY &&
+ (ei->move_leave_type == LEAVE_TYPE_UNLIMITED ||
+ ei->can_leave_element_last))
+ {
+ Feld[x][y] = ei->move_leave_element;
+ InitField(x, y, FALSE);
+
+ if (GFX_CRUMBLED(Feld[x][y]))
+ DrawLevelFieldCrumbledSandNeighbours(x, y);
+ }
+
+ ei->can_leave_element_last = ei->can_leave_element;
+ ei->can_leave_element = FALSE;
+#endif
+
#if 0
/* 2.1.1 (does not work correctly for spring) */
if (!CAN_MOVE(element))
MovDir[newx][newy] = 0;
*/
+#if 0
if (!CAN_MOVE(element) ||
(CAN_FALL(element) && direction == MV_DOWN))
GfxDir[x][y] = MovDir[newx][newy] = 0;
+#else
+ if (!CAN_MOVE(element) ||
+ (CAN_FALL(element) && direction == MV_DOWN &&
+ (element == EL_SPRING ||
+ element_info[element].move_pattern == MV_WHEN_PUSHED ||
+ element_info[element].move_pattern == MV_WHEN_DROPPED)))
+ GfxDir[x][y] = MovDir[newx][newy] = 0;
+#endif
#endif
#endif
Stop[newx][newy] = TRUE; /* ignore this element until the next frame */
/* prevent pushed element from moving on in pushed direction */
- if (pushed && CAN_MOVE(element) &&
+ if (pushed_by_player && CAN_MOVE(element) &&
element_info[element].move_pattern & MV_ANY_DIRECTION &&
!(element_info[element].move_pattern & direction))
TurnRound(newx, newy);
- if (!pushed) /* special case: moving object pushed by player */
+#if 1
+ /* prevent elements on conveyor belt from moving on in last direction */
+ if (pushed_by_conveyor && CAN_FALL(element) &&
+ direction & MV_HORIZONTAL)
+ {
+#if 0
+ if (CAN_MOVE(element))
+ InitMovDir(newx, newy);
+ else
+ MovDir[newx][newy] = 0;
+#else
+ MovDir[newx][newy] = 0;
+#endif
+ }
+#endif
+
+ if (!pushed_by_player)
{
+ int nextx = newx + dx, nexty = newy + dy;
+ boolean check_collision_again = IN_LEV_FIELD_AND_IS_FREE(nextx, nexty);
+
WasJustMoving[newx][newy] = 3;
if (CAN_FALL(element) && direction == MV_DOWN)
WasJustFalling[newx][newy] = 3;
+
+ if ((!CAN_FALL(element) || direction == MV_DOWN) && check_collision_again)
+ CheckCollision[newx][newy] = 2;
}
if (DONT_TOUCH(element)) /* object may be nasty to player or others */
Impact(x, newy);
#if 1
- TestIfElementTouchesCustomElement(x, y); /* for empty space */
+ if (pushed_by_player)
+ {
+#if 1
+ int dig_side = MV_DIR_OPPOSITE(direction);
+#else
+ static int trigger_sides[4] =
+ {
+ CH_SIDE_RIGHT, /* moving left */
+ CH_SIDE_LEFT, /* moving right */
+ CH_SIDE_BOTTOM, /* moving up */
+ CH_SIDE_TOP, /* moving down */
+ };
+ int dig_side = trigger_sides[MV_DIR_BIT(direction)];
+#endif
+ struct PlayerInfo *player = PLAYERINFO(x, y);
+
+ CheckElementChangeByPlayer(newx, newy, element, CE_PUSHED_BY_PLAYER,
+ player->index_bit, dig_side);
+ CheckTriggeredElementChangeByPlayer(newx,newy,element,CE_OTHER_GETS_PUSHED,
+ player->index_bit, dig_side);
+ }
+#endif
+
+#if 1
+ TestIfElementTouchesCustomElement(x, y); /* empty or new element */
#endif
#if 0
ChangeElement(newx, newy, ChangePage[newx][newy]);
#endif
+#if 1
+
+ TestIfElementHitsCustomElement(newx, newy, direction);
+
+#else
+
if (!IN_LEV_FIELD(nextx, nexty) || !IS_FREE(nextx, nexty))
{
+ int hitting_element = Feld[newx][newy];
+
/* !!! fix side (direction) orientation here and elsewhere !!! */
- CheckElementSideChange(newx, newy, Feld[newx][newy],
- direction, CE_COLLISION_ACTIVE, -1);
+ CheckElementChangeBySide(newx, newy, hitting_element, CE_HITTING_SOMETHING,
+ direction);
#if 0
if (IN_LEV_FIELD(nextx, nexty))
{
- static int opposite_directions[] =
- {
- MV_RIGHT,
- MV_LEFT,
- MV_DOWN,
- MV_UP
- };
- int move_dir_bit = MV_DIR_BIT(direction);
- int opposite_direction = opposite_directions[move_dir_bit];
+ int opposite_direction = MV_DIR_OPPOSITE(direction);
int hitting_side = direction;
int touched_side = opposite_direction;
- int hitting_element = Feld[newx][newy];
int touched_element = MovingOrBlocked2Element(nextx, nexty);
boolean object_hit = (!IS_MOVING(nextx, nexty) ||
MovDir[nextx][nexty] != direction ||
{
int i;
- CheckElementSideChange(nextx, nexty, Feld[nextx][nexty],
- opposite_direction, CE_COLLISION_PASSIVE, -1);
+ CheckElementChangeBySide(nextx, nexty, touched_element,
+ CE_HIT_BY_SOMETHING, opposite_direction);
if (IS_CUSTOM_ELEMENT(hitting_element) &&
- HAS_ANY_CHANGE_EVENT(hitting_element, CE_OTHER_IS_COLL_ACTIVE))
+ HAS_ANY_CHANGE_EVENT(hitting_element, CE_OTHER_IS_HITTING))
{
for (i = 0; i < element_info[hitting_element].num_change_pages; i++)
{
&element_info[hitting_element].change_page[i];
if (change->can_change &&
- change->events & CH_EVENT_BIT(CE_OTHER_IS_COLL_ACTIVE) &&
- change->sides & touched_side &&
+ change->events & CH_EVENT_BIT(CE_OTHER_IS_HITTING) &&
+ change->trigger_side & touched_side &&
change->trigger_element == touched_element)
{
- CheckElementSideChange(newx, newy, hitting_element,
- CH_SIDE_ANY, CE_OTHER_IS_COLL_ACTIVE, i);
+ CheckElementChangeByPage(newx, newy, hitting_element,
+ touched_element, CE_OTHER_IS_HITTING,i);
break;
}
}
}
if (IS_CUSTOM_ELEMENT(touched_element) &&
- HAS_ANY_CHANGE_EVENT(touched_element, CE_OTHER_IS_COLL_PASSIVE))
+ HAS_ANY_CHANGE_EVENT(touched_element, CE_OTHER_GETS_HIT))
{
for (i = 0; i < element_info[touched_element].num_change_pages; i++)
{
&element_info[touched_element].change_page[i];
if (change->can_change &&
- change->events & CH_EVENT_BIT(CE_OTHER_IS_COLL_PASSIVE) &&
- change->sides & hitting_side &&
+ change->events & CH_EVENT_BIT(CE_OTHER_GETS_HIT) &&
+ change->trigger_side & hitting_side &&
change->trigger_element == hitting_element)
{
- CheckElementSideChange(nextx, nexty, touched_element,
- CH_SIDE_ANY, CE_OTHER_IS_COLL_PASSIVE, i);
+ CheckElementChangeByPage(nextx, nexty, touched_element,
+ hitting_element, CE_OTHER_GETS_HIT, i);
break;
}
}
}
#endif
}
+#endif
TestIfPlayerTouchesCustomElement(newx, newy);
TestIfElementTouchesCustomElement(newx, newy);
{ 0, +1 }
};
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
int x = ax + xy[i][0];
int y = ay + xy[i][1];
if (new_group_nr == 0)
return;
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
x = ax + xy[i][0];
y = ay + xy[i][1];
{ 0, +1 }
};
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
x = ax + xy[i][0];
y = ay + xy[i][1];
if (!IN_LEV_FIELD(x, y))
return;
+#if 1
+ if (IS_FREE(x, y) ||
+ CAN_GROW_INTO(Feld[x][y]) ||
+ Feld[x][y] == EL_QUICKSAND_EMPTY)
+ {
+ newax = x;
+ neway = y;
+ }
+#else
/* !!! extend EL_SAND to anything diggable (but maybe not SP_BASE) !!! */
if (IS_FREE(x, y) ||
Feld[x][y] == EL_SAND || Feld[x][y] == EL_QUICKSAND_EMPTY)
newax = x;
neway = y;
}
+#endif
if (newax == ax && neway == ay)
return;
int start = RND(4);
boolean waiting_for_player = FALSE;
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
int j = (start + i) % 4;
int x = ax + xy[j][0];
if (!IN_LEV_FIELD(x, y))
continue;
+#if 1
+ if (IS_FREE(x, y) ||
+ CAN_GROW_INTO(Feld[x][y]) ||
+ Feld[x][y] == EL_QUICKSAND_EMPTY)
+ {
+ newax = x;
+ neway = y;
+ break;
+ }
+#else
/* !!! extend EL_SAND to anything diggable (but maybe not SP_BASE) !!! */
if (IS_FREE(x, y) ||
Feld[x][y] == EL_SAND || Feld[x][y] == EL_QUICKSAND_EMPTY)
neway = y;
break;
}
+#endif
else if (IS_PLAYER(x, y))
waiting_for_player = TRUE;
}
if (newax == ax && neway == ay) /* amoeba cannot grow */
{
+#if 1
+ if (i == 4 && (!waiting_for_player || element == EL_BD_AMOEBA))
+#else
if (i == 4 && (!waiting_for_player || game.emulation == EMU_BOULDERDASH))
+#endif
{
Feld[ax][ay] = EL_AMOEBA_DEAD;
DrawLevelField(ax, ay);
changed = TRUE;
}
}
+#if 1
+ else if (IS_FREE(xx, yy) || CAN_GROW_INTO(Feld[xx][yy]))
+ { /* free border field */
+ if (nachbarn >= life[2] && nachbarn <= life[3])
+ {
+ Feld[xx][yy] = element;
+ MovDelay[xx][yy] = (element == EL_GAME_OF_LIFE ? 0 : life_time-1);
+ if (!Stop[xx][yy])
+ DrawLevelField(xx, yy);
+ Stop[xx][yy] = TRUE;
+ changed = TRUE;
+ }
+ }
+#else
/* !!! extend EL_SAND to anything diggable (but maybe not SP_BASE) !!! */
else if (IS_FREE(xx, yy) || Feld[xx][yy] == EL_SAND)
{ /* free border field */
changed = TRUE;
}
}
+#endif
}
if (changed)
static void InitTimegateWheel(int x, int y)
{
+#if 1
+ ChangeDelay[x][y] = level.time_timegate * FRAMES_PER_SECOND;
+#else
+ /* another brainless, "type style" bug ... :-( */
ChangeDelay[x][y] = level.time_wheel * FRAMES_PER_SECOND;
+#endif
}
static void RunTimegateWheel(int x, int y)
{ 0, +1 }
};
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
for (j = 0; j < 4; j++)
{
- int xx = x + j*xy[i][0], yy = y + j*xy[i][1];
+ int xx = x + j * xy[i][0], yy = y + j * xy[i][1];
if (IN_LEV_FIELD(xx, yy) &&
(Feld[xx][yy] == EL_FLAMES || Feld[xx][yy] == EL_DRAGON))
if (!dragon_found)
{
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
for (j = 0; j < 3; j++)
{
- int xx = x + j*xy[i][0], yy = y + j*xy[i][1];
+ int xx = x + j * xy[i][0], yy = y + j * xy[i][1];
if (IN_LEV_FIELD(xx, yy) && Feld[xx][yy] == EL_FLAMES)
{
{ 0, +1 }
};
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
int xx = x + xy[i][0], yy = y + xy[i][1];
static void ChangeElementNowExt(int x, int y, int target_element)
{
+ int previous_move_direction = MovDir[x][y];
+#if 1
+ boolean add_player = (ELEM_IS_PLAYER(target_element) &&
+ IS_WALKABLE(Feld[x][y]));
+#else
+ boolean add_player = (ELEM_IS_PLAYER(target_element) &&
+ IS_WALKABLE(Feld[x][y]) &&
+ !IS_MOVING(x, y));
+#endif
+
/* check if element under player changes from accessible to unaccessible
(needed for special case of dropping element which then changes) */
- if (IS_PLAYER(x, y) && !PLAYER_PROTECTED(x, y) &&
+ if (IS_PLAYER(x, y) && !PLAYER_EXPLOSION_PROTECTED(x, y) &&
IS_ACCESSIBLE(Feld[x][y]) && !IS_ACCESSIBLE(target_element))
{
+#if 0
+ printf("::: BOOOM! [%d, '%s']\n", target_element,
+ element_info[target_element].token_name);
+#endif
+
Bang(x, y);
return;
}
- RemoveField(x, y);
- Feld[x][y] = target_element;
+#if 1
+ if (!add_player)
+#endif
+ {
+#if 1
+ if (IS_MOVING(x, y) || IS_BLOCKED(x, y))
+ RemoveMovingField(x, y);
+ else
+ RemoveField(x, y);
- Changed[x][y] |= ChangeEvent[x][y]; /* ignore same changes in this frame */
+ Feld[x][y] = target_element;
+#else
+ RemoveField(x, y);
+ Feld[x][y] = target_element;
+#endif
- ResetGfxAnimation(x, y);
- ResetRandomAnimationValue(x, y);
+ ResetGfxAnimation(x, y);
+ ResetRandomAnimationValue(x, y);
- InitField(x, y, FALSE);
- if (CAN_MOVE(Feld[x][y]))
- InitMovDir(x, y);
+ if (element_info[Feld[x][y]].move_direction_initial == MV_START_PREVIOUS)
+ MovDir[x][y] = previous_move_direction;
- DrawLevelField(x, y);
+#if 1
+ InitField_WithBug1(x, y, FALSE);
+#else
+ InitField(x, y, FALSE);
+ if (CAN_MOVE(Feld[x][y]))
+ InitMovDir(x, y);
+#endif
- if (GFX_CRUMBLED(Feld[x][y]))
- DrawLevelFieldCrumbledSandNeighbours(x, y);
+ DrawLevelField(x, y);
+
+ if (GFX_CRUMBLED(Feld[x][y]))
+ DrawLevelFieldCrumbledSandNeighbours(x, y);
+ }
+#if 0
+ Changed[x][y] |= ChangeEvent[x][y]; /* ignore same changes in this frame */
+#endif
+
+#if 0
TestIfBadThingTouchesHero(x, y);
TestIfPlayerTouchesCustomElement(x, y);
TestIfElementTouchesCustomElement(x, y);
+#endif
+ /* "Changed[][]" not set yet to allow "entered by player" change one time */
if (ELEM_IS_PLAYER(target_element))
RelocatePlayer(x, y, target_element);
+
+#if 1
+ Changed[x][y] |= ChangeEvent[x][y]; /* ignore same changes in this frame */
+#endif
+
+#if 1
+ TestIfBadThingTouchesHero(x, y);
+ TestIfPlayerTouchesCustomElement(x, y);
+ TestIfElementTouchesCustomElement(x, y);
+#endif
}
static boolean ChangeElementNow(int x, int y, int element, int page)
{
struct ElementChangeInfo *change = &element_info[element].change_page[page];
+ int target_element;
+ int old_element = Feld[x][y];
/* always use default change event to prevent running into a loop */
if (ChangeEvent[x][y] == CE_BITMASK_DEFAULT)
ChangeEvent[x][y] = CH_EVENT_BIT(CE_DELAY);
+ if (ChangeEvent[x][y] == CH_EVENT_BIT(CE_DELAY))
+ {
+ /* reset actual trigger element and player */
+ change->actual_trigger_element = EL_EMPTY;
+ change->actual_trigger_player = EL_PLAYER_1;
+ }
+
/* do not change already changed elements with same change event */
#if 0
if (Changed[x][y] & ChangeEvent[x][y])
Changed[x][y] |= ChangeEvent[x][y]; /* ignore same changes in this frame */
- CheckTriggeredElementChange(x, y, Feld[x][y], CE_OTHER_IS_CHANGING);
+#if 0
+ /* !!! indirect change before direct change !!! */
+ CheckTriggeredElementChangeByPage(x,y,Feld[x][y], CE_OTHER_IS_CHANGING,page);
+#endif
if (change->explode)
{
return TRUE;
}
- if (change->use_content)
+ if (change->use_target_content)
{
- boolean complete_change = TRUE;
- boolean can_change[3][3];
+ boolean complete_replace = TRUE;
+ boolean can_replace[3][3];
int xx, yy;
for (yy = 0; yy < 3; yy++) for (xx = 0; xx < 3 ; xx++)
{
- boolean half_destructible;
+ boolean is_empty;
+ boolean is_walkable;
+ boolean is_diggable;
+ boolean is_collectible;
+ boolean is_removable;
+ boolean is_destructible;
int ex = x + xx - 1;
int ey = y + yy - 1;
+ int content_element = change->target_content[xx][yy];
int e;
- can_change[xx][yy] = TRUE;
+ can_replace[xx][yy] = TRUE;
if (ex == x && ey == y) /* do not check changing element itself */
continue;
- if (change->content[xx][yy] == EL_EMPTY_SPACE)
+ if (content_element == EL_EMPTY_SPACE)
{
- can_change[xx][yy] = FALSE; /* do not change empty borders */
+ can_replace[xx][yy] = FALSE; /* do not replace border with space */
continue;
}
if (!IN_LEV_FIELD(ex, ey))
{
- can_change[xx][yy] = FALSE;
- complete_change = FALSE;
+ can_replace[xx][yy] = FALSE;
+ complete_replace = FALSE;
+
+ continue;
+ }
+
+#if 0
+ if (Changed[ex][ey]) /* do not change already changed elements */
+ {
+ can_replace[xx][yy] = FALSE;
+ complete_replace = FALSE;
continue;
}
+#endif
e = Feld[ex][ey];
if (IS_MOVING(ex, ey) || IS_BLOCKED(ex, ey))
e = MovingOrBlocked2Element(ex, ey);
+#if 1
+
+#if 0
+ is_empty = (IS_FREE(ex, ey) ||
+ (IS_PLAYER(ex, ey) && IS_WALKABLE(content_element)) ||
+ (IS_WALKABLE(e) && ELEM_IS_PLAYER(content_element) &&
+ !IS_MOVING(ex, ey) && !IS_BLOCKED(ex, ey)));
+#else
+
+#if 0
+ is_empty = (IS_FREE(ex, ey) ||
+ (IS_PLAYER(ex, ey) && IS_WALKABLE(content_element)));
+#else
+ is_empty = (IS_FREE(ex, ey) ||
+ (IS_FREE_OR_PLAYER(ex, ey) && IS_WALKABLE(content_element)));
+#endif
+
+#endif
+
+ is_walkable = (is_empty || IS_WALKABLE(e));
+ is_diggable = (is_empty || IS_DIGGABLE(e));
+ is_collectible = (is_empty || IS_COLLECTIBLE(e));
+ is_destructible = (is_empty || !IS_INDESTRUCTIBLE(e));
+ is_removable = (is_diggable || is_collectible);
+
+ can_replace[xx][yy] =
+ (((change->replace_when == CP_WHEN_EMPTY && is_empty) ||
+ (change->replace_when == CP_WHEN_WALKABLE && is_walkable) ||
+ (change->replace_when == CP_WHEN_DIGGABLE && is_diggable) ||
+ (change->replace_when == CP_WHEN_COLLECTIBLE && is_collectible) ||
+ (change->replace_when == CP_WHEN_REMOVABLE && is_removable) ||
+ (change->replace_when == CP_WHEN_DESTRUCTIBLE && is_destructible)) &&
+ !(IS_PLAYER(ex, ey) && ELEM_IS_PLAYER(content_element)));
+
+ if (!can_replace[xx][yy])
+ complete_replace = FALSE;
+#else
+ empty_for_element = (IS_FREE(ex, ey) || (IS_FREE_OR_PLAYER(ex, ey) &&
+ IS_WALKABLE(content_element)));
+#if 1
+ half_destructible = (empty_for_element || IS_DIGGABLE(e));
+#else
half_destructible = (IS_FREE(ex, ey) || IS_DIGGABLE(e));
+#endif
- if ((change->power <= CP_NON_DESTRUCTIVE && !IS_FREE(ex, ey)) ||
- (change->power <= CP_HALF_DESTRUCTIVE && !half_destructible) ||
- (change->power <= CP_FULL_DESTRUCTIVE && IS_INDESTRUCTIBLE(e)))
+ if ((change->replace_when <= CP_WHEN_EMPTY && !empty_for_element) ||
+ (change->replace_when <= CP_WHEN_DIGGABLE && !half_destructible) ||
+ (change->replace_when <= CP_WHEN_DESTRUCTIBLE && IS_INDESTRUCTIBLE(e)))
{
- can_change[xx][yy] = FALSE;
- complete_change = FALSE;
+ can_replace[xx][yy] = FALSE;
+ complete_replace = FALSE;
}
+#endif
}
- if (!change->only_complete || complete_change)
+ if (!change->only_if_complete || complete_replace)
{
boolean something_has_changed = FALSE;
- if (change->only_complete && change->use_random_change &&
- RND(100) < change->random)
+ if (change->only_if_complete && change->use_random_replace &&
+ RND(100) < change->random_percentage)
return FALSE;
for (yy = 0; yy < 3; yy++) for (xx = 0; xx < 3 ; xx++)
{
int ex = x + xx - 1;
int ey = y + yy - 1;
+ int content_element;
- if (can_change[xx][yy] && (!change->use_random_change ||
- RND(100) < change->random))
+ if (can_replace[xx][yy] && (!change->use_random_replace ||
+ RND(100) < change->random_percentage))
{
if (IS_MOVING(ex, ey) || IS_BLOCKED(ex, ey))
RemoveMovingField(ex, ey);
ChangeEvent[ex][ey] = ChangeEvent[x][y];
- ChangeElementNowExt(ex, ey, change->content[xx][yy]);
+ content_element = change->target_content[xx][yy];
+ target_element = GET_TARGET_ELEMENT(content_element, change);
+
+ ChangeElementNowExt(ex, ey, target_element);
something_has_changed = TRUE;
}
else
{
- ChangeElementNowExt(x, y, change->target_element);
+ target_element = GET_TARGET_ELEMENT(change->target_element, change);
+
+ ChangeElementNowExt(x, y, target_element);
PlayLevelSoundElementAction(x, y, element, ACTION_CHANGING);
}
+#if 1
+ /* this uses direct change before indirect change */
+ CheckTriggeredElementChangeByPage(x,y,old_element,CE_OTHER_IS_CHANGING,page);
+#endif
+
return TRUE;
}
struct ElementInfo *ei = &element_info[element];
struct ElementChangeInfo *change = &ei->change_page[page];
-#if 0
#ifdef DEBUG
- if (!CAN_CHANGE(element))
+ if (!CAN_CHANGE(element) && !CAN_CHANGE(Back[x][y]))
{
printf("\n\n");
printf("ChangeElement(): %d,%d: element = %d ('%s')\n",
printf("ChangeElement(): This should never happen!\n");
printf("\n\n");
}
-#endif
-#endif
+#endif
+
+ /* this can happen with classic bombs on walkable, changing elements */
+ if (!CAN_CHANGE(element))
+ {
+#if 0
+ if (!CAN_CHANGE(Back[x][y])) /* prevent permanent repetition */
+ ChangeDelay[x][y] = 0;
+#endif
+
+ return;
+ }
if (ChangeDelay[x][y] == 0) /* initialize element change */
{
{
page = ChangePage[x][y];
ChangePage[x][y] = -1;
+
+ change = &ei->change_page[page];
}
+#if 0
+ if (IS_MOVING(x, y) && !change->explode)
+#else
if (IS_MOVING(x, y)) /* never change a running system ;-) */
+#endif
{
ChangeDelay[x][y] = 1; /* try change after next move step */
ChangePage[x][y] = page; /* remember page to use for change */
}
}
-static boolean CheckTriggeredElementSideChange(int lx, int ly,
- int trigger_element,
- int trigger_side,
- int trigger_event)
+static boolean CheckTriggeredElementChangeExt(int lx, int ly,
+ int trigger_element,
+ int trigger_event,
+ int trigger_player,
+ int trigger_side,
+ int trigger_page)
{
int i, j, x, y;
+ int trigger_page_bits = (trigger_page < 0 ? CH_PAGE_ANY : 1 << trigger_page);
if (!(trigger_events[trigger_element] & CH_EVENT_BIT(trigger_event)))
return FALSE;
struct ElementChangeInfo *change = &element_info[element].change_page[j];
if (change->can_change &&
-#if 1
change->events & CH_EVENT_BIT(trigger_event) &&
-#endif
- change->sides & trigger_side &&
- change->trigger_element == trigger_element)
+ change->trigger_side & trigger_side &&
+ change->trigger_player & trigger_player &&
+ change->trigger_page & trigger_page_bits &&
+ IS_EQUAL_OR_IN_GROUP(trigger_element, change->trigger_element))
{
#if 0
if (!(change->events & CH_EVENT_BIT(trigger_event)))
change_element = TRUE;
page = j;
+ change->actual_trigger_element = trigger_element;
+ change->actual_trigger_player = EL_PLAYER_1 + log_2(trigger_player);
+
break;
}
}
return TRUE;
}
-static boolean CheckTriggeredElementChange(int lx, int ly, int trigger_element,
- int trigger_event)
-{
- return CheckTriggeredElementSideChange(lx, ly, trigger_element, CH_SIDE_ANY,
- trigger_event);
-}
-
-static boolean CheckElementSideChange(int x, int y, int element, int side,
- int trigger_event, int page)
+static boolean CheckElementChangeExt(int x, int y,
+ int element,
+ int trigger_element,
+ int trigger_event,
+ int trigger_player,
+ int trigger_side,
+ int trigger_page)
{
if (!CAN_CHANGE(element) || !HAS_ANY_CHANGE_EVENT(element, trigger_event))
return FALSE;
element = Feld[x][y];
}
- if (page < 0)
- page = element_info[element].event_page_nr[trigger_event];
+#if 1
+ if (Feld[x][y] != element) /* check if element has already changed */
+ {
+#if 0
+ printf("::: %d ('%s') != %d ('%s') [%d]\n",
+ Feld[x][y], element_info[Feld[x][y]].token_name,
+ element, element_info[element].token_name,
+ trigger_event);
+#endif
+
+ return FALSE;
+ }
+#endif
+
+#if 1
+ if (trigger_page < 0)
+ {
+ boolean change_element = FALSE;
+ int i;
+
+ for (i = 0; i < element_info[element].num_change_pages; i++)
+ {
+ struct ElementChangeInfo *change = &element_info[element].change_page[i];
+
+ if (change->can_change &&
+ change->events & CH_EVENT_BIT(trigger_event) &&
+ change->trigger_side & trigger_side &&
+ change->trigger_player & trigger_player)
+ {
+ change_element = TRUE;
+ trigger_page = i;
+
+ change->actual_trigger_element = trigger_element;
+ change->actual_trigger_player = EL_PLAYER_1 + log_2(trigger_player);
+
+ break;
+ }
+ }
+
+ if (!change_element)
+ return FALSE;
+ }
+ else
+ {
+ struct ElementInfo *ei = &element_info[element];
+ struct ElementChangeInfo *change = &ei->change_page[trigger_page];
+
+ change->actual_trigger_element = trigger_element;
+ change->actual_trigger_player = EL_PLAYER_1; /* unused */
+ }
+
+#else
+
+ /* !!! this check misses pages with same event, but different side !!! */
- if (!(element_info[element].change_page[page].sides & side))
+ if (trigger_page < 0)
+ trigger_page = element_info[element].event_page_nr[trigger_event];
+
+ if (!(element_info[element].change_page[trigger_page].trigger_side & trigger_side))
return FALSE;
+#endif
ChangeDelay[x][y] = 1;
ChangeEvent[x][y] = CH_EVENT_BIT(trigger_event);
- ChangeElement(x, y, page);
+ ChangeElement(x, y, trigger_page);
return TRUE;
}
-static boolean CheckElementChange(int x, int y, int element, int trigger_event)
-{
- return CheckElementSideChange(x, y, element, CH_SIDE_ANY, trigger_event, -1);
-}
-
static void PlayPlayerSound(struct PlayerInfo *player)
{
int jx = player->jx, jy = player->jy;
if (!player->active || tape.pausing)
return 0;
+#if 0
+ printf("::: [%d %d %d %d] [%d %d]\n",
+ left, right, up, down, button1, button2);
+#endif
+
if (player_action)
{
#if 0
printf("::: player %d acts [%d]\n", player->index_nr, FrameCounter);
#endif
+#if 0
+ /* !!! TEST !!! */
+ if (player->MovPos == 0)
+ CheckGravityMovement(player);
+#endif
if (button1)
snapped = SnapField(player, dx, dy);
else
/* no actions for this player (no input at player's configured device) */
- DigField(player, 0, 0, 0, 0, DF_NO_PUSH);
+ DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH);
SnapField(player, 0, 0);
- CheckGravityMovement(player);
+ CheckGravityMovementWhenNotMoving(player);
if (player->MovPos == 0)
SetPlayerWaiting(player, TRUE);
if (player->MovPos == 0) /* needed for tape.playing */
player->is_moving = FALSE;
+ player->is_dropping = FALSE;
+
return 0;
}
/* no actions for this player (no input at player's configured device) */
- DigField(player, 0, 0, 0, 0, DF_NO_PUSH);
+ DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH);
SnapField(player, 0, 0);
- CheckGravityMovement(player);
+ CheckGravityMovementWhenNotMoving(player);
if (player->MovPos == 0)
InitPlayerGfxAnimation(player, ACTION_DEFAULT, player->MovDir);
action_delay_value =
(tape.playing && tape.fast_forward ? FfwdFrameDelay : GameFrameDelay);
- if (tape.playing && tape.index_search && !tape.pausing)
+ if (tape.playing && tape.warp_forward && !tape.pausing)
action_delay_value = 0;
/* ---------- main game synchronization point ---------- */
#endif
*/
-#if defined(PLATFORM_UNIX)
+#if defined(NETWORK_AVALIABLE)
/* last chance to get network player actions without main loop delay */
HandleNetworking();
#endif
recorded_player_action = (tape.playing ? TapePlayAction() : NULL);
+#if 1
+ if (recorded_player_action == NULL && tape.pausing)
+ return;
+#endif
+
+#if 0
+ printf("::: %d\n", stored_player[0].action);
+#endif
+
+#if 0
+ if (recorded_player_action != NULL)
+ for (i = 0; i < MAX_PLAYERS; i++)
+ stored_player[i].action = recorded_player_action[i];
+#endif
+
for (i = 0; i < MAX_PLAYERS; i++)
{
summarized_player_action |= stored_player[i].action;
stored_player[i].effective_action = stored_player[i].action;
}
-#if defined(PLATFORM_UNIX)
+#if defined(NETWORK_AVALIABLE)
if (network_playing)
SendToServer_MovePlayer(summarized_player_action);
#endif
if (!options.network && !setup.team_mode)
local_player->effective_action = summarized_player_action;
+#if 1
+ if (recorded_player_action != NULL)
+ for (i = 0; i < MAX_PLAYERS; i++)
+ stored_player[i].effective_action = recorded_player_action[i];
+#endif
+
+#if 1
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ tape_action[i] = stored_player[i].effective_action;
+
+ if (tape.recording && tape_action[i] && !tape.player_participates[i])
+ tape.player_participates[i] = TRUE; /* player just appeared from CE */
+ }
+
+ /* only save actions from input devices, but not programmed actions */
+ if (tape.recording)
+ TapeRecordAction(tape_action);
+#endif
+
for (i = 0; i < MAX_PLAYERS; i++)
{
int actual_player_action = stored_player[i].effective_action;
+#if 1
+ /* !!! THIS BREAKS THE FOLLOWING TAPES: !!!
+ - rnd_equinox_tetrachloride 048
+ - rnd_equinox_tetrachloride_ii 096
+ - rnd_emanuel_schmieg 002
+ - doctor_sloan_ww 001, 020
+ */
+ if (stored_player[i].MovPos == 0)
+ CheckGravityMovement(&stored_player[i]);
+#endif
+
+#if 1
+ /* overwrite programmed action with tape action */
if (stored_player[i].programmed_action)
actual_player_action = stored_player[i].programmed_action;
+#endif
+
+#if 0
+ if (stored_player[i].programmed_action)
+ printf("::: %d\n", stored_player[i].programmed_action);
+#endif
if (recorded_player_action)
+ {
+#if 0
+ if (stored_player[i].programmed_action &&
+ stored_player[i].programmed_action != recorded_player_action[i])
+ printf("::: %d: %d <-> %d\n", i,
+ stored_player[i].programmed_action, recorded_player_action[i]);
+#endif
+
+#if 0
actual_player_action = recorded_player_action[i];
+#endif
+ }
+
+#if 0
+ /* overwrite tape action with programmed action */
+ if (stored_player[i].programmed_action)
+ actual_player_action = stored_player[i].programmed_action;
+#endif
+
+#if 0
+ if (i == 0)
+ printf("::: action: %d: %x [%d]\n",
+ stored_player[i].MovPos, actual_player_action, FrameCounter);
+#endif
+#if 1
+ PlayerActions(&stored_player[i], actual_player_action);
+#else
tape_action[i] = PlayerActions(&stored_player[i], actual_player_action);
if (tape.recording && tape_action[i] && !tape.player_participates[i])
tape.player_participates[i] = TRUE; /* player just appeared from CE */
+#endif
ScrollPlayer(&stored_player[i], SCROLL_GO_ON);
}
-#if 1
+#if 0
if (tape.recording)
TapeRecordAction(tape_action);
#endif
#endif
#if 1
+ /* for downwards compatibility, the following code emulates a fixed bug that
+ occured when pushing elements (causing elements that just made their last
+ pushing step to already (if possible) make their first falling step in the
+ same game frame, which is bad); this code is also needed to use the famous
+ "spring push bug" which is used in older levels and might be wanted to be
+ used also in newer levels, but in this case the buggy pushing code is only
+ affecting the "spring" element and no other elements */
+
+#if 1
+ if (game.engine_version < VERSION_IDENT(2,2,0,7) || level.use_spring_bug)
+#else
if (game.engine_version < VERSION_IDENT(2,2,0,7))
+#endif
{
for (i = 0; i < MAX_PLAYERS; i++)
{
int x = player->jx;
int y = player->jy;
+#if 1
+ if (player->active && player->is_pushing && player->is_moving &&
+ IS_MOVING(x, y) &&
+ (game.engine_version < VERSION_IDENT(2,2,0,7) ||
+ Feld[x][y] == EL_SPRING))
+#else
if (player->active && player->is_pushing && player->is_moving &&
IS_MOVING(x, y))
+#endif
{
ContinueMoving(x, y);
WasJustMoving[x][y]--;
if (WasJustFalling[x][y] > 0)
WasJustFalling[x][y]--;
+ if (CheckCollision[x][y] > 0)
+ CheckCollision[x][y]--;
GfxFrame[x][y]++;
StartMoving(x, y);
#if 1
+ element = Feld[x][y];
graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
#if 0
if (element == EL_MOLE)
CheckDynamite(x, y);
#if 0
else if (element == EL_EXPLOSION && !game.explosions_delayed)
- Explode(x, y, ExplodePhase[x][y], EX_NORMAL);
+ Explode(x, y, ExplodePhase[x][y], EX_TYPE_NORMAL);
#endif
else if (element == EL_AMOEBA_GROWING)
AmoebeWaechst(x, y);
#endif
element = Feld[x][y];
+#if 1
+ if (!IS_PLAYER(x,y) &&
+ (element == EL_EMPTY ||
+ CAN_GROW_INTO(element) ||
+ element == EL_QUICKSAND_EMPTY ||
+ element == EL_ACID_SPLASH_LEFT ||
+ element == EL_ACID_SPLASH_RIGHT))
+ {
+ if ((IN_LEV_FIELD(x, y-1) && Feld[x][y-1] == EL_AMOEBA_WET) ||
+ (IN_LEV_FIELD(x-1, y) && Feld[x-1][y] == EL_AMOEBA_WET) ||
+ (IN_LEV_FIELD(x+1, y) && Feld[x+1][y] == EL_AMOEBA_WET) ||
+ (IN_LEV_FIELD(x, y+1) && Feld[x][y+1] == EL_AMOEBA_WET))
+ Feld[x][y] = EL_AMOEBA_DROP;
+ }
+#else
/* !!! extend EL_SAND to anything diggable (but maybe not SP_BASE) !!! */
if (!IS_PLAYER(x,y) &&
(element == EL_EMPTY ||
(IN_LEV_FIELD(x, y+1) && Feld[x][y+1] == EL_AMOEBA_WET))
Feld[x][y] = EL_AMOEBA_DROP;
}
+#endif
random = random * 129 + 1;
}
if (ExplodeField[x][y])
Explode(x, y, EX_PHASE_START, ExplodeField[x][y]);
else if (element == EL_EXPLOSION)
- Explode(x, y, ExplodePhase[x][y], EX_NORMAL);
+ Explode(x, y, ExplodePhase[x][y], EX_TYPE_NORMAL);
- ExplodeField[x][y] = EX_NO_EXPLOSION;
+ ExplodeField[x][y] = EX_TYPE_NONE;
}
game.explosions_delayed = TRUE;
if (TimeFrames >= FRAMES_PER_SECOND)
{
TimeFrames = 0;
- TimePlayed++;
+ TapeTime++;
for (i = 0; i < MAX_PLAYERS; i++)
{
}
}
- if (tape.recording || tape.playing)
- DrawVideoDisplay(VIDEO_STATE_TIME_ON, TimePlayed);
-
- if (TimeLeft > 0)
+ if (!level.use_step_counter)
{
- TimeLeft--;
+ TimePlayed++;
+
+ if (TimeLeft > 0)
+ {
+ TimeLeft--;
- if (TimeLeft <= 10 && setup.time_limit)
- PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE);
+ if (TimeLeft <= 10 && setup.time_limit)
+ PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE);
- DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2);
+ DrawGameValue_Time(TimeLeft);
- if (!TimeLeft && setup.time_limit)
- for (i = 0; i < MAX_PLAYERS; i++)
- KillHero(&stored_player[i]);
+ if (!TimeLeft && setup.time_limit)
+ for (i = 0; i < MAX_PLAYERS; i++)
+ KillHero(&stored_player[i]);
+ }
+ else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */
+ DrawGameValue_Time(TimePlayed);
}
- else if (level.time == 0 && !AllPlayersGone) /* level without time limit */
- DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FONT_TEXT_2);
+
+ if (tape.recording || tape.playing)
+ DrawVideoDisplay(VIDEO_STATE_TIME_ON, TapeTime);
}
DrawAllPlayers();
if (stored_player[i].MovPos != 0)
stored_player[i].StepFrame += move_frames;
+
+ if (stored_player[i].drop_delay > 0)
+ stored_player[i].drop_delay--;
}
#endif
redraw_mask |= REDRAW_FIELD;
}
+#if 0
+static boolean canEnterSupaplexPort(int x, int y, int dx, int dy)
+{
+ int nextx = x + dx, nexty = y + dy;
+ int element = Feld[x][y];
+
+ if ((dx == -1 &&
+ element != EL_SP_PORT_LEFT &&
+ element != EL_SP_GRAVITY_PORT_LEFT &&
+ element != EL_SP_PORT_HORIZONTAL &&
+ element != EL_SP_PORT_ANY) ||
+ (dx == +1 &&
+ element != EL_SP_PORT_RIGHT &&
+ element != EL_SP_GRAVITY_PORT_RIGHT &&
+ element != EL_SP_PORT_HORIZONTAL &&
+ element != EL_SP_PORT_ANY) ||
+ (dy == -1 &&
+ element != EL_SP_PORT_UP &&
+ element != EL_SP_GRAVITY_PORT_UP &&
+ element != EL_SP_PORT_VERTICAL &&
+ element != EL_SP_PORT_ANY) ||
+ (dy == +1 &&
+ element != EL_SP_PORT_DOWN &&
+ element != EL_SP_GRAVITY_PORT_DOWN &&
+ element != EL_SP_PORT_VERTICAL &&
+ element != EL_SP_PORT_ANY) ||
+ !IN_LEV_FIELD(nextx, nexty) ||
+ !IS_FREE(nextx, nexty))
+ return FALSE;
+
+ return TRUE;
+}
+#endif
+
+static boolean canFallDown(struct PlayerInfo *player)
+{
+ int jx = player->jx, jy = player->jy;
+
+ return (IN_LEV_FIELD(jx, jy + 1) &&
+ (IS_FREE(jx, jy + 1) ||
+ (Feld[jx][jy + 1] == EL_ACID && player->can_fall_into_acid)) &&
+ IS_WALKABLE_FROM(Feld[jx][jy], MV_DOWN) &&
+ !IS_WALKABLE_INSIDE(Feld[jx][jy]));
+}
+
+static boolean canPassField(int x, int y, int move_dir)
+{
+ int opposite_dir = MV_DIR_OPPOSITE(move_dir);
+ int dx = (move_dir & MV_LEFT ? -1 : move_dir & MV_RIGHT ? +1 : 0);
+ int dy = (move_dir & MV_UP ? -1 : move_dir & MV_DOWN ? +1 : 0);
+ int nextx = x + dx;
+ int nexty = y + dy;
+ int element = Feld[x][y];
+
+ return (IS_PASSABLE_FROM(element, opposite_dir) &&
+ !CAN_MOVE(element) &&
+ IN_LEV_FIELD(nextx, nexty) && !IS_PLAYER(nextx, nexty) &&
+ IS_WALKABLE_FROM(Feld[nextx][nexty], move_dir) &&
+ (level.can_pass_to_walkable || IS_FREE(nextx, nexty)));
+}
+
+static boolean canMoveToValidFieldWithGravity(int x, int y, int move_dir)
+{
+ int opposite_dir = MV_DIR_OPPOSITE(move_dir);
+ int dx = (move_dir & MV_LEFT ? -1 : move_dir & MV_RIGHT ? +1 : 0);
+ int dy = (move_dir & MV_UP ? -1 : move_dir & MV_DOWN ? +1 : 0);
+ int newx = x + dx;
+ int newy = y + dy;
+#if 0
+ int nextx = newx + dx;
+ int nexty = newy + dy;
+#endif
+
+#if 1
+ return (IN_LEV_FIELD(newx, newy) && !IS_FREE_OR_PLAYER(newx, newy) &&
+ IS_GRAVITY_REACHABLE(Feld[newx][newy]) &&
+#if 0
+ (!IS_SP_PORT(Feld[newx][newy]) || move_dir == MV_UP) &&
+#endif
+ (IS_DIGGABLE(Feld[newx][newy]) ||
+ IS_WALKABLE_FROM(Feld[newx][newy], opposite_dir) ||
+ canPassField(newx, newy, move_dir)));
+#else
+#if 1
+ return (IN_LEV_FIELD(newx, newy) && !IS_FREE_OR_PLAYER(newx, newy) &&
+ IS_GRAVITY_REACHABLE(Feld[newx][newy]) &&
+ (IS_DIGGABLE(Feld[newx][newy]) ||
+ IS_WALKABLE_FROM(Feld[newx][newy], opposite_dir) ||
+ canPassField(newx, newy, move_dir)));
+#else
+#if 1
+ return (IN_LEV_FIELD(newx, newy) && !IS_FREE_OR_PLAYER(newx, newy) &&
+ (IS_DIGGABLE_WITH_GRAVITY(Feld[newx][newy]) ||
+ IS_WALKABLE_FROM(Feld[newx][newy], opposite_dir) ||
+ canPassField(newx, newy, move_dir)));
+#else
+ return (IN_LEV_FIELD(newx, newy) && !IS_FREE_OR_PLAYER(newx, newy) &&
+ (IS_DIGGABLE(Feld[newx][newy]) ||
+ IS_WALKABLE_FROM(Feld[newx][newy], opposite_dir) ||
+ (IS_PASSABLE_FROM(Feld[newx][newy], opposite_dir) &&
+ !CAN_MOVE(Feld[newx][newy]) &&
+ IN_LEV_FIELD(nextx, nexty) && !IS_PLAYER(nextx, nexty) &&
+ IS_WALKABLE_FROM(Feld[nextx][nexty], move_dir) &&
+ (level.can_pass_to_walkable || IS_FREE(nextx, nexty)))));
+#endif
+#endif
+#endif
+}
+
static void CheckGravityMovement(struct PlayerInfo *player)
{
if (game.gravity && !player->programmed_action)
{
- int move_dir_vertical = player->action & (MV_UP | MV_DOWN);
- int move_dir_horizontal = player->action & (MV_LEFT | MV_RIGHT);
+#if 1
+ int move_dir_horizontal = player->effective_action & MV_HORIZONTAL;
+ int move_dir_vertical = player->effective_action & MV_VERTICAL;
+#else
+ int move_dir_horizontal = player->action & MV_HORIZONTAL;
+ int move_dir_vertical = player->action & MV_VERTICAL;
+#endif
+
+#if 1
+ boolean player_is_snapping = player->effective_action & JOY_BUTTON_1;
+#else
+ boolean player_is_snapping = player->action & JOY_BUTTON_1;
+#endif
+
+ int jx = player->jx, jy = player->jy;
+
+ boolean player_is_moving_to_valid_field =
+ (!player_is_snapping &&
+ (canMoveToValidFieldWithGravity(jx, jy, move_dir_horizontal) ||
+ canMoveToValidFieldWithGravity(jx, jy, move_dir_vertical)));
+
+#if 0
int move_dir =
- (player->last_move_dir & (MV_LEFT | MV_RIGHT) ?
+ (player->last_move_dir & MV_HORIZONTAL ?
(move_dir_vertical ? move_dir_vertical : move_dir_horizontal) :
(move_dir_horizontal ? move_dir_horizontal : move_dir_vertical));
- int jx = player->jx, jy = player->jy;
+#endif
+
+#if 0
+ int opposite_dir = MV_DIR_OPPOSITE(move_dir);
int dx = (move_dir & MV_LEFT ? -1 : move_dir & MV_RIGHT ? +1 : 0);
int dy = (move_dir & MV_UP ? -1 : move_dir & MV_DOWN ? +1 : 0);
int new_jx = jx + dx, new_jy = jy + dy;
+ int nextx = new_jx + dx, nexty = new_jy + dy;
+#endif
+
+#if 1
+
+#if 1
+ boolean player_can_fall_down = canFallDown(player);
+#else
+ boolean player_can_fall_down =
+ (IN_LEV_FIELD(jx, jy + 1) &&
+ (IS_FREE(jx, jy + 1) ||
+ (Feld[jx][jy + 1] == EL_ACID && player->can_fall_into_acid)));
+#endif
+
+#else
+ boolean player_can_fall_down =
+ (IN_LEV_FIELD(jx, jy + 1) &&
+ (IS_FREE(jx, jy + 1)));
+#endif
+
+#if 0
+ boolean player_is_moving_to_valid_field =
+ (
+#if 1
+ !player_is_snapping &&
+#endif
+
+#if 1
+ IN_LEV_FIELD(new_jx, new_jy) &&
+ (IS_DIGGABLE(Feld[new_jx][new_jy]) ||
+ (IS_SP_PORT(Feld[new_jx][new_jy]) &&
+ element_info[Feld[new_jx][new_jy]].access_direction & opposite_dir &&
+ IN_LEV_FIELD(nextx, nexty) &&
+ element_info[Feld[nextx][nexty]].access_direction & move_dir))
+#else
+ IN_LEV_FIELD(new_jx, new_jy) &&
+ (Feld[new_jx][new_jy] == EL_SP_BASE ||
+ Feld[new_jx][new_jy] == EL_SAND ||
+ (IS_SP_PORT(Feld[new_jx][new_jy]) &&
+ canEnterSupaplexPort(new_jx, new_jy, dx, dy)))
+ /* !!! extend EL_SAND to anything diggable !!! */
+#endif
+ );
+#endif
+
+#if 0
+ boolean player_is_standing_on_valid_field =
+ (IS_WALKABLE_INSIDE(Feld[jx][jy]) ||
+ (IS_WALKABLE(Feld[jx][jy]) && !ACCESS_FROM(Feld[jx][jy], MV_DOWN)));
+#endif
+
+#if 0
+ printf("::: checking gravity NOW [%d, %d, %d] [%d] [%d / %d] ...\n",
+ player_can_fall_down,
+ player_is_standing_on_valid_field,
+ player_is_moving_to_valid_field,
+ (player_is_moving_to_valid_field ? Feld[new_jx][new_jy] : -1),
+ player->effective_action,
+ player->can_fall_into_acid);
+#endif
+
+ if (player_can_fall_down &&
+#if 0
+ !player_is_standing_on_valid_field &&
+#endif
+ !player_is_moving_to_valid_field)
+ {
+#if 0
+ printf("::: setting programmed_action to MV_DOWN [%d,%d - %d] ...\n",
+ jx, jy, FrameCounter);
+#endif
+
+ player->programmed_action = MV_DOWN;
+ }
+ }
+}
+
+static void CheckGravityMovementWhenNotMoving(struct PlayerInfo *player)
+{
+#if 1
+ return CheckGravityMovement(player);
+#endif
+
+ if (game.gravity && !player->programmed_action)
+ {
+ int jx = player->jx, jy = player->jy;
boolean field_under_player_is_free =
(IN_LEV_FIELD(jx, jy + 1) && IS_FREE(jx, jy + 1));
- boolean player_is_moving_to_valid_field =
- (IN_LEV_FIELD(new_jx, new_jy) &&
- (Feld[new_jx][new_jy] == EL_SP_BASE ||
- Feld[new_jx][new_jy] == EL_SAND));
- /* !!! extend EL_SAND to anything diggable !!! */
+ boolean player_is_standing_on_valid_field =
+ (IS_WALKABLE_INSIDE(Feld[jx][jy]) ||
+ (IS_WALKABLE(Feld[jx][jy]) &&
+ !(element_info[Feld[jx][jy]].access_direction & MV_DOWN)));
- if (field_under_player_is_free &&
- !player_is_moving_to_valid_field &&
- !IS_WALKABLE_INSIDE(Feld[jx][jy]))
+ if (field_under_player_is_free && !player_is_standing_on_valid_field)
player->programmed_action = MV_DOWN;
}
}
int dx, int dy, int real_dx, int real_dy)
{
#if 0
- static int change_sides[4][2] =
+ static int trigger_sides[4][2] =
{
/* enter side leave side */
{ CH_SIDE_RIGHT, CH_SIDE_LEFT }, /* moving left */
dx == +1 ? MV_RIGHT :
dy == -1 ? MV_UP :
dy == +1 ? MV_DOWN : MV_NO_MOVING);
- int enter_side = change_sides[MV_DIR_BIT(move_direction)][0];
- int leave_side = change_sides[MV_DIR_BIT(move_direction)][1];
+ int enter_side = trigger_sides[MV_DIR_BIT(move_direction)][0];
+ int leave_side = trigger_sides[MV_DIR_BIT(move_direction)][1];
#endif
int jx = player->jx, jy = player->jy;
int new_jx = jx + dx, new_jy = jy + dy;
{
if (element == EL_ACID && dx == 0 && dy == 1)
{
- SplashAcid(jx, jy);
+ SplashAcid(new_jx, new_jy);
Feld[jx][jy] = EL_PLAYER_1;
InitMovingField(jx, jy, MV_DOWN);
Store[jx][jy] = EL_ACID;
return MF_MOVING;
}
- can_move = DigField(player, new_jx, new_jy, real_dx, real_dy, DF_DIG);
+ can_move = DigField(player, jx, jy, new_jx, new_jy, real_dx,real_dy, DF_DIG);
if (can_move != MF_MOVING)
return can_move;
player->step_counter++;
+#if 0
+ player->drop_delay = 0;
+#endif
+
PlayerVisit[jx][jy] = FrameCounter;
ScrollPlayer(player, SCROLL_INIT);
#if 0
if (IS_CUSTOM_ELEMENT(Feld[jx][jy]))
{
- CheckTriggeredElementSideChange(jx, jy, Feld[jx][jy], leave_side,
- CE_OTHER_GETS_LEFT);
- CheckElementSideChange(jx, jy, Feld[jx][jy], leave_side,
- CE_LEFT_BY_PLAYER, -1);
+ CheckTriggeredElementChangeBySide(jx, jy, Feld[jx][jy], CE_OTHER_GETS_LEFT,
+ leave_side);
+ CheckElementChangeBySide(jx,jy, Feld[jx][jy],CE_LEFT_BY_PLAYER,leave_side);
}
if (IS_CUSTOM_ELEMENT(Feld[new_jx][new_jy]))
{
- CheckTriggeredElementSideChange(new_jx, new_jy, Feld[new_jx][new_jy],
- enter_side, CE_OTHER_GETS_ENTERED);
- CheckElementSideChange(new_jx, new_jy, Feld[new_jx][new_jy], enter_side,
- CE_ENTERED_BY_PLAYER, -1);
+ CheckTriggeredElementChangeBySide(new_jx, new_jy, Feld[new_jx][new_jy],
+ CE_OTHER_GETS_ENTERED, enter_side);
+ CheckElementChangeBySide(new_jx, new_jy, Feld[new_jx][new_jy],
+ CE_ENTERED_BY_PLAYER, enter_side);
}
#endif
int old_jx = jx, old_jy = jy;
int moved = MF_NO_ACTION;
+#if 1
+ if (!player->active)
+ return FALSE;
+
+ if (!dx && !dy)
+ {
+ if (player->MovPos == 0)
+ {
+ player->is_moving = FALSE;
+ player->is_digging = FALSE;
+ player->is_collecting = FALSE;
+ player->is_snapping = FALSE;
+ player->is_pushing = FALSE;
+ }
+
+ return FALSE;
+ }
+#else
if (!player->active || (!dx && !dy))
return FALSE;
+#endif
#if 0
if (!FrameReached(&player->move_delay, player->move_delay_value) &&
!tape.playing)
return FALSE;
#else
+
+#if 1
+ if (!FrameReached(&player->move_delay, player->move_delay_value))
+ return FALSE;
+#else
if (!FrameReached(&player->move_delay, player->move_delay_value) &&
!(tape.playing && tape.file_version < FILE_VERSION_2_0))
return FALSE;
#endif
+#endif
+
+ /* store if player is automatically moved to next field */
+ player->is_auto_moving = (player->programmed_action != MV_NO_MOVING);
+
/* remove the last programmed player action */
player->programmed_action = 0;
player->move_delay_value = original_move_delay_value;
}
- if (player->last_move_dir & (MV_LEFT | MV_RIGHT))
+ if (player->last_move_dir & MV_HORIZONTAL)
{
if (!(moved |= MovePlayerOneStep(player, 0, dy, dx, dy)))
moved |= MovePlayerOneStep(player, dx, 0, dx, dy);
{
if (jx != old_jx) /* player has moved horizontally */
{
- if ((player->MovDir == MV_LEFT && scroll_x > jx - MIDPOSX + offset) ||
+ if ((player->MovDir == MV_LEFT && scroll_x > jx - MIDPOSX + offset) ||
(player->MovDir == MV_RIGHT && scroll_x < jx - MIDPOSX - offset))
scroll_x = jx-MIDPOSX + (scroll_x < jx-MIDPOSX ? -offset : +offset);
scroll_x = old_scroll_x + SIGN(scroll_x - old_scroll_x);
/* don't scroll against the player's moving direction */
- if ((player->MovDir == MV_LEFT && scroll_x > old_scroll_x) ||
+ if ((player->MovDir == MV_LEFT && scroll_x > old_scroll_x) ||
(player->MovDir == MV_RIGHT && scroll_x < old_scroll_x))
scroll_x = old_scroll_x;
}
else /* player has moved vertically */
{
- if ((player->MovDir == MV_UP && scroll_y > jy - MIDPOSY + offset) ||
+ if ((player->MovDir == MV_UP && scroll_y > jy - MIDPOSY + offset) ||
(player->MovDir == MV_DOWN && scroll_y < jy - MIDPOSY - offset))
scroll_y = jy-MIDPOSY + (scroll_y < jy-MIDPOSY ? -offset : +offset);
scroll_y = old_scroll_y + SIGN(scroll_y - old_scroll_y);
/* don't scroll against the player's moving direction */
- if ((player->MovDir == MV_UP && scroll_y > old_scroll_y) ||
+ if ((player->MovDir == MV_UP && scroll_y > old_scroll_y) ||
(player->MovDir == MV_DOWN && scroll_y < old_scroll_y))
scroll_y = old_scroll_y;
}
player->is_switching = FALSE;
#endif
+ player->is_dropping = FALSE;
+
+
+#if 0
+ /* !!! ENABLE THIS FOR OLD VERSIONS !!! */
#if 1
+ if (game.engine_version < VERSION_IDENT(3,1,0,0))
+#endif
{
- static int change_sides[4][2] =
+ int move_direction = player->MovDir;
+#if 1
+ int enter_side = MV_DIR_OPPOSITE(move_direction);
+ int leave_side = move_direction;
+#else
+ static int trigger_sides[4][2] =
{
/* enter side leave side */
{ CH_SIDE_RIGHT, CH_SIDE_LEFT }, /* moving left */
{ CH_SIDE_BOTTOM, CH_SIDE_TOP }, /* moving up */
{ CH_SIDE_TOP, CH_SIDE_BOTTOM } /* moving down */
};
- int move_direction = player->MovDir;
- int enter_side = change_sides[MV_DIR_BIT(move_direction)][0];
- int leave_side = change_sides[MV_DIR_BIT(move_direction)][1];
+ int enter_side = trigger_sides[MV_DIR_BIT(move_direction)][0];
+ int leave_side = trigger_sides[MV_DIR_BIT(move_direction)][1];
+#endif
+ int old_element = Feld[old_jx][old_jy];
+ int new_element = Feld[jx][jy];
#if 1
- if (IS_CUSTOM_ELEMENT(Feld[old_jx][old_jy]))
- {
- CheckTriggeredElementSideChange(old_jx, old_jy, Feld[old_jx][old_jy],
- leave_side, CE_OTHER_GETS_LEFT);
- CheckElementSideChange(old_jx, old_jy, Feld[old_jx][old_jy],
- leave_side, CE_LEFT_BY_PLAYER, -1);
- }
+ /* !!! TEST ONLY !!! */
+ if (IS_CUSTOM_ELEMENT(old_element))
+ CheckElementChangeByPlayer(old_jx, old_jy, old_element,
+ CE_LEFT_BY_PLAYER,
+ player->index_bit, leave_side);
- if (IS_CUSTOM_ELEMENT(Feld[jx][jy]))
- {
- CheckTriggeredElementSideChange(jx, jy, Feld[jx][jy],
- enter_side, CE_OTHER_GETS_ENTERED);
- CheckElementSideChange(jx, jy, Feld[jx][jy],
- enter_side, CE_ENTERED_BY_PLAYER, -1);
- }
+ CheckTriggeredElementChangeByPlayer(old_jx, old_jy, old_element,
+ CE_OTHER_GETS_LEFT,
+ player->index_bit, leave_side);
+
+ if (IS_CUSTOM_ELEMENT(new_element))
+ CheckElementChangeByPlayer(jx, jy, new_element, CE_ENTERED_BY_PLAYER,
+ player->index_bit, enter_side);
+
+ CheckTriggeredElementChangeByPlayer(jx, jy, new_element,
+ CE_OTHER_GETS_ENTERED,
+ player->index_bit, enter_side);
#endif
}
}
else
{
- CheckGravityMovement(player);
+ CheckGravityMovementWhenNotMoving(player);
/*
player->last_move_dir = MV_NO_MOVING;
#if 0
DrawPlayer(player);
#endif
+
return;
}
else if (!FrameReached(&player->actual_frame_counter, 1))
player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize;
player->GfxPos = move_stepsize * (player->MovPos / move_stepsize);
- if (Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING)
+ if (!player->block_last_field &&
+ Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING)
Feld[last_jx][last_jy] = EL_EMPTY;
/* before DrawPlayer() to draw correct player graphic for this case */
if (player->MovPos == 0) /* player reached destination field */
{
+#if 1
+ if (player->move_delay_reset_counter > 0)
+ {
+ player->move_delay_reset_counter--;
+
+ if (player->move_delay_reset_counter == 0)
+ {
+ /* continue with normal speed after quickly moving through gate */
+ HALVE_PLAYER_SPEED(player);
+
+ /* be able to make the next move without delay */
+ player->move_delay = 0;
+ }
+ }
+#else
if (IS_PASSABLE(Feld[last_jx][last_jy]))
{
/* continue with normal speed after quickly moving through gate */
/* be able to make the next move without delay */
player->move_delay = 0;
}
+#endif
+
+ if (player->block_last_field &&
+ Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING)
+ Feld[last_jx][last_jy] = EL_EMPTY;
player->last_jx = jx;
player->last_jy = jy;
player->LevelSolved = player->GameOver = TRUE;
}
+#if 1
+ /* !!! ENABLE THIS FOR NEW VERSIONS !!! */
+ /* this breaks one level: "machine", level 000 */
+#if 0
+ if (game.engine_version >= VERSION_IDENT(3,1,0,0))
+#endif
+ {
+ int move_direction = player->MovDir;
+#if 1
+ int enter_side = MV_DIR_OPPOSITE(move_direction);
+ int leave_side = move_direction;
+#else
+ static int trigger_sides[4][2] =
+ {
+ /* enter side leave side */
+ { CH_SIDE_RIGHT, CH_SIDE_LEFT }, /* moving left */
+ { CH_SIDE_LEFT, CH_SIDE_RIGHT }, /* moving right */
+ { CH_SIDE_BOTTOM, CH_SIDE_TOP }, /* moving up */
+ { CH_SIDE_TOP, CH_SIDE_BOTTOM } /* moving down */
+ };
+ int enter_side = trigger_sides[MV_DIR_BIT(move_direction)][0];
+ int leave_side = trigger_sides[MV_DIR_BIT(move_direction)][1];
+#endif
+ int old_jx = last_jx;
+ int old_jy = last_jy;
+ int old_element = Feld[old_jx][old_jy];
+ int new_element = Feld[jx][jy];
+
+#if 1
+ /* !!! TEST ONLY !!! */
+ if (IS_CUSTOM_ELEMENT(old_element))
+ CheckElementChangeByPlayer(old_jx, old_jy, old_element,
+ CE_LEFT_BY_PLAYER,
+ player->index_bit, leave_side);
+
+ CheckTriggeredElementChangeByPlayer(old_jx, old_jy, old_element,
+ CE_OTHER_GETS_LEFT,
+ player->index_bit, leave_side);
+
+ if (IS_CUSTOM_ELEMENT(new_element))
+ CheckElementChangeByPlayer(jx, jy, new_element, CE_ENTERED_BY_PLAYER,
+ player->index_bit, enter_side);
+
+ CheckTriggeredElementChangeByPlayer(jx, jy, new_element,
+ CE_OTHER_GETS_ENTERED,
+ player->index_bit, enter_side);
+#endif
+
+ }
+#endif
+
if (game.engine_version >= VERSION_IDENT(3,0,7,0))
{
TestIfHeroTouchesBadThing(jx, jy);
TestIfPlayerTouchesCustomElement(jx, jy);
#if 1
- TestIfElementTouchesCustomElement(jx, jy); /* for empty space */
+#if 1
+ /* needed because pushed element has not yet reached its destination,
+ so it would trigger a change event at its previous field location */
+ if (!player->is_pushing)
+#endif
+ TestIfElementTouchesCustomElement(jx, jy); /* for empty space */
#endif
if (!player->active)
RemoveHero(player);
}
+ if (level.use_step_counter)
+ {
+ int i;
+
+ TimePlayed++;
+
+ if (TimeLeft > 0)
+ {
+ TimeLeft--;
+
+ if (TimeLeft <= 10 && setup.time_limit)
+ PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE);
+
+ DrawGameValue_Time(TimeLeft);
+
+ if (!TimeLeft && setup.time_limit)
+ for (i = 0; i < MAX_PLAYERS; i++)
+ KillHero(&stored_player[i]);
+ }
+ else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */
+ DrawGameValue_Time(TimePlayed);
+ }
+
if (tape.single_step && tape.recording && !tape.pausing &&
!player->programmed_action)
TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
{ +1, 0 },
{ 0, +1 }
};
- static int change_sides[4][2] =
+ static int trigger_sides[4][2] =
{
/* center side border side */
{ CH_SIDE_TOP, CH_SIDE_BOTTOM }, /* check top */
int center_element = Feld[x][y]; /* should always be non-moving! */
int i;
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
int xx = x + xy[i][0];
int yy = y + xy[i][1];
- int center_side = change_sides[i][0];
- int border_side = change_sides[i][1];
+ int center_side = trigger_sides[i][0];
+ int border_side = trigger_sides[i][1];
int border_element;
if (!IN_LEV_FIELD(xx, yy))
if (IS_PLAYER(x, y))
{
+ struct PlayerInfo *player = PLAYERINFO(x, y);
+
if (game.engine_version < VERSION_IDENT(3,0,7,0))
border_element = Feld[xx][yy]; /* may be moving! */
else if (!IS_MOVING(xx, yy) && !IS_BLOCKED(xx, yy))
else
continue; /* center and border element do not touch */
- CheckTriggeredElementSideChange(xx, yy, border_element, border_side,
- CE_OTHER_GETS_TOUCHED);
- CheckElementSideChange(xx, yy, border_element, border_side,
- CE_TOUCHED_BY_PLAYER, -1);
+#if 1
+ /* !!! TEST ONLY !!! */
+ CheckElementChangeByPlayer(xx, yy, border_element, CE_TOUCHED_BY_PLAYER,
+ player->index_bit, border_side);
+ CheckTriggeredElementChangeByPlayer(xx, yy, border_element,
+ CE_OTHER_GETS_TOUCHED,
+ player->index_bit, border_side);
+#else
+ CheckTriggeredElementChangeByPlayer(xx, yy, border_element,
+ CE_OTHER_GETS_TOUCHED,
+ player->index_bit, border_side);
+ CheckElementChangeByPlayer(xx, yy, border_element, CE_TOUCHED_BY_PLAYER,
+ player->index_bit, border_side);
+#endif
}
else if (IS_PLAYER(xx, yy))
{
+ struct PlayerInfo *player = PLAYERINFO(xx, yy);
+
if (game.engine_version >= VERSION_IDENT(3,0,7,0))
{
- struct PlayerInfo *player = PLAYERINFO(xx, yy);
-
if (player->MovPos != 0 && !(player->MovDir & touch_dir[i]))
continue; /* center and border element do not touch */
}
- CheckTriggeredElementSideChange(x, y, center_element, center_side,
- CE_OTHER_GETS_TOUCHED);
- CheckElementSideChange(x, y, center_element, center_side,
- CE_TOUCHED_BY_PLAYER, -1);
+#if 1
+ /* !!! TEST ONLY !!! */
+ CheckElementChangeByPlayer(x, y, center_element, CE_TOUCHED_BY_PLAYER,
+ player->index_bit, center_side);
+ CheckTriggeredElementChangeByPlayer(x, y, center_element,
+ CE_OTHER_GETS_TOUCHED,
+ player->index_bit, center_side);
+#else
+ CheckTriggeredElementChangeByPlayer(x, y, center_element,
+ CE_OTHER_GETS_TOUCHED,
+ player->index_bit, center_side);
+ CheckElementChangeByPlayer(x, y, center_element, CE_TOUCHED_BY_PLAYER,
+ player->index_bit, center_side);
+#endif
break;
}
{ +1, 0 },
{ 0, +1 }
};
- static int change_sides[4][2] =
+ static int trigger_sides[4][2] =
{
/* center side border side */
{ CH_SIDE_TOP, CH_SIDE_BOTTOM }, /* check top */
boolean change_center_element = FALSE;
int center_element_change_page = 0;
int center_element = Feld[x][y]; /* should always be non-moving! */
+ int border_trigger_element = EL_UNDEFINED;
int i, j;
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
int xx = x + xy[i][0];
int yy = y + xy[i][1];
- int center_side = change_sides[i][0];
- int border_side = change_sides[i][1];
+ int center_side = trigger_sides[i][0];
+ int border_side = trigger_sides[i][1];
int border_element;
if (!IN_LEV_FIELD(xx, yy))
if (change->can_change &&
change->events & CH_EVENT_BIT(CE_OTHER_IS_TOUCHING) &&
- change->sides & border_side &&
- change->trigger_element == border_element)
+ change->trigger_side & border_side &&
+#if 1
+ IS_EQUAL_OR_IN_GROUP(border_element, change->trigger_element)
+#else
+ change->trigger_element == border_element
+#endif
+ )
{
change_center_element = TRUE;
center_element_change_page = j;
+ border_trigger_element = border_element;
break;
}
if (change->can_change &&
change->events & CH_EVENT_BIT(CE_OTHER_IS_TOUCHING) &&
- change->sides & center_side &&
- change->trigger_element == center_element)
+ change->trigger_side & center_side &&
+#if 1
+ IS_EQUAL_OR_IN_GROUP(center_element, change->trigger_element)
+#else
+ change->trigger_element == center_element
+#endif
+ )
{
- CheckElementSideChange(xx, yy, border_element, CH_SIDE_ANY,
- CE_OTHER_IS_TOUCHING, j);
+#if 0
+ printf("::: border_element %d, %d\n", x, y);
+#endif
+
+ CheckElementChangeByPage(xx, yy, border_element, center_element,
+ CE_OTHER_IS_TOUCHING, j);
break;
}
}
}
if (change_center_element)
- CheckElementSideChange(x, y, center_element, CH_SIDE_ANY,
- CE_OTHER_IS_TOUCHING, center_element_change_page);
+ {
+#if 0
+ printf("::: center_element %d, %d\n", x, y);
+#endif
+
+ CheckElementChangeByPage(x, y, center_element, border_trigger_element,
+ CE_OTHER_IS_TOUCHING, center_element_change_page);
+ }
+}
+
+void TestIfElementHitsCustomElement(int x, int y, int direction)
+{
+ int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
+ int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
+ int hitx = x + dx, hity = y + dy;
+ int hitting_element = Feld[x][y];
+ int touched_element;
+#if 0
+ boolean object_hit = (IN_LEV_FIELD(hitx, hity) &&
+ !IS_FREE(hitx, hity) &&
+ (!IS_MOVING(hitx, hity) ||
+ MovDir[hitx][hity] != direction ||
+ ABS(MovPos[hitx][hity]) <= TILEY / 2));
+#endif
+
+ if (IN_LEV_FIELD(hitx, hity) && IS_FREE(hitx, hity))
+ return;
+
+#if 0
+ if (IN_LEV_FIELD(hitx, hity) && !object_hit)
+ return;
+#endif
+
+ touched_element = (IN_LEV_FIELD(hitx, hity) ?
+ MovingOrBlocked2Element(hitx, hity) : EL_STEELWALL);
+
+ CheckElementChangeBySide(x, y, hitting_element, touched_element,
+ CE_HITTING_SOMETHING, direction);
+
+ if (IN_LEV_FIELD(hitx, hity))
+ {
+ int opposite_direction = MV_DIR_OPPOSITE(direction);
+ int hitting_side = direction;
+ int touched_side = opposite_direction;
+#if 0
+ int touched_element = MovingOrBlocked2Element(hitx, hity);
+#endif
+#if 1
+ boolean object_hit = (!IS_MOVING(hitx, hity) ||
+ MovDir[hitx][hity] != direction ||
+ ABS(MovPos[hitx][hity]) <= TILEY / 2);
+
+ object_hit = TRUE;
+#endif
+
+ if (object_hit)
+ {
+ int i;
+
+ CheckElementChangeBySide(hitx, hity, touched_element, hitting_element,
+ CE_HIT_BY_SOMETHING, opposite_direction);
+
+ if (IS_CUSTOM_ELEMENT(hitting_element) &&
+ HAS_ANY_CHANGE_EVENT(hitting_element, CE_OTHER_IS_HITTING))
+ {
+ for (i = 0; i < element_info[hitting_element].num_change_pages; i++)
+ {
+ struct ElementChangeInfo *change =
+ &element_info[hitting_element].change_page[i];
+
+ if (change->can_change &&
+ change->events & CH_EVENT_BIT(CE_OTHER_IS_HITTING) &&
+ change->trigger_side & touched_side &&
+
+#if 1
+ IS_EQUAL_OR_IN_GROUP(touched_element, change->trigger_element)
+#else
+ change->trigger_element == touched_element
+#endif
+ )
+ {
+ CheckElementChangeByPage(x, y, hitting_element, touched_element,
+ CE_OTHER_IS_HITTING, i);
+ break;
+ }
+ }
+ }
+
+ if (IS_CUSTOM_ELEMENT(touched_element) &&
+ HAS_ANY_CHANGE_EVENT(touched_element, CE_OTHER_GETS_HIT))
+ {
+ for (i = 0; i < element_info[touched_element].num_change_pages; i++)
+ {
+ struct ElementChangeInfo *change =
+ &element_info[touched_element].change_page[i];
+
+ if (change->can_change &&
+ change->events & CH_EVENT_BIT(CE_OTHER_GETS_HIT) &&
+ change->trigger_side & hitting_side &&
+#if 1
+ IS_EQUAL_OR_IN_GROUP(hitting_element, change->trigger_element)
+#else
+ change->trigger_element == hitting_element
+#endif
+ )
+ {
+ CheckElementChangeByPage(hitx, hity, touched_element,
+ hitting_element, CE_OTHER_GETS_HIT, i);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+#if 0
+void TestIfElementSmashesCustomElement(int x, int y, int direction)
+{
+ int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
+ int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
+ int hitx = x + dx, hity = y + dy;
+ int hitting_element = Feld[x][y];
+ int touched_element;
+#if 0
+ boolean object_hit = (IN_LEV_FIELD(hitx, hity) &&
+ !IS_FREE(hitx, hity) &&
+ (!IS_MOVING(hitx, hity) ||
+ MovDir[hitx][hity] != direction ||
+ ABS(MovPos[hitx][hity]) <= TILEY / 2));
+#endif
+
+ if (IN_LEV_FIELD(hitx, hity) && IS_FREE(hitx, hity))
+ return;
+
+#if 0
+ if (IN_LEV_FIELD(hitx, hity) && !object_hit)
+ return;
+#endif
+
+ touched_element = (IN_LEV_FIELD(hitx, hity) ?
+ MovingOrBlocked2Element(hitx, hity) : EL_STEELWALL);
+
+ CheckElementChangeBySide(x, y, hitting_element, touched_element,
+ EP_CAN_SMASH_EVERYTHING, direction);
+
+ if (IN_LEV_FIELD(hitx, hity))
+ {
+ int opposite_direction = MV_DIR_OPPOSITE(direction);
+ int hitting_side = direction;
+ int touched_side = opposite_direction;
+#if 0
+ int touched_element = MovingOrBlocked2Element(hitx, hity);
+#endif
+#if 1
+ boolean object_hit = (!IS_MOVING(hitx, hity) ||
+ MovDir[hitx][hity] != direction ||
+ ABS(MovPos[hitx][hity]) <= TILEY / 2);
+
+ object_hit = TRUE;
+#endif
+
+ if (object_hit)
+ {
+ int i;
+
+ CheckElementChangeBySide(hitx, hity, touched_element, hitting_element,
+ CE_SMASHED_BY_SOMETHING, opposite_direction);
+
+ if (IS_CUSTOM_ELEMENT(hitting_element) &&
+ HAS_ANY_CHANGE_EVENT(hitting_element, CE_OTHER_IS_SMASHING))
+ {
+ for (i = 0; i < element_info[hitting_element].num_change_pages; i++)
+ {
+ struct ElementChangeInfo *change =
+ &element_info[hitting_element].change_page[i];
+
+ if (change->can_change &&
+ change->events & CH_EVENT_BIT(CE_OTHER_IS_SMASHING) &&
+ change->trigger_side & touched_side &&
+
+#if 1
+ IS_EQUAL_OR_IN_GROUP(touched_element, change->trigger_element)
+#else
+ change->trigger_element == touched_element
+#endif
+ )
+ {
+ CheckElementChangeByPage(x, y, hitting_element, touched_element,
+ CE_OTHER_IS_SMASHING, i);
+ break;
+ }
+ }
+ }
+
+ if (IS_CUSTOM_ELEMENT(touched_element) &&
+ HAS_ANY_CHANGE_EVENT(touched_element, CE_OTHER_GETS_SMASHED))
+ {
+ for (i = 0; i < element_info[touched_element].num_change_pages; i++)
+ {
+ struct ElementChangeInfo *change =
+ &element_info[touched_element].change_page[i];
+
+ if (change->can_change &&
+ change->events & CH_EVENT_BIT(CE_OTHER_GETS_SMASHED) &&
+ change->trigger_side & hitting_side &&
+#if 1
+ IS_EQUAL_OR_IN_GROUP(hitting_element, change->trigger_element)
+#else
+ change->trigger_element == hitting_element
+#endif
+ )
+ {
+ CheckElementChangeByPage(hitx, hity, touched_element,
+ hitting_element, CE_OTHER_GETS_SMASHED,i);
+ break;
+ }
+ }
+ }
+ }
+ }
}
+#endif
void TestIfGoodThingHitsBadThing(int good_x, int good_y, int good_move_dir)
{
int i, kill_x = -1, kill_y = -1;
+ int bad_element = -1;
static int test_xy[4][2] =
{
{ 0, -1 },
MV_DOWN
};
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
int test_x, test_y, test_move_dir, test_element;
test_x = good_x + test_xy[i][0];
test_y = good_y + test_xy[i][1];
+
if (!IN_LEV_FIELD(test_x, test_y))
continue;
{
kill_x = test_x;
kill_y = test_y;
+ bad_element = test_element;
+
break;
}
}
{
struct PlayerInfo *player = PLAYERINFO(good_x, good_y);
+#if 1
+ if (player->shield_deadly_time_left > 0 &&
+ !IS_INDESTRUCTIBLE(bad_element))
+ Bang(kill_x, kill_y);
+ else if (!PLAYER_ENEMY_PROTECTED(good_x, good_y))
+ KillHero(player);
+#else
if (player->shield_deadly_time_left > 0)
Bang(kill_x, kill_y);
- else if (!PLAYER_PROTECTED(good_x, good_y))
+ else if (!PLAYER_ENEMY_PROTECTED(good_x, good_y))
KillHero(player);
+#endif
}
else
Bang(good_x, good_y);
if (bad_element == EL_EXPLOSION) /* skip just exploding bad things */
return;
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
int test_x, test_y, test_move_dir, test_element;
{
struct PlayerInfo *player = PLAYERINFO(kill_x, kill_y);
+#if 1
+ if (player->shield_deadly_time_left > 0 &&
+ !IS_INDESTRUCTIBLE(bad_element))
+ Bang(bad_x, bad_y);
+ else if (!PLAYER_ENEMY_PROTECTED(kill_x, kill_y))
+ KillHero(player);
+#else
if (player->shield_deadly_time_left > 0)
Bang(bad_x, bad_y);
- else if (!PLAYER_PROTECTED(kill_x, kill_y))
+ else if (!PLAYER_ENEMY_PROTECTED(kill_x, kill_y))
KillHero(player);
+#endif
}
else
Bang(kill_x, kill_y);
{ 0, +1 }
};
- for (i = 0; i < 4; i++)
+ for (i = 0; i < NUM_DIRECTIONS; i++)
{
int x, y, element;
BuryHero(player);
}
-static void KillHeroUnlessProtected(int x, int y)
+static void KillHeroUnlessEnemyProtected(int x, int y)
{
- if (!PLAYER_PROTECTED(x, y))
+ if (!PLAYER_ENEMY_PROTECTED(x, y))
+ KillHero(PLAYERINFO(x, y));
+}
+
+static void KillHeroUnlessExplosionProtected(int x, int y)
+{
+ if (!PLAYER_EXPLOSION_PROTECTED(x, y))
KillHero(PLAYERINFO(x, y));
}
*/
int DigField(struct PlayerInfo *player,
- int x, int y, int real_dx, int real_dy, int mode)
+ int oldx, int oldy, int x, int y,
+ int real_dx, int real_dy, int mode)
{
- static int change_sides[4] =
- {
- CH_SIDE_RIGHT, /* moving left */
- CH_SIDE_LEFT, /* moving right */
- CH_SIDE_BOTTOM, /* moving up */
- CH_SIDE_TOP, /* moving down */
- };
+#if 0
boolean use_spring_bug = (game.engine_version < VERSION_IDENT(2,2,0,0));
- int jx = player->jx, jy = player->jy;
+#endif
+ boolean is_player = (IS_PLAYER(oldx, oldy) || mode != DF_DIG);
+ boolean player_was_pushing = player->is_pushing;
+ int jx = oldx, jy = oldy;
int dx = x - jx, dy = y - jy;
int nextx = x + dx, nexty = y + dy;
int move_direction = (dx == -1 ? MV_LEFT :
dx == +1 ? MV_RIGHT :
dy == -1 ? MV_UP :
dy == +1 ? MV_DOWN : MV_NO_MOVING);
- int dig_side = change_sides[MV_DIR_BIT(move_direction)];
+ int opposite_direction = MV_DIR_OPPOSITE(move_direction);
+#if 1
+ int dig_side = MV_DIR_OPPOSITE(move_direction);
+#else
+ static int trigger_sides[4] =
+ {
+ CH_SIDE_RIGHT, /* moving left */
+ CH_SIDE_LEFT, /* moving right */
+ CH_SIDE_BOTTOM, /* moving up */
+ CH_SIDE_TOP, /* moving down */
+ };
+ int dig_side = trigger_sides[MV_DIR_BIT(move_direction)];
+#endif
+ int old_element = Feld[jx][jy];
int element;
- if (player->MovPos == 0)
+ if (is_player) /* function can also be called by EL_PENGUIN */
{
- player->is_digging = FALSE;
- player->is_collecting = FALSE;
- }
+ if (player->MovPos == 0)
+ {
+ player->is_digging = FALSE;
+ player->is_collecting = FALSE;
+ }
- if (player->MovPos == 0) /* last pushing move finished */
- player->is_pushing = FALSE;
+ if (player->MovPos == 0) /* last pushing move finished */
+ player->is_pushing = FALSE;
- if (mode == DF_NO_PUSH) /* player just stopped pushing */
- {
- player->is_switching = FALSE;
- player->push_delay = 0;
+ if (mode == DF_NO_PUSH) /* player just stopped pushing */
+ {
+ player->is_switching = FALSE;
+ player->push_delay = 0;
- return MF_NO_ACTION;
+ return MF_NO_ACTION;
+ }
}
if (IS_MOVING(x, y) || IS_PLAYER(x, y))
return MF_NO_ACTION;
+#if 0
+
#if 0
if (IS_TUBE(Feld[jx][jy]) || IS_TUBE(Back[jx][jy]))
#else
return MF_NO_ACTION; /* tube has no opening in this direction */
}
+#else
+
+ if (IS_TUBE(Back[jx][jy]) && game.engine_version >= VERSION_IDENT(2,2,0,0))
+ old_element = Back[jx][jy];
+
+#endif
+
+ if (IS_WALKABLE(old_element) && !ACCESS_FROM(old_element, move_direction))
+ return MF_NO_ACTION; /* field has no opening in this direction */
+
+ if (IS_PASSABLE(old_element) && !ACCESS_FROM(old_element,opposite_direction))
+ return MF_NO_ACTION; /* field has no opening in this direction */
+
element = Feld[x][y];
+ if (!is_player && !IS_COLLECTIBLE(element)) /* penguin cannot collect it */
+ return MF_NO_ACTION;
+
if (mode == DF_SNAP && !IS_SNAPPABLE(element) &&
game.engine_version >= VERSION_IDENT(2,2,0,0))
return MF_NO_ACTION;
+#if 1
+ if (game.gravity && is_player && !player->is_auto_moving &&
+ canFallDown(player) && move_direction != MV_DOWN &&
+ !canMoveToValidFieldWithGravity(jx, jy, move_direction))
+ return MF_NO_ACTION; /* player cannot walk here due to gravity */
+#endif
+
+#if 0
+ if (element == EL_EMPTY_SPACE &&
+ game.gravity && !player->is_auto_moving &&
+ canFallDown(player) && move_direction != MV_DOWN)
+ return MF_NO_ACTION; /* player cannot walk here due to gravity */
+#endif
+
switch (element)
{
+#if 0
case EL_SP_PORT_LEFT:
case EL_SP_PORT_RIGHT:
case EL_SP_PORT_UP:
case EL_SP_GRAVITY_PORT_RIGHT:
case EL_SP_GRAVITY_PORT_UP:
case EL_SP_GRAVITY_PORT_DOWN:
+#if 1
+ if (!canEnterSupaplexPort(x, y, dx, dy))
+ return MF_NO_ACTION;
+#else
if ((dx == -1 &&
element != EL_SP_PORT_LEFT &&
element != EL_SP_GRAVITY_PORT_LEFT &&
!IN_LEV_FIELD(nextx, nexty) ||
!IS_FREE(nextx, nexty))
return MF_NO_ACTION;
+#endif
if (element == EL_SP_GRAVITY_PORT_LEFT ||
element == EL_SP_GRAVITY_PORT_RIGHT ||
/* automatically move to the next field with double speed */
player->programmed_action = move_direction;
+#if 1
+ if (player->move_delay_reset_counter == 0)
+ {
+ player->move_delay_reset_counter = 2; /* two double speed steps */
+
+ DOUBLE_PLAYER_SPEED(player);
+ }
+#else
+ player->move_delay_reset_counter = 2;
+
DOUBLE_PLAYER_SPEED(player);
+#endif
+
+#if 0
+ printf("::: passing port %d,%d [%d]\n", x, y, FrameCounter);
+#endif
PlayLevelSound(x, y, SND_CLASS_SP_PORT_PASSING);
break;
+#endif
+#if 0
case EL_TUBE_ANY:
case EL_TUBE_VERTICAL:
case EL_TUBE_HORIZONTAL:
PlayLevelSound(x, y, SND_CLASS_TUBE_WALKING);
}
break;
+#endif
default:
+#if 1
+ if (IS_WALKABLE(element) && ACCESS_FROM(element, opposite_direction))
+#else
if (IS_WALKABLE(element))
+#endif
{
+ int sound_element = SND_ELEMENT(element);
int sound_action = ACTION_WALKING;
- if (element >= EL_GATE_1 && element <= EL_GATE_4)
+#if 0
+ if (!ACCESS_FROM(element, opposite_direction))
+ return MF_NO_ACTION; /* field not accessible from this direction */
+#endif
+
+#if 0
+ if (element == EL_EMPTY_SPACE &&
+ game.gravity && !player->is_auto_moving &&
+ canFallDown(player) && move_direction != MV_DOWN)
+ return MF_NO_ACTION; /* player cannot walk here due to gravity */
+#endif
+
+ if (IS_GATE(element))
{
if (!player->key[element - EL_GATE_1])
return MF_NO_ACTION;
}
- else if (element >= EL_GATE_1_GRAY && element <= EL_GATE_4_GRAY)
+ else if (IS_GATE_GRAY(element))
{
if (!player->key[element - EL_GATE_1_GRAY])
return MF_NO_ACTION;
}
/* play sound from background or player, whatever is available */
- if (element_info[element].sound[sound_action] != SND_UNDEFINED)
- PlayLevelSoundElementAction(x, y, element, sound_action);
+ if (element_info[sound_element].sound[sound_action] != SND_UNDEFINED)
+ PlayLevelSoundElementAction(x, y, sound_element, sound_action);
else
PlayLevelSoundElementAction(x, y, player->element_nr, sound_action);
break;
}
+#if 1
+ else if (IS_PASSABLE(element) && canPassField(x, y, move_direction))
+#else
else if (IS_PASSABLE(element))
+#endif
{
+#if 0
+ if (!canPassField(x, y, move_direction))
+ return MF_NO_ACTION;
+#else
+
+#if 0
+#if 1
+ if (!IN_LEV_FIELD(nextx, nexty) || IS_PLAYER(nextx, nexty) ||
+ !IS_WALKABLE_FROM(Feld[nextx][nexty], move_direction) ||
+ (!level.can_pass_to_walkable && !IS_FREE(nextx, nexty)))
+ return MF_NO_ACTION;
+#else
if (!IN_LEV_FIELD(nextx, nexty) || !IS_FREE(nextx, nexty))
return MF_NO_ACTION;
+#endif
+#endif
+
+#if 1
+ if (!ACCESS_FROM(element, opposite_direction))
+ return MF_NO_ACTION; /* field not accessible from this direction */
+#else
+ if (IS_CUSTOM_ELEMENT(element) &&
+ !ACCESS_FROM(element, opposite_direction))
+ return MF_NO_ACTION; /* field not accessible from this direction */
+#endif
#if 1
if (CAN_MOVE(element)) /* only fixed elements can be passed! */
return MF_NO_ACTION;
#endif
- if (element >= EL_EM_GATE_1 && element <= EL_EM_GATE_4)
+#endif
+
+ if (IS_EM_GATE(element))
{
if (!player->key[element - EL_EM_GATE_1])
return MF_NO_ACTION;
}
- else if (element >= EL_EM_GATE_1_GRAY && element <= EL_EM_GATE_4_GRAY)
+ else if (IS_EM_GATE_GRAY(element))
{
if (!player->key[element - EL_EM_GATE_1_GRAY])
return MF_NO_ACTION;
}
+ else if (IS_SP_PORT(element))
+ {
+ if (element == EL_SP_GRAVITY_PORT_LEFT ||
+ element == EL_SP_GRAVITY_PORT_RIGHT ||
+ element == EL_SP_GRAVITY_PORT_UP ||
+ element == EL_SP_GRAVITY_PORT_DOWN)
+ game.gravity = !game.gravity;
+ else if (element == EL_SP_GRAVITY_ON_PORT_LEFT ||
+ element == EL_SP_GRAVITY_ON_PORT_RIGHT ||
+ element == EL_SP_GRAVITY_ON_PORT_UP ||
+ element == EL_SP_GRAVITY_ON_PORT_DOWN)
+ game.gravity = TRUE;
+ else if (element == EL_SP_GRAVITY_OFF_PORT_LEFT ||
+ element == EL_SP_GRAVITY_OFF_PORT_RIGHT ||
+ element == EL_SP_GRAVITY_OFF_PORT_UP ||
+ element == EL_SP_GRAVITY_OFF_PORT_DOWN)
+ game.gravity = FALSE;
+ }
/* automatically move to the next field with double speed */
player->programmed_action = move_direction;
+#if 1
+ if (player->move_delay_reset_counter == 0)
+ {
+ player->move_delay_reset_counter = 2; /* two double speed steps */
+
+ DOUBLE_PLAYER_SPEED(player);
+ }
+#else
+ player->move_delay_reset_counter = 2;
+
DOUBLE_PLAYER_SPEED(player);
+#endif
PlayLevelSoundAction(x, y, ACTION_PASSING);
PlayLevelSoundElementAction(x, y, element, ACTION_DIGGING);
- CheckTriggeredElementChange(x, y, element, CE_OTHER_GETS_DIGGED);
+ CheckTriggeredElementChangeByPlayer(x, y, element,CE_OTHER_GETS_DIGGED,
+ player->index_bit, dig_side);
#if 1
if (mode == DF_SNAP)
{
RemoveField(x, y);
- if (mode != DF_SNAP)
+ if (is_player && mode != DF_SNAP)
{
GfxElement[x][y] = element;
player->is_collecting = TRUE;
else if (element == EL_EXTRA_TIME && level.time > 0)
{
TimeLeft += 10;
- DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2);
+ DrawGameValue_Time(TimeLeft);
}
else if (element == EL_SHIELD_NORMAL || element == EL_SHIELD_DEADLY)
{
if (player->inventory_size < MAX_INVENTORY_SIZE)
player->inventory_element[player->inventory_size++] = element;
- DrawText(DX_DYNAMITE, DY_DYNAMITE,
- int2str(local_player->inventory_size, 3), FONT_TEXT_2);
+ DrawGameValue_Dynamite(local_player->inventory_size);
}
else if (element == EL_DYNABOMB_INCREASE_NUMBER)
{
player->key[key_nr] = TRUE;
- DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
- el2edimg(EL_KEY_1 + key_nr));
+ DrawGameValue_Keys(player);
+
redraw_mask |= REDRAW_DOOR_1;
}
else if (IS_ENVELOPE(element))
ShowEnvelope(element - EL_ENVELOPE_1);
#endif
}
- else if (IS_DROPPABLE(element)) /* can be collected and dropped */
+ else if (IS_DROPPABLE(element) ||
+ IS_THROWABLE(element)) /* can be collected and dropped */
{
int i;
- for (i = 0; i < element_info[element].collect_count; i++)
- if (player->inventory_size < MAX_INVENTORY_SIZE)
- player->inventory_element[player->inventory_size++] = element;
+ if (element_info[element].collect_count == 0)
+ player->inventory_infinite_element = element;
+ else
+ for (i = 0; i < element_info[element].collect_count; i++)
+ if (player->inventory_size < MAX_INVENTORY_SIZE)
+ player->inventory_element[player->inventory_size++] = element;
- DrawText(DX_DYNAMITE, DY_DYNAMITE,
- int2str(local_player->inventory_size, 3), FONT_TEXT_2);
+ DrawGameValue_Dynamite(local_player->inventory_size);
}
else if (element_info[element].collect_count > 0)
{
if (local_player->gems_still_needed < 0)
local_player->gems_still_needed = 0;
- DrawText(DX_EMERALDS, DY_EMERALDS,
- int2str(local_player->gems_still_needed, 3), FONT_TEXT_2);
+ DrawGameValue_Emeralds(local_player->gems_still_needed);
}
RaiseScoreElement(element);
PlayLevelSoundElementAction(x, y, element, ACTION_COLLECTING);
- CheckTriggeredElementChange(x, y, element, CE_OTHER_GETS_COLLECTED);
+ if (is_player)
+ CheckTriggeredElementChangeByPlayer(x, y, element,
+ CE_OTHER_GETS_COLLECTED,
+ player->index_bit, dig_side);
#if 1
if (mode == DF_SNAP)
return MF_NO_ACTION;
if (CAN_FALL(element) && IN_LEV_FIELD(x, y + 1) && IS_FREE(x, y + 1) &&
- !(element == EL_SPRING && use_spring_bug))
+ !(element == EL_SPRING && level.use_spring_bug))
return MF_NO_ACTION;
#if 1
#endif
#if 1
- if (game.engine_version >= VERSION_IDENT(3,0,7,1))
+
+#if 1
+ if (game.engine_version >= VERSION_IDENT(3,1,0,0))
+ {
+ if (player->push_delay_value == -1 || !player_was_pushing)
+ player->push_delay_value = GET_NEW_PUSH_DELAY(element);
+ }
+ else if (game.engine_version >= VERSION_IDENT(3,0,7,1))
{
if (player->push_delay_value == -1)
player->push_delay_value = GET_NEW_PUSH_DELAY(element);
}
+#else
+ if (game.engine_version >= VERSION_IDENT(3,0,7,1))
+ {
+ if (player->push_delay_value == -1 || !player_was_pushing)
+ player->push_delay_value = GET_NEW_PUSH_DELAY(element);
+ }
+#endif
else if (game.engine_version >= VERSION_IDENT(2,2,0,7))
{
if (!player->is_pushing)
#endif
#if 0
- printf("::: push delay: %ld [%d, %d] [%d]\n",
- player->push_delay_value, FrameCounter, game.engine_version,
- player->is_pushing);
+ printf("::: push delay: %ld -> %ld [%d, %d] [%d / %d] [%d '%s': %d]\n",
+ player->push_delay, player->push_delay_value,
+ FrameCounter, game.engine_version,
+ player_was_pushing, player->is_pushing,
+ element, element_info[element].token_name,
+ GET_NEW_PUSH_DELAY(element));
#endif
player->is_pushing = TRUE;
else
player->push_delay_value = -1; /* get new value later */
- CheckTriggeredElementSideChange(x, y, element, dig_side,
- CE_OTHER_GETS_PUSHED);
- CheckElementSideChange(x, y, element, dig_side,
- CE_PUSHED_BY_PLAYER, -1);
+#if 1
+ /* check for element change _after_ element has been pushed! */
+#else
+
+#if 1
+ /* !!! TEST ONLY !!! */
+ CheckElementChangeByPlayer(x, y, element, CE_PUSHED_BY_PLAYER,
+ player->index_bit, dig_side);
+ CheckTriggeredElementChangeByPlayer(x, y, element,CE_OTHER_GETS_PUSHED,
+ player->index_bit, dig_side);
+#else
+ CheckTriggeredElementChangeByPlayer(x, y, element,CE_OTHER_GETS_PUSHED,
+ player->index_bit, dig_side);
+ CheckElementChangeByPlayer(x, y, element, CE_PUSHED_BY_PLAYER,
+ player->index_bit, dig_side);
+#endif
+#endif
break;
}
else if (IS_SWITCHABLE(element))
{
if (PLAYER_SWITCHING(player, x, y))
+ {
+ CheckTriggeredElementChangeByPlayer(x,y, element,
+ CE_OTHER_GETS_PRESSED,
+ player->index_bit, dig_side);
+
return MF_ACTION;
+ }
player->is_switching = TRUE;
player->switch_x = x;
{
Feld[x][y] = EL_TIME_ORB_EMPTY;
TimeLeft += 10;
- DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2);
+ DrawGameValue_Time(TimeLeft);
DrawLevelField(x, y);
#endif
}
+ CheckTriggeredElementChangeByPlayer(x, y, element,
+ CE_OTHER_IS_SWITCHING,
+ player->index_bit, dig_side);
+
+ CheckTriggeredElementChangeByPlayer(x,y, element,CE_OTHER_GETS_PRESSED,
+ player->index_bit, dig_side);
+
return MF_ACTION;
}
else
player->switch_x = x;
player->switch_y = y;
- CheckTriggeredElementSideChange(x, y, element, dig_side,
- CE_OTHER_IS_SWITCHING);
- CheckElementSideChange(x, y, element, dig_side, CE_SWITCHED, -1);
+#if 1
+ /* !!! TEST ONLY !!! */
+ CheckElementChangeByPlayer(x, y, element, CE_SWITCHED,
+ player->index_bit, dig_side);
+ CheckTriggeredElementChangeByPlayer(x, y, element,
+ CE_OTHER_IS_SWITCHING,
+ player->index_bit, dig_side);
+#else
+ CheckTriggeredElementChangeByPlayer(x, y, element,
+ CE_OTHER_IS_SWITCHING,
+ player->index_bit, dig_side);
+ CheckElementChangeByPlayer(x, y, element, CE_SWITCHED,
+ player->index_bit, dig_side);
+#endif
}
- CheckTriggeredElementSideChange(x, y, element, dig_side,
- CE_OTHER_GETS_PRESSED);
- CheckElementSideChange(x, y, element, dig_side,
- CE_PRESSED_BY_PLAYER, -1);
+#if 1
+ /* !!! TEST ONLY !!! (this breaks "machine", level 000) */
+ CheckElementChangeByPlayer(x, y, element, CE_PRESSED_BY_PLAYER,
+ player->index_bit, dig_side);
+ CheckTriggeredElementChangeByPlayer(x,y, element,CE_OTHER_GETS_PRESSED,
+ player->index_bit, dig_side);
+#else
+ CheckTriggeredElementChangeByPlayer(x,y, element,CE_OTHER_GETS_PRESSED,
+ player->index_bit, dig_side);
+ CheckElementChangeByPlayer(x, y, element, CE_PRESSED_BY_PLAYER,
+ player->index_bit, dig_side);
+#endif
}
return MF_NO_ACTION;
dy == -1 ? MV_UP :
dy == +1 ? MV_DOWN : MV_NO_MOVING);
- if (player->MovPos && game.engine_version >= VERSION_IDENT(2,2,0,0))
+#if 0
+ if (player->MovPos != 0)
+ return FALSE;
+#else
+ if (player->MovPos != 0 && game.engine_version >= VERSION_IDENT(2,2,0,0))
return FALSE;
+#endif
if (!player->active || !IN_LEV_FIELD(x, y))
return FALSE;
player->MovDir = snap_direction;
- player->is_moving = FALSE;
- player->is_digging = FALSE;
- player->is_collecting = FALSE;
+#if 1
+ if (player->MovPos == 0)
+#endif
+ {
+ player->is_moving = FALSE;
+ player->is_digging = FALSE;
+ player->is_collecting = FALSE;
+ }
+
+ player->is_dropping = FALSE;
- if (DigField(player, x, y, 0, 0, DF_SNAP) == MF_NO_ACTION)
+ if (DigField(player, jx, jy, x, y, 0, 0, DF_SNAP) == MF_NO_ACTION)
return FALSE;
player->is_snapping = TRUE;
- player->is_moving = FALSE;
- player->is_digging = FALSE;
- player->is_collecting = FALSE;
+#if 1
+ if (player->MovPos == 0)
+#endif
+ {
+ player->is_moving = FALSE;
+ player->is_digging = FALSE;
+ player->is_collecting = FALSE;
+ }
+
+#if 1
+ if (player->MovPos != 0) /* prevent graphic bugs in versions < 2.2.0 */
+ DrawLevelField(player->last_jx, player->last_jy);
+#endif
DrawLevelField(x, y);
+
+#if 0
BackToFront();
+#endif
return TRUE;
}
boolean DropElement(struct PlayerInfo *player)
{
- int jx = player->jx, jy = player->jy;
- int old_element;
+ int old_element, new_element;
+ int dropx = player->jx, dropy = player->jy;
+ int drop_direction = player->MovDir;
+#if 1
+ int drop_side = drop_direction;
+#else
+ static int trigger_sides[4] =
+ {
+ CH_SIDE_LEFT, /* dropping left */
+ CH_SIDE_RIGHT, /* dropping right */
+ CH_SIDE_TOP, /* dropping up */
+ CH_SIDE_BOTTOM, /* dropping down */
+ };
+ int drop_side = trigger_sides[MV_DIR_BIT(drop_direction)];
+#endif
+ int drop_element = (player->inventory_size > 0 ?
+ player->inventory_element[player->inventory_size - 1] :
+ player->inventory_infinite_element != EL_UNDEFINED ?
+ player->inventory_infinite_element :
+ player->dynabombs_left > 0 ?
+ EL_DYNABOMB_PLAYER_1_ACTIVE + player->index_nr :
+ EL_UNDEFINED);
- if (!player->active || player->MovPos)
- return FALSE;
+ if (IS_THROWABLE(drop_element))
+ {
+ dropx += GET_DX_FROM_DIR(drop_direction);
+ dropy += GET_DY_FROM_DIR(drop_direction);
+
+ if (!IN_LEV_FIELD(dropx, dropy))
+ return FALSE;
+ }
- old_element = Feld[jx][jy];
+ old_element = Feld[dropx][dropy]; /* old element at dropping position */
+ new_element = drop_element; /* default: no change when dropping */
+
+ /* check if player is active, not moving and ready to drop */
+ if (!player->active || player->MovPos || player->drop_delay > 0)
+ return FALSE;
/* check if player has anything that can be dropped */
- if (player->inventory_size == 0 && player->dynabombs_left == 0)
+#if 1
+ if (new_element == EL_UNDEFINED)
+ return FALSE;
+#else
+ if (player->inventory_size == 0 &&
+ player->inventory_infinite_element == EL_UNDEFINED &&
+ player->dynabombs_left == 0)
return FALSE;
+#endif
/* check if anything can be dropped at the current position */
if (IS_ACTIVE_BOMB(old_element) || old_element == EL_EXPLOSION)
return FALSE;
/* collected custom elements can only be dropped on empty fields */
+#if 1
+ if (IS_CUSTOM_ELEMENT(new_element) && old_element != EL_EMPTY)
+ return FALSE;
+#else
if (player->inventory_size > 0 &&
IS_CUSTOM_ELEMENT(player->inventory_element[player->inventory_size - 1])
&& old_element != EL_EMPTY)
return FALSE;
+#endif
if (old_element != EL_EMPTY)
- Back[jx][jy] = old_element; /* store old element on this field */
+ Back[dropx][dropy] = old_element; /* store old element on this field */
- MovDelay[jx][jy] = 96;
+ ResetGfxAnimation(dropx, dropy);
+ ResetRandomAnimationValue(dropx, dropy);
- ResetGfxAnimation(jx, jy);
- ResetRandomAnimationValue(jx, jy);
-
- if (player->inventory_size > 0)
+ if (player->inventory_size > 0 ||
+ player->inventory_infinite_element != EL_UNDEFINED)
{
- int new_element = player->inventory_element[--player->inventory_size];
+ if (player->inventory_size > 0)
+ {
+ player->inventory_size--;
+
+#if 0
+ new_element = player->inventory_element[player->inventory_size];
+#endif
+
+ DrawGameValue_Dynamite(local_player->inventory_size);
- Feld[jx][jy] = (new_element == EL_DYNAMITE ? EL_DYNAMITE_ACTIVE :
- new_element == EL_SP_DISK_RED ? EL_SP_DISK_RED_ACTIVE :
- new_element);
+ if (new_element == EL_DYNAMITE)
+ new_element = EL_DYNAMITE_ACTIVE;
+ else if (new_element == EL_SP_DISK_RED)
+ new_element = EL_SP_DISK_RED_ACTIVE;
+ }
+
+ Feld[dropx][dropy] = new_element;
- DrawText(DX_DYNAMITE, DY_DYNAMITE,
- int2str(local_player->inventory_size, 3), FONT_TEXT_2);
+ if (IN_SCR_FIELD(SCREENX(dropx), SCREENY(dropy)))
+ DrawGraphicThruMask(SCREENX(dropx), SCREENY(dropy),
+ el2img(Feld[dropx][dropy]), 0);
- if (IN_SCR_FIELD(SCREENX(jx), SCREENY(jy)))
- DrawGraphicThruMask(SCREENX(jx), SCREENY(jy), el2img(Feld[jx][jy]), 0);
+ PlayLevelSoundAction(dropx, dropy, ACTION_DROPPING);
- PlayLevelSoundAction(jx, jy, ACTION_DROPPING);
+#if 1
+ /* needed if previous element just changed to "empty" in the last frame */
+ Changed[dropx][dropy] = 0; /* allow another change */
+#endif
- CheckTriggeredElementChange(jx, jy, new_element, CE_OTHER_GETS_DROPPED);
- CheckElementChange(jx, jy, new_element, CE_DROPPED_BY_PLAYER);
+#if 1
+ /* !!! TEST ONLY !!! */
+ CheckElementChangeByPlayer(dropx, dropy, new_element, CE_DROPPED_BY_PLAYER,
+ player->index_bit, drop_side);
+ CheckTriggeredElementChangeByPlayer(dropx, dropy, new_element,
+ CE_OTHER_GETS_DROPPED,
+ player->index_bit, drop_side);
+#else
+ CheckTriggeredElementChangeByPlayer(dropx, dropy, new_element,
+ CE_OTHER_GETS_DROPPED,
+ player->index_bit, drop_side);
+ CheckElementChangeByPlayer(dropx, dropy, new_element, CE_DROPPED_BY_PLAYER,
+ player->index_bit, drop_side);
+#endif
- TestIfElementTouchesCustomElement(jx, jy);
+ TestIfElementTouchesCustomElement(dropx, dropy);
}
else /* player is dropping a dyna bomb */
{
player->dynabombs_left--;
- Feld[jx][jy] =
- EL_DYNABOMB_PLAYER_1_ACTIVE + (player->element_nr - EL_PLAYER_1);
+#if 0
+ new_element = EL_DYNABOMB_PLAYER_1_ACTIVE + player->index_nr;
+#endif
+
+ Feld[dropx][dropy] = new_element;
+
+ if (IN_SCR_FIELD(SCREENX(dropx), SCREENY(dropy)))
+ DrawGraphicThruMask(SCREENX(dropx), SCREENY(dropy),
+ el2img(Feld[dropx][dropy]), 0);
+
+ PlayLevelSoundAction(dropx, dropy, ACTION_DROPPING);
+ }
+
+
+
+#if 1
+
+ if (Feld[dropx][dropy] == new_element) /* uninitialized unless CE change */
+ {
+#if 1
+ InitField_WithBug1(dropx, dropy, FALSE);
+#else
+ InitField(dropx, dropy, FALSE);
+ if (CAN_MOVE(Feld[dropx][dropy]))
+ InitMovDir(dropx, dropy);
+#endif
+ }
+
+ new_element = Feld[dropx][dropy]; /* element might have changed */
+
+ if (IS_CUSTOM_ELEMENT(new_element) && CAN_MOVE(new_element) &&
+ element_info[new_element].move_pattern == MV_WHEN_DROPPED)
+ {
+#if 0
+ int move_stepsize = element_info[new_element].move_stepsize;
+#endif
+ int move_direction, nextx, nexty;
+
+ if (element_info[new_element].move_direction_initial == MV_START_AUTOMATIC)
+ MovDir[dropx][dropy] = drop_direction;
+
+ move_direction = MovDir[dropx][dropy];
+ nextx = dropx + GET_DX_FROM_DIR(move_direction);
+ nexty = dropy + GET_DY_FROM_DIR(move_direction);
+
+#if 1
+ Changed[dropx][dropy] = 0; /* allow another change */
+ CheckCollision[dropx][dropy] = 2;
+#else
+
+ if (IN_LEV_FIELD_AND_IS_FREE(nextx, nexty))
+ {
+#if 0
+ WasJustMoving[dropx][dropy] = 3;
+#else
+#if 1
+ InitMovingField(dropx, dropy, move_direction);
+ ContinueMoving(dropx, dropy);
+#endif
+#endif
+ }
+#if 0
+ /* !!! commented out from 3.1.0-4 to 3.1.0-5 !!! */
+ else
+ {
+ Changed[dropx][dropy] = 0; /* allow another change */
+
+#if 1
+ TestIfElementHitsCustomElement(dropx, dropy, move_direction);
+#else
+ CheckElementChangeBySide(dropx, dropy, new_element, touched_element,
+ CE_HITTING_SOMETHING, move_direction);
+#endif
+ }
+#endif
- if (IN_SCR_FIELD(SCREENX(jx), SCREENY(jy)))
- DrawGraphicThruMask(SCREENX(jx), SCREENY(jy), el2img(Feld[jx][jy]), 0);
+#endif
- PlayLevelSoundAction(jx, jy, ACTION_DROPPING);
+#if 0
+ player->drop_delay = 2 * TILEX / move_stepsize + 1;
+#endif
}
+#if 0
+ player->drop_delay = 8 + 8 + 8;
+#endif
+
+#if 1
+ player->drop_delay = GET_NEW_DROP_DELAY(drop_element);
+#endif
+
+#endif
+
+ player->is_dropping = TRUE;
+
+
return TRUE;
}
static void PlayLevelSoundElementAction(int x, int y, int element, int action)
{
- int sound_effect = element_info[element].sound[action];
+ int sound_effect = element_info[SND_ELEMENT(element)].sound[action];
if (sound_effect != SND_UNDEFINED)
PlayLevelSound(x, y, sound_effect);
static void PlayLevelSoundElementActionIfLoop(int x, int y, int element,
int action)
{
- int sound_effect = element_info[element].sound[action];
+ int sound_effect = element_info[SND_ELEMENT(element)].sound[action];
if (sound_effect != SND_UNDEFINED && IS_LOOP_SOUND(sound_effect))
PlayLevelSound(x, y, sound_effect);
static void PlayLevelSoundActionIfLoop(int x, int y, int action)
{
- int sound_effect = element_info[Feld[x][y]].sound[action];
+ int sound_effect = element_info[SND_ELEMENT(Feld[x][y])].sound[action];
if (sound_effect != SND_UNDEFINED && IS_LOOP_SOUND(sound_effect))
PlayLevelSound(x, y, sound_effect);
static void StopLevelSoundActionIfLoop(int x, int y, int action)
{
- int sound_effect = element_info[Feld[x][y]].sound[action];
+ int sound_effect = element_info[SND_ELEMENT(Feld[x][y])].sound[action];
if (sound_effect != SND_UNDEFINED && IS_LOOP_SOUND(sound_effect))
StopSound(sound_effect);
void RaiseScore(int value)
{
local_player->score += value;
- DrawText(DX_SCORE, DY_SCORE, int2str(local_player->score, 5), FONT_TEXT_2);
+
+ DrawGameValue_Score(local_player->score);
}
void RaiseScoreElement(int element)
Request("Do you really want to quit the game ?",
REQ_ASK | REQ_STAY_CLOSED))
{
-#if defined(PLATFORM_UNIX)
+#if defined(NETWORK_AVALIABLE)
if (options.network)
SendToServer_StopPlaying();
else
}
else
{
+
+#if 1
+ if (tape.playing && tape.deactivate_display)
+ TapeDeactivateDisplayOff(TRUE);
+#endif
+
OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
+
+#if 1
+ if (tape.playing && tape.deactivate_display)
+ TapeDeactivateDisplayOn();
+#endif
+
}
}
case GAME_CTRL_ID_PAUSE:
if (options.network)
{
-#if defined(PLATFORM_UNIX)
+#if defined(NETWORK_AVALIABLE)
if (tape.pausing)
SendToServer_ContinuePlaying();
else
case GAME_CTRL_ID_PLAY:
if (tape.pausing)
{
-#if defined(PLATFORM_UNIX)
+#if defined(NETWORK_AVALIABLE)
if (options.network)
SendToServer_ContinuePlaying();
else
#include "main.h"
-/* score for elements (also used by editor.c) */
-#define SC_EMERALD 0
-#define SC_DIAMOND 1
-#define SC_BUG 2
-#define SC_SPACESHIP 3
-#define SC_YAMYAM 4
-#define SC_ROBOT 5
-#define SC_PACMAN 6
-#define SC_NUT 7
-#define SC_DYNAMITE 8
-#define SC_KEY 9
-#define SC_TIME_BONUS 10
-#define SC_CRYSTAL 11
-#define SC_PEARL 12
-#define SC_SHIELD 13
-
void GetPlayerConfig(void);
void DrawGameDoorValues(void);
void InitGameSound();
void KillHero(struct PlayerInfo *);
void BuryHero(struct PlayerInfo *);
void RemoveHero(struct PlayerInfo *);
-int DigField(struct PlayerInfo *, int, int, int, int, int);
boolean SnapField(struct PlayerInfo *, int, int);
boolean DropElement(struct PlayerInfo *);
int num_property_mappings = getImageListPropertyMappingSize();
int i, act, dir;
+ if (graphic_info == NULL) /* still at startup phase */
+ return;
+
/* set values to -1 to identify later as "uninitialized" values */
for (i = 0; i < MAX_NUM_ELEMENTS; i++)
{
int direction = element_to_graphic[i].direction;
boolean crumbled = element_to_graphic[i].crumbled;
int graphic = element_to_graphic[i].graphic;
+ int base_graphic = el2baseimg(element);
if (graphic_info[graphic].bitmap == NULL)
continue;
if ((action > -1 || direction > -1 || crumbled == TRUE) &&
- el2img(element) != -1)
+ base_graphic != -1)
{
- boolean base_redefined = getImageListEntry(el2img(element))->redefined;
+ boolean base_redefined = getImageListEntry(base_graphic)->redefined;
boolean act_dir_redefined = getImageListEntry(graphic)->redefined;
/* if the base graphic ("emerald", for example) has been redefined,
int default_direction_crumbled[NUM_DIRECTIONS];
if (default_graphic == -1)
- default_graphic = IMG_CHAR_QUESTION;
+ default_graphic = IMG_UNKNOWN;
if (default_crumbled == -1)
default_crumbled = IMG_EMPTY;
for (act = 0; act < NUM_ACTIONS; act++)
{
- boolean act_remove = (act == ACTION_DIGGING ||
- act == ACTION_SNAPPING ||
- act == ACTION_COLLECTING);
+ boolean act_remove = ((IS_DIGGABLE(i) && act == ACTION_DIGGING) ||
+ (IS_SNAPPABLE(i) && act == ACTION_SNAPPING) ||
+ (IS_COLLECTIBLE(i) && act == ACTION_COLLECTING));
boolean act_turning = (act == ACTION_TURNING_FROM_LEFT ||
act == ACTION_TURNING_FROM_RIGHT ||
act == ACTION_TURNING_FROM_UP ||
if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
+#if 1
+ /* !!! make this better !!! */
+ if (i == EL_EMPTY_SPACE)
+ {
+ default_action_graphic = element_info[EL_DEFAULT].graphic[act];
+ default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
+ }
+#endif
+
if (default_action_graphic == -1)
default_action_graphic = default_graphic;
if (default_action_crumbled == -1)
if (options.verbose)
{
for (i = 0; i < MAX_NUM_ELEMENTS; i++)
- if (element_info[i].graphic[ACTION_DEFAULT] == IMG_CHAR_QUESTION &&
- i != EL_CHAR_QUESTION)
+ if (element_info[i].graphic[ACTION_DEFAULT] == IMG_UNKNOWN &&
+ i != EL_UNKNOWN)
Error(ERR_RETURN, "warning: no graphic for element '%s' (%d)",
element_info[i].token_name, i);
}
int element = element_to_special_graphic[i].element;
int special = element_to_special_graphic[i].special;
int graphic = element_to_special_graphic[i].graphic;
- boolean base_redefined = getImageListEntry(el2img(element))->redefined;
+ int base_graphic = el2baseimg(element);
+ boolean base_redefined = getImageListEntry(base_graphic)->redefined;
boolean special_redefined = getImageListEntry(graphic)->redefined;
/* if the base graphic ("emerald", for example) has been redefined,
InitGameModeMusicInfo(); /* game mode music mapping */
}
+static int get_special_property_bit(int element, int property_bit_nr)
+{
+ struct PropertyBitInfo
+ {
+ int element;
+ int bit_nr;
+ };
+
+ static struct PropertyBitInfo pb_can_move_into_acid[] =
+ {
+ /* the player may be able fall into acid when gravity is activated */
+ { EL_PLAYER_1, 0 },
+ { EL_PLAYER_2, 0 },
+ { EL_PLAYER_3, 0 },
+ { EL_PLAYER_4, 0 },
+ { EL_SP_MURPHY, 0 },
+ { EL_SOKOBAN_FIELD_PLAYER, 0 },
+
+ /* all element that can move may be able to also move into acid */
+ { EL_BUG, 1 },
+ { EL_BUG_LEFT, 1 },
+ { EL_BUG_RIGHT, 1 },
+ { EL_BUG_UP, 1 },
+ { EL_BUG_DOWN, 1 },
+ { EL_SPACESHIP, 2 },
+ { EL_SPACESHIP_LEFT, 2 },
+ { EL_SPACESHIP_RIGHT, 2 },
+ { EL_SPACESHIP_UP, 2 },
+ { EL_SPACESHIP_DOWN, 2 },
+ { EL_BD_BUTTERFLY, 3 },
+ { EL_BD_BUTTERFLY_LEFT, 3 },
+ { EL_BD_BUTTERFLY_RIGHT, 3 },
+ { EL_BD_BUTTERFLY_UP, 3 },
+ { EL_BD_BUTTERFLY_DOWN, 3 },
+ { EL_BD_FIREFLY, 4 },
+ { EL_BD_FIREFLY_LEFT, 4 },
+ { EL_BD_FIREFLY_RIGHT, 4 },
+ { EL_BD_FIREFLY_UP, 4 },
+ { EL_BD_FIREFLY_DOWN, 4 },
+ { EL_YAMYAM, 5 },
+ { EL_DARK_YAMYAM, 6 },
+ { EL_ROBOT, 7 },
+ { EL_PACMAN, 8 },
+ { EL_PACMAN_LEFT, 8 },
+ { EL_PACMAN_RIGHT, 8 },
+ { EL_PACMAN_UP, 8 },
+ { EL_PACMAN_DOWN, 8 },
+ { EL_MOLE, 9 },
+ { EL_MOLE_LEFT, 9 },
+ { EL_MOLE_RIGHT, 9 },
+ { EL_MOLE_UP, 9 },
+ { EL_MOLE_DOWN, 9 },
+ { EL_PENGUIN, 10 },
+ { EL_PIG, 11 },
+ { EL_DRAGON, 12 },
+ { EL_SATELLITE, 13 },
+ { EL_SP_SNIKSNAK, 14 },
+ { EL_SP_ELECTRON, 15 },
+ { EL_BALLOON, 16 },
+ { EL_SPRING, 17 },
+
+ { -1, -1 },
+ };
+
+ static struct PropertyBitInfo pb_dont_collide_with[] =
+ {
+ { EL_SP_SNIKSNAK, 0 },
+ { EL_SP_ELECTRON, 1 },
+
+ { -1, -1 },
+ };
+
+ static struct
+ {
+ int bit_nr;
+ struct PropertyBitInfo *pb_info;
+ } pb_definition[] =
+ {
+ { EP_CAN_MOVE_INTO_ACID, pb_can_move_into_acid },
+ { EP_DONT_COLLIDE_WITH, pb_dont_collide_with },
+
+ { -1, NULL },
+ };
+
+ struct PropertyBitInfo *pb_info = NULL;
+ int i;
+
+ for (i = 0; pb_definition[i].bit_nr != -1; i++)
+ if (pb_definition[i].bit_nr == property_bit_nr)
+ pb_info = pb_definition[i].pb_info;
+
+ if (pb_info == NULL)
+ return -1;
+
+ for (i = 0; pb_info[i].element != -1; i++)
+ if (pb_info[i].element == element)
+ return pb_info[i].bit_nr;
+
+ return -1;
+}
+
+#if 1
+void setBitfieldProperty(int *bitfield, int property_bit_nr, int element,
+ boolean property_value)
+{
+ int bit_nr = get_special_property_bit(element, property_bit_nr);
+
+ if (bit_nr > -1)
+ {
+ if (property_value)
+ *bitfield |= (1 << bit_nr);
+ else
+ *bitfield &= ~(1 << bit_nr);
+ }
+}
+
+boolean getBitfieldProperty(int *bitfield, int property_bit_nr, int element)
+{
+ int bit_nr = get_special_property_bit(element, property_bit_nr);
+
+ if (bit_nr > -1)
+ return ((*bitfield & (1 << bit_nr)) != 0);
+
+ return FALSE;
+}
+
+#else
+
+void setMoveIntoAcidProperty(struct LevelInfo *level, int element, boolean set)
+{
+ int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID);
+
+ if (bit_nr > -1)
+ {
+ level->can_move_into_acid_bits &= ~(1 << bit_nr);
+
+ if (set)
+ level->can_move_into_acid_bits |= (1 << bit_nr);
+ }
+}
+
+boolean getMoveIntoAcidProperty(struct LevelInfo *level, int element)
+{
+ int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID);
+
+ if (bit_nr > -1)
+ return ((level->can_move_into_acid_bits & (1 << bit_nr)) != 0);
+
+ return FALSE;
+}
+#endif
+
void InitElementPropertiesStatic()
{
static int ep_diggable[] =
EL_INVISIBLE_SAND_ACTIVE,
/* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
+ /* (if amoeba can grow into anything diggable, maybe keep these out) */
#if 0
EL_LANDMINE,
EL_TRAP_ACTIVE,
static int ep_can_move[] =
{
+ /* same elements as in 'pb_can_move_into_acid' */
EL_BUG,
EL_SPACESHIP,
EL_BD_BUTTERFLY,
EL_SP_ELECTRON,
EL_BALLOON,
EL_SPRING,
- EL_MAZE_RUNNER,
-1
};
-1
};
- static int ep_can_explode_by_fire[] =
+ static int ep_explodes_by_fire[] =
{
- /* same elements as in 'ep_can_explode_impact' */
+ /* same elements as in 'ep_explodes_impact' */
EL_BOMB,
EL_SP_DISK_ORANGE,
EL_DX_SUPABOMB,
- /* same elements as in 'ep_can_explode_smashed' */
+ /* same elements as in 'ep_explodes_smashed' */
EL_SATELLITE,
EL_PIG,
EL_DRAGON,
EL_SP_DISK_YELLOW,
EL_SP_SNIKSNAK,
EL_SP_ELECTRON,
+#if 0
+ EL_BLACK_ORB,
+#endif
-1
};
- static int ep_can_explode_smashed[] =
+ static int ep_explodes_smashed[] =
{
- /* same elements as in 'ep_can_explode_impact' */
+ /* same elements as in 'ep_explodes_impact' */
EL_BOMB,
EL_SP_DISK_ORANGE,
EL_DX_SUPABOMB,
-1
};
- static int ep_can_explode_impact[] =
+ static int ep_explodes_impact[] =
{
EL_BOMB,
EL_SP_DISK_ORANGE,
EL_SP_GRAVITY_PORT_RIGHT,
EL_SP_GRAVITY_PORT_UP,
EL_SP_GRAVITY_PORT_DOWN,
+ EL_SP_GRAVITY_ON_PORT_LEFT,
+ EL_SP_GRAVITY_ON_PORT_RIGHT,
+ EL_SP_GRAVITY_ON_PORT_UP,
+ EL_SP_GRAVITY_ON_PORT_DOWN,
+ EL_SP_GRAVITY_OFF_PORT_LEFT,
+ EL_SP_GRAVITY_OFF_PORT_RIGHT,
+ EL_SP_GRAVITY_OFF_PORT_UP,
+ EL_SP_GRAVITY_OFF_PORT_DOWN,
-1
};
-1
};
- static int ep_can_explode_1x1[] =
+ static int ep_explodes_1x1_old[] =
{
-1
};
-1
};
+ static int ep_explodes_cross_old[] =
+ {
+ -1
+ };
+
+ static int ep_protected[] =
+ {
+ /* same elements as in 'ep_walkable_inside' */
+ EL_TUBE_ANY,
+ EL_TUBE_VERTICAL,
+ EL_TUBE_HORIZONTAL,
+ EL_TUBE_VERTICAL_LEFT,
+ EL_TUBE_VERTICAL_RIGHT,
+ EL_TUBE_HORIZONTAL_UP,
+ EL_TUBE_HORIZONTAL_DOWN,
+ EL_TUBE_LEFT_UP,
+ EL_TUBE_LEFT_DOWN,
+ EL_TUBE_RIGHT_UP,
+ EL_TUBE_RIGHT_DOWN,
+
+ /* same elements as in 'ep_passable_over' */
+ EL_EM_GATE_1,
+ EL_EM_GATE_2,
+ EL_EM_GATE_3,
+ EL_EM_GATE_4,
+ EL_EM_GATE_1_GRAY,
+ EL_EM_GATE_2_GRAY,
+ EL_EM_GATE_3_GRAY,
+ EL_EM_GATE_4_GRAY,
+ EL_SWITCHGATE_OPEN,
+ EL_TIMEGATE_OPEN,
+
+ /* same elements as in 'ep_passable_inside' */
+ EL_SP_PORT_LEFT,
+ EL_SP_PORT_RIGHT,
+ EL_SP_PORT_UP,
+ EL_SP_PORT_DOWN,
+ EL_SP_PORT_HORIZONTAL,
+ EL_SP_PORT_VERTICAL,
+ EL_SP_PORT_ANY,
+ EL_SP_GRAVITY_PORT_LEFT,
+ EL_SP_GRAVITY_PORT_RIGHT,
+ EL_SP_GRAVITY_PORT_UP,
+ EL_SP_GRAVITY_PORT_DOWN,
+ EL_SP_GRAVITY_ON_PORT_LEFT,
+ EL_SP_GRAVITY_ON_PORT_RIGHT,
+ EL_SP_GRAVITY_ON_PORT_UP,
+ EL_SP_GRAVITY_ON_PORT_DOWN,
+ EL_SP_GRAVITY_OFF_PORT_LEFT,
+ EL_SP_GRAVITY_OFF_PORT_RIGHT,
+ EL_SP_GRAVITY_OFF_PORT_UP,
+ EL_SP_GRAVITY_OFF_PORT_DOWN,
+ -1
+ };
+
+ static int ep_throwable[] =
+ {
+ -1
+ };
+
+ static int ep_can_explode[] =
+ {
+ /* same elements as in 'ep_explodes_impact' */
+ EL_BOMB,
+ EL_SP_DISK_ORANGE,
+ EL_DX_SUPABOMB,
+
+ /* same elements as in 'ep_explodes_smashed' */
+ EL_SATELLITE,
+ EL_PIG,
+ EL_DRAGON,
+ EL_MOLE,
+
+ /* elements that can explode by explosion or by dragonfire */
+ EL_DYNAMITE_ACTIVE,
+ EL_DYNAMITE,
+ EL_DYNABOMB_PLAYER_1_ACTIVE,
+ EL_DYNABOMB_PLAYER_2_ACTIVE,
+ EL_DYNABOMB_PLAYER_3_ACTIVE,
+ EL_DYNABOMB_PLAYER_4_ACTIVE,
+ EL_DYNABOMB_INCREASE_NUMBER,
+ EL_DYNABOMB_INCREASE_SIZE,
+ EL_DYNABOMB_INCREASE_POWER,
+ EL_SP_DISK_RED_ACTIVE,
+ EL_BUG,
+ EL_PENGUIN,
+ EL_SP_DISK_RED,
+ EL_SP_DISK_YELLOW,
+ EL_SP_SNIKSNAK,
+ EL_SP_ELECTRON,
+
+ /* elements that can explode only by explosion */
+ EL_BLACK_ORB,
+ -1
+ };
+
+ static int ep_gravity_reachable[] =
+ {
+ EL_SAND,
+ EL_SP_BASE,
+ EL_TRAP,
+ EL_INVISIBLE_SAND,
+ EL_INVISIBLE_SAND_ACTIVE,
+ EL_SP_PORT_LEFT,
+ EL_SP_PORT_RIGHT,
+ EL_SP_PORT_UP,
+ EL_SP_PORT_DOWN,
+ EL_SP_PORT_HORIZONTAL,
+ EL_SP_PORT_VERTICAL,
+ EL_SP_PORT_ANY,
+ EL_SP_GRAVITY_PORT_LEFT,
+ EL_SP_GRAVITY_PORT_RIGHT,
+ EL_SP_GRAVITY_PORT_UP,
+ EL_SP_GRAVITY_PORT_DOWN,
+ EL_SP_GRAVITY_ON_PORT_LEFT,
+ EL_SP_GRAVITY_ON_PORT_RIGHT,
+ EL_SP_GRAVITY_ON_PORT_UP,
+ EL_SP_GRAVITY_ON_PORT_DOWN,
+ EL_SP_GRAVITY_OFF_PORT_LEFT,
+ EL_SP_GRAVITY_OFF_PORT_RIGHT,
+ EL_SP_GRAVITY_OFF_PORT_UP,
+ EL_SP_GRAVITY_OFF_PORT_DOWN,
+ -1
+ };
+
static int ep_player[] =
{
EL_PLAYER_1,
EL_PLAYER_3,
EL_PLAYER_4,
EL_SP_MURPHY,
+ EL_SOKOBAN_FIELD_PLAYER,
+ EL_TRIGGER_PLAYER,
-1
};
EL_EXIT_OPEN,
EL_STEELWALL,
EL_PLAYER_1,
+ EL_PLAYER_2,
+ EL_PLAYER_3,
+ EL_PLAYER_4,
EL_BD_FIREFLY,
EL_BD_FIREFLY_1,
EL_BD_FIREFLY_2,
EL_BD_BUTTERFLY_4,
EL_BD_AMOEBA,
EL_CHAR_QUESTION,
+ EL_UNKNOWN,
-1
};
/* should always be valid */
EL_EMPTY,
+ /* standard classic Supaplex elements */
EL_SP_EMPTY,
EL_SP_ZONK,
EL_SP_BASE,
EL_SP_HARDWARE_BASE_6,
EL_SP_CHIP_TOP,
EL_SP_CHIP_BOTTOM,
+
/* additional elements that appeared in newer Supaplex levels */
EL_INVISIBLE_WALL,
- /* more than one murphy in a level results in an inactive clone */
+
+ /* additional gravity port elements (not switching, but setting gravity) */
+ EL_SP_GRAVITY_ON_PORT_LEFT,
+ EL_SP_GRAVITY_ON_PORT_RIGHT,
+ EL_SP_GRAVITY_ON_PORT_UP,
+ EL_SP_GRAVITY_ON_PORT_DOWN,
+ EL_SP_GRAVITY_OFF_PORT_LEFT,
+ EL_SP_GRAVITY_OFF_PORT_RIGHT,
+ EL_SP_GRAVITY_OFF_PORT_UP,
+ EL_SP_GRAVITY_OFF_PORT_DOWN,
+
+ /* more than one Murphy in a level results in an inactive clone */
EL_SP_MURPHY_CLONE,
- /* runtime elements*/
+
+ /* runtime Supaplex elements */
EL_SP_DISK_RED_ACTIVE,
EL_SP_TERMINAL_ACTIVE,
EL_SP_BUGGY_BASE_ACTIVATING,
EL_SOKOBAN_OBJECT,
EL_SOKOBAN_FIELD_EMPTY,
EL_SOKOBAN_FIELD_FULL,
+ EL_SOKOBAN_FIELD_PLAYER,
EL_PLAYER_1,
+ EL_PLAYER_2,
+ EL_PLAYER_3,
+ EL_PLAYER_4,
EL_INVISIBLE_STEELWALL,
-1
};
-1
};
+ static int ep_can_turn_each_move[] =
+ {
+ /* !!! do something with this one !!! */
+ -1
+ };
+
+ static int ep_can_grow[] =
+ {
+ EL_BD_AMOEBA,
+ EL_AMOEBA_DROP,
+ EL_AMOEBA_WET,
+ EL_AMOEBA_DRY,
+ EL_AMOEBA_FULL,
+ EL_GAME_OF_LIFE,
+ EL_BIOMAZE,
+ -1
+ };
+
static int ep_active_bomb[] =
{
EL_DYNAMITE_ACTIVE,
EL_SP_HARDWARE_BASE_4,
EL_SP_HARDWARE_BASE_5,
EL_SP_HARDWARE_BASE_6,
+ EL_SP_GRAVITY_ON_PORT_LEFT,
+ EL_SP_GRAVITY_ON_PORT_RIGHT,
+ EL_SP_GRAVITY_ON_PORT_UP,
+ EL_SP_GRAVITY_ON_PORT_DOWN,
+ EL_SP_GRAVITY_OFF_PORT_LEFT,
+ EL_SP_GRAVITY_OFF_PORT_RIGHT,
+ EL_SP_GRAVITY_OFF_PORT_UP,
+ EL_SP_GRAVITY_OFF_PORT_DOWN,
EL_CONVEYOR_BELT_1_SWITCH_LEFT,
EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
{ ep_can_smash_player, EP_CAN_SMASH_PLAYER },
{ ep_can_smash_enemies, EP_CAN_SMASH_ENEMIES },
{ ep_can_smash_everything, EP_CAN_SMASH_EVERYTHING },
- { ep_can_explode_by_fire, EP_CAN_EXPLODE_BY_FIRE },
- { ep_can_explode_smashed, EP_CAN_EXPLODE_SMASHED },
- { ep_can_explode_impact, EP_CAN_EXPLODE_IMPACT },
+ { ep_explodes_by_fire, EP_EXPLODES_BY_FIRE },
+ { ep_explodes_smashed, EP_EXPLODES_SMASHED },
+ { ep_explodes_impact, EP_EXPLODES_IMPACT },
{ ep_walkable_over, EP_WALKABLE_OVER },
{ ep_walkable_inside, EP_WALKABLE_INSIDE },
{ ep_walkable_under, EP_WALKABLE_UNDER },
{ ep_passable_inside, EP_PASSABLE_INSIDE },
{ ep_passable_under, EP_PASSABLE_UNDER },
{ ep_droppable, EP_DROPPABLE },
- { ep_can_explode_1x1, EP_CAN_EXPLODE_1X1 },
+ { ep_explodes_1x1_old, EP_EXPLODES_1X1_OLD },
{ ep_pushable, EP_PUSHABLE },
+ { ep_explodes_cross_old, EP_EXPLODES_CROSS_OLD },
+ { ep_protected, EP_PROTECTED },
+ { ep_throwable, EP_THROWABLE },
+ { ep_can_explode, EP_CAN_EXPLODE },
+ { ep_gravity_reachable, EP_GRAVITY_REACHABLE },
{ ep_player, EP_PLAYER },
{ ep_can_pass_magic_wall, EP_CAN_PASS_MAGIC_WALL },
{ ep_amoeboid, EP_AMOEBOID },
{ ep_amoebalive, EP_AMOEBALIVE },
{ ep_has_content, EP_HAS_CONTENT },
+ { ep_can_turn_each_move, EP_CAN_TURN_EACH_MOVE },
+ { ep_can_grow, EP_CAN_GROW },
{ ep_active_bomb, EP_ACTIVE_BOMB },
{ ep_inactive, EP_INACTIVE },
EL_PACMAN_LEFT, EL_PACMAN_RIGHT,
EL_PACMAN_UP, EL_PACMAN_DOWN
},
+ {
+ EL_MOLE,
+ EL_MOLE_LEFT, EL_MOLE_RIGHT,
+ EL_MOLE_UP, EL_MOLE_DOWN
+ },
{
-1,
-1, -1, -1, -1
EP_DONT_TOUCH,
EP_DONT_RUN_INTO,
EP_GEM,
- EP_CAN_EXPLODE_BY_FIRE,
+ EP_EXPLODES_BY_FIRE,
EP_PUSHABLE,
EP_PLAYER,
EP_HAS_CONTENT,
EP_ACTIVE_BOMB,
EP_ACCESSIBLE,
+
-1
};
InitElementPropertiesStatic();
#endif
+ /* important: after initialization in InitElementPropertiesStatic(), the
+ elements are not again initialized to a default value; therefore all
+ changes have to make sure that they leave the element with a defined
+ property (which means that conditional property changes must be set to
+ a reliable default value before) */
+
/* set all special, combined or engine dependent element properties */
for (i = 0; i < MAX_NUM_ELEMENTS; i++)
{
#endif
/* ---------- INACTIVE ------------------------------------------------- */
- if (i >= EL_CHAR_START && i <= EL_CHAR_END)
- SET_PROPERTY(i, EP_INACTIVE, TRUE);
+ SET_PROPERTY(i, EP_INACTIVE, (i >= EL_CHAR_START && i <= EL_CHAR_END));
/* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
/* ---------- COLLECTIBLE ---------------------------------------------- */
SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
- IS_DROPPABLE(i)));
+ IS_DROPPABLE(i) ||
+ IS_THROWABLE(i)));
/* ---------- SNAPPABLE ------------------------------------------------ */
SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
!IS_DIGGABLE(i) &&
!IS_COLLECTIBLE(i)));
+#if 0
+ /* ---------- PROTECTED ------------------------------------------------ */
+ if (IS_ACCESSIBLE_INSIDE(i))
+ SET_PROPERTY(i, EP_PROTECTED, TRUE);
+#endif
+
/* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
else if (engine_version < VERSION_IDENT(2,2,0,0))
SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
else
+#if 1
+ SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
+ (!IS_WALKABLE(i) ||
+ IS_PROTECTED(i))));
+#else
+#if 1
SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
!IS_WALKABLE_OVER(i) &&
!IS_WALKABLE_UNDER(i)));
+#else
+ SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
+ IS_PROTECTED(i)));
+#endif
+#endif
if (IS_CUSTOM_ELEMENT(i))
{
+ /* these are additional properties which are initially false when set */
+
/* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
if (DONT_TOUCH(i))
SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
CAN_SMASH_ENEMIES(i) ||
CAN_SMASH_EVERYTHING(i)));
+#if 0
/* ---------- CAN_EXPLODE ---------------------------------------------- */
SET_PROPERTY(i, EP_CAN_EXPLODE, (CAN_EXPLODE_BY_FIRE(i) ||
CAN_EXPLODE_SMASHED(i) ||
CAN_EXPLODE_IMPACT(i)));
+#endif
+#if 0
/* ---------- CAN_EXPLODE_3X3 ------------------------------------------ */
+#if 0
+ SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (!CAN_EXPLODE_1X1(i) &&
+ !CAN_EXPLODE_CROSS(i)));
+#else
SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (CAN_EXPLODE(i) &&
- !CAN_EXPLODE_1X1(i)));
+ !CAN_EXPLODE_1X1(i) &&
+ !CAN_EXPLODE_CROSS(i)));
+#endif
+#endif
+
+ /* ---------- CAN_EXPLODE_BY_FIRE -------------------------------------- */
+ SET_PROPERTY(i, EP_CAN_EXPLODE_BY_FIRE, (CAN_EXPLODE(i) &&
+ EXPLODES_BY_FIRE(i)));
+
+ /* ---------- CAN_EXPLODE_SMASHED -------------------------------------- */
+ SET_PROPERTY(i, EP_CAN_EXPLODE_SMASHED, (CAN_EXPLODE(i) &&
+ EXPLODES_SMASHED(i)));
+
+ /* ---------- CAN_EXPLODE_IMPACT --------------------------------------- */
+ SET_PROPERTY(i, EP_CAN_EXPLODE_IMPACT, (CAN_EXPLODE(i) &&
+ EXPLODES_IMPACT(i)));
+
+ /* ---------- CAN_EXPLODE_BY_DRAGONFIRE -------------------------------- */
+ SET_PROPERTY(i, EP_CAN_EXPLODE_BY_DRAGONFIRE, CAN_EXPLODE_BY_FIRE(i));
+
+ /* ---------- CAN_EXPLODE_BY_EXPLOSION --------------------------------- */
+ SET_PROPERTY(i, EP_CAN_EXPLODE_BY_EXPLOSION, (CAN_EXPLODE_BY_FIRE(i) ||
+ i == EL_BLACK_ORB));
+
+ /* ---------- COULD_MOVE_INTO_ACID ------------------------------------- */
+ SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, (ELEM_IS_PLAYER(i) ||
+ CAN_MOVE(i) ||
+ IS_CUSTOM_ELEMENT(i)));
+
+ /* ---------- MAYBE_DONT_COLLIDE_WITH ---------------------------------- */
+ SET_PROPERTY(i, EP_MAYBE_DONT_COLLIDE_WITH, (i == EL_SP_SNIKSNAK ||
+ i == EL_SP_ELECTRON));
+
+ /* ---------- CAN_MOVE_INTO_ACID --------------------------------------- */
+ if (COULD_MOVE_INTO_ACID(i) && !IS_CUSTOM_ELEMENT(i))
+ SET_PROPERTY(i, EP_CAN_MOVE_INTO_ACID,
+ getMoveIntoAcidProperty(&level, i));
+
+ /* ---------- DONT_COLLIDE_WITH ---------------------------------------- */
+ if (MAYBE_DONT_COLLIDE_WITH(i))
+ SET_PROPERTY(i, EP_DONT_COLLIDE_WITH,
+ getDontCollideWithProperty(&level, i));
+
+ /* ---------- SP_PORT -------------------------------------------------- */
+ SET_PROPERTY(i, EP_SP_PORT, (IS_SP_ELEMENT(i) &&
+ IS_PASSABLE_INSIDE(i)));
/* ---------- CAN_CHANGE ----------------------------------------------- */
SET_PROPERTY(i, EP_CAN_CHANGE, FALSE); /* default: cannot change */
if (element_info[element].push_delay_random == -1)
element_info[element].push_delay_random = game.default_push_delay_random;
}
+
+ /* set some other uninitialized values of custom elements in older levels */
+ if (engine_version < VERSION_IDENT(3,1,0,0))
+ {
+ for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ int element = EL_CUSTOM_START + i;
+
+ element_info[element].access_direction = MV_ALL_DIRECTIONS;
+
+ element_info[element].explosion_delay = 17;
+ element_info[element].ignition_delay = 8;
+ }
+ }
+
+#if 0
+ /* set element properties that were handled incorrectly in older levels */
+ if (engine_version < VERSION_IDENT(3,1,0,0))
+ {
+ SET_PROPERTY(EL_SP_SNIKSNAK, EP_DONT_COLLIDE_WITH, FALSE);
+ SET_PROPERTY(EL_SP_ELECTRON, EP_DONT_COLLIDE_WITH, FALSE);
+ }
#endif
+
+#endif
+
+ /* this is needed because some graphics depend on element properties */
+ if (game_status == GAME_MODE_PLAYING)
+ InitElementGraphicInfo();
}
static void InitGlobal()
{
global.autoplay_leveldir = NULL;
+ global.convert_leveldir = NULL;
global.frames_per_second = 0;
global.fps_slowdown = FALSE;
global.autoplay_level_nr = atoi(str_ptr); /* get level_nr value */
}
}
+ else if (strncmp(command, "convert ", 8) == 0)
+ {
+ char *str_copy = getStringCopy(&command[8]);
+ char *str_ptr = strchr(str_copy, ' ');
+
+ global.convert_leveldir = str_copy;
+ global.convert_level_nr = -1;
+
+ if (str_ptr != NULL)
+ {
+ *str_ptr++ = '\0'; /* terminate leveldir string */
+ global.convert_level_nr = atoi(str_ptr); /* get level_nr value */
+ }
+ }
else
{
Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
void InitNetworkServer()
{
-#if defined(PLATFORM_UNIX)
+#if defined(NETWORK_AVALIABLE)
int nr_wanted;
#endif
if (!options.network)
return;
-#if defined(PLATFORM_UNIX)
+#if defined(NETWORK_AVALIABLE)
nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
if (!ConnectToServer(options.server_host, options.server_port))
return artwork_new_identifier;
}
-void ReloadCustomArtwork()
+void ReloadCustomArtwork(int force_reload)
{
char *gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
char *snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
char *mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
+ boolean force_reload_gfx = (force_reload & (1 << ARTWORK_TYPE_GRAPHICS));
+ boolean force_reload_snd = (force_reload & (1 << ARTWORK_TYPE_SOUNDS));
+ boolean force_reload_mus = (force_reload & (1 << ARTWORK_TYPE_MUSIC));
boolean redraw_screen = FALSE;
- if (gfx_new_identifier != NULL)
+ if (gfx_new_identifier != NULL || force_reload_gfx)
{
#if 0
printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
redraw_screen = TRUE;
}
- if (snd_new_identifier != NULL)
+ if (snd_new_identifier != NULL || force_reload_snd)
{
ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
redraw_screen = TRUE;
}
- if (mus_new_identifier != NULL)
+ if (mus_new_identifier != NULL || force_reload_mus)
{
ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
AutoPlayTape();
return;
}
+ else if (global.convert_leveldir)
+ {
+ ConvertLevels();
+ return;
+ }
game_status = GAME_MODE_MAIN;
FreeAllImages();
FreeTileClipmasks();
+#if defined(TARGET_SDL)
+ if (network_server) /* terminate network server */
+ SDL_KillThread(server_thread);
+#endif
+
CloseVideoDisplay();
ClosePlatformDependentStuff();
#include "main.h"
+#if 1
+#define setMoveIntoAcidProperty(l, e, v) \
+ (setBitfieldProperty(&(l)->can_move_into_acid_bits, \
+ EP_CAN_MOVE_INTO_ACID, e, v))
+#define getMoveIntoAcidProperty(l, e) \
+ (getBitfieldProperty(&(l)->can_move_into_acid_bits, \
+ EP_CAN_MOVE_INTO_ACID, e))
+#define setDontCollideWithProperty(l, e, v) \
+ (setBitfieldProperty(&(l)->can_move_into_acid_bits, \
+ EP_DONT_COLLIDE_WITH, e, v))
+#define getDontCollideWithProperty(l, e) \
+ (getBitfieldProperty(&(l)->can_move_into_acid_bits, \
+ EP_DONT_COLLIDE_WITH, e))
+
+void setBitfieldProperty(int *, int, int, boolean);
+boolean getBitfieldProperty(int *, int, int);
+
+#else
+
+void setMoveIntoAcidProperty(struct LevelInfo *, int, boolean);
+boolean getMoveIntoAcidProperty(struct LevelInfo *, int);
+#endif
+
void InitElementPropertiesStatic(void);
void InitElementPropertiesEngine(int);
-void ReloadCustomArtwork(void);
+void ReloadCustomArtwork(int);
void KeyboardAutoRepeatOffUnlessAutoplay();
{
gi->selectbox.open = FALSE;
- /* redraw closed selectbox */
- DrawGadget(gi, FALSE, FALSE);
-
/* restore background under selectbox */
BlitBitmap(gfx.field_save_buffer, drawto,
gi->selectbox.x, gi->selectbox.y,
gi->selectbox.width, gi->selectbox.height,
gi->selectbox.x, gi->selectbox.y);
+ /* redraw closed selectbox */
+ DrawGadget(gi, FALSE, FALSE);
+
redraw_selectbox = TRUE;
}
}
gi->y > gfx.vy ? REDRAW_DOOR_2 : REDRAW_DOOR_3);
}
+static int get_minimal_size_for_numeric_input(int minmax_value)
+{
+ int min_size = 1; /* value needs at least one digit */
+ int i;
+
+ /* add number of digits needed for absolute value */
+ for (i = 10; i <= ABS(minmax_value); i *= 10)
+ min_size++;
+
+ /* if min/max value is negative, add one digit for minus sign */
+ if (minmax_value < 0)
+ min_size++;
+
+ return min_size;
+}
+
static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
{
int tag = first_tag;
int border_xsize = gi->border.xsize;
int border_ysize = gi->border.ysize;
+ if (gi->type == GD_TYPE_TEXT_INPUT_NUMERIC)
+ {
+ int number_min = gi->textinput.number_min;
+ int number_max = gi->textinput.number_max;
+ int min_size_min = get_minimal_size_for_numeric_input(number_min);
+ int min_size_max = get_minimal_size_for_numeric_input(number_max);
+ int min_size = MAX(min_size_min, min_size_max);
+
+ /* expand gadget text input size, if maximal value is too large */
+ if (gi->textinput.size < min_size)
+ gi->textinput.size = min_size;
+ }
+
gi->width = 2 * border_xsize + (gi->textinput.size + 1) * font_width;
gi->height = 2 * border_ysize + font_height;
}
return (last_gi && (last_gi->type & GD_TYPE_SELECTBOX) && last_gi->mapped);
}
+static boolean insideSelectboxLine(struct GadgetInfo *gi, int mx, int my)
+{
+ return(gi != NULL &&
+ gi->type & GD_TYPE_SELECTBOX &&
+ mx >= gi->x && mx < gi->x + gi->width &&
+ my >= gi->y && my < gi->y + gi->height);
+}
+
+static boolean insideSelectboxArea(struct GadgetInfo *gi, int mx, int my)
+{
+ return(gi != NULL &&
+ gi->type & GD_TYPE_SELECTBOX &&
+ mx >= gi->selectbox.x && mx < gi->selectbox.x + gi->selectbox.width &&
+ my >= gi->selectbox.y && my < gi->selectbox.y + gi->selectbox.height);
+}
+
boolean anyTextGadgetActive()
{
return (anyTextInputGadgetActive() ||
static unsigned long pressed_delay = 0;
static int last_button = 0;
static int last_mx = 0, last_my = 0;
+ static int pressed_mx = 0, pressed_my = 0;
int scrollbar_mouse_pos = 0;
struct GadgetInfo *new_gi, *gi;
boolean press_event;
boolean release_event;
boolean mouse_moving;
+ boolean mouse_inside_select_line;
+ boolean mouse_inside_select_area;
+ boolean mouse_released_where_pressed;
boolean gadget_pressed;
boolean gadget_pressed_repeated;
+ boolean gadget_pressed_off_borders;
+ boolean gadget_pressed_inside_select_line;
boolean gadget_moving;
boolean gadget_moving_inside;
boolean gadget_moving_off_borders;
last_mx = mx;
last_my = my;
+ if (press_event && new_gi != last_gi)
+ {
+ pressed_mx = mx;
+ pressed_my = my;
+ }
+
+ mouse_released_where_pressed =
+ (release_event && mx == pressed_mx && my == pressed_my);
+
+ mouse_inside_select_line = insideSelectboxLine(new_gi, mx, my);
+ mouse_inside_select_area = insideSelectboxArea(new_gi, mx, my);
+
+ gadget_pressed_off_borders = (press_event && new_gi != last_gi);
+
+ gadget_pressed_inside_select_line =
+ (press_event && new_gi != NULL &&
+ new_gi->type & GD_TYPE_SELECTBOX && new_gi->selectbox.open &&
+ insideSelectboxLine(new_gi, mx, my));
+
/* if mouse button pressed outside text or selectbox gadget, deactivate it */
+#if 1
+ if (anyTextGadgetActive() &&
+ (gadget_pressed_off_borders ||
+ (gadget_pressed_inside_select_line && !mouse_inside_select_area)))
+#else
if (anyTextGadgetActive() &&
button != 0 && !motion_status && new_gi != last_gi)
+#endif
{
CheckRangeOfNumericInputGadget(last_gi); /* in case of numeric gadget */
last_gi->callback_action(last_gi);
last_gi = NULL;
+
+ if (gadget_pressed_inside_select_line)
+ new_gi = NULL;
}
gadget_pressed =
{
struct GadgetInfo *gi = last_gi;
+#if 1
+ gadget_released_inside_select_line = insideSelectboxLine(gi, mx, my);
+ gadget_released_inside_select_area = insideSelectboxArea(gi, mx, my);
+#else
gadget_released_inside_select_line =
(mx >= gi->x && mx < gi->x + gi->width &&
my >= gi->y && my < gi->y + gi->height);
gadget_released_inside_select_area =
(mx >= gi->selectbox.x && mx < gi->selectbox.x + gi->selectbox.width &&
my >= gi->selectbox.y && my < gi->selectbox.y + gi->selectbox.height);
+#endif
}
else
{
/* if mouse button released, no gadget needs to be handled anymore */
if (gadget_released)
{
- if (last_gi->type & GD_TYPE_SELECTBOX &&
+#if 1
+ if (gi->type & GD_TYPE_SELECTBOX &&
+ (mouse_released_where_pressed ||
+ !gadget_released_inside_select_area)) /* selectbox stays open */
+ {
+ gi->selectbox.stay_open = TRUE;
+ pressed_mx = 0;
+ pressed_my = 0;
+ }
+#else
+ if (gi->type & GD_TYPE_SELECTBOX &&
(gadget_released_inside_select_line ||
gadget_released_off_borders)) /* selectbox stays open */
gi->selectbox.stay_open = TRUE;
- else if (!(last_gi->type & GD_TYPE_TEXT_INPUT ||
- last_gi->type & GD_TYPE_TEXT_AREA)) /* text input stays open */
+#endif
+ else if (!(gi->type & GD_TYPE_TEXT_INPUT ||
+ gi->type & GD_TYPE_TEXT_AREA)) /* text input stays open */
last_gi = NULL;
}
if (gi->textarea.cursor_position != old_cursor_position)
DrawGadget(gi, DG_PRESSED, gi->direct_draw);
}
- else if (gi->type & GD_TYPE_SELECTBOX)
+ else if (gi->type & GD_TYPE_SELECTBOX && gi->selectbox.open)
{
int old_index = gi->selectbox.current_index;
if (gi->type & GD_TYPE_SELECTBOX)
{
+#if 1
+ if (mouse_released_where_pressed ||
+ !gadget_released_inside_select_area) /* selectbox stays open */
+ deactivate_gadget = FALSE;
+#else
if (gadget_released_inside_select_line ||
- gadget_released_off_borders) /* selectbox stays open */
+ gadget_released_off_borders) /* selectbox stays open */
deactivate_gadget = FALSE;
+#endif
else
gi->selectbox.index = gi->selectbox.current_index;
}
XPutImage(ximageinfo->display, ximageinfo->pixmap, gc,
ximage, 0, 0, 0, 0, ximage->width, ximage->height);
- XDestroyImage(ximage);
+ X11DestroyImage(ximage);
return ximageinfo;
}
dst_width, dst_height);
/* free temporary images */
- XDestroyImage(src_ximage);
- XDestroyImage(dst_ximage);
+ X11DestroyImage(src_ximage);
+ X11DestroyImage(dst_ximage);
}
void freeXImage(Image *image, XImageInfo *ximageinfo)
if ((img_info->bitmap = LoadImage(filename)) == NULL)
{
- Error(ERR_WARN, "cannot read image file '%s': LoadImage() failed: %s",
+ Error(ERR_WARN, "cannot load image file '%s': LoadImage() failed: %s",
filename, GetError());
free(img_info);
return NULL;
fprintf_line(stdout, line_string, line_length);
}
+
/* int2str() returns a number converted to a string;
the used memory is static, but will be overwritten by later calls,
so if you want to save the result, copy it to a private string buffer;
}
}
+
/* something similar to "int2str()" above, but allocates its own memory
and has a different interface; we cannot use "itoa()", because this
seems to be already defined when cross-compiling to the win32 target */
}
+/* calculate base-2 logarithm of argument (rounded down to integer;
+ this function returns the number of the highest bit set in argument) */
+
+int log_2(unsigned int x)
+{
+ int e = 0;
+
+ while ((1 << e) < x)
+ {
+ x -= (1 << e); /* for rounding down (rounding up: remove this line) */
+ e++;
+ }
+
+ return e;
+}
+
+
/* ------------------------------------------------------------------------- */
/* counter functions */
/* ------------------------------------------------------------------------- */
if (option_arg == next_option)
options_left++;
- /* adjust path for level directory accordingly */
+ /* adjust paths for sub-directories in base directory accordingly */
options.level_directory =
getPath2(options.ro_base_directory, LEVELS_DIRECTORY);
+ options.graphics_directory =
+ getPath2(options.ro_base_directory, GRAPHICS_DIRECTORY);
+ options.sounds_directory =
+ getPath2(options.ro_base_directory, SOUNDS_DIRECTORY);
+ options.music_directory =
+ getPath2(options.ro_base_directory, MUSIC_DIRECTORY);
+ options.docs_directory =
+ getPath2(options.ro_base_directory, DOCS_DIRECTORY);
}
else if (strncmp(option, "-levels", option_len) == 0)
{
options.execute_command = option_arg;
if (option_arg == next_option)
options_left++;
+
+#if 1
+ /* when doing batch processing, always enable verbose mode (warnings) */
+ options.verbose = TRUE;
+#endif
}
else if (*option == '-')
{
*y2 = help_y;
}
-short getFile16BitInteger(FILE *file, int byte_order)
+int getFile16BitInteger(FILE *file, int byte_order)
{
if (byte_order == BYTE_ORDER_BIG_ENDIAN)
- return ((fgetc(file) << 8) |
- (fgetc(file) << 0));
+ return ((fgetc(file) << 8) |
+ (fgetc(file) << 0));
else /* BYTE_ORDER_LITTLE_ENDIAN */
- return ((fgetc(file) << 0) |
- (fgetc(file) << 8));
+ return ((fgetc(file) << 0) |
+ (fgetc(file) << 8));
}
-void putFile16BitInteger(FILE *file, short value, int byte_order)
+void putFile16BitInteger(FILE *file, int value, int byte_order)
{
if (byte_order == BYTE_ORDER_BIG_ENDIAN)
{
- fputc((value >> 8) & 0xff, file);
- fputc((value >> 0) & 0xff, file);
+ fputc((value >> 8) & 0xff, file);
+ fputc((value >> 0) & 0xff, file);
}
else /* BYTE_ORDER_LITTLE_ENDIAN */
{
- fputc((value >> 0) & 0xff, file);
- fputc((value >> 8) & 0xff, file);
+ fputc((value >> 0) & 0xff, file);
+ fputc((value >> 8) & 0xff, file);
}
}
char c = name_ptr[6];
if (c >= '0' && c <= '9')
- key = KSYM_0 + (Key)(c - '0');
+ key = KSYM_KP_0 + (Key)(c - '0');
}
else if (strncmp(name_ptr, "XK_F", 4) == 0 && strlen(name_ptr) <= 6)
{
new_list_entry = &(*list)[*num_list_entries - 1];
new_list_entry->token = getStringCopy(token);
+ new_list_entry->default_filename = NULL;
new_list_entry->filename = NULL;
new_list_entry->parameter = checked_calloc(parameter_array_size);
#endif
for (i = 0; i < num_dynamic_file_list_entries; i++)
+ {
LoadArtworkToList(artwork_info, &artwork_info->dynamic_artwork_list[i],
dynamic_file_list[i].filename, i);
+#if 0
+ printf("::: '%s', '0x%08x'\n",
+ dynamic_file_list[i].filename,
+ dynamic_file_list[i].default_filename);
+#endif
+ }
+
#if 0
dumpList(artwork_info->content_list);
#endif
void printf_line(char *, int);
char *int2str(int, int);
char *i_to_a(unsigned int);
+int log_2(unsigned int);
void InitCounter(void);
unsigned long Counter(void);
inline void swap_numbers(int *, int *);
inline void swap_number_pairs(int *, int *, int *, int *);
-short getFile16BitInteger(FILE *, int);
-void putFile16BitInteger(FILE *, short, int);
+int getFile16BitInteger(FILE *, int);
+void putFile16BitInteger(FILE *, int, int);
int getFile32BitInteger(FILE *, int);
void putFile32BitInteger(FILE *, int, int);
boolean getFileChunk(FILE *, char *, int *, int);
#define PLATFORM_UNIX
#endif
+
/* ========================================================================= */
/* define additional keywords for MS-DOS platform */
/* ========================================================================= */
#endif
+
/* ========================================================================= */
/* define additional keywords for several Unix platforms */
/* ========================================================================= */
#define PLATFORM_MACOSX
#endif
+#if defined(NeXT)
+#define PLATFORM_NEXT
+#endif
+
/* detecting HP-UX by the following compiler keyword definitions:
- in K&R mode (the default), the HP C compiler defines "hpux"
- in ANSI mode (-Aa or -Ae), the HP C compiler defines "__hpux"
#define PLATFORM_HPUX
#endif
+
+/* ========================================================================= */
+/* this should better go into "system.h" or "features.h" (yet to be created) */
+/* ========================================================================= */
+
+#if defined(PLATFORM_UNIX) || defined(TARGET_SDL)
+#define NETWORK_AVALIABLE
+#endif
+
+
#endif /* PLATFORM_H */
#include "SDL.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
+#include "SDL_net.h"
+#include "SDL_thread.h"
/* definitions needed for "system.c" */
return level_dir;
}
-static char *getCurrentLevelDir()
+char *getCurrentLevelDir()
{
return getLevelDirFromTreeInfo(leveldir_current);
}
return LEVELDIR_ARTWORK_PATH(leveldir_current, type);
}
-char *getLevelFilename(int nr)
-{
- static char *filename = NULL;
- char basename[MAX_FILENAME_LEN];
-
- checked_free(filename);
-
- if (nr < 0)
- sprintf(basename, "template.%s", LEVELFILE_EXTENSION);
- else
- sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION);
-
- filename = getPath2(getCurrentLevelDir(), basename);
-
- return filename;
-}
-
char *getTapeFilename(int nr)
{
static char *filename = NULL;
checked_free(filename);
sprintf(basename, "%03d.%s", nr, TAPEFILE_EXTENSION);
- filename = getPath2(getTapeDir(leveldir_current->filename), basename);
+ filename = getPath2(getTapeDir(leveldir_current->subdir), basename);
return filename;
}
checked_free(filename);
sprintf(basename, "%03d.%s", nr, SCOREFILE_EXTENSION);
- filename = getPath2(getScoreDir(leveldir_current->filename), basename);
+ filename = getPath2(getScoreDir(leveldir_current->subdir), basename);
return filename;
}
printf(" ");
#if 1
- printf("filename == '%s' ['%s', '%s'] [%d])\n",
- node->filename, node->fullpath, node->basepath, node->user_defined);
+ printf("subdir == '%s' ['%s', '%s'] [%d])\n",
+ node->subdir, node->fullpath, node->basepath, node->user_defined);
#else
- printf("filename == '%s' (%s) [%s] (%d)\n",
- node->filename, node->name, node->identifier, node->sort_priority);
+ printf("subdir == '%s' (%s) [%s] (%d)\n",
+ node->subdir, node->name, node->identifier, node->sort_priority);
#endif
if (node->node_group != NULL)
#define LEVELINFO_TOKEN_GRAPHICS_SET 11
#define LEVELINFO_TOKEN_SOUNDS_SET 12
#define LEVELINFO_TOKEN_MUSIC_SET 13
+#define LEVELINFO_TOKEN_FILENAME 14
+#define LEVELINFO_TOKEN_FILETYPE 15
+#define LEVELINFO_TOKEN_HANDICAP 16
-#define NUM_LEVELINFO_TOKENS 14
+#define NUM_LEVELINFO_TOKENS 17
static LevelDirTree ldi;
static struct TokenInfo levelinfo_tokens[] =
{
/* level directory info */
- { TYPE_STRING, &ldi.identifier, "identifier" },
- { TYPE_STRING, &ldi.name, "name" },
- { TYPE_STRING, &ldi.name_sorting, "name_sorting" },
- { TYPE_STRING, &ldi.author, "author" },
- { TYPE_STRING, &ldi.imported_from, "imported_from" },
- { TYPE_INTEGER, &ldi.levels, "levels" },
- { TYPE_INTEGER, &ldi.first_level, "first_level" },
- { TYPE_INTEGER, &ldi.sort_priority, "sort_priority" },
- { TYPE_BOOLEAN, &ldi.latest_engine, "latest_engine" },
- { TYPE_BOOLEAN, &ldi.level_group, "level_group" },
- { TYPE_BOOLEAN, &ldi.readonly, "readonly" },
- { TYPE_STRING, &ldi.graphics_set, "graphics_set" },
- { TYPE_STRING, &ldi.sounds_set, "sounds_set" },
- { TYPE_STRING, &ldi.music_set, "music_set" }
+ { TYPE_STRING, &ldi.identifier, "identifier" },
+ { TYPE_STRING, &ldi.name, "name" },
+ { TYPE_STRING, &ldi.name_sorting, "name_sorting" },
+ { TYPE_STRING, &ldi.author, "author" },
+ { TYPE_STRING, &ldi.imported_from, "imported_from" },
+ { TYPE_INTEGER, &ldi.levels, "levels" },
+ { TYPE_INTEGER, &ldi.first_level, "first_level" },
+ { TYPE_INTEGER, &ldi.sort_priority, "sort_priority" },
+ { TYPE_BOOLEAN, &ldi.latest_engine, "latest_engine" },
+ { TYPE_BOOLEAN, &ldi.level_group, "level_group" },
+ { TYPE_BOOLEAN, &ldi.readonly, "readonly" },
+ { TYPE_STRING, &ldi.graphics_set, "graphics_set" },
+ { TYPE_STRING, &ldi.sounds_set, "sounds_set" },
+ { TYPE_STRING, &ldi.music_set, "music_set" },
+ { TYPE_STRING, &ldi.level_filename, "filename" },
+ { TYPE_STRING, &ldi.level_filetype, "filetype" },
+ { TYPE_BOOLEAN, &ldi.handicap, "handicap" }
};
static void setTreeInfoToDefaults(TreeInfo *ldi, int type)
ldi->cl_first = -1;
ldi->cl_cursor = -1;
- ldi->filename = NULL;
+ ldi->subdir = NULL;
ldi->fullpath = NULL;
ldi->basepath = NULL;
ldi->identifier = NULL;
ldi->sounds_path = getStringCopy(UNDEFINED_FILENAME);
ldi->music_path = getStringCopy(UNDEFINED_FILENAME);
+ ldi->level_filename = NULL;
+ ldi->level_filetype = NULL;
+
ldi->levels = 0;
ldi->first_level = 0;
ldi->last_level = 0;
ldi->level_group = FALSE;
ldi->handicap_level = 0;
ldi->readonly = TRUE;
+ ldi->handicap = TRUE;
}
}
ldi->cl_first = -1;
ldi->cl_cursor = -1;
- ldi->filename = NULL;
+ ldi->subdir = NULL;
ldi->fullpath = NULL;
ldi->basepath = NULL;
ldi->identifier = NULL;
ldi->sounds_path = getStringCopy(UNDEFINED_FILENAME);
ldi->music_path = getStringCopy(UNDEFINED_FILENAME);
+ ldi->level_filename = NULL;
+ ldi->level_filetype = NULL;
+
ldi->levels = 0;
ldi->first_level = 0;
ldi->last_level = 0;
ldi->level_group = FALSE;
ldi->handicap_level = 0;
ldi->readonly = TRUE;
+ ldi->handicap = TRUE;
}
-
#else
/* first copy all values from the parent structure ... */
other structure's pointer may point to them!
*/
- ldi->filename = NULL;
+ ldi->subdir = NULL;
ldi->fullpath = NULL;
ldi->basepath = NULL;
ldi->identifier = NULL;
static void freeTreeInfo(TreeInfo *ldi)
{
- checked_free(ldi->filename);
+ checked_free(ldi->subdir);
checked_free(ldi->fullpath);
checked_free(ldi->basepath);
checked_free(ldi->identifier);
if (ldi->type == TREE_TYPE_LEVEL_DIR)
{
+ checked_free(ldi->imported_from);
+
checked_free(ldi->graphics_set);
checked_free(ldi->sounds_set);
checked_free(ldi->music_set);
checked_free(ldi->graphics_path);
checked_free(ldi->sounds_path);
checked_free(ldi->music_path);
+
+ checked_free(ldi->level_filename);
+ checked_free(ldi->level_filetype);
}
}
setString(&ti_new->name, ".. (parent directory)");
setString(&ti_new->name_sorting, ti_new->name);
- setString(&ti_new->filename, "..");
+ setString(&ti_new->subdir, "..");
setString(&ti_new->fullpath, node_parent->fullpath);
ti_new->sort_priority = node_parent->sort_priority;
ti_new->name = ".. (parent directory)";
ti_new->name_sorting = getStringCopy(ti_new->name);
- ti_new->filename = "..";
+ ti_new->subdir = "..";
ti_new->fullpath = getStringCopy(node_parent->fullpath);
ti_new->sort_priority = node_parent->sort_priority;
else
setTreeInfoToDefaults(leveldir_new, TREE_TYPE_LEVEL_DIR);
- leveldir_new->filename = getStringCopy(directory_name);
+ leveldir_new->subdir = getStringCopy(directory_name);
checkSetupFileHashIdentifier(setup_file_hash, getCookie("LEVELINFO"));
#if 1
if (strcmp(leveldir_new->name, ANONYMOUS_NAME) == 0)
- setString(&leveldir_new->name, leveldir_new->filename);
+ setString(&leveldir_new->name, leveldir_new->subdir);
#else
if (strcmp(leveldir_new->name, ANONYMOUS_NAME) == 0)
{
free(leveldir_new->name);
- leveldir_new->name = getStringCopy(leveldir_new->filename);
+ leveldir_new->name = getStringCopy(leveldir_new->subdir);
}
#endif
DrawInitText(leveldir_new->name, 150, FC_YELLOW);
if (leveldir_new->identifier == NULL)
- leveldir_new->identifier = getStringCopy(leveldir_new->filename);
+ leveldir_new->identifier = getStringCopy(leveldir_new->subdir);
if (leveldir_new->name_sorting == NULL)
leveldir_new->name_sorting = getStringCopy(leveldir_new->name);
if (node_parent == NULL) /* top level group */
{
leveldir_new->basepath = getStringCopy(level_directory);
- leveldir_new->fullpath = getStringCopy(leveldir_new->filename);
+ leveldir_new->fullpath = getStringCopy(leveldir_new->subdir);
}
else /* sub level group */
{
#endif
leveldir_new->handicap_level = /* set handicap to default value */
- (leveldir_new->user_defined ?
- leveldir_new->last_level :
- leveldir_new->first_level);
+ (leveldir_new->user_defined || !leveldir_new->handicap ?
+ leveldir_new->last_level : leveldir_new->first_level);
pushTreeInfo(node_first, leveldir_new);
else
setTreeInfoToDefaults(artwork_new, type);
- artwork_new->filename = getStringCopy(directory_name);
+ artwork_new->subdir = getStringCopy(directory_name);
if (setup_file_hash) /* (before defining ".color" and ".class_desc") */
{
#if 1
if (strcmp(artwork_new->name, ANONYMOUS_NAME) == 0)
- setString(&artwork_new->name, artwork_new->filename);
+ setString(&artwork_new->name, artwork_new->subdir);
#else
if (strcmp(artwork_new->name, ANONYMOUS_NAME) == 0)
{
free(artwork_new->name);
- artwork_new->name = getStringCopy(artwork_new->filename);
+ artwork_new->name = getStringCopy(artwork_new->subdir);
}
#endif
#endif
if (artwork_new->identifier == NULL)
- artwork_new->identifier = getStringCopy(artwork_new->filename);
+ artwork_new->identifier = getStringCopy(artwork_new->subdir);
if (artwork_new->name_sorting == NULL)
artwork_new->name_sorting = getStringCopy(artwork_new->name);
if (node_parent == NULL) /* top level group */
{
artwork_new->basepath = getStringCopy(base_directory);
- artwork_new->fullpath = getStringCopy(artwork_new->filename);
+ artwork_new->fullpath = getStringCopy(artwork_new->subdir);
}
else /* sub level group */
{
}
#endif
- if (strcmp(artwork_new->filename, ".") == 0)
+ if (strcmp(artwork_new->subdir, ".") == 0)
{
if (artwork_new->user_defined)
{
else
{
#if 1
- setString(&artwork_new->identifier, artwork_new->filename);
+ setString(&artwork_new->identifier, artwork_new->subdir);
#else
- artwork_new->identifier = getStringCopy(artwork_new->filename);
+ artwork_new->identifier = getStringCopy(artwork_new->subdir);
#endif
}
setTreeInfoToDefaults(artwork_new, type);
#if 1
- setString(&artwork_new->filename, UNDEFINED_FILENAME);
+ setString(&artwork_new->subdir, UNDEFINED_FILENAME);
setString(&artwork_new->fullpath, UNDEFINED_FILENAME);
setString(&artwork_new->basepath, UNDEFINED_FILENAME);
setString(&artwork_new->name, UNDEFINED_FILENAME);
setString(&artwork_new->name_sorting, UNDEFINED_FILENAME);
#else
- artwork_new->filename = getStringCopy(UNDEFINED_FILENAME);
+ artwork_new->subdir = getStringCopy(UNDEFINED_FILENAME);
artwork_new->fullpath = getStringCopy(UNDEFINED_FILENAME);
artwork_new->basepath = getStringCopy(UNDEFINED_FILENAME);
#if 0
if (!level_node->parent_link)
printf("CHECKING '%s' ['%s', '%s'] ...\n", path,
- level_node->filename, level_node->name);
+ level_node->subdir, level_node->name);
#endif
if (!level_node->parent_link)
free((*artwork_node)->name);
free((*artwork_node)->name_sorting);
- (*artwork_node)->identifier = getStringCopy(level_node->filename);
+ (*artwork_node)->identifier = getStringCopy(level_node->subdir);
(*artwork_node)->name = getStringCopy(level_node->name);
(*artwork_node)->name_sorting = getStringCopy(level_node->name);
for (i = 0; i < NUM_LEVELINFO_TOKENS; i++)
if (i != LEVELINFO_TOKEN_IDENTIFIER &&
i != LEVELINFO_TOKEN_NAME_SORTING &&
- i != LEVELINFO_TOKEN_IMPORTED_FROM)
+ i != LEVELINFO_TOKEN_IMPORTED_FROM &&
+ i != LEVELINFO_TOKEN_FILENAME &&
+ i != LEVELINFO_TOKEN_FILETYPE)
fprintf(file, "%s\n", getSetupLine(levelinfo_tokens, "", i));
fclose(file);
/* ----------------------------------------------------------------------- */
char *filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME);
- char *level_subdir = leveldir_current->filename;
+ char *level_subdir = leveldir_current->subdir;
FILE *file;
InitUserDataDirectory();
{
char *filename;
SetupFileHash *level_setup_hash = NULL;
- char *level_subdir = leveldir_current->filename;
+ char *level_subdir = leveldir_current->subdir;
/* always start with reliable default values */
level_nr = leveldir_current->first_level;
/* ~/.<program>/levelsetup/<level series>/levelsetup.conf */
/* ----------------------------------------------------------------------- */
- level_subdir = leveldir_current->filename;
+ level_subdir = leveldir_current->subdir;
filename = getPath2(getLevelSetupDir(level_subdir), LEVELSETUP_FILENAME);
if (level_nr > leveldir_current->last_level + 1)
level_nr = leveldir_current->last_level;
- if (leveldir_current->user_defined)
+ if (leveldir_current->user_defined || !leveldir_current->handicap)
level_nr = leveldir_current->last_level;
leveldir_current->handicap_level = level_nr;
void SaveLevelSetup_SeriesInfo()
{
char *filename;
- char *level_subdir = leveldir_current->filename;
+ char *level_subdir = leveldir_current->subdir;
char *level_nr_str = int2str(level_nr, 0);
char *handicap_level_str = int2str(leveldir_current->handicap_level, 0);
FILE *file;
char *setLevelArtworkDir(TreeInfo *);
-char *getLevelFilename(int);
char *getTapeFilename(int);
char *getSolutionTapeFilename(int);
char *getScoreFilename(int);
char *getUserDataDir(void);
char *getCommonDataDir(void);
char *getSetupDir(void);
+char *getCurrentLevelDir(void);
+
void createDirectory(char *, char *, int);
void InitUserDataDirectory(void);
void SetFilePermissions(char *, int);
boolean music_already_used = FALSE;
int i;
+ /* skip all music files that are configured in music config file */
for (i = 0; i < num_music; i++)
{
struct FileInfo *music = getMusicListEntry(i);
closedir(dir);
draw_init_text = FALSE;
-
- if (num_music_noconf == 0)
- Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
- music_directory);
}
int getSoundListSize()
#if defined(TARGET_SDL)
if (SDL_Init(SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE) < 0)
Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
+
+ SDLNet_Init();
#endif
}
". c #ffffff",
" c None",
+#if 1
+ /* some people complained about a "white dot" on the screen and thought it
+ was a graphical error... OK, let's just remove the whole pointer :-) */
+
+ /* pixels */
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+
+ /* hot spot */
+ "0,0"
+#else
/* pixels */
" X ",
"X.X ",
/* hot spot */
"1,1"
+#endif
};
#if defined(TARGET_SDL)
#define DEFAULT_KEY_DOWN KSYM_Down
#if defined(PLATFORM_MACOSX)
#define DEFAULT_KEY_SNAP KSYM_Control_L
-#define DEFAULT_KEY_BOMB KSYM_KP_Enter
+#define DEFAULT_KEY_DROP KSYM_KP_Enter
#else
-#define DEFAULT_KEY_SNAP KSYM_Shift_L
-#define DEFAULT_KEY_BOMB KSYM_Shift_R
+#define DEFAULT_KEY_SNAP KSYM_Control_L
+#define DEFAULT_KEY_DROP KSYM_Control_R
#endif
#define DEFAULT_KEY_OKAY KSYM_Return
#define DEFAULT_KEY_CANCEL KSYM_Escape
(x) == MV_RIGHT ? MV_BIT_RIGHT : \
(x) == MV_UP ? MV_BIT_UP : MV_BIT_DOWN)
+#define MV_DIR_OPPOSITE(x) ((x) == MV_LEFT ? MV_RIGHT : \
+ (x) == MV_RIGHT ? MV_LEFT : \
+ (x) == MV_UP ? MV_DOWN : \
+ (x) == MV_DOWN ? MV_UP : MV_NO_MOVING)
+
/* values for animation mode (frame order and direction) */
#define ANIM_NONE 0
#define SETUP_FILENAME "setup.cnf"
#define LEVELSETUP_FILENAME "lvlsetup.cnf"
#define EDITORSETUP_FILENAME "edsetup.cnf"
-#define HELPANIM_FILENAME "helpanim.conf"
-#define HELPTEXT_FILENAME "helptext.conf"
+#define HELPANIM_FILENAME "helpanim.cnf"
+#define HELPTEXT_FILENAME "helptext.cnf"
#define LEVELINFO_FILENAME "lvlinfo.cnf"
#define GRAPHICSINFO_FILENAME "gfxinfo.cnf"
#define SOUNDSINFO_FILENAME "sndinfo.cnf"
PAGEX3: buffer for animations
*/
-#define DOOR_GFX_PAGESIZE (gfx.dxsize)
+/* these values are hard-coded to be able to use them in initialization */
+#define DOOR_GFX_PAGE_WIDTH 100 /* should be set to "gfx.dxsize" */
+#define DOOR_GFX_PAGE_HEIGHT 280 /* should be set to "gfx.dysize" */
+
+#define DOOR_GFX_PAGESIZE (DOOR_GFX_PAGE_WIDTH)
#define DOOR_GFX_PAGEX1 (0 * DOOR_GFX_PAGESIZE)
#define DOOR_GFX_PAGEX2 (1 * DOOR_GFX_PAGESIZE)
#define DOOR_GFX_PAGEX3 (2 * DOOR_GFX_PAGESIZE)
#define DOOR_GFX_PAGEX7 (6 * DOOR_GFX_PAGESIZE)
#define DOOR_GFX_PAGEX8 (7 * DOOR_GFX_PAGESIZE)
#define DOOR_GFX_PAGEY1 (0)
-#define DOOR_GFX_PAGEY2 (gfx.dysize)
+#define DOOR_GFX_PAGEY2 (DOOR_GFX_PAGE_HEIGHT)
/* macros for version handling */
int xleft, xmiddle, xright;
int yupper, ymiddle, ylower;
- int snap;
- int bomb;
+ int snap, drop;
};
struct SetupKeyboardInfo
{
- Key left;
- Key right;
- Key up;
- Key down;
- Key snap;
- Key bomb;
+ Key left, right, up, down;
+ Key snap, drop;
};
struct SetupInputInfo
/* fields for "type == TREE_TYPE_LEVEL_DIR" */
- char *filename; /* tree info sub-directory basename (may be ".") */
+ char *subdir; /* tree info sub-directory basename (may be ".") */
char *fullpath; /* complete path relative to tree base directory */
char *basepath; /* absolute base path of tree base directory */
char *identifier; /* identifier string for configuration files */
char *sounds_path; /* path to optional custom sounds set (level only) */
char *music_path; /* path to optional custom music set (level only) */
+ char *level_filename; /* filename of level file (for packed level file) */
+ char *level_filetype; /* type of levels in level directory or level file */
+
int levels; /* number of levels in level series */
int first_level; /* first level number (to allow start with 0 or 1) */
int last_level; /* last level number (automatically calculated) */
boolean parent_link; /* entry links back to parent directory */
boolean user_defined; /* user defined levels are stored in home directory */
boolean readonly; /* readonly levels can not be changed with editor */
+ boolean handicap; /* level set has no handicap when set to "false" */
int color; /* color to use on selection screen for this level */
char *class_desc; /* description of level series class */
AllPlanes, ZPixmap);
pixel_value = XGetPixel(pixel_image, 0, 0);
- XDestroyImage(pixel_image);
+ X11DestroyImage(pixel_image);
return pixel_value;
}
}
#endif /* TARGET_X11_NATIVE */
+inline void X11DestroyImage(XImage *ximage)
+{
+#if defined(TARGET_X11_NATIVE)
+ /* this seems to be needed for OS/2, but does not hurt on other platforms */
+ if (ximage->data != NULL)
+ {
+ free(ximage->data);
+ ximage->data = NULL;
+ }
+#endif /* TARGET_X11_NATIVE */
+
+ XDestroyImage(ximage);
+}
+
/* ------------------------------------------------------------------------- */
/* mouse pointer functions */
inline void X11DrawSimpleLine(Bitmap *, int, int, int, int, Pixel);
inline Pixel X11GetPixel(Bitmap *, int, int);
inline Pixel X11GetPixelFromRGB(unsigned int, unsigned int, unsigned int);
+inline void X11DestroyImage(XImage *);
#if defined(TARGET_X11_NATIVE)
void X11SetMouseCursor(struct MouseCursorInfo *);
boolean level_editor_test_game = FALSE;
boolean network_playing = FALSE;
+#if defined(TARGET_SDL)
+boolean network_server = FALSE;
+SDL_Thread *server_thread;
+#endif
+
int key_joystick_mapping = 0;
boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
unsigned long ChangeEvent[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
short WasJustMoving[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
short WasJustFalling[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+short CheckCollision[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
short AmoebaNr[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
short AmoebaCnt[MAX_NUM_AMOEBA];
short AmoebaCnt2[MAX_NUM_AMOEBA];
-short ExplodePhase[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
short ExplodeField[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+short ExplodePhase[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+short ExplodeDelay[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
int RunnerVisit[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
int PlayerVisit[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
int ExitX, ExitY;
int AllPlayersGone;
-int TimeFrames, TimePlayed, TimeLeft;
+int TimeFrames, TimePlayed, TimeLeft, TapeTime;
boolean network_player_action_received = FALSE;
"invisible steel wall"
},
{
- "maze_runner",
- "maze_runner",
- "maze runner"
+ "sokoban_field_player",
+ "sokoban",
+ "sokoban field with player"
},
{
"dynabomb_increase_number",
{
"black_orb",
"black_orb",
- "bomb"
+ "black orb bomb"
},
{
"amoeba_to_diamond",
"envelope",
"mail envelope 4"
},
+ {
+ "group_1",
+ "group",
+ "group element 1"
+ },
+ {
+ "group_2",
+ "group",
+ "group element 2"
+ },
+ {
+ "group_3",
+ "group",
+ "group element 3"
+ },
+ {
+ "group_4",
+ "group",
+ "group element 4"
+ },
+ {
+ "group_5",
+ "group",
+ "group element 5"
+ },
+ {
+ "group_6",
+ "group",
+ "group element 6"
+ },
+ {
+ "group_7",
+ "group",
+ "group element 7"
+ },
+ {
+ "group_8",
+ "group",
+ "group element 8"
+ },
+ {
+ "group_9",
+ "group",
+ "group element 9"
+ },
+ {
+ "group_10",
+ "group",
+ "group element 10"
+ },
+ {
+ "group_11",
+ "group",
+ "group element 11"
+ },
+ {
+ "group_12",
+ "group",
+ "group element 12"
+ },
+ {
+ "group_13",
+ "group",
+ "group element 13"
+ },
+ {
+ "group_14",
+ "group",
+ "group element 14"
+ },
+ {
+ "group_15",
+ "group",
+ "group element 15"
+ },
+ {
+ "group_16",
+ "group",
+ "group element 16"
+ },
+ {
+ "group_17",
+ "group",
+ "group element 17"
+ },
+ {
+ "group_18",
+ "group",
+ "group element 18"
+ },
+ {
+ "group_19",
+ "group",
+ "group element 19"
+ },
+ {
+ "group_20",
+ "group",
+ "group element 20"
+ },
+ {
+ "group_21",
+ "group",
+ "group element 21"
+ },
+ {
+ "group_22",
+ "group",
+ "group element 22"
+ },
+ {
+ "group_23",
+ "group",
+ "group element 23"
+ },
+ {
+ "group_24",
+ "group",
+ "group element 24"
+ },
+ {
+ "group_25",
+ "group",
+ "group element 25"
+ },
+ {
+ "group_26",
+ "group",
+ "group element 26"
+ },
+ {
+ "group_27",
+ "group",
+ "group element 27"
+ },
+ {
+ "group_28",
+ "group",
+ "group element 28"
+ },
+ {
+ "group_29",
+ "group",
+ "group element 29"
+ },
+ {
+ "group_30",
+ "group",
+ "group element 30"
+ },
+ {
+ "group_31",
+ "group",
+ "group element 31"
+ },
+ {
+ "group_32",
+ "group",
+ "group element 32"
+ },
+ {
+ "unknown",
+ "unknown",
+ "unknown element"
+ },
+ {
+ "trigger_element",
+ "trigger",
+ "element triggering change"
+ },
+ {
+ "trigger_player",
+ "trigger",
+ "player triggering change"
+ },
+ {
+ "sp_gravity_on_port_right",
+ "sp_port",
+ "gravity on port (leading right)"
+ },
+ {
+ "sp_gravity_on_port_down",
+ "sp_port",
+ "gravity on port (leading down)"
+ },
+ {
+ "sp_gravity_on_port_left",
+ "sp_port",
+ "gravity on port (leading left)"
+ },
+ {
+ "sp_gravity_on_port_up",
+ "sp_port",
+ "gravity on port (leading up)"
+ },
+ {
+ "sp_gravity_off_port_right",
+ "sp_port",
+ "gravity off port (leading right)"
+ },
+ {
+ "sp_gravity_off_port_down",
+ "sp_port",
+ "gravity off port (leading down)"
+ },
+ {
+ "sp_gravity_off_port_left",
+ "sp_port",
+ "gravity off port (leading left)"
+ },
+ {
+ "sp_gravity_off_port_up",
+ "sp_port",
+ "gravity off port (leading up)"
+ },
/* ----------------------------------------------------------------------- */
/* "real" (and therefore drawable) runtime elements */
"-",
"-"
},
+ {
+ "player_is_exploding_1",
+ "-",
+ "-"
+ },
+ {
+ "player_is_exploding_2",
+ "-",
+ "-"
+ },
+ {
+ "player_is_exploding_3",
+ "-",
+ "-"
+ },
+ {
+ "player_is_exploding_4",
+ "-",
+ "-"
+ },
{
"quicksand.filling",
"quicksand",
"-"
},
{
- "dummy",
- "dummy",
+ "internal_clipboard_custom",
+ "internal",
+ "empty custom element"
+ },
+ {
+ "internal_clipboard_change",
+ "internal",
+ "empty change page"
+ },
+ {
+ "internal_clipboard_group",
+ "internal",
+ "empty group element"
+ },
+ {
+ "internal_dummy",
+ "internal",
"-"
},
" --serveronly only start network server\n"
" -v, --verbose verbose mode\n"
" --debug display debugging information\n"
- " -e, --execute COMMAND execute batch COMMAND:\n"
+ " -e, --execute COMMAND execute batch COMMAND\n"
"\n"
"Valid commands for '--execute' option:\n"
" \"print graphicsinfo.conf\" print default graphics config\n"
" \"print helptext.conf\" print default helptext config\n"
" \"dump level FILE\" dump level data from FILE\n"
" \"dump tape FILE\" dump tape data from FILE\n"
- " \"autoplay LEVELDIR\" play level tapes for LEVELDIR\n"
+ " \"autoplay LEVELDIR [NR]\" play level tapes for LEVELDIR\n"
+ " \"convert LEVELDIR [NR]\" convert levels in LEVELDIR\n"
"\n",
program.command_basename);
}
#define EP_CAN_SMASH_PLAYER 10
#define EP_CAN_SMASH_ENEMIES 11
#define EP_CAN_SMASH_EVERYTHING 12
-#define EP_CAN_EXPLODE_BY_FIRE 13
-#define EP_CAN_EXPLODE_SMASHED 14
-#define EP_CAN_EXPLODE_IMPACT 15
+#define EP_EXPLODES_BY_FIRE 13
+#define EP_EXPLODES_SMASHED 14
+#define EP_EXPLODES_IMPACT 15
#define EP_WALKABLE_OVER 16
#define EP_WALKABLE_INSIDE 17
#define EP_WALKABLE_UNDER 18
#define EP_PASSABLE_INSIDE 20
#define EP_PASSABLE_UNDER 21
#define EP_DROPPABLE 22
-#define EP_CAN_EXPLODE_1X1 23
+#define EP_EXPLODES_1X1_OLD 23
#define EP_PUSHABLE 24
+#define EP_EXPLODES_CROSS_OLD 25
+#define EP_PROTECTED 26
+#define EP_CAN_MOVE_INTO_ACID 27
+#define EP_THROWABLE 28
+#define EP_CAN_EXPLODE 29
+#define EP_GRAVITY_REACHABLE 30
/* values for pre-defined properties */
#define EP_PLAYER 32
#define EP_AMOEBOID 50
#define EP_AMOEBALIVE 51
#define EP_HAS_CONTENT 52
-#define EP_ACTIVE_BOMB 53
-#define EP_INACTIVE 54
+#define EP_CAN_TURN_EACH_MOVE 53
+#define EP_CAN_GROW 54
+#define EP_ACTIVE_BOMB 55
+#define EP_INACTIVE 56
/* values for special configurable properties (depending on level settings) */
-#define EP_EM_SLIPPERY_WALL 55
+#define EP_EM_SLIPPERY_WALL 57
/* values for special graphics properties (no effect on game engine) */
-#define EP_GFX_CRUMBLED 56
+#define EP_GFX_CRUMBLED 58
/* values for derived properties (determined from properties above) */
-#define EP_ACCESSIBLE_OVER 57
-#define EP_ACCESSIBLE_INSIDE 58
-#define EP_ACCESSIBLE_UNDER 59
-#define EP_WALKABLE 60
-#define EP_PASSABLE 61
-#define EP_ACCESSIBLE 62
-#define EP_COLLECTIBLE 63
-#define EP_SNAPPABLE 64
-#define EP_WALL 65
-#define EP_SOLID_FOR_PUSHING 66
-#define EP_DRAGONFIRE_PROOF 67
-#define EP_EXPLOSION_PROOF 68
-#define EP_CAN_SMASH 69
-#define EP_CAN_EXPLODE 70
-#define EP_CAN_EXPLODE_3X3 71
+#define EP_ACCESSIBLE_OVER 59
+#define EP_ACCESSIBLE_INSIDE 60
+#define EP_ACCESSIBLE_UNDER 61
+#define EP_WALKABLE 62
+#define EP_PASSABLE 63
+#define EP_ACCESSIBLE 64
+#define EP_COLLECTIBLE 65
+#define EP_SNAPPABLE 66
+#define EP_WALL 67
+#define EP_SOLID_FOR_PUSHING 68
+#define EP_DRAGONFIRE_PROOF 69
+#define EP_EXPLOSION_PROOF 70
+#define EP_CAN_SMASH 71
+#define EP_EXPLODES_3X3_OLD 72
+#define EP_CAN_EXPLODE_BY_FIRE 73
+#define EP_CAN_EXPLODE_SMASHED 74
+#define EP_CAN_EXPLODE_IMPACT 75
+#define EP_SP_PORT 76
+#define EP_CAN_EXPLODE_BY_DRAGONFIRE 77
+#define EP_CAN_EXPLODE_BY_EXPLOSION 78
+#define EP_COULD_MOVE_INTO_ACID 79
+#define EP_MAYBE_DONT_COLLIDE_WITH 80
/* values for internal purpose only (level editor) */
-#define EP_EXPLODE_RESULT 72
-#define EP_WALK_TO_OBJECT 73
-#define EP_DEADLY 74
+#define EP_WALK_TO_OBJECT 81
+#define EP_DEADLY 82
-#define NUM_ELEMENT_PROPERTIES 75
+#define NUM_ELEMENT_PROPERTIES 83
#define NUM_EP_BITFIELDS ((NUM_ELEMENT_PROPERTIES + 31) / 32)
#define EP_BITFIELD_BASE 0
#define CE_PRESSED_BY_PLAYER 2
#define CE_PUSHED_BY_PLAYER 3
#define CE_DROPPED_BY_PLAYER 4
-#define CE_COLLISION_ACTIVE 5
+#define CE_HITTING_SOMETHING 5
#define CE_IMPACT 6
#define CE_SMASHED 7
#define CE_OTHER_IS_TOUCHING 8
#define CE_OTHER_GETS_LEFT 24
#define CE_SWITCHED 25
#define CE_OTHER_IS_SWITCHING 26
-#define CE_COLLISION_PASSIVE 27
-#define CE_OTHER_IS_COLL_ACTIVE 28
-#define CE_OTHER_IS_COLL_PASSIVE 29
+#define CE_HIT_BY_SOMETHING 27
+#define CE_OTHER_IS_HITTING 28
+#define CE_OTHER_GETS_HIT 29
+#define CE_BLOCKED 30
-#define NUM_CHANGE_EVENTS 30
+#define NUM_CHANGE_EVENTS 31
#define CE_BITMASK_DEFAULT 0
(CH_EVENT_VAR(e) |= CH_EVENT_BIT(c)) : \
(CH_EVENT_VAR(e) &= ~CH_EVENT_BIT(c))) : 0)
-/* values for change sides for custom elements */
+/* values for change side for custom elements */
#define CH_SIDE_NONE MV_NO_MOVING
#define CH_SIDE_LEFT MV_LEFT
#define CH_SIDE_RIGHT MV_RIGHT
#define CH_SIDE_TOP_BOTTOM MV_VERTICAL
#define CH_SIDE_ANY MV_ANY_DIRECTION
-/* values for change power for custom elements */
-#define CP_NON_DESTRUCTIVE 0
-#define CP_HALF_DESTRUCTIVE 1
-#define CP_FULL_DESTRUCTIVE 2
+/* values for change player for custom elements */
+#define CH_PLAYER_NONE 0
+#define CH_PLAYER_1 (1 << 0)
+#define CH_PLAYER_2 (1 << 1)
+#define CH_PLAYER_3 (1 << 2)
+#define CH_PLAYER_4 (1 << 3)
+#define CH_PLAYER_ANY (CH_PLAYER_1 | CH_PLAYER_2 | CH_PLAYER_3 | \
+ CH_PLAYER_4)
+
+/* values for change page for custom elements */
+#define CH_PAGE_ANY_FILE (0xff)
+#define CH_PAGE_ANY (0xffffffff)
-/* values for special move patterns (bits 0-3: basic move directions) */
+/* values for change power for custom elements */
+#define CP_WHEN_EMPTY 0
+#define CP_WHEN_DIGGABLE 1
+#define CP_WHEN_DESTRUCTIBLE 2
+#define CP_WHEN_COLLECTIBLE 3
+#define CP_WHEN_REMOVABLE 4
+#define CP_WHEN_WALKABLE 5
+
+/* values for custom move patterns (bits 0 - 3: basic move directions) */
#define MV_BIT_TOWARDS_PLAYER 4
#define MV_BIT_AWAY_FROM_PLAYER 5
#define MV_BIT_ALONG_LEFT_SIDE 6
#define MV_BIT_WHEN_PUSHED 10
#define MV_BIT_MAZE_RUNNER 11
#define MV_BIT_MAZE_HUNTER 12
+#define MV_BIT_WHEN_DROPPED 13
+#define MV_BIT_TURNING_LEFT_RIGHT 14
+#define MV_BIT_TURNING_RIGHT_LEFT 15
+#define MV_BIT_TURNING_RANDOM 16
-/* values for special move patterns for custom elements */
+/* values for custom move patterns */
#define MV_HORIZONTAL (MV_LEFT | MV_RIGHT)
-#define MV_VERTICAL (MV_UP | MV_DOWN)
-#define MV_ALL_DIRECTIONS (MV_HORIZONTAL | MV_VERTICAL)
+#define MV_VERTICAL (MV_UP | MV_DOWN)
+#define MV_ALL_DIRECTIONS (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)
#define MV_ANY_DIRECTION (MV_ALL_DIRECTIONS)
#define MV_TOWARDS_PLAYER (1 << MV_BIT_TOWARDS_PLAYER)
#define MV_AWAY_FROM_PLAYER (1 << MV_BIT_AWAY_FROM_PLAYER)
#define MV_MAZE_RUNNER (1 << MV_BIT_MAZE_RUNNER)
#define MV_MAZE_HUNTER (1 << MV_BIT_MAZE_HUNTER)
#define MV_MAZE_RUNNER_STYLE (MV_MAZE_RUNNER | MV_MAZE_HUNTER)
+#define MV_WHEN_DROPPED (1 << MV_BIT_WHEN_DROPPED)
+#define MV_TURNING_LEFT_RIGHT (1 << MV_BIT_TURNING_LEFT_RIGHT)
+#define MV_TURNING_RIGHT_LEFT (1 << MV_BIT_TURNING_RIGHT_LEFT)
+#define MV_TURNING_RANDOM (1 << MV_BIT_TURNING_RANDOM)
+
+/* values for initial move direction (bits 0 - 3: basic move directions) */
+#define MV_START_BIT_PREVIOUS 4
+
+/* values for initial move direction */
+#define MV_START_AUTOMATIC (MV_NO_MOVING)
+#define MV_START_LEFT (MV_LEFT)
+#define MV_START_RIGHT (MV_RIGHT)
+#define MV_START_UP (MV_UP)
+#define MV_START_DOWN (MV_DOWN)
+#define MV_START_RANDOM (MV_ALL_DIRECTIONS)
+#define MV_START_PREVIOUS (1 << MV_START_BIT_PREVIOUS)
+
+/* values for elements left behind by custom elements */
+#define LEAVE_TYPE_UNLIMITED 0
+#define LEAVE_TYPE_LIMITED 1
/* values for slippery property for custom elements */
#define SLIPPERY_ANY_RANDOM 0
#define SLIPPERY_ONLY_LEFT 3
#define SLIPPERY_ONLY_RIGHT 4
+/* values for explosion type for custom elements */
+#define EXPLODES_3X3 0
+#define EXPLODES_1X1 1
+#define EXPLODES_CROSS 2
+
/* macros for configurable properties */
#define IS_DIGGABLE(e) HAS_PROPERTY(e, EP_DIGGABLE)
#define IS_COLLECTIBLE_ONLY(e) HAS_PROPERTY(e, EP_COLLECTIBLE_ONLY)
#define CAN_SMASH_PLAYER(e) HAS_PROPERTY(e, EP_CAN_SMASH_PLAYER)
#define CAN_SMASH_ENEMIES(e) HAS_PROPERTY(e, EP_CAN_SMASH_ENEMIES)
#define CAN_SMASH_EVERYTHING(e) HAS_PROPERTY(e, EP_CAN_SMASH_EVERYTHING)
-#define CAN_EXPLODE_BY_FIRE(e) HAS_PROPERTY(e, EP_CAN_EXPLODE_BY_FIRE)
-#define CAN_EXPLODE_SMASHED(e) HAS_PROPERTY(e, EP_CAN_EXPLODE_SMASHED)
-#define CAN_EXPLODE_IMPACT(e) HAS_PROPERTY(e, EP_CAN_EXPLODE_IMPACT)
+#define EXPLODES_BY_FIRE(e) HAS_PROPERTY(e, EP_EXPLODES_BY_FIRE)
+#define EXPLODES_SMASHED(e) HAS_PROPERTY(e, EP_EXPLODES_SMASHED)
+#define EXPLODES_IMPACT(e) HAS_PROPERTY(e, EP_EXPLODES_IMPACT)
#define IS_WALKABLE_OVER(e) HAS_PROPERTY(e, EP_WALKABLE_OVER)
#define IS_WALKABLE_INSIDE(e) HAS_PROPERTY(e, EP_WALKABLE_INSIDE)
#define IS_WALKABLE_UNDER(e) HAS_PROPERTY(e, EP_WALKABLE_UNDER)
#define IS_PASSABLE_INSIDE(e) HAS_PROPERTY(e, EP_PASSABLE_INSIDE)
#define IS_PASSABLE_UNDER(e) HAS_PROPERTY(e, EP_PASSABLE_UNDER)
#define IS_DROPPABLE(e) HAS_PROPERTY(e, EP_DROPPABLE)
-#define CAN_EXPLODE_1X1(e) HAS_PROPERTY(e, EP_CAN_EXPLODE_1X1)
+#define EXPLODES_1X1_OLD(e) HAS_PROPERTY(e, EP_EXPLODES_1X1_OLD)
#define IS_PUSHABLE(e) HAS_PROPERTY(e, EP_PUSHABLE)
+#define EXPLODES_CROSS_OLD(e) HAS_PROPERTY(e, EP_EXPLODES_CROSS_OLD)
+#define IS_PROTECTED(e) HAS_PROPERTY(e, EP_PROTECTED)
+#define CAN_MOVE_INTO_ACID(e) HAS_PROPERTY(e, EP_CAN_MOVE_INTO_ACID)
+#define IS_THROWABLE(e) HAS_PROPERTY(e, EP_THROWABLE)
+#define CAN_EXPLODE(e) HAS_PROPERTY(e, EP_CAN_EXPLODE)
+#define IS_GRAVITY_REACHABLE(e) HAS_PROPERTY(e, EP_GRAVITY_REACHABLE)
/* macros for special configurable properties */
#define IS_EM_SLIPPERY_WALL(e) HAS_PROPERTY(e, EP_EM_SLIPPERY_WALL)
#define IS_AMOEBOID(e) HAS_PROPERTY(e, EP_AMOEBOID)
#define IS_AMOEBALIVE(e) HAS_PROPERTY(e, EP_AMOEBALIVE)
#define HAS_CONTENT(e) HAS_PROPERTY(e, EP_HAS_CONTENT)
+#define CAN_TURN_EACH_MOVE(e) HAS_PROPERTY(e, EP_CAN_TURN_EACH_MOVE)
+#define CAN_GROW(e) HAS_PROPERTY(e, EP_CAN_GROW)
#define IS_ACTIVE_BOMB(e) HAS_PROPERTY(e, EP_ACTIVE_BOMB)
#define IS_INACTIVE(e) HAS_PROPERTY(e, EP_INACTIVE)
#define IS_DRAGONFIRE_PROOF(e) HAS_PROPERTY(e, EP_DRAGONFIRE_PROOF)
#define IS_EXPLOSION_PROOF(e) HAS_PROPERTY(e, EP_EXPLOSION_PROOF)
#define CAN_SMASH(e) HAS_PROPERTY(e, EP_CAN_SMASH)
-#define CAN_EXPLODE(e) HAS_PROPERTY(e, EP_CAN_EXPLODE)
-#define CAN_EXPLODE_3X3(e) HAS_PROPERTY(e, EP_CAN_EXPLODE_3X3)
+#define EXPLODES_3X3_OLD(e) HAS_PROPERTY(e, EP_EXPLODES_3X3_OLD)
+#define CAN_EXPLODE_BY_FIRE(e) HAS_PROPERTY(e, EP_CAN_EXPLODE_BY_FIRE)
+#define CAN_EXPLODE_SMASHED(e) HAS_PROPERTY(e, EP_CAN_EXPLODE_SMASHED)
+#define CAN_EXPLODE_IMPACT(e) HAS_PROPERTY(e, EP_CAN_EXPLODE_IMPACT)
+#define IS_SP_PORT(e) HAS_PROPERTY(e, EP_SP_PORT)
+#define CAN_EXPLODE_BY_DRAGONFIRE(e) \
+ HAS_PROPERTY(e, EP_CAN_EXPLODE_BY_DRAGONFIRE)
+#define CAN_EXPLODE_BY_EXPLOSION(e) \
+ HAS_PROPERTY(e, EP_CAN_EXPLODE_BY_EXPLOSION)
+#define COULD_MOVE_INTO_ACID(e) HAS_PROPERTY(e, EP_COULD_MOVE_INTO_ACID)
+#define MAYBE_DONT_COLLIDE_WITH(e) HAS_PROPERTY(e, EP_MAYBE_DONT_COLLIDE_WITH)
/* special macros used in game engine */
#define IS_CUSTOM_ELEMENT(e) ((e) >= EL_CUSTOM_START && \
(e) <= EL_CUSTOM_END)
+#define IS_GROUP_ELEMENT(e) ((e) >= EL_GROUP_START && \
+ (e) <= EL_GROUP_END)
+
+#define IS_CLIPBOARD_ELEMENT(e) ((e) >= EL_INTERNAL_CLIPBOARD_START && \
+ (e) <= EL_INTERNAL_CLIPBOARD_END)
+
+#define IS_INTERNAL_ELEMENT(e) ((e) >= EL_INTERNAL_START && \
+ (e) <= EL_INTERNAL_END)
+
#define IS_ENVELOPE(e) ((e) >= EL_ENVELOPE_1 && \
(e) <= EL_ENVELOPE_4)
+#define IS_GATE(e) ((e) >= EL_GATE_1 && \
+ (e) <= EL_GATE_4)
+
+#define IS_GATE_GRAY(e) ((e) >= EL_GATE_1_GRAY && \
+ (e) <= EL_GATE_4_GRAY)
+
+#define IS_EM_GATE(e) ((e) >= EL_EM_GATE_1 && \
+ (e) <= EL_EM_GATE_4)
+
+#define IS_EM_GATE_GRAY(e) ((e) >= EL_EM_GATE_1_GRAY && \
+ (e) <= EL_EM_GATE_4_GRAY)
+
#define GFX_ELEMENT(e) (element_info[e].use_gfx_element ? \
element_info[e].gfx_element : e)
-#define IS_PLAYER(x,y) (ELEM_IS_PLAYER(StorePlayer[x][y]))
+/* !!! "use sound" deactivated due to problems with level "bug machine" !!! */
+/* (solution: add separate "use sound of element" to level file and editor) */
+#if 0
+#define SND_ELEMENT(e) GFX_ELEMENT(e)
+#else
+#define SND_ELEMENT(e) (e)
+#endif
-#define IS_FREE(x,y) (Feld[x][y] == EL_EMPTY && !IS_PLAYER(x,y))
-#define IS_FREE_OR_PLAYER(x,y) (Feld[x][y] == EL_EMPTY)
+#define IS_PLAYER(x, y) (ELEM_IS_PLAYER(StorePlayer[x][y]))
+
+#define IS_FREE(x, y) (Feld[x][y] == EL_EMPTY && !IS_PLAYER(x, y))
+#define IS_FREE_OR_PLAYER(x, y) (Feld[x][y] == EL_EMPTY)
#define IS_MOVING(x,y) (MovPos[x][y] != 0)
#define IS_FALLING(x,y) (MovPos[x][y] != 0 && MovDir[x][y] == MV_DOWN)
#define PLAYERINFO(x,y) (&stored_player[StorePlayer[x][y]-EL_PLAYER_1])
#define SHIELD_ON(p) ((p)->shield_normal_time_left > 0)
+
+#if 1
+
+#define ENEMY_PROTECTED_FIELD(x,y) (IS_PROTECTED(Feld[x][y]) || \
+ IS_PROTECTED(Back[x][y]))
+#define EXPLOSION_PROTECTED_FIELD(x,y) (IS_EXPLOSION_PROOF(Feld[x][y]))
+#define PLAYER_ENEMY_PROTECTED(x,y) (SHIELD_ON(PLAYERINFO(x, y)) || \
+ ENEMY_PROTECTED_FIELD(x, y))
+#define PLAYER_EXPLOSION_PROTECTED(x,y) (SHIELD_ON(PLAYERINFO(x, y)) || \
+ EXPLOSION_PROTECTED_FIELD(x, y))
+
+#else
+
#define PROTECTED_FIELD(x,y) (IS_ACCESSIBLE_INSIDE(Feld[x][y]) && \
IS_INDESTRUCTIBLE(Feld[x][y]))
-#define PLAYER_PROTECTED(x,y) (SHIELD_ON(PLAYERINFO(x, y)) || \
+#define PLAYER_ENEMY_PROTECTED(x,y) (SHIELD_ON(PLAYERINFO(x, y)) || \
PROTECTED_FIELD(x, y))
+#define PLAYER_EXPLOSION_PROTECTED(x,y) (SHIELD_ON(PLAYERINFO(x, y)) || \
+ PROTECTED_FIELD(x, y))
+#endif
#define PLAYER_SWITCHING(p,x,y) ((p)->is_switching && \
(p)->switch_x == (x) && (p)->switch_y == (y))
/* fundamental game speed values */
+#define ONE_SECOND_DELAY 1000 /* delay value for one second */
#define GAME_FRAME_DELAY 20 /* frame delay in milliseconds */
#define FFWD_FRAME_DELAY 10 /* 200% speed for fast forward */
-#define FRAMES_PER_SECOND (1000 / GAME_FRAME_DELAY)
+#define FRAMES_PER_SECOND (ONE_SECOND_DELAY / GAME_FRAME_DELAY)
#define MICROLEVEL_SCROLL_DELAY 50 /* delay for scrolling micro level */
#define MICROLEVEL_LABEL_DELAY 250 /* delay for micro level label */
#define MAX_SCORE_ENTRIES 100
#define MAX_NUM_AMOEBA 100
#define MAX_INVENTORY_SIZE 1000
+#define MAX_KEYS 4
+#define NUM_BELTS 4
+#define NUM_BELT_PARTS 3
#define MIN_ENVELOPE_XSIZE 1
#define MIN_ENVELOPE_YSIZE 1
#define MAX_ENVELOPE_XSIZE 30
#define MAX_ENVELOPE_YSIZE 20
#define MAX_ENVELOPE_TEXT_LEN (MAX_ENVELOPE_XSIZE * MAX_ENVELOPE_YSIZE)
#define MIN_CHANGE_PAGES 1
-#define MAX_CHANGE_PAGES 16
+#define MAX_CHANGE_PAGES 32
+#define MIN_ELEMENTS_IN_GROUP 1
+#define MAX_ELEMENTS_IN_GROUP 16
/* values for elements with content */
#define MIN_ELEMENT_CONTENTS 1
#define MICROLABEL_YPOS (MICROLEV_YPOS + MICROLEV_YSIZE + 7)
+/* score for elements */
+#define SC_EMERALD 0
+#define SC_DIAMOND 1
+#define SC_BUG 2
+#define SC_SPACESHIP 3
+#define SC_YAMYAM 4
+#define SC_ROBOT 5
+#define SC_PACMAN 6
+#define SC_NUT 7
+#define SC_DYNAMITE 8
+#define SC_KEY 9
+#define SC_TIME_BONUS 10
+#define SC_CRYSTAL 11
+#define SC_PEARL 12
+#define SC_SHIELD 13
+
+
/* "real" level file elements */
#define EL_UNDEFINED -1
#define EL_DARK_YAMYAM 60
#define EL_BD_MAGIC_WALL 61
#define EL_INVISIBLE_STEELWALL 62
-
-#define EL_MAZE_RUNNER 63
-
+#define EL_SOKOBAN_FIELD_PLAYER 63
#define EL_DYNABOMB_INCREASE_NUMBER 64
#define EL_DYNABOMB_INCREASE_SIZE 65
#define EL_DYNABOMB_INCREASE_POWER 66
#define EL_ENVELOPE_3 622
#define EL_ENVELOPE_4 623
-#define NUM_FILE_ELEMENTS 624
+/* ---------- begin of group elements section ------------------------------ */
+#define EL_GROUP_START 624
+
+#include "conf_grp.h" /* include auto-generated data structure definitions */
+
+#define NUM_GROUP_ELEMENTS 32
+#define EL_GROUP_END 655
+/* ---------- end of custom elements section ------------------------------- */
+
+#define EL_UNKNOWN 656
+#define EL_TRIGGER_ELEMENT 657
+#define EL_TRIGGER_PLAYER 658
+
+#define EL_SP_GRAVITY_ON_PORT_RIGHT 659
+#define EL_SP_GRAVITY_ON_PORT_DOWN 660
+#define EL_SP_GRAVITY_ON_PORT_LEFT 661
+#define EL_SP_GRAVITY_ON_PORT_UP 662
+#define EL_SP_GRAVITY_OFF_PORT_RIGHT 663
+#define EL_SP_GRAVITY_OFF_PORT_DOWN 664
+#define EL_SP_GRAVITY_OFF_PORT_LEFT 665
+#define EL_SP_GRAVITY_OFF_PORT_UP 666
+
+#define NUM_FILE_ELEMENTS 667
/* "real" (and therefore drawable) runtime elements */
#define EL_EXPANDABLE_WALL_GROWING (EL_FIRST_RUNTIME_UNREAL + 8)
#define EL_FLAMES (EL_FIRST_RUNTIME_UNREAL + 9)
#define EL_PLAYER_IS_LEAVING (EL_FIRST_RUNTIME_UNREAL + 10)
-#define EL_QUICKSAND_FILLING (EL_FIRST_RUNTIME_UNREAL + 11)
-#define EL_MAGIC_WALL_FILLING (EL_FIRST_RUNTIME_UNREAL + 12)
-#define EL_BD_MAGIC_WALL_FILLING (EL_FIRST_RUNTIME_UNREAL + 13)
+#define EL_PLAYER_IS_EXPLODING_1 (EL_FIRST_RUNTIME_UNREAL + 11)
+#define EL_PLAYER_IS_EXPLODING_2 (EL_FIRST_RUNTIME_UNREAL + 12)
+#define EL_PLAYER_IS_EXPLODING_3 (EL_FIRST_RUNTIME_UNREAL + 13)
+#define EL_PLAYER_IS_EXPLODING_4 (EL_FIRST_RUNTIME_UNREAL + 14)
+#define EL_QUICKSAND_FILLING (EL_FIRST_RUNTIME_UNREAL + 15)
+#define EL_MAGIC_WALL_FILLING (EL_FIRST_RUNTIME_UNREAL + 16)
+#define EL_BD_MAGIC_WALL_FILLING (EL_FIRST_RUNTIME_UNREAL + 17)
/* dummy elements (never used as game elements, only used as graphics) */
-#define EL_FIRST_DUMMY (EL_FIRST_RUNTIME_UNREAL + 14)
+#define EL_FIRST_DUMMY (EL_FIRST_RUNTIME_UNREAL + 18)
#define EL_STEELWALL_TOPLEFT (EL_FIRST_DUMMY + 0)
#define EL_STEELWALL_TOPRIGHT (EL_FIRST_DUMMY + 1)
#define EL_BD_DEFAULT (EL_FIRST_DUMMY + 22)
#define EL_SP_DEFAULT (EL_FIRST_DUMMY + 23)
#define EL_SB_DEFAULT (EL_FIRST_DUMMY + 24)
-#define EL_DUMMY (EL_FIRST_DUMMY + 25)
-#define MAX_NUM_ELEMENTS (EL_FIRST_DUMMY + 26)
+/* internal elements (only used for internal purposes like copying) */
+#define EL_FIRST_INTERNAL (EL_FIRST_DUMMY + 25)
+
+#define EL_INTERNAL_CLIPBOARD_CUSTOM (EL_FIRST_INTERNAL + 0)
+#define EL_INTERNAL_CLIPBOARD_CHANGE (EL_FIRST_INTERNAL + 1)
+#define EL_INTERNAL_CLIPBOARD_GROUP (EL_FIRST_INTERNAL + 2)
+#define EL_INTERNAL_DUMMY (EL_FIRST_INTERNAL + 3)
+
+#define EL_INTERNAL_CLIPBOARD_START (EL_FIRST_INTERNAL + 0)
+#define EL_INTERNAL_CLIPBOARD_END (EL_FIRST_INTERNAL + 2)
+#define EL_INTERNAL_START (EL_FIRST_INTERNAL + 0)
+#define EL_INTERNAL_END (EL_FIRST_INTERNAL + 3)
+
+#define MAX_NUM_ELEMENTS (EL_FIRST_INTERNAL + 4)
/* values for graphics/sounds action types */
/* program information and versioning definitions */
#define PROGRAM_VERSION_MAJOR 3
-#define PROGRAM_VERSION_MINOR 0
-#define PROGRAM_VERSION_PATCH 8
-#define PROGRAM_VERSION_BUILD 3
+#define PROGRAM_VERSION_MINOR 1
+#define PROGRAM_VERSION_PATCH 0
+#define PROGRAM_VERSION_BUILD 5
#define PROGRAM_TITLE_STRING "Rocks'n'Diamonds"
#define PROGRAM_AUTHOR_STRING "Holger Schemel"
-#define PROGRAM_COPYRIGHT_STRING "Copyright ©1995-2003 by Holger Schemel"
+#define PROGRAM_COPYRIGHT_STRING "Copyright ©1995-2004 by Holger Schemel"
#define ICON_TITLE_STRING PROGRAM_TITLE_STRING
#define COOKIE_PREFIX "ROCKSNDIAMONDS"
{
boolean present; /* player present in level playfield */
boolean connected; /* player connected (locally or via network) */
- boolean active; /* player (present && connected) */
+ boolean active; /* player present and connected */
- int index_nr, client_nr, element_nr;
+ int index_nr; /* player number (0 to 3) */
+ int index_bit; /* player number bit (1 << 0 to 1 << 3) */
+ int element_nr; /* element (EL_PLAYER_1 to EL_PLAYER_4) */
+ int client_nr; /* network client identifier */
byte action; /* action from local input device */
byte effective_action; /* action acknowledged from network server
boolean use_murphy_graphic;
+ boolean block_last_field;
+ boolean can_fall_into_acid;
+
boolean LevelSolved, GameOver;
int last_move_dir;
boolean is_waiting;
boolean is_moving;
+ boolean is_auto_moving;
boolean is_digging;
boolean is_snapping;
boolean is_collecting;
boolean is_pushing;
boolean is_switching;
+ boolean is_dropping;
boolean is_bored;
boolean is_sleeping;
unsigned long move_delay;
int move_delay_value;
+ int move_delay_reset_counter;
+
unsigned long push_delay;
unsigned long push_delay_value;
unsigned long actual_frame_counter;
+ int drop_delay;
+
int step_counter;
int score;
int shield_deadly_time_left;
int inventory_element[MAX_INVENTORY_SIZE];
+ int inventory_infinite_element;
int inventory_size;
};
int music[MAX_LEVELS];
};
+struct LevelFileInfo
+{
+ int nr;
+ int type;
+ boolean packed;
+ char *basename;
+ char *filename;
+};
+
struct LevelInfo
{
int file_version; /* file format version the level is stored with */
boolean encoding_16bit_amoeba; /* amoeba contains 16-bit elements */
int fieldx, fieldy;
+
int time;
int gems_needed;
+
char name[MAX_LEVEL_NAME_LEN + 1];
char author[MAX_LEVEL_AUTHOR_LEN + 1];
+
char envelope_text[4][MAX_ENVELOPE_TEXT_LEN + 1];
int envelope_xsize[4], envelope_ysize[4];
+
int score[LEVEL_SCORE_ELEMENTS];
+
int yamyam_content[MAX_ELEMENT_CONTENTS][3][3];
int num_yamyam_contents;
+
int amoeba_speed;
int amoeba_content;
+
int time_magic_wall;
int time_wheel;
int time_light;
int time_timegate;
+
+ int can_move_into_acid_bits; /* bitfield to store property for elements */
+ int dont_collide_with_bits; /* bitfield to store property for elements */
+
boolean double_speed;
boolean initial_gravity;
boolean em_slippery_gems; /* EM style "gems slip from wall" behaviour */
+ boolean block_last_field; /* player blocks previous field while moving */
+ boolean sp_block_last_field; /* player blocks previous field while moving */
+ boolean use_spring_bug; /* for compatibility with old levels */
+ boolean instant_relocation; /* no visual delay when relocating player */
+ boolean can_pass_to_walkable; /* player can pass to empty or walkable tile */
+ boolean grow_into_diggable; /* amoeba can grow into anything diggable */
+
+ /* ('int' instead of 'boolean' because used as selectbox value in editor) */
+ int use_step_counter; /* count steps instead of seconds for level */
short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
boolean use_custom_template; /* use custom properties from template file */
- boolean no_level_file; /* set for currently undefined levels */
+ boolean no_valid_file; /* set when level file missing or invalid */
};
struct TapeInfo
boolean pause_before_death;
boolean recording, playing, pausing;
boolean fast_forward;
- boolean index_search;
+ boolean warp_forward;
+ boolean deactivate_display;
boolean auto_play;
boolean auto_play_level_solved;
boolean quick_resume;
byte action[MAX_PLAYERS];
byte delay;
} pos[MAX_TAPELEN];
+
+ boolean no_valid_file; /* set when tape file missing or invalid */
};
struct GameInfo
char *autoplay_leveldir;
int autoplay_level_nr;
+ char *convert_leveldir;
+ int convert_level_nr;
+
int num_toons;
float frames_per_second;
boolean can_change; /* use or ignore this change info */
unsigned long events; /* change events */
- int sides; /* change sides */
+
+ int trigger_player; /* player triggering change */
+ int trigger_side; /* side triggering change */
+ int trigger_page; /* page triggering change */
short target_element; /* target element after change */
int delay_random; /* added frame delay before changed (random) */
int delay_frames; /* either 1 (frames) or 50 (seconds; 50 fps) */
- short trigger_element; /* custom element triggering change */
+ short trigger_element; /* element triggering change */
- int content[3][3]; /* new elements after extended change */
- boolean use_content; /* use extended change content */
- boolean only_complete; /* only use complete content */
- boolean use_random_change; /* use random value for setting content */
- int random; /* random value for setting content */
- int power; /* power of extended change */
+ int target_content[3][3]; /* elements for extended change target */
+ boolean use_target_content; /* use extended change target */
+ boolean only_if_complete; /* only use complete target content */
+ boolean use_random_replace; /* use random value for replacing elements */
+ int random_percentage; /* random value for replacing elements */
+ int replace_when; /* type of elements that can be replaced */
boolean explode; /* explode instead of change */
+ /* ---------- internal values used at runtime when playing ---------- */
+
/* functions that are called before, while and after the change of an
element -- currently only used for non-custom elements */
void (*pre_change_function)(int x, int y);
void (*change_function)(int x, int y);
void (*post_change_function)(int x, int y);
+ short actual_trigger_element; /* element that actually triggered change */
+ int actual_trigger_player; /* player which actually triggered change */
+
/* ---------- internal values used in level editor ---------- */
int direct_action; /* change triggered by actions on element */
int other_action; /* change triggered by other element actions */
};
+struct ElementGroupInfo
+{
+ int num_elements; /* number of elements in this group */
+ short element[MAX_ELEMENTS_IN_GROUP]; /* list of elements in this group */
+
+ int choice_mode; /* how to choose element from group */
+
+ /* ---------- internal values used at runtime when playing ---------- */
+
+ /* the following is the same as above, but with recursively resolved group
+ elements (group elements may also contain further group elements!) */
+ int num_elements_resolved;
+ short element_resolved[NUM_FILE_ELEMENTS];
+
+ int choice_pos; /* current element choice position */
+};
+
struct ElementInfo
{
/* ---------- token and description strings ---------- */
char *class_name; /* element class used in config files */
char *editor_description; /* pre-defined description for level editor */
char *custom_description; /* alternative description from config file */
- char description[MAX_ELEMENT_NAME_LEN + 1]; /* for custom elements */
+ char description[MAX_ELEMENT_NAME_LEN + 1]; /* for custom/group elements */
/* ---------- graphic and sound definitions ---------- */
boolean use_gfx_element; /* use custom graphic element */
short gfx_element; /* optional custom graphic element */
+ int access_direction; /* accessible from which direction */
+
int collect_score; /* score value for collecting */
int collect_count; /* count value for collecting */
- int push_delay_fixed; /* constant frame delay for pushing */
- int push_delay_random; /* additional random frame delay for pushing */
- int move_delay_fixed; /* constant frame delay for moving */
- int move_delay_random; /* additional random frame delay for moving */
+ int push_delay_fixed; /* constant delay before pushing */
+ int push_delay_random; /* additional random delay before pushing */
+ int drop_delay_fixed; /* constant delay after dropping */
+ int drop_delay_random; /* additional random delay after dropping */
+ int move_delay_fixed; /* constant delay after moving */
+ int move_delay_random; /* additional random delay after moving */
int move_pattern; /* direction movable element moves to */
int move_direction_initial; /* initial direction element moves to */
int move_stepsize; /* step size element moves with */
+ int move_enter_element; /* element that can be entered (and removed) */
+ int move_leave_element; /* element that can be left behind */
+ int move_leave_type; /* change (limited) or leave (unlimited) */
+
int slippery_type; /* how/where other elements slip away */
int content[3][3]; /* new elements after explosion */
+ int explosion_type; /* type of explosion, like 3x3, 3+3 or 1x1 */
+ int explosion_delay; /* duration of explosion of this element */
+ int ignition_delay; /* delay for explosion by other explosion */
+
struct ElementChangeInfo *change_page; /* actual list of change pages */
struct ElementChangeInfo *change; /* pointer to current change page */
int num_change_pages; /* actual number of change pages */
int current_change_page; /* currently edited change page */
+ struct ElementGroupInfo *group; /* pointer to element group info */
+
/* ---------- internal values used at runtime when playing ---------- */
unsigned long change_events; /* bitfield for combined change events */
int event_page_nr[NUM_CHANGE_EVENTS]; /* page number for each event */
struct ElementChangeInfo *event_page[NUM_CHANGE_EVENTS]; /* page for event */
+ boolean in_group[NUM_GROUP_ELEMENTS];
+
+#if 0
+ boolean can_leave_element; /* element can leave other element behind */
+ boolean can_leave_element_last;
+#endif
+
/* ---------- internal values used in level editor ---------- */
int access_type; /* walkable or passable */
int access_layer; /* accessible over/inside/under */
+ int access_protected; /* protection against deadly elements */
int walk_to_action; /* diggable/collectible/pushable */
int smash_targets; /* can smash player/enemies/everything */
int deadliness; /* deadly when running/colliding/touching */
- int consistency; /* indestructible/can explode */
boolean can_explode_by_fire; /* element explodes by fire */
boolean can_explode_smashed; /* element explodes when smashed */
extern boolean level_editor_test_game;
extern boolean network_playing;
+#if defined(TARGET_SDL)
+extern boolean network_server;
+extern SDL_Thread *server_thread;
+#endif
+
extern int key_joystick_mapping;
extern boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
extern unsigned long ChangeEvent[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short WasJustMoving[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short WasJustFalling[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern short CheckCollision[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short AmoebaNr[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short AmoebaCnt[MAX_NUM_AMOEBA];
extern short AmoebaCnt2[MAX_NUM_AMOEBA];
-extern short ExplodePhase[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short ExplodeField[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern short ExplodePhase[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern short ExplodeDelay[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern int RunnerVisit[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern int PlayerVisit[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern int ExitX, ExitY;
extern int AllPlayersGone;
-extern int TimeFrames, TimePlayed, TimeLeft;
+extern int TimeFrames, TimePlayed, TimeLeft, TapeTime;
extern boolean SiebAktiv;
extern int SiebCount;
* Germany *
* e-mail: info@artsoft.org *
*----------------------------------------------------------*
-* network.c *
+* netserv.c *
***********************************************************/
#include "libgame/platform.h"
-#if defined(PLATFORM_UNIX)
+#if defined(NETWORK_AVALIABLE)
#include <fcntl.h>
#include <sys/time.h>
#include <signal.h>
-#include <sys/socket.h>
#include <errno.h>
+
+#if defined(TARGET_SDL)
+#include "main.h"
+#else
+#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
+#include <sys/select.h> /* apparently needed for OS/2 port */
+#endif
#include "libgame/libgame.h"
struct NetworkServerPlayerInfo
{
+#if defined(TARGET_SDL)
+ TCPsocket fd;
+#else
int fd;
+#endif
+
char player_name[16];
unsigned char number;
struct NetworkServerPlayerInfo *next;
#define NEXT(player) ((player)->next ? (player)->next : first_player)
+#if defined(TARGET_SDL)
+/* TODO: peer address */
+static TCPsocket lfd; /* listening socket */
+static SDLNet_SocketSet fds; /* socket set */
+#else
static struct sockaddr_in saddr;
-static int lfd;
+static int lfd; /* listening socket */
+static fd_set fds; /* socket set */
+static int tcp = -1;
+#endif
+
static unsigned char realbuffer[512], *buffer = realbuffer + 4;
static int interrupt;
-static int tcp = -1;
static unsigned long ServerFrameCounter = 0;
-static fd_set fds;
-
static void addtobuffer(struct NetworkServerPlayerInfo *player,
unsigned char *b, int len)
{
{
if (player->nwrite)
{
+#if defined(TARGET_SDL)
+ SDLNet_TCP_Send(player->fd, player->writbuffer, player->nwrite);
+#else
write(player->fd, player->writbuffer, player->nwrite);
+#endif
player->nwrite = 0;
}
}
}
}
}
+
+#if defined(TARGET_SDL)
+ SDLNet_TCP_DelSocket(fds, player->fd);
+ SDLNet_TCP_Close(player->fd);
+#else
close(player->fd);
+#endif
if (player->introduced)
{
}
}
+#if defined(TARGET_SDL)
+static void AddPlayer(TCPsocket fd)
+#else
static void AddPlayer(int fd)
+#endif
{
struct NetworkServerPlayerInfo *player, *v;
unsigned char nxn;
player->action = 0;
player->action_received = FALSE;
+#if defined(TARGET_SDL)
+ SDLNet_TCP_AddSocket(fds, fd);
+#endif
+
first_player = player;
nxn = 1;
#endif
player->number = nxn;
+#if !defined(TARGET_SDL)
if (options.verbose)
Error(ERR_NETWORK_SERVER, "client %d connecting from %s",
nxn, inet_ntoa(saddr.sin_addr));
+#endif
clients++;
buffer[0] = 0;
ServerFrameCounter++;
}
+#if defined(TARGET_SDL)
+/* the following is not used for a standalone server;
+ the pointer points to an integer containing the port-number */
+int NetworkServerThread(void *ptr)
+{
+ NetworkServer(*((int *) ptr), 0);
+
+ /* should never be reached */
+ return 0;
+}
+#endif
+
void NetworkServer(int port, int serveronly)
{
- int i, sl, on;
+ int sl;
struct NetworkServerPlayerInfo *player;
- int mfd;
int r;
unsigned int len;
+#if defined(TARGET_SDL)
+ IPaddress ip;
+#else
+ int i, on;
+ int is_daemon = 0;
struct protoent *tcpproto;
struct timeval tv;
- int is_daemon = 0;
+ int mfd;
+#endif
-#ifndef NeXT
+#if defined(PLATFORM_UNIX) && !defined(PLATFORM_NEXT)
struct sigaction sact;
#endif
if (!serveronly)
onceonly = 1;
+#if !defined(TARGET_SDL)
if ((tcpproto = getprotobyname("tcp")) != NULL)
tcp = tcpproto->p_proto;
+#endif
-#ifdef NeXT
+#if defined(PLATFORM_UNIX)
+#if defined(PLATFORM_NEXT)
signal(SIGPIPE, SIG_IGN);
#else
sact.sa_handler = SIG_IGN;
sact.sa_flags = 0;
sigaction(SIGPIPE, &sact, NULL);
#endif
+#endif
+
+#if defined(TARGET_SDL)
+
+ /* assume that SDL is already initialized */
+#if 0
+ if (SDLNet_Init() == -1)
+ Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_Init() failed");
+ atexit(SDLNet_Quit);
+#endif
+
+ if (SDLNet_ResolveHost(&ip, NULL, port) == -1)
+ Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_ResolveHost() failed");
+ lfd = SDLNet_TCP_Open(&ip);
+ if (!lfd)
+ Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_Open() failed");
+
+ fds = SDLNet_AllocSocketSet(MAX_PLAYERS+1);
+ SDLNet_TCP_AddSocket(fds, lfd);
+
+#else
if ((lfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
Error(ERR_EXIT_NETWORK_SERVER, "socket() failed");
Error(ERR_EXIT_NETWORK_SERVER, "bind() failed");
listen(lfd, 5);
+#endif
+#if !defined(TARGET_SDL)
if (is_daemon)
{
/* become a daemon, breaking all ties with the controlling terminal */
open("/dev/null", O_WRONLY);
open("/dev/null", O_WRONLY);
}
+#endif
if (options.verbose)
{
for (player = first_player; player; player = player->next)
flushuser(player);
+#if defined(TARGET_SDL)
+ if ((sl = SDLNet_CheckSockets(fds, 500000)) < 1)
+ {
+ Error(ERR_NETWORK_SERVER, SDLNet_GetError());
+ perror("SDLNet_CheckSockets");
+ }
+
+#else
+
FD_ZERO(&fds);
mfd = lfd;
player = first_player;
else
continue;
}
+#endif
if (sl < 0)
continue;
if (sl == 0)
continue;
+ /* accept incoming connections */
+#if defined(TARGET_SDL)
+ if (SDLNet_SocketReady(lfd))
+ {
+ TCPsocket newsock;
+
+ newsock = SDLNet_TCP_Accept(lfd);
+
+ if (newsock)
+ AddPlayer(newsock);
+ }
+
+#else
+
if (FD_ISSET(lfd, &fds))
{
int newfd, slen;
}
continue;
}
+#endif
player = first_player;
do
{
+#if defined(TARGET_SDL)
+ if (SDLNet_SocketReady(player->fd))
+#else
if (FD_ISSET(player->fd, &fds))
+#endif
{
- r = read(player->fd, player->readbuffer + player->nread, MAX_BUFFER_SIZE - player->nread);
+#if defined(TARGET_SDL)
+ /* read only 1 byte, because SDLNet blocks when we want more than is
+ in the buffer */
+ r = SDLNet_TCP_Recv(player->fd, player->readbuffer + player->nread, 1);
+#else
+ r = read(player->fd, player->readbuffer + player->nread,
+ MAX_BUFFER_SIZE - player->nread);
+#endif
+
if (r <= 0)
{
if (options.verbose)
}
}
-#endif /* PLATFORM_UNIX */
+#endif /* NETWORK_AVALIABLE */
#define MAX_BUFFER_SIZE 4096
+#if defined(TARGET_SDL)
+int NetworkServerThread(void *);
+#endif
+
void NetworkServer(int, int);
#endif
#include "libgame/platform.h"
-#if defined(PLATFORM_UNIX)
+#if defined(NETWORK_AVALIABLE)
#include <signal.h>
#include <sys/time.h>
+
+#if defined(TARGET_SDL)
+#include "main.h"
+#else
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
+#endif
#include "libgame/libgame.h"
/* server stuff */
-static int sfd;
+#if defined(TARGET_SDL)
+static TCPsocket sfd; /* server socket */
+static SDLNet_SocketSet rfds; /* socket set */
+#else
+static int sfd; /* server socket */
+#endif
+
static byte realbuffer[512];
static byte readbuffer[MAX_BUFFER_SIZE], writbuffer[MAX_BUFFER_SIZE];
static byte *buffer = realbuffer + 4;
nwrite += 4 + size;
/* directly send the buffer to the network server */
+#if defined(TARGET_SDL)
+ SDLNet_TCP_Send(sfd, writbuffer, nwrite);
+#else
write(sfd, writbuffer, nwrite);
+#endif
nwrite = 0;
}
static void StartNetworkServer(int port)
{
+#if defined(TARGET_SDL)
+ static int p;
+
+ p = port;
+ server_thread = SDL_CreateThread(NetworkServerThread, &p);
+ network_server = TRUE;
+
+#else
+
switch (fork())
{
case 0:
/* we are parent process -- resume normal operation */
return;
}
+#endif
}
+#if defined(TARGET_SDL)
+boolean ConnectToServer(char *hostname, int port)
+{
+ IPaddress ip;
+ int i;
+
+ if (port == 0)
+ port = DEFAULT_SERVER_PORT;
+
+ rfds = SDLNet_AllocSocketSet(1);
+
+ if (hostname)
+ {
+ SDLNet_ResolveHost(&ip, hostname, port);
+ if (ip.host == INADDR_NONE)
+ Error(ERR_EXIT, "cannot locate host '%s'", hostname);
+ }
+ else
+ {
+ SDLNet_Write32(0x7f000001, &ip.host); /* 127.0.0.1 */
+ SDLNet_Write16(port, &ip.port);
+ }
+
+ sfd = SDLNet_TCP_Open(&ip);
+
+ if (sfd)
+ {
+ SDLNet_TCP_AddSocket(rfds, sfd);
+ return TRUE;
+ }
+ else
+ {
+ printf("SDLNet_TCP_Open(): %s\n", SDLNet_GetError());
+ }
+
+ if (hostname) /* connect to specified server failed */
+ return FALSE;
+
+ printf("No rocksndiamonds server on localhost -- starting up one ...\n");
+ StartNetworkServer(port);
+
+ /* wait for server to start up and try connecting several times */
+ for (i = 0; i < 6; i++)
+ {
+ Delay(500); /* wait 500 ms == 0.5 seconds */
+
+ if ((sfd = SDLNet_TCP_Open(&ip))) /* connected */
+ {
+ SDLNet_TCP_AddSocket(rfds, sfd);
+ return TRUE;
+ }
+ }
+
+ /* when reaching this point, connect to newly started server has failed */
+ return FALSE;
+}
+
+#else
+
boolean ConnectToServer(char *hostname, int port)
{
struct sockaddr_in s;
if (hostname) /* connect to specified server failed */
return FALSE;
- printf("No rocksndiamonds server on localhost - starting up one ...\n");
+ printf("No rocksndiamonds server on localhost -- starting up one ...\n");
StartNetworkServer(port);
/* wait for server to start up and try connecting several times */
/* when reaching this point, connect to newly started server has failed */
return FALSE;
}
+#endif /* defined(TARGET_SDL) */
void SendToServer_PlayerName(char *player_name)
{
}
if (first_player.nr > MAX_PLAYERS)
- Error(ERR_EXIT, "sorry - no more than %d players", MAX_PLAYERS);
+ Error(ERR_EXIT, "sorry, more than %d players not allowed", MAX_PLAYERS);
Error(ERR_NETWORK_CLIENT, "you get client # %d", new_client_nr);
}
fflush(stdout);
}
+/* TODO */
+
void HandleNetworking()
{
+#if !defined(TARGET_SDL)
static struct timeval tv = { 0, 0 };
fd_set rfds;
+#endif
int r = 0;
- FD_ZERO(&rfds);
- FD_SET(sfd, &rfds);
-
- r = select(sfd + 1, &rfds, NULL, NULL, &tv);
+ do
+ {
+#if defined(TARGET_SDL)
+ if ((r = SDLNet_CheckSockets(rfds, 1)) < 0)
+ Error(ERR_EXIT, "HandleNetworking(): SDLNet_CheckSockets() failed");
- if (r < 0 && errno != EINTR)
- Error(ERR_EXIT, "HandleNetworking(): select() failed");
+#else
- if (r < 0)
FD_ZERO(&rfds);
+ FD_SET(sfd, &rfds);
- if (FD_ISSET(sfd, &rfds))
- {
- int r;
+ r = select(sfd + 1, &rfds, NULL, NULL, &tv);
- r = read(sfd, readbuffer + nread, MAX_BUFFER_SIZE - nread);
+ if (r < 0 && errno != EINTR)
+ Error(ERR_EXIT, "HandleNetworking(): select() failed");
if (r < 0)
- Error(ERR_EXIT, "error reading from network server");
+ FD_ZERO(&rfds);
+#endif
+
+#if defined(TARGET_SDL)
+ if (r > 0)
+#else
+ if (FD_ISSET(sfd, &rfds))
+#endif
+ {
+#if defined(TARGET_SDL)
+ r = SDLNet_TCP_Recv(sfd, readbuffer + nread, 1);
+#else
+ r = read(sfd, readbuffer + nread, MAX_BUFFER_SIZE - nread);
+#endif
+
+ if (r < 0)
+ Error(ERR_EXIT, "error reading from network server");
- if (r == 0)
- Error(ERR_EXIT, "connection to network server lost");
+ if (r == 0)
+ Error(ERR_EXIT, "connection to network server lost");
- nread += r;
+ nread += r;
- HandleNetworkingMessages();
+ HandleNetworkingMessages();
+ }
}
+ while (r > 0);
}
#endif /* PLATFORM_UNIX */
leveldir_last_valid = leveldir_current;
/* needed if last screen (level choice) changed graphics, sounds or music */
- ReloadCustomArtwork();
+ ReloadCustomArtwork(0);
#ifdef TARGET_SDL
SetDrawtoField(DRAW_BACKBUFFER);
if (setup.autorecord)
TapeStartRecording();
-#if defined(PLATFORM_UNIX)
+#if defined(NETWORK_AVALIABLE)
if (options.network)
SendToServer_StartPlaying();
else
setup.music_set = artwork.mus_current->identifier;
/* needed if last screen (setup choice) changed graphics, sounds or music */
- ReloadCustomArtwork();
+ ReloadCustomArtwork(0);
/* needed for displaying artwork name instead of artwork identifier */
graphics_set_name = artwork.gfx_current->name;
{ &custom_key.up, "Joystick Up" },
{ &custom_key.down, "Joystick Down" },
{ &custom_key.snap, "Button 1" },
- { &custom_key.bomb, "Button 2" }
+ { &custom_key.drop, "Button 2" }
};
static char *joystick_name[MAX_PLAYERS] =
{
DrawText(mSX+11*32, mSY+2*32, int2str(player_nr +1, 1), FONT_INPUT_1_ACTIVE);
#if 1
+ ClearRectangleOnBackground(drawto, mSX + 8 * TILEX, mSY + 2 * TILEY,
+ TILEX, TILEY);
DrawGraphicThruMaskExt(drawto, mSX + 8 * TILEX, mSY + 2 * TILEY,
PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0);
#else
DrawText(mSX+2*32, mSY+8*32, ":", FONT_VALUE_OLD);
DrawText(mSX+2*32, mSY+9*32, ":", FONT_VALUE_OLD);
DrawText(mSX+32, mSY+10*32, "Snap Field:", FONT_VALUE_OLD);
- DrawText(mSX+32, mSY+12*32, "Place Bomb:", FONT_VALUE_OLD);
+ DrawText(mSX+32, mSY+12*32, "Drop Element:", FONT_VALUE_OLD);
for (i = 0; i < 6; i++)
{
char *text;
} customize_step[] =
{
- { &custom_key.left, "Move Left" },
- { &custom_key.right, "Move Right" },
- { &custom_key.up, "Move Up" },
- { &custom_key.down, "Move Down" },
- { &custom_key.snap, "Snap Field" },
- { &custom_key.bomb, "Place Bomb" }
+ { &custom_key.left, "Move Left" },
+ { &custom_key.right, "Move Right" },
+ { &custom_key.up, "Move Up" },
+ { &custom_key.down, "Move Down" },
+ { &custom_key.snap, "Snap Field" },
+ { &custom_key.drop, "Drop Element" }
};
/* read existing key bindings from player setup */
#include "cartoons.h"
/* tape button identifiers */
-#define TAPE_CTRL_ID_EJECT 0
-#define TAPE_CTRL_ID_INDEX 1
-#define TAPE_CTRL_ID_STOP 2
-#define TAPE_CTRL_ID_PAUSE 3
-#define TAPE_CTRL_ID_RECORD 4
-#define TAPE_CTRL_ID_PLAY 5
+#define TAPE_CTRL_ID_EJECT 0
+#define TAPE_CTRL_ID_EXTRA 1
+#define TAPE_CTRL_ID_STOP 2
+#define TAPE_CTRL_ID_PAUSE 3
+#define TAPE_CTRL_ID_RECORD 4
+#define TAPE_CTRL_ID_PLAY 5
-#define NUM_TAPE_BUTTONS 6
+#define NUM_TAPE_BUTTONS 6
/* values for tape handling */
#define TAPE_PAUSE_SECONDS_BEFORE_DEATH 5
/* forward declaration for internal use */
static void HandleTapeButtons(struct GadgetInfo *);
-static void TapeStopIndexSearch();
+static void TapeStopWarpForward();
static struct GadgetInfo *tape_gadget[NUM_TAPE_BUTTONS];
/* ========================================================================= */
/* some positions in the video tape control window */
-#define VIDEO_DATE_LABEL_XPOS (VIDEO_DISPLAY1_XPOS)
-#define VIDEO_DATE_LABEL_YPOS (VIDEO_DISPLAY1_YPOS)
-#define VIDEO_DATE_LABEL_XSIZE (VIDEO_DISPLAY_XSIZE)
-#define VIDEO_DATE_LABEL_YSIZE (VIDEO_DISPLAY_YSIZE)
-#define VIDEO_DATE_XPOS (VIDEO_DISPLAY1_XPOS + 2)
-#define VIDEO_DATE_YPOS (VIDEO_DISPLAY1_YPOS + 14)
-#define VIDEO_DATE_XSIZE (VIDEO_DISPLAY_XSIZE)
-#define VIDEO_DATE_YSIZE 16
-#define VIDEO_REC_LABEL_XPOS (VIDEO_DISPLAY2_XPOS)
-#define VIDEO_REC_LABEL_YPOS (VIDEO_DISPLAY2_YPOS)
-#define VIDEO_REC_LABEL_XSIZE 20
-#define VIDEO_REC_LABEL_YSIZE 12
-#define VIDEO_REC_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS + 20)
-#define VIDEO_REC_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS)
-#define VIDEO_REC_SYMBOL_XSIZE 16
-#define VIDEO_REC_SYMBOL_YSIZE 16
-#define VIDEO_PLAY_LABEL_XPOS (VIDEO_DISPLAY2_XPOS + 65)
-#define VIDEO_PLAY_LABEL_YPOS (VIDEO_DISPLAY2_YPOS)
-#define VIDEO_PLAY_LABEL_XSIZE 22
-#define VIDEO_PLAY_LABEL_YSIZE 12
-#define VIDEO_PLAY_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS + 52)
-#define VIDEO_PLAY_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS)
-#define VIDEO_PLAY_SYMBOL_XSIZE 11
-#define VIDEO_PLAY_SYMBOL_YSIZE 13
-#define VIDEO_PAUSE_LABEL_XPOS (VIDEO_DISPLAY2_XPOS)
-#define VIDEO_PAUSE_LABEL_YPOS (VIDEO_DISPLAY2_YPOS + 20)
-#define VIDEO_PAUSE_LABEL_XSIZE 35
-#define VIDEO_PAUSE_LABEL_YSIZE 8
-#define VIDEO_PAUSE_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS + 35)
-#define VIDEO_PAUSE_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS)
-#define VIDEO_PAUSE_SYMBOL_XSIZE 17
-#define VIDEO_PAUSE_SYMBOL_YSIZE 13
-#define VIDEO_TIME_XPOS (VIDEO_DISPLAY2_XPOS + 39)
-#define VIDEO_TIME_YPOS (VIDEO_DISPLAY2_YPOS + 14)
-#define VIDEO_TIME_XSIZE 50
-#define VIDEO_TIME_YSIZE 16
-
-/* special */
-#define VIDEO_PBEND_LABEL_XPOS 5
-#define VIDEO_PBEND_LABEL_YPOS 220
-#define VIDEO_PBEND_LABEL_XSIZE 35
-#define VIDEO_PBEND_LABEL_YSIZE 30
-
-#define VIDEO_STATE_OFF (VIDEO_STATE_PLAY_OFF | \
- VIDEO_STATE_REC_OFF | \
- VIDEO_STATE_PAUSE_OFF | \
- VIDEO_STATE_FFWD_OFF | \
- VIDEO_STATE_PBEND_OFF | \
- VIDEO_STATE_DATE_OFF | \
- VIDEO_STATE_TIME_OFF)
-#define VIDEO_PRESS_OFF (VIDEO_PRESS_PLAY_OFF | \
- VIDEO_PRESS_REC_OFF | \
- VIDEO_PRESS_PAUSE_OFF | \
- VIDEO_PRESS_STOP_OFF | \
- VIDEO_PRESS_EJECT_OFF)
-#define VIDEO_ALL_OFF (VIDEO_STATE_OFF | VIDEO_PRESS_OFF)
-
-#define VIDEO_STATE_ON (VIDEO_STATE_PLAY_ON | \
- VIDEO_STATE_REC_ON | \
- VIDEO_STATE_PAUSE_ON | \
- VIDEO_STATE_FFWD_ON | \
- VIDEO_STATE_PBEND_ON | \
- VIDEO_STATE_DATE_ON | \
- VIDEO_STATE_TIME_ON)
-#define VIDEO_PRESS_ON (VIDEO_PRESS_PLAY_ON | \
- VIDEO_PRESS_REC_ON | \
- VIDEO_PRESS_PAUSE_ON | \
- VIDEO_PRESS_STOP_ON | \
- VIDEO_PRESS_EJECT_ON)
-#define VIDEO_ALL_ON (VIDEO_STATE_ON | VIDEO_PRESS_ON)
-
-#define VIDEO_STATE (VIDEO_STATE_ON | VIDEO_STATE_OFF)
-#define VIDEO_PRESS (VIDEO_PRESS_ON | VIDEO_PRESS_OFF)
-#define VIDEO_ALL (VIDEO_ALL_ON | VIDEO_ALL_OFF)
+#define VIDEO_DATE_LABEL_XPOS (VIDEO_DISPLAY1_XPOS)
+#define VIDEO_DATE_LABEL_YPOS (VIDEO_DISPLAY1_YPOS)
+#define VIDEO_DATE_LABEL_XSIZE (VIDEO_DISPLAY_XSIZE)
+#define VIDEO_DATE_LABEL_YSIZE (VIDEO_DISPLAY_YSIZE)
+#define VIDEO_DATE_XPOS (VIDEO_DISPLAY1_XPOS + 2)
+#define VIDEO_DATE_YPOS (VIDEO_DISPLAY1_YPOS + 14)
+#define VIDEO_DATE_XSIZE (VIDEO_DISPLAY_XSIZE)
+#define VIDEO_DATE_YSIZE 16
+#define VIDEO_REC_LABEL_XPOS (VIDEO_DISPLAY2_XPOS)
+#define VIDEO_REC_LABEL_YPOS (VIDEO_DISPLAY2_YPOS)
+#define VIDEO_REC_LABEL_XSIZE 20
+#define VIDEO_REC_LABEL_YSIZE 12
+#define VIDEO_REC_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS + 20)
+#define VIDEO_REC_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS)
+#define VIDEO_REC_SYMBOL_XSIZE 16
+#define VIDEO_REC_SYMBOL_YSIZE 16
+#define VIDEO_PLAY_LABEL_XPOS (VIDEO_DISPLAY2_XPOS + 65)
+#define VIDEO_PLAY_LABEL_YPOS (VIDEO_DISPLAY2_YPOS)
+#define VIDEO_PLAY_LABEL_XSIZE 22
+#define VIDEO_PLAY_LABEL_YSIZE 12
+#define VIDEO_PLAY_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS + 52)
+#define VIDEO_PLAY_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS)
+#define VIDEO_PLAY_SYMBOL_XSIZE 11
+#define VIDEO_PLAY_SYMBOL_YSIZE 13
+#define VIDEO_PAUSE_LABEL_XPOS (VIDEO_DISPLAY2_XPOS)
+#define VIDEO_PAUSE_LABEL_YPOS (VIDEO_DISPLAY2_YPOS + 20)
+#define VIDEO_PAUSE_LABEL_XSIZE 35
+#define VIDEO_PAUSE_LABEL_YSIZE 8
+#define VIDEO_PAUSE_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS + 35)
+#define VIDEO_PAUSE_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS)
+#define VIDEO_PAUSE_SYMBOL_XSIZE 17
+#define VIDEO_PAUSE_SYMBOL_YSIZE 13
+#define VIDEO_TIME_XPOS (VIDEO_DISPLAY2_XPOS + 39)
+#define VIDEO_TIME_YPOS (VIDEO_DISPLAY2_YPOS + 14)
+#define VIDEO_TIME_XSIZE 50
+#define VIDEO_TIME_YSIZE 16
+
+/* some default values for tape labels and symbols */
+#define VIDEO_LABEL_XPOS 5
+#define VIDEO_LABEL_YPOS 42
+#define VIDEO_LABEL_XSIZE 40
+#define VIDEO_LABEL_YSIZE 28
+#define VIDEO_SYMBOL_XPOS 39
+#define VIDEO_SYMBOL_YPOS 42
+#define VIDEO_SYMBOL_XSIZE 56
+#define VIDEO_SYMBOL_YSIZE 13
+
+/* values for certain tape labels and symbols */
+#define VIDEO_FFWD_LABEL_XPOS VIDEO_LABEL_XPOS
+#define VIDEO_FFWD_LABEL_YPOS 193
+#define VIDEO_FFWD_LABEL_XSIZE VIDEO_LABEL_XSIZE
+#define VIDEO_FFWD_LABEL_YSIZE VIDEO_LABEL_YSIZE
+#define VIDEO_FFWD_SYMBOL_XPOS VIDEO_SYMBOL_XPOS
+#define VIDEO_FFWD_SYMBOL_YPOS 193
+#define VIDEO_FFWD_SYMBOL_XSIZE 27
+#define VIDEO_FFWD_SYMBOL_YSIZE VIDEO_SYMBOL_YSIZE
+
+#define VIDEO_PBEND_LABEL_XPOS VIDEO_LABEL_XPOS
+#define VIDEO_PBEND_LABEL_YPOS 221
+#define VIDEO_PBEND_LABEL_XSIZE VIDEO_LABEL_XSIZE
+#define VIDEO_PBEND_LABEL_YSIZE VIDEO_LABEL_YSIZE
+#define VIDEO_PBEND_SYMBOL_XPOS VIDEO_SYMBOL_XPOS
+#define VIDEO_PBEND_SYMBOL_YPOS 221
+#define VIDEO_PBEND_SYMBOL_XSIZE 27
+#define VIDEO_PBEND_SYMBOL_YSIZE VIDEO_SYMBOL_YSIZE
+
+#define VIDEO_WARP_LABEL_XPOS VIDEO_LABEL_XPOS
+#define VIDEO_WARP_LABEL_YPOS 165
+#define VIDEO_WARP_LABEL_XSIZE VIDEO_LABEL_XSIZE
+#define VIDEO_WARP_LABEL_YSIZE VIDEO_LABEL_YSIZE
+#define VIDEO_WARP_SYMBOL_XPOS VIDEO_SYMBOL_XPOS
+#define VIDEO_WARP_SYMBOL_YPOS 165
+#define VIDEO_WARP_SYMBOL_XSIZE 27
+#define VIDEO_WARP_SYMBOL_YSIZE VIDEO_SYMBOL_YSIZE
+#define VIDEO_WARP2_SYMBOL_XPOS VIDEO_SYMBOL_XPOS
+#define VIDEO_WARP2_SYMBOL_YPOS 152
+#define VIDEO_WARP2_SYMBOL_XSIZE 27
+#define VIDEO_WARP2_SYMBOL_YSIZE VIDEO_SYMBOL_YSIZE
+
+#define VIDEO_1STEP_SYMBOL_XPOS (VIDEO_SYMBOL_XPOS + 18)
+#define VIDEO_1STEP_SYMBOL_YPOS 139
+#define VIDEO_1STEP_SYMBOL_XSIZE (VIDEO_SYMBOL_XSIZE - 18)
+#define VIDEO_1STEP_SYMBOL_YSIZE VIDEO_SYMBOL_YSIZE
+
+#define PG_X3(x) (DOOR_GFX_PAGEX3 + (x))
+#define PG_X4(x) (DOOR_GFX_PAGEX4 + (x))
+#define PG_X5(x) (DOOR_GFX_PAGEX5 + (x))
+#define PG_X6(x) (DOOR_GFX_PAGEX6 + (x))
+
+#define PG_Y1(y) (DOOR_GFX_PAGEY1 + (y))
+#define PG_Y2(y) (DOOR_GFX_PAGEY2 + (y))
+
+#define VIDEO_INFO_OFF (VIDEO_STATE_DATE_OFF | \
+ VIDEO_STATE_TIME_OFF)
+#define VIDEO_STATE_OFF (VIDEO_STATE_PLAY_OFF | \
+ VIDEO_STATE_REC_OFF | \
+ VIDEO_STATE_PAUSE_OFF | \
+ VIDEO_STATE_FFWD_OFF | \
+ VIDEO_STATE_PBEND_OFF | \
+ VIDEO_STATE_1STEP_OFF)
+#define VIDEO_PRESS_OFF (VIDEO_PRESS_PLAY_OFF | \
+ VIDEO_PRESS_REC_OFF | \
+ VIDEO_PRESS_PAUSE_OFF | \
+ VIDEO_PRESS_STOP_OFF | \
+ VIDEO_PRESS_EJECT_OFF)
+#define VIDEO_ALL_OFF (VIDEO_INFO_OFF | \
+ VIDEO_STATE_OFF | \
+ VIDEO_PRESS_OFF)
+
+#define VIDEO_INFO_ON (VIDEO_STATE_DATE_ON | \
+ VIDEO_STATE_TIME_ON)
+#define VIDEO_STATE_ON (VIDEO_STATE_PLAY_ON | \
+ VIDEO_STATE_REC_ON | \
+ VIDEO_STATE_PAUSE_ON | \
+ VIDEO_STATE_FFWD_ON | \
+ VIDEO_STATE_PBEND_ON | \
+ VIDEO_STATE_1STEP_ON)
+#define VIDEO_PRESS_ON (VIDEO_PRESS_PLAY_ON | \
+ VIDEO_PRESS_REC_ON | \
+ VIDEO_PRESS_PAUSE_ON | \
+ VIDEO_PRESS_STOP_ON | \
+ VIDEO_PRESS_EJECT_ON)
+#define VIDEO_ALL_ON (VIDEO_INFO_ON | \
+ VIDEO_STATE_ON | \
+ VIDEO_PRESS_ON)
+
+#define VIDEO_INFO (VIDEO_INFO_ON | VIDEO_INFO_OFF)
+#define VIDEO_STATE (VIDEO_STATE_ON | VIDEO_STATE_OFF)
+#define VIDEO_PRESS (VIDEO_PRESS_ON | VIDEO_PRESS_OFF)
+#define VIDEO_ALL (VIDEO_ALL_ON | VIDEO_ALL_OFF)
+
+#define NUM_TAPE_FUNCTIONS 10
+#define NUM_TAPE_FUNCTION_PARTS 2
+#define NUM_TAPE_FUNCTION_STATES 2
/* ========================================================================= */
void DrawVideoDisplay(unsigned long state, unsigned long value)
{
- int i;
- int part_label = 0, part_symbol = 1;
- int xpos = 0, ypos = 1, xsize = 2, ysize = 3;
+ int i, j, k;
static char *monatsname[12] =
{
"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
"JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
};
- static int video_pos[5][2][4] =
+ static struct
+ {
+ int gd_x1, gd_y1;
+ int gd_x2, gd_y2;
+ int x, y;
+ int width, height;
+ }
+ video_pos[NUM_TAPE_FUNCTIONS][NUM_TAPE_FUNCTION_PARTS] =
{
- {{ VIDEO_PLAY_LABEL_XPOS, VIDEO_PLAY_LABEL_YPOS,
- VIDEO_PLAY_LABEL_XSIZE,VIDEO_PLAY_LABEL_YSIZE },
- { VIDEO_PLAY_SYMBOL_XPOS, VIDEO_PLAY_SYMBOL_YPOS,
- VIDEO_PLAY_SYMBOL_XSIZE,VIDEO_PLAY_SYMBOL_YSIZE }},
-
- {{ VIDEO_REC_LABEL_XPOS, VIDEO_REC_LABEL_YPOS,
- VIDEO_REC_LABEL_XSIZE,VIDEO_REC_LABEL_YSIZE },
- { VIDEO_REC_SYMBOL_XPOS, VIDEO_REC_SYMBOL_YPOS,
- VIDEO_REC_SYMBOL_XSIZE,VIDEO_REC_SYMBOL_YSIZE }},
-
- {{ VIDEO_PAUSE_LABEL_XPOS, VIDEO_PAUSE_LABEL_YPOS,
- VIDEO_PAUSE_LABEL_XSIZE,VIDEO_PAUSE_LABEL_YSIZE },
- { VIDEO_PAUSE_SYMBOL_XPOS, VIDEO_PAUSE_SYMBOL_YPOS,
- VIDEO_PAUSE_SYMBOL_XSIZE,VIDEO_PAUSE_SYMBOL_YSIZE }},
-
- {{ VIDEO_DATE_LABEL_XPOS, VIDEO_DATE_LABEL_YPOS,
- VIDEO_DATE_LABEL_XSIZE,VIDEO_DATE_LABEL_YSIZE },
- { VIDEO_DATE_XPOS, VIDEO_DATE_YPOS,
- VIDEO_DATE_XSIZE,VIDEO_DATE_YSIZE }},
-
- {{ 0,0,
- 0,0 },
- { VIDEO_TIME_XPOS, VIDEO_TIME_YPOS,
- VIDEO_TIME_XSIZE,VIDEO_TIME_YSIZE }}
+ {
+ {
+ PG_X4(VIDEO_PLAY_LABEL_XPOS), PG_Y2(VIDEO_PLAY_LABEL_YPOS),
+ PG_X3(VIDEO_PLAY_LABEL_XPOS), PG_Y2(VIDEO_PLAY_LABEL_YPOS),
+ VIDEO_PLAY_LABEL_XPOS, VIDEO_PLAY_LABEL_YPOS,
+ VIDEO_PLAY_LABEL_XSIZE, VIDEO_PLAY_LABEL_YSIZE
+ },
+ {
+ PG_X4(VIDEO_PLAY_SYMBOL_XPOS), PG_Y2(VIDEO_PLAY_SYMBOL_YPOS),
+ PG_X3(VIDEO_PLAY_SYMBOL_XPOS), PG_Y2(VIDEO_PLAY_SYMBOL_YPOS),
+ VIDEO_PLAY_SYMBOL_XPOS, VIDEO_PLAY_SYMBOL_YPOS,
+ VIDEO_PLAY_SYMBOL_XSIZE, VIDEO_PLAY_SYMBOL_YSIZE
+ }
+ },
+ {
+ {
+ PG_X4(VIDEO_REC_LABEL_XPOS), PG_Y2(VIDEO_REC_LABEL_YPOS),
+ PG_X3(VIDEO_REC_LABEL_XPOS), PG_Y2(VIDEO_REC_LABEL_YPOS),
+ VIDEO_REC_LABEL_XPOS, VIDEO_REC_LABEL_YPOS,
+ VIDEO_REC_LABEL_XSIZE, VIDEO_REC_LABEL_YSIZE
+ },
+ {
+ PG_X4(VIDEO_REC_SYMBOL_XPOS), PG_Y2(VIDEO_REC_SYMBOL_YPOS),
+ PG_X3(VIDEO_REC_SYMBOL_XPOS), PG_Y2(VIDEO_REC_SYMBOL_YPOS),
+ VIDEO_REC_SYMBOL_XPOS, VIDEO_REC_SYMBOL_YPOS,
+ VIDEO_REC_SYMBOL_XSIZE, VIDEO_REC_SYMBOL_YSIZE
+ }
+ },
+ {
+ {
+ PG_X4(VIDEO_PAUSE_LABEL_XPOS), PG_Y2(VIDEO_PAUSE_LABEL_YPOS),
+ PG_X3(VIDEO_PAUSE_LABEL_XPOS), PG_Y2(VIDEO_PAUSE_LABEL_YPOS),
+ VIDEO_PAUSE_LABEL_XPOS, VIDEO_PAUSE_LABEL_YPOS,
+ VIDEO_PAUSE_LABEL_XSIZE, VIDEO_PAUSE_LABEL_YSIZE
+ },
+ {
+ PG_X4(VIDEO_PAUSE_SYMBOL_XPOS), PG_Y2(VIDEO_PAUSE_SYMBOL_YPOS),
+ PG_X3(VIDEO_PAUSE_SYMBOL_XPOS), PG_Y2(VIDEO_PAUSE_SYMBOL_YPOS),
+ VIDEO_PAUSE_SYMBOL_XPOS, VIDEO_PAUSE_SYMBOL_YPOS,
+ VIDEO_PAUSE_SYMBOL_XSIZE, VIDEO_PAUSE_SYMBOL_YSIZE
+ }
+ },
+ {
+ {
+ PG_X4(VIDEO_DATE_LABEL_XPOS), PG_Y2(VIDEO_DATE_LABEL_YPOS),
+ PG_X3(VIDEO_DATE_LABEL_XPOS), PG_Y2(VIDEO_DATE_LABEL_YPOS),
+ VIDEO_DATE_LABEL_XPOS, VIDEO_DATE_LABEL_YPOS,
+ VIDEO_DATE_LABEL_XSIZE, VIDEO_DATE_LABEL_YSIZE
+ },
+ {
+ PG_X4(VIDEO_DATE_XPOS), PG_Y2(VIDEO_DATE_YPOS),
+ PG_X3(VIDEO_DATE_XPOS), PG_Y2(VIDEO_DATE_YPOS),
+ VIDEO_DATE_XPOS, VIDEO_DATE_YPOS,
+ VIDEO_DATE_XSIZE, VIDEO_DATE_YSIZE
+ }
+ },
+ {
+ {
+ -1, -1,
+ -1, -1,
+ -1, -1,
+ -1, -1
+ },
+ {
+ PG_X4(VIDEO_TIME_XPOS), PG_Y2(VIDEO_TIME_YPOS),
+ PG_X3(VIDEO_TIME_XPOS), PG_Y2(VIDEO_TIME_YPOS),
+ VIDEO_TIME_XPOS, VIDEO_TIME_YPOS,
+ VIDEO_TIME_XSIZE, VIDEO_TIME_YSIZE
+ }
+ },
+ {
+ {
+ PG_X6(VIDEO_FFWD_LABEL_XPOS), PG_Y1(VIDEO_FFWD_LABEL_YPOS),
+ PG_X3(VIDEO_LABEL_XPOS), PG_Y2(VIDEO_LABEL_YPOS),
+ VIDEO_LABEL_XPOS, VIDEO_LABEL_YPOS,
+ VIDEO_LABEL_XSIZE, VIDEO_LABEL_YSIZE
+ },
+ {
+ PG_X6(VIDEO_FFWD_SYMBOL_XPOS), PG_Y1(VIDEO_FFWD_SYMBOL_YPOS),
+ PG_X3(VIDEO_FFWD_SYMBOL_XPOS), PG_Y2(VIDEO_SYMBOL_YPOS),
+ VIDEO_SYMBOL_XPOS, VIDEO_SYMBOL_YPOS,
+ VIDEO_FFWD_SYMBOL_XSIZE, VIDEO_FFWD_SYMBOL_YSIZE
+ }
+ },
+ {
+ {
+ PG_X6(VIDEO_PBEND_LABEL_XPOS), PG_Y1(VIDEO_PBEND_LABEL_YPOS),
+ PG_X3(VIDEO_LABEL_XPOS), PG_Y2(VIDEO_LABEL_YPOS),
+ VIDEO_LABEL_XPOS, VIDEO_LABEL_YPOS,
+ VIDEO_LABEL_XSIZE, VIDEO_LABEL_YSIZE
+ },
+ {
+ PG_X6(VIDEO_PBEND_SYMBOL_XPOS), PG_Y1(VIDEO_PBEND_SYMBOL_YPOS),
+ PG_X3(VIDEO_PBEND_SYMBOL_XPOS), PG_Y2(VIDEO_SYMBOL_YPOS),
+ VIDEO_SYMBOL_XPOS, VIDEO_SYMBOL_YPOS,
+ VIDEO_PBEND_SYMBOL_XSIZE, VIDEO_PBEND_SYMBOL_YSIZE
+ }
+ },
+ {
+ {
+ PG_X6(VIDEO_WARP_LABEL_XPOS), PG_Y1(VIDEO_WARP_LABEL_YPOS),
+ PG_X3(VIDEO_LABEL_XPOS), PG_Y2(VIDEO_LABEL_YPOS),
+ VIDEO_LABEL_XPOS, VIDEO_LABEL_YPOS,
+ VIDEO_LABEL_XSIZE, VIDEO_LABEL_YSIZE
+ },
+ {
+ PG_X6(VIDEO_WARP_SYMBOL_XPOS), PG_Y1(VIDEO_WARP_SYMBOL_YPOS),
+ PG_X3(VIDEO_WARP_SYMBOL_XPOS), PG_Y2(VIDEO_SYMBOL_YPOS),
+ VIDEO_SYMBOL_XPOS, VIDEO_SYMBOL_YPOS,
+ VIDEO_WARP_SYMBOL_XSIZE, VIDEO_WARP_SYMBOL_YSIZE
+ }
+ },
+ {
+ {
+ -1, -1,
+ -1, -1,
+ -1, -1,
+ -1, -1
+ },
+ {
+ PG_X6(VIDEO_WARP2_SYMBOL_XPOS), PG_Y1(VIDEO_WARP2_SYMBOL_YPOS),
+ PG_X3(VIDEO_WARP2_SYMBOL_XPOS), PG_Y2(VIDEO_SYMBOL_YPOS),
+ VIDEO_SYMBOL_XPOS, VIDEO_SYMBOL_YPOS,
+ VIDEO_WARP2_SYMBOL_XSIZE, VIDEO_WARP2_SYMBOL_YSIZE
+ }
+ },
+ {
+ {
+ -1, -1,
+ -1, -1,
+ -1, -1,
+ -1, -1
+ },
+ {
+ PG_X6(VIDEO_1STEP_SYMBOL_XPOS), PG_Y1(VIDEO_1STEP_SYMBOL_YPOS),
+ PG_X3(VIDEO_1STEP_SYMBOL_XPOS), PG_Y2(VIDEO_SYMBOL_YPOS),
+ VIDEO_1STEP_SYMBOL_XPOS, VIDEO_SYMBOL_YPOS,
+ VIDEO_1STEP_SYMBOL_XSIZE, VIDEO_1STEP_SYMBOL_YSIZE
+ }
+ },
};
+#if 0
+ if (state & VIDEO_STATE_FFWD_OFF)
+ {
+#if 1
+ int cx = DOOR_GFX_PAGEX3, cy = DOOR_GFX_PAGEY2;
+
+ if (value != VIDEO_DISPLAY_SYMBOL_ONLY)
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ cx + VIDEO_LABEL_XPOS,
+ cy + VIDEO_LABEL_YPOS,
+ VIDEO_LABEL_XSIZE,
+ VIDEO_LABEL_YSIZE,
+ VX + VIDEO_LABEL_XPOS,
+ VY + VIDEO_LABEL_YPOS);
+
+ cx = DOOR_GFX_PAGEX3;
+ cy = DOOR_GFX_PAGEY2;
+
+ if (value != VIDEO_DISPLAY_LABEL_ONLY)
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ cx + VIDEO_FFWD_SYMBOL_XPOS,
+ cy + VIDEO_SYMBOL_YPOS,
+ VIDEO_FFWD_SYMBOL_XSIZE,
+ VIDEO_FFWD_SYMBOL_YSIZE,
+ VX + VIDEO_SYMBOL_XPOS,
+ VY + VIDEO_SYMBOL_YPOS);
+#else
+ int cx = DOOR_GFX_PAGEX3, cy = DOOR_GFX_PAGEY2;
+
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ cx + VIDEO_PLAY_SYMBOL_XPOS - 9,
+ cy + VIDEO_PLAY_SYMBOL_YPOS,
+ VIDEO_PLAY_SYMBOL_XSIZE - 2,
+ VIDEO_PLAY_SYMBOL_YSIZE,
+ VX + VIDEO_PLAY_SYMBOL_XPOS - 9,
+ VY + VIDEO_PLAY_SYMBOL_YPOS);
+#endif
+ }
+#endif
+
+#if 0
if (state & VIDEO_STATE_PBEND_OFF)
{
+#if 1
+ int cx = DOOR_GFX_PAGEX3, cy = DOOR_GFX_PAGEY2;
+
+ if (value != VIDEO_DISPLAY_SYMBOL_ONLY)
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ cx + VIDEO_LABEL_XPOS,
+ cy + VIDEO_LABEL_YPOS,
+ VIDEO_LABEL_XSIZE,
+ VIDEO_LABEL_YSIZE,
+ VX + VIDEO_LABEL_XPOS,
+ VY + VIDEO_LABEL_YPOS);
+
+ cx = DOOR_GFX_PAGEX3;
+ cy = DOOR_GFX_PAGEY2;
+
+ if (value != VIDEO_DISPLAY_LABEL_ONLY)
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ cx + VIDEO_PBEND_SYMBOL_XPOS,
+ cy + VIDEO_SYMBOL_YPOS,
+ VIDEO_PBEND_SYMBOL_XSIZE,
+ VIDEO_PBEND_SYMBOL_YSIZE,
+ VX + VIDEO_PBEND_SYMBOL_XPOS,
+ VY + VIDEO_SYMBOL_YPOS);
+#else
int cx = DOOR_GFX_PAGEX3, cy = DOOR_GFX_PAGEY2;
BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
VIDEO_PBEND_LABEL_YSIZE,
VX + VIDEO_REC_LABEL_XPOS,
VY + VIDEO_REC_LABEL_YPOS);
+#endif
}
+#endif
- for (i = 0; i < 10; i++)
+#if 0
+ if (state & VIDEO_STATE_1STEP_OFF)
{
- if (state & (1<<i))
- {
- int pos = i/2, cx, cy = DOOR_GFX_PAGEY2;
+ int cx = DOOR_GFX_PAGEX3, cy = DOOR_GFX_PAGEY2;
- if (i%2) /* i ungerade => STATE_ON / PRESS_OFF */
- cx = DOOR_GFX_PAGEX4;
- else
- cx = DOOR_GFX_PAGEX3; /* i gerade => STATE_OFF / PRESS_ON */
-
- if (video_pos[pos][part_label][0] && value != VIDEO_DISPLAY_SYMBOL_ONLY)
- BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
- cx + video_pos[pos][part_label][xpos],
- cy + video_pos[pos][part_label][ypos],
- video_pos[pos][part_label][xsize],
- video_pos[pos][part_label][ysize],
- VX + video_pos[pos][part_label][xpos],
- VY + video_pos[pos][part_label][ypos]);
- if (video_pos[pos][part_symbol][0] && value != VIDEO_DISPLAY_LABEL_ONLY)
- BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
- cx + video_pos[pos][part_symbol][xpos],
- cy + video_pos[pos][part_symbol][ypos],
- video_pos[pos][part_symbol][xsize],
- video_pos[pos][part_symbol][ysize],
- VX + video_pos[pos][part_symbol][xpos],
- VY + video_pos[pos][part_symbol][ypos]);
+ if (value != VIDEO_DISPLAY_LABEL_ONLY)
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ cx + VIDEO_1STEP_SYMBOL_XPOS,
+ cy + VIDEO_SYMBOL_YPOS,
+ VIDEO_1STEP_SYMBOL_XSIZE,
+ VIDEO_1STEP_SYMBOL_YSIZE,
+ VX + VIDEO_1STEP_SYMBOL_XPOS,
+ VY + VIDEO_SYMBOL_YPOS);
+ }
+#endif
+
+ for (k = 0; k < NUM_TAPE_FUNCTION_STATES; k++) /* on or off states */
+ {
+ for (i = 0; i < NUM_TAPE_FUNCTIONS; i++) /* record, play, ... */
+ {
+ for (j = 0; j < NUM_TAPE_FUNCTION_PARTS; j++) /* label or symbol */
+ {
+ if (state & (1 << (i * 2 + k)))
+ {
+ int gd_x, gd_y;
+ int skip_value =
+ (j == 0 ? VIDEO_DISPLAY_SYMBOL_ONLY : VIDEO_DISPLAY_LABEL_ONLY);
+
+ if (k == 1) /* on */
+ {
+ gd_x = video_pos[i][j].gd_x1;
+ gd_y = video_pos[i][j].gd_y1;
+ }
+ else /* off */
+ {
+ gd_x = video_pos[i][j].gd_x2;
+ gd_y = video_pos[i][j].gd_y2;
+ }
+
+ if (video_pos[i][j].x != -1 && value != skip_value)
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ gd_x, gd_y,
+ video_pos[i][j].width,
+ video_pos[i][j].height,
+ VX + video_pos[i][j].x,
+ VY + video_pos[i][j].y);
+ }
+ }
}
}
+#if 0
if (state & VIDEO_STATE_FFWD_ON)
{
+#if 1
+ int cx = DOOR_GFX_PAGEX6, cy = DOOR_GFX_PAGEY1;
+
+ if (value != VIDEO_DISPLAY_SYMBOL_ONLY)
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ cx + VIDEO_FFWD_LABEL_XPOS,
+ cy + VIDEO_FFWD_LABEL_YPOS,
+ VIDEO_LABEL_XSIZE,
+ VIDEO_LABEL_YSIZE,
+ VX + VIDEO_LABEL_XPOS,
+ VY + VIDEO_LABEL_YPOS);
+
+ cx = DOOR_GFX_PAGEX6;
+ cy = DOOR_GFX_PAGEY1;
+
+ if (value != VIDEO_DISPLAY_LABEL_ONLY)
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ cx + VIDEO_FFWD_SYMBOL_XPOS,
+ cy + VIDEO_FFWD_SYMBOL_YPOS,
+ VIDEO_FFWD_SYMBOL_XSIZE,
+ VIDEO_FFWD_SYMBOL_YSIZE,
+ VX + VIDEO_SYMBOL_XPOS,
+ VY + VIDEO_SYMBOL_YPOS);
+#else
int cx = DOOR_GFX_PAGEX4, cy = DOOR_GFX_PAGEY2;
BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
VIDEO_PLAY_SYMBOL_YSIZE,
VX + VIDEO_PLAY_SYMBOL_XPOS - 9,
VY + VIDEO_PLAY_SYMBOL_YPOS);
+#endif
}
+#endif
+#if 0
if (state & VIDEO_STATE_PBEND_ON)
{
+#if 1
+ int cx = DOOR_GFX_PAGEX6, cy = DOOR_GFX_PAGEY1;
+
+ if (value != VIDEO_DISPLAY_SYMBOL_ONLY)
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ cx + VIDEO_PBEND_LABEL_XPOS,
+ cy + VIDEO_PBEND_LABEL_YPOS,
+ VIDEO_LABEL_XSIZE,
+ VIDEO_LABEL_YSIZE,
+ VX + VIDEO_LABEL_XPOS,
+ VY + VIDEO_LABEL_YPOS);
+
+ cx = DOOR_GFX_PAGEX6;
+ cy = DOOR_GFX_PAGEY1;
+
+ if (value != VIDEO_DISPLAY_LABEL_ONLY)
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ cx + VIDEO_PBEND_SYMBOL_XPOS,
+ cy + VIDEO_PBEND_SYMBOL_YPOS,
+ VIDEO_PBEND_SYMBOL_XSIZE,
+ VIDEO_PBEND_SYMBOL_YSIZE,
+ VX + VIDEO_SYMBOL_XPOS,
+ VY + VIDEO_SYMBOL_YPOS);
+#else
int cx = DOOR_GFX_PAGEX6, cy = DOOR_GFX_PAGEY1;
BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
VIDEO_PBEND_LABEL_YSIZE,
VX + VIDEO_REC_LABEL_XPOS,
VY + VIDEO_REC_LABEL_YPOS);
+#endif
}
+#endif
+
+#if 0
+ if (state & VIDEO_STATE_1STEP_ON)
+ {
+ int cx = DOOR_GFX_PAGEX6, cy = DOOR_GFX_PAGEY1;
+
+ if (value != VIDEO_DISPLAY_LABEL_ONLY)
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ cx + VIDEO_1STEP_SYMBOL_XPOS,
+ cy + VIDEO_1STEP_SYMBOL_YPOS,
+ VIDEO_1STEP_SYMBOL_XSIZE,
+ VIDEO_1STEP_SYMBOL_YSIZE,
+ VX + VIDEO_1STEP_SYMBOL_XPOS,
+ VY + VIDEO_SYMBOL_YPOS);
+ }
+#endif
if (state & VIDEO_STATE_DATE_ON)
{
int2str(sec, 2), FONT_TAPE_RECORDER);
}
+#if 1
+ redraw_mask |= REDRAW_DOOR_2;
+#else
if (state & VIDEO_STATE_DATE)
redraw_mask |= REDRAW_VIDEO_1;
if ((state & ~VIDEO_STATE_DATE) & VIDEO_STATE)
redraw_mask |= REDRAW_VIDEO_2;
if (state & VIDEO_PRESS)
redraw_mask |= REDRAW_VIDEO_3;
+#endif
}
void DrawCompleteVideoDisplay()
DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
}
+void TapeDeactivateDisplayOn()
+{
+ SetDrawDeactivationMask(REDRAW_FIELD);
+ audio.sound_deactivated = TRUE;
+}
+
+void TapeDeactivateDisplayOff(boolean redraw_display)
+{
+ SetDrawDeactivationMask(REDRAW_NONE);
+ audio.sound_deactivated = FALSE;
+
+ if (redraw_display)
+ {
+ RedrawPlayfield(TRUE, 0,0,0,0);
+ DrawGameDoorValues();
+ }
+}
+
/* ========================================================================= */
/* tape control functions */
/* ========================================================================= */
-void TapeErase()
+static void TapeSetDate()
{
time_t epoch_seconds = time(NULL);
- struct tm *time = localtime(&epoch_seconds);
+ struct tm *now = localtime(&epoch_seconds);
+
+ tape.date = 10000 * (now->tm_year % 100) + 100 * now->tm_mon + now->tm_mday;
+}
+
+void TapeErase()
+{
int i;
tape.length = 0;
tape.pos[tape.counter].delay = 0;
tape.changed = TRUE;
- tape.date = 10000*(time->tm_year % 100) + 100*time->tm_mon + time->tm_mday;
tape.random_seed = InitRND(NEW_RANDOMIZE);
tape.file_version = FILE_VERSION_ACTUAL;
tape.game_version = GAME_VERSION_ACTUAL;
tape.engine_version = level.game_version;
+ TapeSetDate();
+
#if 0
printf("::: tape.engine_version = level.game_version = %d \n",
level.game_version);
tape.recording = FALSE;
tape.playing = FALSE;
tape.fast_forward = FALSE;
- tape.index_search = FALSE;
+ tape.warp_forward = FALSE;
+ tape.deactivate_display = FALSE;
tape.auto_play = (global.autoplay_leveldir != NULL);
tape.auto_play_level_solved = FALSE;
tape.quick_resume = FALSE;
DrawVideoDisplay(VIDEO_STATE_REC_ON, 0);
DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
DrawVideoDisplay(VIDEO_STATE_TIME_ON, 0);
- MapTapeIndexButton();
+ MapTapeWarpButton();
SetDrawDeactivationMask(REDRAW_NONE);
audio.sound_deactivated = FALSE;
{
TapeStartRecording();
-#if defined(PLATFORM_UNIX)
+#if defined(NETWORK_AVALIABLE)
if (options.network)
SendToServer_StartPlaying();
else
tape.recording = TRUE;
tape.changed = TRUE;
- DrawVideoDisplay(VIDEO_STATE_PLAY_OFF | VIDEO_STATE_REC_ON,0);
+ TapeSetDate();
+
+ DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
+ DrawVideoDisplay(VIDEO_STATE_PLAY_OFF | VIDEO_STATE_REC_ON, 0);
}
void TapeHaltRecording()
{
int i;
+#if 1
+ if (!tape.recording) /* record action even when tape is paused! */
+ return;
+#else
if (!tape.recording || tape.pausing)
return;
+#endif
if (tape.counter >= MAX_TAPELEN - 1)
{
return;
}
+#if 0
+ printf("::: %05d: recording action: %d\n", FrameCounter, action[0]);
+#endif
+
if (tape.pos[tape.counter].delay > 0) /* already stored action */
{
boolean changed_events = FALSE;
if (tape.pos[tape.counter].delay == 0) /* store new action */
{
+
+#if 0
+ printf("::: %05d: new sequence\n", FrameCounter);
+#endif
+
for (i = 0; i < MAX_PLAYERS; i++)
tape.pos[tape.counter].action[i] = action[i];
void TapeTogglePause(boolean toggle_manual)
{
- unsigned long state;
+ int state = 0;
#if 0
if (!tape.recording && !tape.playing)
return;
#endif
+ if (tape.pause_before_death)
+ state |= VIDEO_STATE_PBEND_OFF;
+ else if (tape.fast_forward)
+ state |= VIDEO_STATE_FFWD_OFF;
+
tape.pausing = !tape.pausing;
tape.fast_forward = FALSE;
tape.pause_before_death = FALSE;
if (tape.single_step && toggle_manual)
tape.single_step = FALSE;
- state = (tape.pausing ? VIDEO_STATE_PAUSE_ON : VIDEO_STATE_PAUSE_OFF);
+ state |= (tape.pausing ? VIDEO_STATE_PAUSE_ON : VIDEO_STATE_PAUSE_OFF);
if (tape.playing)
- state |= VIDEO_STATE_PBEND_OFF;
+ state |= VIDEO_STATE_PLAY_ON;
+ else
+ state |= (tape.single_step ? VIDEO_STATE_1STEP_ON : VIDEO_STATE_1STEP_OFF);
DrawVideoDisplay(state, 0);
- if (tape.index_search)
+#if 0
+ if (tape.pausing)
+ DrawVideoDisplay(VIDEO_STATE_PAUSE_ON, 0);
+#endif
+
+ if (tape.warp_forward)
{
- TapeStopIndexSearch();
+ TapeStopWarpForward();
if (tape.quick_resume)
{
tape.quick_resume = FALSE;
TapeAppendRecording();
+#if 0
TapeTogglePause(toggle_manual);
+#endif
}
}
}
DrawVideoDisplay(VIDEO_STATE_PLAY_ON, 0);
DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
DrawVideoDisplay(VIDEO_STATE_TIME_ON, 0);
- MapTapeIndexButton();
+ MapTapeWarpButton();
SetDrawDeactivationMask(REDRAW_NONE);
audio.sound_deactivated = FALSE;
tape.playing = FALSE;
tape.pausing = FALSE;
- if (tape.index_search)
- TapeStopIndexSearch();
+ if (tape.warp_forward)
+ TapeStopWarpForward();
DrawVideoDisplay(VIDEO_STATE_PLAY_OFF, 0);
MapTapeEjectButton();
DrawVideoDisplay(VIDEO_STATE_PBEND_OFF, VIDEO_DISPLAY_LABEL_ONLY);
}
- if (TimePlayed > tape.length_seconds - TAPE_PAUSE_SECONDS_BEFORE_DEATH)
+ if (tape.warp_forward)
+ {
+ if (tape.deactivate_display)
+ DrawVideoDisplay(VIDEO_STATE_WARP_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
+ else
+ DrawVideoDisplay(VIDEO_STATE_WARP2_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
+ }
+
+ if (TapeTime > tape.length_seconds - TAPE_PAUSE_SECONDS_BEFORE_DEATH)
{
TapeTogglePause(TAPE_TOGGLE_MANUAL);
return NULL;
}
}
+ else if (tape.fast_forward)
+ {
+ if ((FrameCounter / 20) % 2)
+ DrawVideoDisplay(VIDEO_STATE_FFWD_ON, VIDEO_DISPLAY_LABEL_ONLY);
+ else
+ DrawVideoDisplay(VIDEO_STATE_FFWD_OFF, VIDEO_DISPLAY_LABEL_ONLY);
+
+ if (tape.warp_forward)
+ {
+ if (tape.deactivate_display)
+ DrawVideoDisplay(VIDEO_STATE_WARP_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
+ else
+ DrawVideoDisplay(VIDEO_STATE_WARP2_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
+ }
+ }
+#if 0
+ /* !!! this makes things much slower !!! */
+ else if (tape.warp_forward)
+ {
+ if ((FrameCounter / 20) % 2)
+ DrawVideoDisplay(VIDEO_STATE_WARP_ON, VIDEO_DISPLAY_LABEL_ONLY);
+ else
+ DrawVideoDisplay(VIDEO_STATE_WARP_OFF, VIDEO_DISPLAY_LABEL_ONLY);
+
+ DrawVideoDisplay(VIDEO_STATE_WARP_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
+ }
+#endif
if (tape.counter >= tape.length) /* end of tape reached */
{
- if (tape.index_search && !tape.auto_play)
+ if (tape.warp_forward && !tape.auto_play)
TapeTogglePause(TAPE_TOGGLE_MANUAL);
else
TapeStop();
tape.delay_played = 0;
}
+#if 0
+ printf("::: %05d: replaying action: %d\n", FrameCounter, action[0]);
+#endif
+
return action;
}
void TapeStop()
{
+#if 0
+ if (tape.recording)
+ printf("::: stopped recording: %d\n", FrameCounter);
+ else if (tape.playing)
+ printf("::: stopped playing: %d\n\n", FrameCounter);
+#endif
+
TapeStopRecording();
TapeStopPlaying();
- DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
+ DrawVideoDisplay(VIDEO_STATE_OFF, 0);
+
if (tape.date && tape.length)
{
DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
return(tape_length * GAME_FRAME_DELAY / 1000);
}
-static void TapeStartIndexSearch()
+static void TapeStartWarpForward()
{
- tape.index_search = TRUE;
+ tape.warp_forward = TRUE;
+#if 1
+ if (!tape.fast_forward && !tape.pause_before_death)
+ {
+ tape.pausing = FALSE;
+ tape.deactivate_display = TRUE;
+
+ TapeDeactivateDisplayOn();
+ }
+#else
if (!tape.fast_forward || tape.pause_before_death)
{
tape.pausing = FALSE;
+ tape.deactivate_display = TRUE;
- SetDrawDeactivationMask(REDRAW_FIELD);
- audio.sound_deactivated = TRUE;
+ TapeDeactivateDisplayOn();
}
+#endif
+
+ if (tape.fast_forward || tape.pause_before_death)
+ DrawVideoDisplay(VIDEO_STATE_WARP_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
+ else
+ DrawVideoDisplay(VIDEO_STATE_WARP_ON, 0);
}
-static void TapeStopIndexSearch()
+static void TapeStopWarpForward()
{
- tape.index_search = FALSE;
+ int state = (tape.pausing ? VIDEO_STATE_PAUSE_ON : VIDEO_STATE_PAUSE_OFF);
- SetDrawDeactivationMask(REDRAW_NONE);
- audio.sound_deactivated = FALSE;
+ tape.warp_forward = FALSE;
+ tape.deactivate_display = FALSE;
+
+ TapeDeactivateDisplayOff(game_status == GAME_MODE_PLAYING);
+
+#if 0
+#if 1
+ if (game_status == GAME_MODE_PLAYING)
+#endif
+ {
+ RedrawPlayfield(TRUE, 0,0,0,0);
+ DrawGameDoorValues();
+ }
+#endif
- RedrawPlayfield(TRUE, 0,0,0,0);
- DrawGameDoorValues();
+ if (tape.pause_before_death)
+ state |= VIDEO_STATE_WARP_OFF | VIDEO_STATE_PBEND_ON;
+ else if (tape.fast_forward)
+ state |= VIDEO_STATE_WARP_OFF | VIDEO_STATE_FFWD_ON;
+ else
+ state |= VIDEO_STATE_WARP_OFF | VIDEO_STATE_PLAY_ON;
+
+ DrawVideoDisplay(state, 0);
}
static void TapeSingleStep()
TapeTogglePause(TAPE_TOGGLE_MANUAL);
tape.single_step = !tape.single_step;
+
+ DrawVideoDisplay((tape.single_step ? VIDEO_STATE_1STEP_ON :
+ VIDEO_STATE_1STEP_OFF), 0);
}
void TapeQuickSave()
void TapeQuickLoad()
{
+ if (tape.recording && !Request("Stop recording and load tape ?",
+ REQ_ASK | REQ_STAY_CLOSED))
+ {
+ BlitBitmap(bitmap_db_door, bitmap_db_door,
+ DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
+ DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+ OpenDoor(DOOR_OPEN_1);
+
+ return;
+ }
+
if (game_status == GAME_MODE_PLAYING || game_status == GAME_MODE_MAIN)
{
TapeStop();
if (!TAPE_IS_EMPTY(tape))
{
TapeStartGamePlaying();
- TapeStartIndexSearch();
+ TapeStartWarpForward();
tape.quick_resume = TRUE;
}
printf("Level %03d: ", level_nr);
LoadLevel(level_nr);
- if (level.no_level_file)
+ if (level.no_valid_file)
{
printf("(no level)\n");
continue;
}
LoadSolutionTape(level_nr);
+#if 1
+ if (tape.no_valid_file)
+#else
if (TAPE_IS_EMPTY(tape))
+#endif
{
printf("(no tape)\n");
continue;
printf("playing tape ... ");
TapeStartGamePlaying();
- TapeStartIndexSearch();
+ TapeStartWarpForward();
return;
}
printf("LEVELDIR '%s', SOLVED %d/%d (%d%%)",
autoplay_leveldir->identifier, num_levels_solved, num_levels_played,
(num_levels_played ? num_levels_solved * 100 / num_levels_played :0));
+
if (num_levels_played != num_levels_solved)
{
printf(", FAILED:");
if (levels_failed[i])
printf(" %03d", i);
}
+
printf("\n");
printf_line("=", 79);
#define TAPE_BUTTON_YPOS 77
#define TAPE_BUTTON_EJECT_XPOS (TAPE_BUTTON_XPOS + 0 * TAPE_BUTTON_XSIZE)
-#define TAPE_BUTTON_INDEX_XPOS (TAPE_BUTTON_XPOS + 0 * TAPE_BUTTON_XSIZE)
+#define TAPE_BUTTON_EXTRA_XPOS (TAPE_BUTTON_XPOS + 0 * TAPE_BUTTON_XSIZE)
#define TAPE_BUTTON_STOP_XPOS (TAPE_BUTTON_XPOS + 1 * TAPE_BUTTON_XSIZE)
#define TAPE_BUTTON_PAUSE_XPOS (TAPE_BUTTON_XPOS + 2 * TAPE_BUTTON_XSIZE)
#define TAPE_BUTTON_RECORD_XPOS (TAPE_BUTTON_XPOS + 3 * TAPE_BUTTON_XSIZE)
"eject tape"
},
{
- TAPE_BUTTON_INDEX_XPOS, TAPE_BUTTON_YPOS,
- TAPE_CTRL_ID_INDEX,
- "index mark"
+ TAPE_BUTTON_EXTRA_XPOS, TAPE_BUTTON_YPOS,
+ TAPE_CTRL_ID_EXTRA,
+ "extra functions"
},
{
TAPE_BUTTON_STOP_XPOS, TAPE_BUTTON_YPOS,
gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
gd_y = DOOR_GFX_PAGEY2 + gd_yoffset;
- if (i == TAPE_CTRL_ID_INDEX)
+ if (i == TAPE_CTRL_ID_EXTRA)
{
gd_x1 = DOOR_GFX_PAGEX6 + gd_xoffset;
gd_x2 = DOOR_GFX_PAGEX5 + gd_xoffset;
void MapTapeEjectButton()
{
- UnmapGadget(tape_gadget[TAPE_CTRL_ID_INDEX]);
+ UnmapGadget(tape_gadget[TAPE_CTRL_ID_EXTRA]);
MapGadget(tape_gadget[TAPE_CTRL_ID_EJECT]);
}
-void MapTapeIndexButton()
+void MapTapeWarpButton()
{
UnmapGadget(tape_gadget[TAPE_CTRL_ID_EJECT]);
- MapGadget(tape_gadget[TAPE_CTRL_ID_INDEX]);
+ MapGadget(tape_gadget[TAPE_CTRL_ID_EXTRA]);
}
void MapTapeButtons()
int i;
for (i = 0; i < NUM_TAPE_BUTTONS; i++)
- if (i != TAPE_CTRL_ID_INDEX)
+ if (i != TAPE_CTRL_ID_EXTRA)
MapGadget(tape_gadget[i]);
if (tape.recording || tape.playing)
- MapTapeIndexButton();
+ MapTapeWarpButton();
}
void UnmapTapeButtons()
DrawCompleteVideoDisplay();
break;
- case TAPE_CTRL_ID_INDEX:
+ case TAPE_CTRL_ID_EXTRA:
if (tape.playing)
- TapeStartIndexSearch();
+ {
+ if (!tape.warp_forward) /* PLAY -> WARP FORWARD PLAY */
+ {
+ TapeStartWarpForward();
+ }
+ else /* WARP FORWARD PLAY -> PLAY */
+ {
+ TapeStopWarpForward();
+
+#if 0
+ if (tape.pause_before_death)
+ DrawVideoDisplay(VIDEO_STATE_WARP_OFF | VIDEO_STATE_PLAY_ON, 0);
+ else if (tape.fast_forward)
+ DrawVideoDisplay(VIDEO_STATE_WARP_OFF | VIDEO_STATE_FFWD_ON, 0);
+ else
+ DrawVideoDisplay(VIDEO_STATE_WARP_OFF | VIDEO_STATE_PBEND_ON, 0);
+#endif
+ }
+ }
else if (tape.recording)
TapeSingleStep();
break;
TapeStartGameRecording();
else if (tape.pausing)
{
- if (tape.playing) /* PLAYING -> PAUSING -> RECORDING */
+ if (tape.playing) /* PLAY -> PAUSE -> RECORD */
TapeAppendRecording();
else
TapeTogglePause(TAPE_TOGGLE_MANUAL);
else if (!tape.pause_before_death) /* FFWD PLAY -> AUTO PAUSE */
{
tape.pause_before_death = TRUE;
+#if 1
+ DrawVideoDisplay(VIDEO_STATE_FFWD_OFF | VIDEO_STATE_PBEND_ON, 0);
+#else
DrawVideoDisplay(VIDEO_STATE_PBEND_ON, VIDEO_DISPLAY_LABEL_ONLY);
+#endif
}
else /* AUTO PAUSE -> NORMAL PLAY */
{
+#if 1
+ if (tape.warp_forward)
+ TapeStopWarpForward();
+#else
+ tape.warp_forward = FALSE;
+#endif
tape.fast_forward = FALSE;
tape.pause_before_death = FALSE;
+
+#if 1
+ DrawVideoDisplay(VIDEO_STATE_PBEND_OFF | VIDEO_STATE_PLAY_ON, 0);
+#else
DrawVideoDisplay(VIDEO_STATE_FFWD_OFF | VIDEO_STATE_PBEND_OFF, 0);
+#endif
}
}
break;
#define VIDEO_CONTROL_YSIZE VIDEO_BUTTON_YSIZE
/* values for video tape control */
-#define VIDEO_STATE_PLAY_OFF (1L << 0)
-#define VIDEO_STATE_PLAY_ON (1L << 1)
+#define VIDEO_STATE_PLAY_OFF (1 << 0)
+#define VIDEO_STATE_PLAY_ON (1 << 1)
#define VIDEO_STATE_PLAY (VIDEO_STATE_PLAY_OFF | VIDEO_STATE_PLAY_ON)
-#define VIDEO_STATE_REC_OFF (1L << 2)
-#define VIDEO_STATE_REC_ON (1L << 3)
+#define VIDEO_STATE_REC_OFF (1 << 2)
+#define VIDEO_STATE_REC_ON (1 << 3)
#define VIDEO_STATE_REC (VIDEO_STATE_REC_OFF | VIDEO_STATE_REC_ON)
-#define VIDEO_STATE_PAUSE_OFF (1L << 4)
-#define VIDEO_STATE_PAUSE_ON (1L << 5)
+#define VIDEO_STATE_PAUSE_OFF (1 << 4)
+#define VIDEO_STATE_PAUSE_ON (1 << 5)
#define VIDEO_STATE_PAUSE (VIDEO_STATE_PAUSE_OFF | VIDEO_STATE_PAUSE_ON)
-#define VIDEO_STATE_DATE_OFF (1L << 6)
-#define VIDEO_STATE_DATE_ON (1L << 7)
+#define VIDEO_STATE_DATE_OFF (1 << 6)
+#define VIDEO_STATE_DATE_ON (1 << 7)
#define VIDEO_STATE_DATE (VIDEO_STATE_DATE_OFF | VIDEO_STATE_DATE_ON)
-#define VIDEO_STATE_TIME_OFF (1L << 8)
-#define VIDEO_STATE_TIME_ON (1L << 9)
+#define VIDEO_STATE_TIME_OFF (1 << 8)
+#define VIDEO_STATE_TIME_ON (1 << 9)
#define VIDEO_STATE_TIME (VIDEO_STATE_TIME_OFF | VIDEO_STATE_TIME_ON)
-#define VIDEO_PRESS_PLAY_ON (1L << 10)
-#define VIDEO_PRESS_PLAY_OFF (1L << 11)
+
+#define VIDEO_STATE_FFWD_OFF (1 << 10)
+#define VIDEO_STATE_FFWD_ON (1 << 11)
+#define VIDEO_STATE_FFWD (VIDEO_STATE_FFWD_OFF | VIDEO_STATE_FFWD_ON)
+#define VIDEO_STATE_PBEND_OFF (1 << 12)
+#define VIDEO_STATE_PBEND_ON (1 << 13)
+#define VIDEO_STATE_PBEND (VIDEO_STATE_PBEND_OFF | VIDEO_STATE_PBEND_ON)
+#define VIDEO_STATE_WARP_OFF (1 << 14)
+#define VIDEO_STATE_WARP_ON (1 << 15)
+#define VIDEO_STATE_WARP (VIDEO_STATE_WARP_OFF | VIDEO_STATE_WARP_ON)
+#define VIDEO_STATE_WARP2_OFF (1 << 16)
+#define VIDEO_STATE_WARP2_ON (1 << 17)
+#define VIDEO_STATE_WARP2 (VIDEO_STATE_WARP_OFF | VIDEO_STATE_WARP_ON)
+#define VIDEO_STATE_1STEP_OFF (1 << 18)
+#define VIDEO_STATE_1STEP_ON (1 << 19)
+#define VIDEO_STATE_1STEP (VIDEO_STATE_1STEP_OFF | VIDEO_STATE_1STEP_ON)
+
+#define VIDEO_PRESS_PLAY_ON (1 << 20)
+#define VIDEO_PRESS_PLAY_OFF (1 << 21)
#define VIDEO_PRESS_PLAY (VIDEO_PRESS_PLAY_OFF | VIDEO_PRESS_PLAY_ON)
-#define VIDEO_PRESS_REC_ON (1L << 12)
-#define VIDEO_PRESS_REC_OFF (1L << 13)
+#define VIDEO_PRESS_REC_ON (1 << 22)
+#define VIDEO_PRESS_REC_OFF (1 << 23)
#define VIDEO_PRESS_REC (VIDEO_PRESS_REC_OFF | VIDEO_PRESS_REC_ON)
-#define VIDEO_PRESS_PAUSE_ON (1L << 14)
-#define VIDEO_PRESS_PAUSE_OFF (1L << 15)
+#define VIDEO_PRESS_PAUSE_ON (1 << 24)
+#define VIDEO_PRESS_PAUSE_OFF (1 << 25)
#define VIDEO_PRESS_PAUSE (VIDEO_PRESS_PAUSE_OFF | VIDEO_PRESS_PAUSE_ON)
-#define VIDEO_PRESS_STOP_ON (1L << 16)
-#define VIDEO_PRESS_STOP_OFF (1L << 17)
+#define VIDEO_PRESS_STOP_ON (1 << 26)
+#define VIDEO_PRESS_STOP_OFF (1 << 27)
#define VIDEO_PRESS_STOP (VIDEO_PRESS_STOP_OFF | VIDEO_PRESS_STOP_ON)
-#define VIDEO_PRESS_EJECT_ON (1L << 18)
-#define VIDEO_PRESS_EJECT_OFF (1L << 19)
+#define VIDEO_PRESS_EJECT_ON (1 << 28)
+#define VIDEO_PRESS_EJECT_OFF (1 << 29)
#define VIDEO_PRESS_EJECT (VIDEO_PRESS_EJECT_OFF | VIDEO_PRESS_EJECT_ON)
-/* special */
-#define VIDEO_STATE_FFWD_OFF ((1L << 20) | VIDEO_STATE_PAUSE_OFF)
-#define VIDEO_STATE_FFWD_ON (1L << 21)
-#define VIDEO_STATE_FFWD (VIDEO_STATE_FFWD_OFF | VIDEO_STATE_FFWD_ON)
-#define VIDEO_STATE_PBEND_OFF (1L << 22)
-#define VIDEO_STATE_PBEND_ON (1L << 23)
-#define VIDEO_STATE_PBEND (VIDEO_STATE_PBEND_OFF | VIDEO_STATE_PBEND_ON)
-
/* tags to draw video display labels or symbols only */
/* (negative values to prevent misinterpretation in DrawVideoDisplay(), where
the variable "value" is also used for tape length -- better fix this) */
void DrawVideoDisplay(unsigned long, unsigned long);
void DrawCompleteVideoDisplay(void);
+void TapeDeactivateDisplayOn();
+void TapeDeactivateDisplayOff(boolean);
+
void TapeStartRecording(void);
void TapeHaltRecording(void);
void TapeStopRecording(void);
void CreateTapeButtons();
void FreeTapeButtons();
void MapTapeEjectButton();
-void MapTapeIndexButton();
+void MapTapeWarpButton();
void MapTapeButtons();
void UnmapTapeButtons();
static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
static int request_gadget_id = -1;
+static char *print_if_not_empty(int element)
+{
+ static char *s = NULL;
+ char *token_name = element_info[element].token_name;
+
+ if (s != NULL)
+ free(s);
+
+ s = checked_malloc(strlen(token_name) + 10 + 1);
+
+ if (element != EL_EMPTY)
+ sprintf(s, "%d\t['%s']", element, token_name);
+ else
+ sprintf(s, "%d", element);
+
+ return s;
+}
+
+void DumpTile(int x, int y)
+{
+ int sx = SCREENX(x);
+ int sy = SCREENY(y);
+
+ printf_line("-", 79);
+ printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
+ printf_line("-", 79);
+
+ if (!IN_LEV_FIELD(x, y))
+ {
+ printf("(not in level field)\n");
+ printf("\n");
+
+ return;
+ }
+
+ printf(" Feld: %d\t['%s']\n", Feld[x][y],
+ element_info[Feld[x][y]].token_name);
+ printf(" Back: %s\n", print_if_not_empty(Back[x][y]));
+ printf(" Store: %s\n", print_if_not_empty(Store[x][y]));
+ printf(" Store2: %s\n", print_if_not_empty(Store2[x][y]));
+ printf(" StorePlayer: %s\n", print_if_not_empty(StorePlayer[x][y]));
+ printf(" MovPos: %d\n", MovPos[x][y]);
+ printf(" MovDir: %d\n", MovDir[x][y]);
+ printf(" MovDelay: %d\n", MovDelay[x][y]);
+ printf(" ChangeDelay: %d\n", ChangeDelay[x][y]);
+ printf(" GfxElement: %d\n", GfxElement[x][y]);
+ printf(" GfxAction: %d\n", GfxAction[x][y]);
+ printf(" GfxFrame: %d\n", GfxFrame[x][y]);
+ printf("\n");
+}
+
void SetDrawtoField(int mode)
{
if (mode == DRAW_BUFFERED && setup.soft_scrolling)
{
if (redraw_mask & REDRAW_DOOR_1)
BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
+
if (redraw_mask & REDRAW_DOOR_2)
{
+#if 0
if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
- BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
+#endif
+ BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
+#if 0
else
{
if (redraw_mask & REDRAW_VIDEO_1)
BlitBitmap(backbuffer, window,
- VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
- VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
- VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
+ VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS,
+ VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
+ VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS);
if (redraw_mask & REDRAW_VIDEO_2)
BlitBitmap(backbuffer, window,
- VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
- VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
- VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
+ VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS,
+ VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
+ VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS);
if (redraw_mask & REDRAW_VIDEO_3)
BlitBitmap(backbuffer, window,
- VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
- VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
- VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
+ VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS,
+ VIDEO_CONTROL_XSIZE, VIDEO_CONTROL_YSIZE,
+ VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS);
}
+#endif
}
if (redraw_mask & REDRAW_DOOR_3)
if (redraw_mask & REDRAW_TILES)
{
for (x = 0; x < SCR_FIELDX; x++)
- for (y =0 ; y < SCR_FIELDY; y++)
+ for (y = 0 ; y < SCR_FIELDY; y++)
if (redraw[redraw_x1 + x][redraw_y1 + y])
BlitBitmap(buffer, window,
- FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
+ FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
SX + x * TILEX, SY + y * TILEY);
}
player->is_collecting ? ACTION_COLLECTING :
player->is_moving ? ACTION_MOVING :
player->is_snapping ? ACTION_SNAPPING :
+ player->is_dropping ? ACTION_DROPPING :
player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
InitPlayerGfxAnimation(player, action, move_dir);
/* draw elements the player is just walking/passing through/under */
/* ----------------------------------------------------------------------- */
- /* handle the field the player is leaving ... */
- if (player_is_moving && IS_ACCESSIBLE_INSIDE(last_element))
- DrawLevelField(last_jx, last_jy);
- else if (player_is_moving && IS_ACCESSIBLE_UNDER(last_element))
- DrawLevelFieldThruMask(last_jx, last_jy);
+ if (player_is_moving)
+ {
+ /* handle the field the player is leaving ... */
+ if (IS_ACCESSIBLE_INSIDE(last_element))
+ DrawLevelField(last_jx, last_jy);
+ else if (IS_ACCESSIBLE_UNDER(last_element))
+ DrawLevelFieldThruMask(last_jx, last_jy);
+ }
- /* ... and the field the player is entering */
- if (IS_ACCESSIBLE_INSIDE(element))
- DrawLevelField(jx, jy);
- else if (IS_ACCESSIBLE_UNDER(element))
- DrawLevelFieldThruMask(jx, jy);
+#if 1
+ /* do not redraw accessible elements if the player is just pushing them */
+ if (!player_is_moving || !player->is_pushing)
+ {
+ /* ... and the field the player is entering */
+ if (IS_ACCESSIBLE_INSIDE(element))
+ DrawLevelField(jx, jy);
+ else if (IS_ACCESSIBLE_UNDER(element))
+ DrawLevelFieldThruMask(jx, jy);
+ }
+
+#else
+
+#if 0
+ /* !!! I have forgotton what this should be good for !!! */
+ /* !!! causes player being visible when pushing from within tubes !!! */
+ if (!player->is_pushing)
+#endif
+ {
+ /* ... and the field the player is entering */
+ if (IS_ACCESSIBLE_INSIDE(element))
+ DrawLevelField(jx, jy);
+ else if (IS_ACCESSIBLE_UNDER(element))
+ DrawLevelFieldThruMask(jx, jy);
+ }
+#endif
if (setup.direct_draw)
{
SetDrawtoField(DRAW_DIRECT);
}
- MarkTileDirty(sx,sy);
+ MarkTileDirty(sx, sy);
}
void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
}
-void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
+void DrawGraphicShifted(int x, int y, int dx, int dy, int graphic, int frame,
int cut_mode, int mask_mode)
{
Bitmap *src_bitmap;
BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
dest_x, dest_y);
- MarkTileDirty(x,y);
+ MarkTileDirty(x, y);
}
void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
int frame, int cut_mode)
{
- DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
+ DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
}
void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
}
+#define TILE_GFX_ELEMENT(x, y) \
+ (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
+ GfxElement[x][y] : Feld[x][y])
+
static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
{
Bitmap *src_bitmap;
if (!IN_LEV_FIELD(x, y))
return;
- element = (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ?
- GfxElement[x][y] : Feld[x][y]);
+ element = TILE_GFX_ELEMENT(x, y);
/* crumble field itself */
if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
int xx = x + xy[i][0];
int yy = y + xy[i][1];
+#if 1
+ element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
+ BorderElement);
+#else
element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
+#endif
/* check if neighbour field is of same type */
if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
int sxx = sx + xy[i][0];
int syy = sy + xy[i][1];
+#if 1
+ if (!IN_LEV_FIELD(xx, yy) ||
+ !IN_SCR_FIELD(sxx, syy) ||
+ IS_MOVING(xx, yy))
+ continue;
+
+ element = TILE_GFX_ELEMENT(xx, yy);
+
+ if (!GFX_CRUMBLED(element))
+ continue;
+#else
if (!IN_LEV_FIELD(xx, yy) ||
!IN_SCR_FIELD(sxx, syy) ||
!GFX_CRUMBLED(Feld[xx][yy]) ||
IS_MOVING(xx, yy))
continue;
+#endif
#if 1
graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
if (content == EL_ACID)
- DrawLevelElementThruMask(lx, ly + 1, EL_ACID);
+ {
+ int dir = MovDir[lx][ly];
+ int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
+ int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
+
+ DrawLevelElementThruMask(newlx, newly, EL_ACID);
+ }
}
else if (IS_BLOCKED(lx, ly))
{
void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
{
int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
+#if 1
+ Bitmap *src_bitmap = graphic_info[graphic].bitmap;
+ int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
+#else
boolean draw_masked = graphic_info[graphic].draw_masked;
int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
+#endif
boolean ffwd_delay = (tape.playing && tape.fast_forward);
+ boolean no_delay = (tape.warp_forward);
unsigned long anim_delay = 0;
- int anim_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
+ int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
+ int anim_delay_value = (no_delay ? 0 : frame_delay_value);
int font_nr = FONT_ENVELOPE_1 + envelope_nr;
int font_width = getFontWidth(font_nr);
int font_height = getFontHeight(font_nr);
int sound_opening = element_info[element].sound[ACTION_OPENING];
int sound_closing = element_info[element].sound[ACTION_CLOSING];
boolean ffwd_delay = (tape.playing && tape.fast_forward);
- int wait_delay_value = (ffwd_delay ? 500 : 1000);
+ boolean no_delay = (tape.warp_forward);
+ int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
+ int wait_delay_value = (no_delay ? 0 : normal_delay_value);
int anim_mode = graphic_info[graphic].anim_mode;
int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
}
}
+#if 1
+ /* disable deactivated drawing when quick-loading level tape recording */
+ if (tape.playing && tape.deactivate_display)
+ TapeDeactivateDisplayOff(TRUE);
+#endif
+
#if 1
SetMouseCursor(CURSOR_DEFAULT);
#endif
-#if defined(PLATFORM_UNIX)
+#if defined(NETWORK_AVALIABLE)
/* pause network game while waiting for request to answer */
if (options.network &&
game_status == GAME_MODE_PLAYING &&
if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
{
BlitBitmap(bitmap_db_door, bitmap_db_door,
- DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
- DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
+ DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
+ DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
OpenDoor(DOOR_OPEN_1);
}
}
SetDrawBackgroundMask(REDRAW_FIELD);
-#if defined(PLATFORM_UNIX)
+#if defined(NETWORK_AVALIABLE)
/* continue network game after request */
if (options.network &&
game_status == GAME_MODE_PLAYING &&
SendToServer_ContinuePlaying();
#endif
+#if 1
+ /* restore deactivated drawing when quick-loading level tape recording */
+ if (tape.playing && tape.deactivate_display)
+ TapeDeactivateDisplayOn();
+#endif
+
return result;
}
stepsize = 20; /* must be choosen to always draw last frame */
door_delay_value = 0;
+#if 0
StopSound(SND_DOOR_OPENING);
StopSound(SND_DOOR_CLOSING);
+#endif
}
if (global.autoplay_leveldir)
door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
int x;
- if (!(door_state & DOOR_NO_DELAY))
+ if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
{
/* opening door sound has priority over simultaneously closing door */
if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
}
}
+#if 0
if (setup.quick_doors)
{
StopSound(SND_DOOR_OPENING);
StopSound(SND_DOOR_CLOSING);
}
+#endif
if (door_state & DOOR_ACTION_1)
door1 = door_state & DOOR_ACTION_1;
int el_act_dir2img(int element, int action, int direction)
{
element = GFX_ELEMENT(element);
- direction = MV_DIR_BIT(direction);
+ direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
return element_info[element].direction_graphic[action][direction];
}
static int el_act_dir2crm(int element, int action, int direction)
{
element = GFX_ELEMENT(element);
- direction = MV_DIR_BIT(direction);
+ direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
return element_info[element].direction_crumbled[action][direction];
}
return el_act_dir2img(element, ACTION_DEFAULT, direction);
}
+int el2baseimg(int element)
+{
+ return element_info[element].graphic[ACTION_DEFAULT];
+}
+
int el2img(int element)
{
element = GFX_ELEMENT(element);
#define REQUEST_WAIT_FOR (REQ_ASK | REQ_CONFIRM | REQ_PLAYER)
+void DumpTile(int, int);
+
void SetDrawtoField(int);
void RedrawPlayfield(boolean, int, int, int, int);
void BackToFront();
int el_act_dir2img(int, int, int);
int el_act2img(int, int);
int el_dir2img(int, int);
+int el2baseimg(int);
int el2img(int);
int el2edimg(int);
int el2preimg(int);