added support for BD game engine to Makefile for Android
[rocksndiamonds.git] / src / game_bd / bd_cavedb.c
1 /*
2  * Copyright (c) 2007, 2008, 2009, Czirkos Zoltan <cirix@fw.hu>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include "main_bd.h"
18
19
20 // some cells are created inside the game (by merging two cells from the png etc);
21 // those are used only in the editor.
22 // this enum is used to give each and every one a different index automatically.
23 enum _generated_cells_indexes
24 {
25   // the first one gets the first available index.
26   // the following ones will be generated by the compiler automatically.
27   i_stonefly_1 = GD_NUM_OF_CELLS_X * GD_NUM_OF_CELLS_Y,
28   i_stonefly_2,
29   i_stonefly_3,
30   i_stonefly_4,
31   i_alt_guard_1,
32   i_alt_guard_2,
33   i_alt_guard_3,
34   i_alt_guard_4,
35   i_steel_eatable,
36   i_brick_eatable,
37   i_dirt_glued,
38   i_diamond_glued,
39   i_stone_glued,
40   i_falling_wall,
41   i_falling_wall_falling,
42   i_expanding_wall,
43   i_h_expanding_wall,
44   i_v_expanding_wall,
45   i_expanding_steel_wall,
46   i_h_expanding_steel_wall,
47   i_v_expanding_steel_wall,
48   i_mega_stone_falling,
49   i_time_penalty,
50   i_biter_1,
51   i_biter_2,
52   i_biter_3,
53   i_biter_4,
54   i_cow_1,
55   i_cow_2,
56   i_cow_3,
57   i_cow_4,
58   i_guard_1,
59   i_guard_2,
60   i_guard_3,
61   i_guard_4,
62   i_butter_1,
63   i_butter_2,
64   i_butter_3,
65   i_butter_4,
66   i_dragonfly_1,
67   i_dragonfly_2,
68   i_dragonfly_3,
69   i_dragonfly_4,
70   i_cow_enclosed,
71   i_pre_outbox_nonblink,
72   i_invis_outbox,
73   i_brick_non_sloped,
74   i_outbox,
75   i_stone_f,
76   i_flying_stone_f,
77   i_diamond_f,
78   i_flying_diamond_f,
79   i_pre_invis_outbox,
80   i_unknown,
81   i_waiting_stone,
82   i_pre_outbox_frame_1,    // this will have 8 frames.
83   i_pre_outbox_frame_2,
84   i_pre_outbox_frame_3,
85   i_pre_outbox_frame_4,
86   i_pre_outbox_frame_5,
87   i_pre_outbox_frame_6,
88   i_pre_outbox_frame_7,
89   i_pre_outbox_frame_8,
90   i_nitro_pack_f,
91   i_alt_butter_1,
92   i_alt_butter_2,
93   i_alt_butter_3,
94   i_alt_butter_4,
95   i_conveyor_left,
96   i_conveyor_right,
97   i_nitro_explode,
98   i_walled_diamond,
99   i_walled_key_1,
100   i_walled_key_2,
101   i_walled_key_3,
102   i_player,
103   i_player_glued,
104   i_nut_f,
105
106   i_max_cell_num
107 };
108
109 /*
110   elements description array. do not miss an index!
111   the game will check if one is missing and stop the game.
112   the identifier in the saved file might also not match, reading an "outbox" from
113   the file should store an O_PRE_OUTBOX.
114
115   images are: image in editor, image in editor - animated, game image
116   indexes which are in the png have to be given as numeric constants.
117   for generated cells (ie. guard + an arrow), use the above enum
118 */
119 GdElements gd_elements[] =
120 {
121   { O_SPACE, N_("Space"), P_AMOEBA_CONSUMES, "SPACE", ' ', 0, 0, 0 },
122   { O_DIRT, N_("Dirt"), P_AMOEBA_CONSUMES | P_VISUAL_EFFECT | P_DIRT | P_DIGGABLE, "DIRT", '.', 2, 2, 2 },
123   { O_DIRT_SLOPED_UP_RIGHT, N_("Sloped dirt (up & right)"), P_DIRT | P_SLOPED_UP | P_SLOPED_RIGHT | P_AMOEBA_CONSUMES | P_DIGGABLE, "DIRTSLOPEDUPRIGHT", 0, 280, 280, 280 },
124   { O_DIRT_SLOPED_UP_LEFT, N_("Sloped dirt (up & left)"), P_DIRT | P_SLOPED_UP | P_SLOPED_LEFT | P_AMOEBA_CONSUMES | P_DIGGABLE, "DIRTSLOPEDUPLEFT", 0, 281, 281, 281 },
125   { O_DIRT_SLOPED_DOWN_LEFT, N_("Sloped dirt (down & left)"), P_DIRT | P_SLOPED_DOWN | P_SLOPED_LEFT | P_AMOEBA_CONSUMES | P_DIGGABLE, "DIRTSLOPEDDOWNLEFT", 0, 282, 282, 282 },
126   { O_DIRT_SLOPED_DOWN_RIGHT, N_("Sloped dirt (down & right)"), P_DIRT | P_SLOPED_DOWN | P_SLOPED_RIGHT | P_AMOEBA_CONSUMES | P_DIGGABLE, "DIRTSLOPEDDOWNRIGHT", 0, 283, 283, 283 },
127   { O_DIRT_BALL, N_("Dirt ball"), P_DIRT | P_SLOPED | P_AMOEBA_CONSUMES | P_MOVED_BY_CONVEYOR_TOP | P_DIGGABLE | P_CAN_FALL, "DIRTBALL", 0, 289, 289, 289, 120 },    // has ckdelay
128   { O_DIRT_BALL_F, N_("Dirt ball (falling)"), P_FALLING | P_DIGGABLE, "DIRTBALLf", 0, 289, 289, 289, 120 },    // has ckdelay
129   { O_DIRT_LOOSE, N_("Loose dirt"), P_DIRT | P_AMOEBA_CONSUMES | P_MOVED_BY_CONVEYOR_TOP | P_DIGGABLE | P_CAN_FALL, "DIRTLOOSE", 0, 352, 352, 352, 60 },    // has ckdelay
130   { O_DIRT_LOOSE_F, N_("Loose dirt (falling)"), P_FALLING, "DIRTLOOSEf", 0, 352, 352, 352, 60 },    // has ckdelay
131   { O_DIRT2, N_("Dirt 2"), P_DIRT | P_AMOEBA_CONSUMES | P_DIGGABLE, "DIRT2", 0, 3, 3, 3 },
132   { O_BRICK, N_("Brick wall"), P_SLOPED|P_BLADDER_SLOPED|P_CAN_BE_HAMMERED, "WALL", 'w', 5, 5, 5 },
133   { O_BRICK_SLOPED_UP_RIGHT, N_("Sloped brick wall (up & right)"), P_SLOPED_UP|P_SLOPED_RIGHT|P_BLADDER_SLOPED|P_CAN_BE_HAMMERED, "WALLSLOPEDUPRIGHT", 0, 276, 276, 276 },
134   { O_BRICK_SLOPED_UP_LEFT, N_("Sloped brick wall (up & left)"), P_SLOPED_UP|P_SLOPED_LEFT|P_BLADDER_SLOPED|P_CAN_BE_HAMMERED, "WALLSLOPEDUPLEFT", 0, 277, 277, 277 },
135   { O_BRICK_SLOPED_DOWN_LEFT, N_("Sloped brick wall (down & left)"), P_SLOPED_DOWN|P_SLOPED_LEFT|P_BLADDER_SLOPED|P_CAN_BE_HAMMERED, "WALLSLOPEDDOWNLEFT", 0, 278, 278, 278 },
136   { O_BRICK_SLOPED_DOWN_RIGHT, N_("Sloped brick wall (down & right)"), P_SLOPED_DOWN|P_SLOPED_RIGHT|P_BLADDER_SLOPED|P_CAN_BE_HAMMERED, "WALLSLOPEDDOWNRIGHT", 0, 279, 279, 279 },
137   { O_BRICK_NON_SLOPED, N_("Non-sloped brick wall"), P_CAN_BE_HAMMERED, "WALLNONSLOPED", 0, i_brick_non_sloped, i_brick_non_sloped, 5 },
138   { O_MAGIC_WALL, N_("Magic wall"), P_CAN_BE_HAMMERED, "MAGICWALL", 'M', 184, -184, -184 },
139   { O_PRE_OUTBOX, N_("Outbox"), 0, "OUTBOX", 'X', i_pre_outbox_nonblink, -i_pre_outbox_frame_1, 22 },
140   { O_OUTBOX, N_("Outbox (open)"), 0, "OUTBOXopen", 0, i_outbox, i_outbox, 22 },
141   { O_PRE_INVIS_OUTBOX, N_("Invisible outbox"), 0, "HIDDENOUTBOX", 'H', i_pre_invis_outbox, i_pre_invis_outbox, 22 },
142   { O_INVIS_OUTBOX, N_("Invisible outbox (open)"), 0, "HIDDENOUTBOXopen", 0, i_invis_outbox, i_invis_outbox, 22 },
143   { O_STEEL, N_("Steel wall"), P_NON_EXPLODABLE, "STEELWALL", 'W', 4, 4, 4 },
144   { O_STEEL_SLOPED_UP_RIGHT, N_("Sloped steel wall (up & right)"), P_SLOPED_UP|P_SLOPED_RIGHT|P_NON_EXPLODABLE, "STEELWALLSLOPEDUPRIGHT", 0, 284, 284, 284 },
145   { O_STEEL_SLOPED_UP_LEFT, N_("Sloped steel wall (up & left)"), P_SLOPED_UP|P_SLOPED_LEFT|P_NON_EXPLODABLE, "STEELWALLSLOPEDUPLEFT", 0, 285, 285, 285 },
146   { O_STEEL_SLOPED_DOWN_LEFT, N_("Sloped steel wall (down & left)"), P_SLOPED_DOWN|P_SLOPED_LEFT|P_NON_EXPLODABLE, "STEELWALLSLOPEDDOWNLEFT", 0, 286, 286, 286 },
147   { O_STEEL_SLOPED_DOWN_RIGHT, N_("Sloped steel wall (down & right)"), P_SLOPED_DOWN|P_SLOPED_RIGHT|P_NON_EXPLODABLE, "STEELWALLSLOPEDDOWNRIGHT", 0, 287, 287, 287 },
148   { O_STEEL_EXPLODABLE, N_("Explodable steel wall"), P_CAN_BE_HAMMERED, "STEELWALLDESTRUCTABLE", 'E', 72, 72, 4 },
149   { O_STEEL_EATABLE, N_("Eatable steel wall"), P_DIGGABLE, "STEELWALLEATABLE", 0, i_steel_eatable, i_steel_eatable, 4 },
150   { O_BRICK_EATABLE, N_("Eatable brick wall"), P_DIGGABLE, "WALLEATABLE", 0, i_brick_eatable, i_brick_eatable, 5 },
151   { O_STONE, N_("Stone"), P_SLOPED | P_MOVED_BY_CONVEYOR_TOP | P_PUSHABLE | P_CAN_FALL, "BOULDER", 'r', 1, 1, 1, 156 },    // has ckdelay
152   { O_STONE_F, N_("Stone, falling"), P_FALLING, "BOULDERf", 'R', i_stone_f, i_stone_f, 1, 156 },    // has ckdelay
153   { O_FLYING_STONE, N_("Flying stone"), P_SLOPED | P_MOVED_BY_CONVEYOR_BOTTOM | P_PUSHABLE | P_CAN_FALL, "FLYINGBOULDER", 0, 357, 357, 357, 156 },    // has ckdelay
154   { O_FLYING_STONE_F, N_("Flying stone, flying"), P_FALLING, "FLYINGBOULDERf", 0, i_flying_stone_f, i_flying_stone_f, 357, 156 },    // has ckdelay
155   { O_MEGA_STONE, N_("Mega stone"), P_SLOPED | P_MOVED_BY_CONVEYOR_TOP | P_PUSHABLE | P_CAN_FALL, "MEGABOULDER", 0, 272, 272, 272, 156 },    // has ckdelay
156   { O_MEGA_STONE_F, N_("Mega stone, falling"), P_FALLING, "MEGABOULDERf", 0, i_mega_stone_falling, i_mega_stone_falling, 272, 156 },    // has ckdelay
157   { O_DIAMOND, N_("Diamond"), P_SLOPED | P_MOVED_BY_CONVEYOR_TOP | P_COLLECTIBLE | P_CAN_FALL, "DIAMOND", 'd', 248, -248, -248, 156 },    // has ckdelay
158   { O_DIAMOND_F, N_("Diamond, falling"), P_FALLING, "DIAMONDf", 'D', i_diamond_f, i_diamond_f, -248, 156 },    // has ckdelay
159   { O_FLYING_DIAMOND, N_("Flying diamond"), P_SLOPED | P_MOVED_BY_CONVEYOR_BOTTOM | P_COLLECTIBLE | P_CAN_FALL, "FLYINGDIAMOND", 0, 344, -344, -344, 156 },    // has ckdelay
160   { O_FLYING_DIAMOND_F, N_("Flying diamond, flying"), P_FALLING, "FLYINGDIAMONDf", 0, i_flying_diamond_f, i_flying_diamond_f, -344, 156 },    // has ckdelay
161   { O_NUT, N_("Nut"), P_SLOPED | P_MOVED_BY_CONVEYOR_TOP | P_PUSHABLE | P_CAN_FALL, "NUT", 0, 358, 358, 358, 156 },    // has ckdelay
162   { O_NUT_F, N_("Nut, falling"), P_FALLING, "NUTf", 0, i_nut_f, i_nut_f, 358, 156 },    // has ckdelay
163   { O_BLADDER_SPENDER, N_("Bladder Spender"), P_PUSHABLE, "BLADDERSPENDER", 0, 6, 6, 6, 20 },    // has ckdelay
164   { O_INBOX, N_("Inbox"), 0, "INBOX", 'P', 35, 35, 22 },
165   { O_H_EXPANDING_WALL, N_("Expanding wall, horizontal"), P_VISUAL_EFFECT | P_CAN_BE_HAMMERED, "HEXPANDINGWALL", 'x', i_h_expanding_wall, i_h_expanding_wall, 5, 111 },    // has ckdelay
166   { O_V_EXPANDING_WALL, N_("Expanding wall, vertical"), P_VISUAL_EFFECT | P_CAN_BE_HAMMERED, "VEXPANDINGWALL", 'v', i_v_expanding_wall, i_v_expanding_wall, 5, 111 },    // has ckdelay
167   { O_EXPANDING_WALL, N_("Expanding wall"), P_VISUAL_EFFECT | P_CAN_BE_HAMMERED, "EXPANDINGWALL", 'e', i_expanding_wall, i_expanding_wall, 5, 111 },    // has ckdelay
168   { O_H_EXPANDING_STEEL_WALL, N_("Expanding steel wall, horizontal"), P_NON_EXPLODABLE, "HEXPANDINGSTEELWALL", 0, i_h_expanding_steel_wall, i_h_expanding_steel_wall, 4, 111 },    // has ckdelay
169   { O_V_EXPANDING_STEEL_WALL, N_("Expanding steel wall, vertical"), P_NON_EXPLODABLE, "VEXPANDINGSTEELWALL", 0, i_v_expanding_steel_wall, i_v_expanding_steel_wall, 4, 111 },    // has ckdelay
170   { O_EXPANDING_STEEL_WALL, N_("Expanding steel wall"), P_NON_EXPLODABLE, "EXPANDINGSTEELWALL", 0, i_expanding_steel_wall, i_expanding_steel_wall, 4, 111 },    // has ckdelay
171   { O_EXPANDING_WALL_SWITCH, N_("Expanding wall switch"), 0, "EXPANDINGWALLSWITCH", 0, 40, 40, 40 },
172   { O_CREATURE_SWITCH, N_("Creature direction switch"), 0, "FIREFLYBUTTERFLYSWITCH", 0, 18, 18, 18 },
173   { O_BITER_SWITCH, N_("Biter switch"), 0, "BITERSWITCH", 0, 12, 12, 12 },
174   { O_REPLICATOR_SWITCH, N_("Replicator switch"), 0, "REPLICATORSWITCH", 0, 290, 290, 290 },
175   { O_CONVEYOR_SWITCH, N_("Conveyor belt power switch"), 0, "CONVEYORSWITCH", 0, 356, 356, 356 },
176   { O_CONVEYOR_DIR_SWITCH, N_("Conveyor belt direction switch"), 0, "CONVEYORDIRECTIONSWITCH", 0, 353, 353, 353 },
177   { O_ACID, N_("Acid"), 0, "ACID", 0, 20, 20, 20, 128 },    // has ckdelay
178   { O_FALLING_WALL, N_("Falling wall"), P_CAN_BE_HAMMERED | P_CAN_FALL, "FALLINGWALL", 0, i_falling_wall, i_falling_wall, 5, 80 },    // has ckdelay
179   { O_FALLING_WALL_F, N_("Falling wall, falling"), P_CAN_BE_HAMMERED | P_FALLING, "FALLINGWALLf", 0, i_falling_wall_falling, i_falling_wall_falling, 5, 80 },    // has ckdelay
180   { O_BOX, N_("Box"), P_PUSHABLE, "SOKOBANBOX", 0, 21, 21, 21 },
181   { O_TIME_PENALTY, N_("Time penalty"), P_NON_EXPLODABLE, "TIMEPENALTY", 0, i_time_penalty, i_time_penalty, 9 },
182   { O_GRAVESTONE, N_("Gravestone"), P_NON_EXPLODABLE, "GRAVESTONE", 'G', 9, 9, 9 },
183   { O_STONE_GLUED, N_("Glued stone"), P_SLOPED, "GLUEDBOULDER", 0, i_stone_glued, i_stone_glued, 1 },
184   { O_DIAMOND_GLUED, N_("Glued diamond"), P_SLOPED, "GLUEDDIAMOND", 0, i_diamond_glued, i_diamond_glued, -248 },
185   { O_DIAMOND_KEY, N_("Diamond key"), P_COLLECTIBLE, "DIAMONDRELEASEKEY", 0, 11, 11, 11 },
186   { O_TRAPPED_DIAMOND, N_("Trapped diamond"), P_NON_EXPLODABLE, "TRAPPEDDIAMOND", 0, 10, 10, 10 },
187   { O_CLOCK, N_("Clock"), P_COLLECTIBLE, "CLOCK", 0, 16, 16, 16 },
188   { O_DIRT_GLUED, N_("Glued dirt"), 0, "GLUEDDIRT", 0, i_dirt_glued, i_dirt_glued, 2 },
189   { O_KEY_1, N_("Key 1"), P_COLLECTIBLE, "KEY1", 0, 67, 67, 67 },
190   { O_KEY_2, N_("Key 2"), P_COLLECTIBLE, "KEY2", 0, 68, 68, 68 },
191   { O_KEY_3, N_("Key 3"), P_COLLECTIBLE, "KEY3", 0, 69, 69, 69 },
192   { O_DOOR_1, N_("Door 1"), 0, "DOOR1", 0, 64, 64, 64 },
193   { O_DOOR_2, N_("Door 2"), 0, "DOOR2", 0, 65, 65, 65 },
194   { O_DOOR_3, N_("Door 3"), 0, "DOOR3", 0, 66, 66, 66 },
195
196   { O_POT, N_("Pot"), 0, "POT", 0, 63, 63, 63 },
197   { O_GRAVITY_SWITCH, N_("Gravity switch"), 0, "GRAVITY_SWITCH", 0, 274, 274, 274 },
198   { O_PNEUMATIC_HAMMER, N_("Pneumatic hammer"), P_COLLECTIBLE, "PNEUMATIC_HAMMER", 0, 62, 62, 62 },
199   { O_TELEPORTER, N_("Teleporter"), 0, "TELEPORTER", 0, 61, 61, 61 },
200   { O_SKELETON, N_("Skeleton"), 0, "SKELETON", 0, 273, 273, 273 },
201   { O_WATER, N_("Water"), 0, "WATER", 0, 96, -96, -96, 100 },    // has ckdelay
202   { O_WATER_1, N_("Water (1)"), 0, "WATER1", 0, 96, -96, -96 },
203   { O_WATER_2, N_("Water (2)"), 0, "WATER2", 0, 96, -96, -96 },
204   { O_WATER_3, N_("Water (3)"), 0, "WATER3", 0, 96, -96, -96 },
205   { O_WATER_4, N_("Water (4)"), 0, "WATER4", 0, 96, -96, -96 },
206   { O_WATER_5, N_("Water (5)"), 0, "WATER5", 0, 96, -96, -96 },
207   { O_WATER_6, N_("Water (6)"), 0, "WATER6", 0, 96, -96, -96 },
208   { O_WATER_7, N_("Water (7)"), 0, "WATER7", 0, 96, -96, -96 },
209   { O_WATER_8, N_("Water (8)"), 0, "WATER8", 0, 96, -96, -96 },
210   { O_WATER_9, N_("Water (9)"), 0, "WATER9", 0, 96, -96, -96 },
211   { O_WATER_10, N_("Water (10)"), 0, "WATER10", 0, 96, -96, -96 },
212   { O_WATER_11, N_("Water (11)"), 0, "WATER11", 0, 96, -96, -96 },
213   { O_WATER_12, N_("Water (12)"), 0, "WATER12", 0, 96, -96, -96 },
214   { O_WATER_13, N_("Water (13)"), 0, "WATER13", 0, 96, -96, -96 },
215   { O_WATER_14, N_("Water (14)"), 0, "WATER14", 0, 96, -96, -96 },
216   { O_WATER_15, N_("Water (15)"), 0, "WATER15", 0, 96, -96, -96 },
217   { O_WATER_16, N_("Water (16)"), 0, "WATER16", 0, 96, -96, -96 },
218   { O_COW_1, N_("Cow (left)"), P_CCW | P_CAN_MOVE, "COWl", 0, i_cow_1, -88, -88, 384 },    // has ckdelay
219   { O_COW_2, N_("Cow (up)"), P_CCW | P_CAN_MOVE, "COWu", 0, i_cow_2, -88, -88, 384 },      // has ckdelay
220   { O_COW_3, N_("Cow (right)"), P_CCW | P_CAN_MOVE, "COWr", 0, i_cow_3, -88, -88, 384 },   // has ckdelay
221   { O_COW_4, N_("Cow (down)"), P_CCW | P_CAN_MOVE, "COWd", 0, i_cow_4, -88, -88, 384 },    // has ckdelay
222   { O_COW_ENCLOSED_1, N_("Cow (enclosed, 1)"), 0, "COW_ENCLOSED1", 0, i_cow_enclosed, -88, -88, 120 },    // has ckdelay
223   { O_COW_ENCLOSED_2, N_("Cow (enclosed, 2)"), 0, "COW_ENCLOSED2", 0, i_cow_enclosed, -88, -88, 120 },    // has ckdelay
224   { O_COW_ENCLOSED_3, N_("Cow (enclosed, 3)"), 0, "COW_ENCLOSED3", 0, i_cow_enclosed, -88, -88, 120 },    // has ckdelay
225   { O_COW_ENCLOSED_4, N_("Cow (enclosed, 4)"), 0, "COW_ENCLOSED4", 0, i_cow_enclosed, -88, -88, 120 },    // has ckdelay
226   { O_COW_ENCLOSED_5, N_("Cow (enclosed, 5)"), 0, "COW_ENCLOSED5", 0, i_cow_enclosed, -88, -88, 120 },    // has ckdelay
227   { O_COW_ENCLOSED_6, N_("Cow (enclosed, 6)"), 0, "COW_ENCLOSED6", 0, i_cow_enclosed, -88, -88, 120 },    // has ckdelay
228   { O_COW_ENCLOSED_7, N_("Cow (enclosed, 7)"), 0, "COW_ENCLOSED7", 0, i_cow_enclosed, -88, -88, 120 },    // has ckdelay
229   { O_WALLED_DIAMOND, N_("Walled diamond"), P_CAN_BE_HAMMERED, "WALLED_DIAMOND", 0, i_walled_diamond, i_walled_diamond, 5 },
230   { O_WALLED_KEY_1, N_("Walled key 1"), P_CAN_BE_HAMMERED, "WALLED_KEY1", 0, i_walled_key_1, i_walled_key_1, 5 },
231   { O_WALLED_KEY_2, N_("Walled key 2"), P_CAN_BE_HAMMERED, "WALLED_KEY2", 0, i_walled_key_2, i_walled_key_2, 5 },
232   { O_WALLED_KEY_3, N_("Walled key 3"), P_CAN_BE_HAMMERED, "WALLED_KEY3", 0, i_walled_key_3, i_walled_key_3, 5 },
233
234   { O_AMOEBA, N_("Amoeba"), P_BLOWS_UP_FLIES | P_CAN_MOVE, "AMOEBA", 'a', 192, -192, -192, 260 },    // has ckdelay
235   { O_AMOEBA_2, N_("Amoeba 2"), P_BLOWS_UP_FLIES | P_CAN_MOVE | P_VISUAL_EFFECT, "AMOEBA2", 0, 296, -296, -296, 260 },    // has ckdelay
236   { O_REPLICATOR, N_("Replicator"), P_NON_EXPLODABLE, "REPLICATOR", 0, 304, -304, -304, 210 },    // has ckdelay
237   { O_CONVEYOR_LEFT, N_("Conveyor belt (left)"), P_NON_EXPLODABLE, "CONVEYORLEFT", 0, i_conveyor_left, -328, -328, 256  },    // has ckdelay
238   { O_CONVEYOR_RIGHT, N_("Conveyor belt (right)"), P_NON_EXPLODABLE, "CONVEYORRIGHT", 0, i_conveyor_right, -320, -320  },
239   { O_LAVA, N_("Lava"), P_NON_EXPLODABLE, "LAVA", 0, 312, -312, -312 },
240   { O_SWEET, N_("Sweet"), P_COLLECTIBLE, "SWEET", 0, 8, 8, 8 },
241   { O_VOODOO, N_("Voodoo doll"), P_BLOWS_UP_FLIES, "DUMMY", 'F', 7, 7, 7 },
242   { O_SLIME, N_("Slime"), 0, "SLIME", 's', 200, -200, -200, 211 },        // has ckdelay
243   { O_BLADDER, N_("Bladder"), 0, "BLADDER", 0, 176, -176, -176, 267 },    // has ckdelay
244   { O_BLADDER_1, N_("Bladder (1)"), 0, "BLADDERd1", 0, 176, -176, -176 },
245   { O_BLADDER_2, N_("Bladder (2)"), 0, "BLADDERd2", 0, 176, -176, -176 },
246   { O_BLADDER_3, N_("Bladder (3)"), 0, "BLADDERd3", 0, 176, -176, -176 },
247   { O_BLADDER_4, N_("Bladder (4)"), 0, "BLADDERd4", 0, 176, -176, -176 },
248   { O_BLADDER_5, N_("Bladder (5)"), 0, "BLADDERd5", 0, 176, -176, -176 },
249   { O_BLADDER_6, N_("Bladder (6)"), 0, "BLADDERd6", 0, 176, -176, -176 },
250   { O_BLADDER_7, N_("Bladder (7)"), 0, "BLADDERd7", 0, 176, -176, -176 },
251   { O_BLADDER_8, N_("Bladder (8)"), 0, "BLADDERd8", 0, 176, -176, -176 },
252
253   { O_WAITING_STONE, N_("Waiting stone"), P_SLOPED | P_PUSHABLE, "WAITINGBOULDER", 0, i_waiting_stone, i_waiting_stone, 1, 176 },    // has ckdelay
254   { O_CHASING_STONE, N_("Chasing stone"), P_SLOPED | P_CAN_MOVE | P_PUSHABLE, "CHASINGBOULDER", 0, 17, 17, 17, 269 },    // has ckdelay
255   { O_GHOST, N_("Ghost"), P_CAN_MOVE, "GHOST", 'g', 160, -160, -160, 50 },    // has ckdelay
256   { O_FIREFLY_1, N_("Guard, left"), P_EXPLODES_BY_HIT | P_CCW | P_CAN_MOVE, "FIREFLYl", 'Q', i_guard_1, -136, -136, 384 },    // has ckdelay
257   { O_FIREFLY_2, N_("Guard, up"), P_EXPLODES_BY_HIT | P_CCW | P_CAN_MOVE, "FIREFLYu", 'o', i_guard_2, -136, -136, 384 },      // has ckdelay
258   { O_FIREFLY_3, N_("Guard, right"), P_EXPLODES_BY_HIT | P_CCW | P_CAN_MOVE, "FIREFLYr", 'O', i_guard_3, -136, -136, 384 },   // has ckdelay
259   { O_FIREFLY_4, N_("Guard, down"), P_EXPLODES_BY_HIT | P_CCW | P_CAN_MOVE, "FIREFLYd", 'q', i_guard_4, -136, -136, 384 },    // has ckdelay
260   { O_ALT_FIREFLY_1, N_("Alternative guard, left"), P_EXPLODES_BY_HIT | P_CAN_MOVE, "A_FIREFLYl", 0, i_alt_guard_1, -104, -104, 384 },    // has ckdelay
261   { O_ALT_FIREFLY_2, N_("Alternative guard, up"), P_EXPLODES_BY_HIT | P_CAN_MOVE, "A_FIREFLYu", 0, i_alt_guard_2, -104, -104, 384 },      // has ckdelay
262   { O_ALT_FIREFLY_3, N_("Alternative guard, right"), P_EXPLODES_BY_HIT | P_CAN_MOVE, "A_FIREFLYr", 0, i_alt_guard_3, -104, -104, 384 },   // has ckdelay
263   { O_ALT_FIREFLY_4, N_("Alternative guard, down"), P_EXPLODES_BY_HIT | P_CAN_MOVE, "A_FIREFLYd", 0, i_alt_guard_4, -104, -104, 384 },    // has ckdelay
264   { O_BUTTER_1, N_("Butterfly, left"), P_EXPLODES_BY_HIT | P_CAN_MOVE, "BUTTERFLYl", 'C', i_butter_1, -144, -144, 384 },    // has ckdelay
265   { O_BUTTER_2, N_("Butterfly, up"), P_EXPLODES_BY_HIT | P_CAN_MOVE, "BUTTERFLYu", 'b', i_butter_2, -144, -144, 384 },      // has ckdelay
266   { O_BUTTER_3, N_("Butterfly, right"), P_EXPLODES_BY_HIT | P_CAN_MOVE, "BUTTERFLYr", 'B', i_butter_3, -144, -144, 384 },   // has ckdelay
267   { O_BUTTER_4, N_("Butterfly, down"), P_EXPLODES_BY_HIT | P_CAN_MOVE, "BUTTERFLYd", 'c', i_butter_4, -144, -144, 384 },    // has ckdelay
268   { O_ALT_BUTTER_1, N_("Alternative butterfly, left"), P_EXPLODES_BY_HIT | P_CCW | P_CAN_MOVE, "A_BUTTERFLYl", 0, i_alt_butter_1, -112, -112, 384 },    // has ckdelay
269   { O_ALT_BUTTER_2, N_("Alternative butterfly, up"), P_EXPLODES_BY_HIT | P_CCW | P_CAN_MOVE, "A_BUTTERFLYu", 0, i_alt_butter_2, -112, -112, 384 },      // has ckdelay
270   { O_ALT_BUTTER_3, N_("Alternative butterfly, right"), P_EXPLODES_BY_HIT | P_CCW | P_CAN_MOVE, "A_BUTTERFLYr", 0, i_alt_butter_3, -112, -112, 384 },   // has ckdelay
271   { O_ALT_BUTTER_4, N_("Alternative butterfly, down"), P_EXPLODES_BY_HIT | P_CCW | P_CAN_MOVE, "A_BUTTERFLYd", 0, i_alt_butter_4, -112, -112, 384 },    // has ckdelay
272   { O_STONEFLY_1, N_("Stonefly, left"), P_EXPLODES_BY_HIT | P_CAN_MOVE, "STONEFLYl", 0, i_stonefly_1, -152, -152, 384 },    // has ckdelay
273   { O_STONEFLY_2, N_("Stonefly, up"), P_EXPLODES_BY_HIT | P_CAN_MOVE, "STONEFLYu", 0, i_stonefly_2, -152, -152, 384 },      // has ckdelay
274   { O_STONEFLY_3, N_("Stonefly, right"), P_EXPLODES_BY_HIT | P_CAN_MOVE, "STONEFLYr", 0, i_stonefly_3, -152, -152, 384 },   // has ckdelay
275   { O_STONEFLY_4, N_("Stonefly, down"), P_EXPLODES_BY_HIT | P_CAN_MOVE, "STONEFLYd", 0, i_stonefly_4, -152, -152, 384 },    // has ckdelay
276   { O_BITER_1, N_("Biter, up"), P_CAN_MOVE, "BITERu", 0, i_biter_1, -168, -168, 518 },    // has ckdelay
277   { O_BITER_2, N_("Biter, right"), P_CAN_MOVE, "BITERr", 0, i_biter_2, -168, -168, 518 },    // has ckdelay
278   { O_BITER_3, N_("Biter, down"), P_CAN_MOVE, "BITERd", 0, i_biter_3, -168, -168, 518 },    // has ckdelay
279   { O_BITER_4, N_("Biter, left"), P_CAN_MOVE, "BITERl", 0, i_biter_4, -168, -168, 518 },    // has ckdelay
280   { O_DRAGONFLY_1, N_("Dragonfly, left"), P_EXPLODES_BY_HIT | P_CCW | P_CAN_MOVE, "DRAGONFLYl", 0, i_dragonfly_1, -336, -336, 256  },    // has ckdelay
281   { O_DRAGONFLY_2, N_("Dragonfly, up"), P_EXPLODES_BY_HIT | P_CCW | P_CAN_MOVE, "DRAGONFLYu", 0, i_dragonfly_2, -336, -336, 256  },      // has ckdelay
282   { O_DRAGONFLY_3, N_("Dragonfly, right"), P_EXPLODES_BY_HIT | P_CCW | P_CAN_MOVE, "DRAGONFLYr", 0, i_dragonfly_3, -336, -336, 256  },   // has ckdelay
283   { O_DRAGONFLY_4, N_("Dragonfly, down"), P_EXPLODES_BY_HIT | P_CCW | P_CAN_MOVE, "DRAGONFLYd", 0, i_dragonfly_4, -336, -336, 256  },    // has ckdelay
284
285   { O_PRE_PL_1, N_("Player birth (1)"), P_GROWING, "GUYBIRTH1", 0, 32, 32, 32 },
286   { O_PRE_PL_2, N_("Player birth (2)"), P_GROWING, "GUYBIRTH2", 0, 33, 33, 33 },
287   { O_PRE_PL_3, N_("Player birth (3)"), P_GROWING, "GUYBIRTH3", 0, 34, 34, 34 },
288   { O_PLAYER, N_("Player"), P_BLOWS_UP_FLIES | P_EXPLODES_BY_HIT | P_PLAYER, "GUY", 0, i_player, i_player, 35, 32 },    // has ckdelay
289   { O_PLAYER_BOMB, N_("Player with bomb"), P_BLOWS_UP_FLIES | P_EXPLODES_BY_HIT | P_PLAYER, "GUYBOMB", 0, 42, 42, 42, 25 },    // has ckdelay
290   { O_PLAYER_ROCKET_LAUNCHER, N_("Player with rocket launcher"), P_BLOWS_UP_FLIES | P_EXPLODES_BY_HIT | P_PLAYER, "GUYROCKETLAUNCER", 0, 369, 369, 369, 25 },    // has ckdelay
291   { O_PLAYER_GLUED, N_("Glued player"), P_BLOWS_UP_FLIES | P_EXPLODES_BY_HIT, "GUYGLUED", 0, i_player_glued, i_player_glued, 35 },    // is not a real player! so active x, y will not find it. no P_PLAYER bit!
292   { O_PLAYER_STIRRING, N_("Player stirring"), P_BLOWS_UP_FLIES | P_EXPLODES_BY_HIT | P_PLAYER, "GUYSTIRRING", 0, 256, -256, -256 },
293
294   { O_ROCKET_LAUNCHER, N_("Rocket launcher"), 0, "ROCKET_LAUNCHER", 0, 368, 368, 368 },
295   { O_ROCKET_1, N_("Rocket (right)"), 0, "ROCKETr", 0, 364, 364, 364, 40 },    // has ckdelay
296   { O_ROCKET_2, N_("Rocket (up)"), 0, "ROCKETu", 0, 365, 365, 365, 40 },    // has ckdelay
297   { O_ROCKET_3, N_("Rocket (left)"), 0, "ROCKETl", 0, 366, 366, 366, 40 },    // has ckdelay
298   { O_ROCKET_4, N_("Rocket (down)"), 0, "ROCKETd", 0, 367, 367, 367, 40 },    // has ckdelay
299
300   { O_BOMB, N_("Bomb"), P_COLLECTIBLE, "BOMB", 0, 48, 48, 48 },
301   { O_BOMB_TICK_1, N_("Ticking bomb (1)"), P_EXPLOSION_FIRST_STAGE, "IGNITEDBOMB1", 0, 49, 49, 49 },
302   { O_BOMB_TICK_2, N_("Ticking bomb (2)"), 0, "IGNITEDBOMB2", 0, 50, 50, 50 },
303   { O_BOMB_TICK_3, N_("Ticking bomb (3)"), 0, "IGNITEDBOMB3", 0, 51, 51, 51 },
304   { O_BOMB_TICK_4, N_("Ticking bomb (4)"), 0, "IGNITEDBOMB4", 0, 52, 52, 52 },
305   { O_BOMB_TICK_5, N_("Ticking bomb (5)"), 0, "IGNITEDBOMB5", 0, 53, 53, 53 },
306   { O_BOMB_TICK_6, N_("Ticking bomb (6)"), 0, "IGNITEDBOMB6", 0, 54, 54, 54 },
307   { O_BOMB_TICK_7, N_("Ticking bomb (7)"), 0, "IGNITEDBOMB7", 0, 55, 55, 55 },
308
309   { O_NITRO_PACK, N_("Nitro pack"), P_SLOPED | P_EXPLODES_BY_HIT | P_MOVED_BY_CONVEYOR_TOP | P_PUSHABLE | P_CAN_FALL, "NITRO", 0, 288, 288, 288 },
310   { O_NITRO_PACK_F, N_("Nitro pack, falling"), P_EXPLODES_BY_HIT | P_FALLING, "NITROf", 0, i_nitro_pack_f, i_nitro_pack_f, 288 },
311   { O_NITRO_PACK_EXPLODE, N_("Nitro pack, triggered"), P_EXPLODES_BY_HIT, "NITROtriggered", 0, i_nitro_explode, i_nitro_explode, 288 },
312
313   { O_PRE_CLOCK_1, N_("Clock birth (1)"), P_GROWING | P_EXPLOSION_FIRST_STAGE, "CLOCKBIRTH1", 0, 28, 28, 28, 280 },    // has ckdelay
314   { O_PRE_CLOCK_2, N_("Clock birth (2)"), P_GROWING, "CLOCKBIRTH2", 0, 29, 29, 29, 280 },    // has ckdelay
315   { O_PRE_CLOCK_3, N_("Clock birth (3)"), P_GROWING, "CLOCKBIRTH3", 0, 30, 30, 30, 280 },    // has ckdelay
316   { O_PRE_CLOCK_4, N_("Clock birth (4)"), P_GROWING, "CLOCKBIRTH4", 0, 31, 31, 31, 280 },    // has ckdelay
317   { O_PRE_DIA_1, N_("Diamond birth (1)"), P_GROWING | P_EXPLOSION_FIRST_STAGE, "DIAMONDBIRTH1", 0, 56, 56, 56, 280 },    // has ckdelay
318   { O_PRE_DIA_2, N_("Diamond birth (2)"), P_GROWING, "DIAMONDBIRTH2", 0, 57, 57, 57, 280 },    // has ckdelay
319   { O_PRE_DIA_3, N_("Diamond birth (3)"), P_GROWING, "DIAMONDBIRTH3", 0, 58, 58, 58, 280 },    // has ckdelay
320   { O_PRE_DIA_4, N_("Diamond birth (4)"), P_GROWING, "DIAMONDBIRTH4", 0, 59, 59, 59, 280 },    // has ckdelay
321   { O_PRE_DIA_5, N_("Diamond birth (5)"), P_GROWING, "DIAMONDBIRTH5", 0, 60, 60, 60, 280 },    // has ckdelay
322   { O_EXPLODE_1, N_("Explosion (1)"), P_EXPLOSION | P_EXPLOSION_FIRST_STAGE, "EXPLOSION1", 0, 43, 43, 43, 280 },    // has ckdelay
323   { O_EXPLODE_2, N_("Explosion (2)"), P_EXPLOSION, "EXPLOSION2", 0, 44, 44, 44, 280 },    // has ckdelay
324   { O_EXPLODE_3, N_("Explosion (3)"), P_EXPLOSION, "EXPLOSION3", 0, 45, 45, 45, 280 },    // has ckdelay
325   { O_EXPLODE_4, N_("Explosion (4)"), P_EXPLOSION, "EXPLOSION4", 0, 46, 46, 46, 280 },    // has ckdelay
326   { O_EXPLODE_5, N_("Explosion (5)"), P_EXPLOSION, "EXPLOSION5", 0, 47, 47, 47, 280 },    // has ckdelay
327   { O_PRE_STONE_1, N_("Stone birth (1)"), P_GROWING | P_EXPLOSION_FIRST_STAGE, "BOULDERBIRTH1", 0, 36, 36, 36, 280 },    // has ckdelay
328   { O_PRE_STONE_2, N_("Stone birth (2)"), P_GROWING, "BOULDERBIRTH2", 0, 37, 37, 37, 280 },    // has ckdelay
329   { O_PRE_STONE_3, N_("Stone birth (3)"), P_GROWING, "BOULDERBIRTH3", 0, 38, 38, 38, 280 },    // has ckdelay
330   { O_PRE_STONE_4, N_("Stone birth (4)"), P_GROWING, "BOULDERBIRTH4", 0, 39, 39, 39, 280 },    // has ckdelay
331   { O_PRE_STEEL_1, N_("Steel birth (1)"), P_GROWING | P_EXPLOSION_FIRST_STAGE, "STEELWALLBIRTH1", 0, 24, 24, 24, 280 },    // has ckdelay
332   { O_PRE_STEEL_2, N_("Steel birth (2)"), P_GROWING, "STEELWALLBIRTH2", 0, 25, 25, 25, 280 },    // has ckdelay
333   { O_PRE_STEEL_3, N_("Steel birth (3)"), P_GROWING, "STEELWALLBIRTH3", 0, 26, 26, 26, 280 },    // has ckdelay
334   { O_PRE_STEEL_4, N_("Steel birth (4)"), P_GROWING, "STEELWALLBIRTH4", 0, 27, 27, 27, 280 },    // has ckdelay
335   { O_GHOST_EXPL_1, N_("Ghost explosion (1)"), P_EXPLOSION | P_EXPLOSION_FIRST_STAGE, "GHOSTEXPLOSION1", 0, 80, 80, 80, 280 },    // has ckdelay
336   { O_GHOST_EXPL_2, N_("Ghost explosion (2)"), P_EXPLOSION, "GHOSTEXPLOSION2", 0, 81, 81, 81, 280 },    // has ckdelay
337   { O_GHOST_EXPL_3, N_("Ghost explosion (3)"), P_EXPLOSION, "GHOSTEXPLOSION3", 0, 82, 82, 82, 280 },    // has ckdelay
338   { O_GHOST_EXPL_4, N_("Ghost explosion (4)"), P_EXPLOSION, "GHOSTEXPLOSION4", 0, 83, 83, 83, 280 },    // has ckdelay
339   { O_BOMB_EXPL_1, N_("Bomb explosion (1)"), P_EXPLOSION | P_EXPLOSION_FIRST_STAGE, "BOMBEXPLOSION1", 0, 84, 84, 84, 280 },    // has ckdelay
340   { O_BOMB_EXPL_2, N_("Bomb explosion (2)"), P_EXPLOSION, "BOMBEXPLOSION2", 0, 85, 85, 85, 280 },    // has ckdelay
341   { O_BOMB_EXPL_3, N_("Bomb explosion (3)"), P_EXPLOSION, "BOMBEXPLOSION3", 0, 86, 86, 86, 280 },    // has ckdelay
342   { O_BOMB_EXPL_4, N_("Bomb explosion (4)"), P_EXPLOSION, "BOMBEXPLOSION4", 0, 87, 87, 87, 280 },    // has ckdelay
343   { O_NITRO_EXPL_1, N_("Nitro pack explosion (1)"), P_EXPLOSION | P_EXPLOSION_FIRST_STAGE, "NITROEXPLOSION1", 0, 44, 44, 44, 280 },    // has ckdelay
344   { O_NITRO_EXPL_2, N_("Nitro pack explosion (2)"), P_EXPLOSION, "NITROEXPLOSION2", 0, 45, 45, 45, 280 },    // has ckdelay
345   { O_NITRO_EXPL_3, N_("Nitro pack explosion (3)"), P_EXPLOSION, "NITROEXPLOSION3", 0, 46, 46, 46, 280 },    // has ckdelay
346   { O_NITRO_EXPL_4, N_("Nitro pack explosion (4)"), P_EXPLOSION, "NITROEXPLOSION4", 0, 47, 47, 47, 280 },    // has ckdelay
347   { O_AMOEBA_2_EXPL_1, N_("Amoeba 2 explosion (1)"), P_EXPLOSION | P_EXPLOSION_FIRST_STAGE, "AMOEBA2EXPLOSION1", 0, 292, 292, 292, 280 },    // has ckdelay
348   { O_AMOEBA_2_EXPL_2, N_("Amoeba 2 explosion (2)"), P_EXPLOSION, "AMOEBA2EXPLOSION2", 0, 293, 293, 293, 280 },    // has ckdelay
349   { O_AMOEBA_2_EXPL_3, N_("Amoeba 2 explosion (3)"), P_EXPLOSION, "AMOEBA2EXPLOSION3", 0, 294, 294, 294, 280 },    // has ckdelay
350   { O_AMOEBA_2_EXPL_4, N_("Amoeba 2 explosion (4)"), P_EXPLOSION, "AMOEBA2EXPLOSION4", 0, 295, 295, 295, 280 },    // has ckdelay
351   { O_NUT_EXPL_1, N_("Nut explosion (1)"), P_SLOPED | P_EXPLOSION | P_EXPLOSION_FIRST_STAGE, "NUTEXPLOSION1", 0, 360, 360, 360, 280 },    // has ckdelay
352   { O_NUT_EXPL_2, N_("Nut explosion (2)"), P_SLOPED | P_EXPLOSION, "NUTEXPLOSION2", 0, 361, 361, 361, 280 },    /* has ckdelay */        /* these are rounded!! */
353   { O_NUT_EXPL_3, N_("Nut explosion (3)"), P_SLOPED | P_EXPLOSION, "NUTEXPLOSION3", 0, 362, 362, 362, 280 },    // has ckdelay
354   { O_NUT_EXPL_4, N_("Nut explosion (4)"), P_SLOPED | P_EXPLOSION, "NUTEXPLOSION4", 0, 363, 363, 363, 280 },    // has ckdelay
355
356   { O_PLAYER_PNEUMATIC_LEFT, NULL /* Player using hammer, left */, P_BLOWS_UP_FLIES | P_EXPLODES_BY_HIT | P_PLAYER, "GUYHAMMERl", 0, 265, 265, 265 },
357   { O_PLAYER_PNEUMATIC_RIGHT, NULL /* Player using hammer, right */, P_BLOWS_UP_FLIES | P_EXPLODES_BY_HIT | P_PLAYER, "GUYHAMMERr", 0, 268, 268, 268 },
358   { O_PNEUMATIC_ACTIVE_LEFT, NULL /* Active hammer, left */, 0, "HAMMERACTIVEl", 0, 264, 264, 264 },
359   { O_PNEUMATIC_ACTIVE_RIGHT, NULL /* Active hammer, right */, 0, "HAMMERACTIVEr", 0, 269, 269, 269 },
360
361   { O_UNKNOWN, N_("Unknown element"), P_NON_EXPLODABLE, "UNKNOWN", 0, i_unknown, i_unknown, 4 },
362   { O_NONE, N_("No element"), 0, "NONE", 0, 79, 79, 79 },
363   { O_MAX },
364
365   // these are just helpers, for all the element -> image index information to be in this array
366   { O_FAKE_BONUS, NULL, 0, NULL, 0, 120, -120, -120 },
367   { O_INBOX_CLOSED, NULL, 0, NULL, 0, 22, 22, 22 },
368   { O_INBOX_OPEN, NULL, 0, NULL, 0, 23, 23, 23 },
369
370   // game graphics
371   // also for imported diego effects, but don't know if it is used anywhere in original games
372   { O_OUTBOX_CLOSED, NULL, 0, NULL, 0, 22, 22, 22 },
373   { O_OUTBOX_OPEN, NULL, 0, NULL, 0, 23, 23, 23 },
374   { O_COVERED, NULL, 0, NULL, 0, 128, -128, -128 },
375   { O_PLAYER_LEFT, NULL, P_PLAYER, NULL, 0, 232, -232, -232 },
376   { O_PLAYER_RIGHT, NULL, P_PLAYER, NULL, 0, 240, -240, -240 },
377   { O_PLAYER_UP, NULL, P_PLAYER, NULL, 0, 376, -376, -376 },
378   { O_PLAYER_DOWN, NULL, P_PLAYER, NULL, 0, 384, -384, -384 },
379   { O_PLAYER_TAP, NULL, P_PLAYER, NULL, 0, 216, -216, -216 },
380   { O_PLAYER_BLINK, NULL, P_PLAYER, NULL, 0, 208, -208, -208 },
381   { O_PLAYER_TAP_BLINK, NULL, P_PLAYER, NULL, 0, 224, -224, -224 },
382   { O_PLAYER_PUSH_LEFT, N_("Player, pushing left"), P_PLAYER, NULL, 0, 392, -392, -392 },
383   { O_PLAYER_PUSH_RIGHT, N_("Player, pushing right"), P_PLAYER, NULL, 0, 400, -400, -400 },
384   { O_CREATURE_SWITCH_ON, NULL, 0, NULL, 0, 19, 19, 19 },
385   { O_EXPANDING_WALL_SWITCH_HORIZ, NULL, 0, NULL, 0, 40, 40, 40 },
386   { O_EXPANDING_WALL_SWITCH_VERT, NULL, 0, NULL, 0, 41, 41, 41 },
387   { O_GRAVITY_SWITCH_ACTIVE, NULL, 0, NULL, 0, 275, 275, 275 },
388   { O_REPLICATOR_SWITCH_ON, NULL, 0, NULL, 0, 290, 290, 290 },
389   { O_REPLICATOR_SWITCH_OFF, NULL, 0, NULL, 0, 291, 291, 291 },
390   { O_CONVEYOR_DIR_NORMAL, NULL, 0, NULL, 0, 353, 353, 353 },
391   { O_CONVEYOR_DIR_CHANGED, NULL, 0, NULL, 0, 354, 354, 354 },
392   { O_CONVEYOR_SWITCH_OFF, NULL, 0, NULL, 0, 355, 355, 355 },
393   { O_CONVEYOR_SWITCH_ON, NULL, 0, NULL, 0, 356, 356, 356 },
394
395   { O_MAGIC_WALL_ACTIVE, NULL, 0, NULL, 0, 184, -184, -184 },
396   { O_REPLICATOR_ACTIVE, NULL, 0, NULL, 0, 304, -304, -304 },
397   { O_CONVEYOR_LEFT_ACTIVE, NULL, 0, NULL, 0, i_conveyor_left, -328, -328 },
398   { O_CONVEYOR_RIGHT_ACTIVE, NULL, 0, NULL, 0, i_conveyor_right, -320, -320  },
399   { O_BITER_SWITCH_1, NULL, 0, NULL, 0, 12, 12, 12 },
400   { O_BITER_SWITCH_2, NULL, 0, NULL, 0, 13, 13, 13 },
401   { O_BITER_SWITCH_3, NULL, 0, NULL, 0, 14, 14, 14 },
402   { O_BITER_SWITCH_4, NULL, 0, NULL, 0, 15, 15, 15 },
403
404   { O_QUESTION_MARK, NULL, 0, NULL, 0, 70, 70, 70 },
405   { O_EATABLE, NULL, 0, NULL, 0, 71, 71, 71 },
406   { O_DOWN_ARROW, NULL, 0, NULL, 0, 73, 73, 73 },
407   { O_LEFTRIGHT_ARROW, NULL, 0, NULL, 0, 74, 74, 74 },
408   { O_EVERYDIR_ARROW, NULL, 0, NULL, 0, 75, 75, 75 },
409   { O_GLUED, NULL, 0, NULL, 0, 76, 76, 76 },
410   { O_OUT, NULL, 0, NULL, 0, 77, 77, 77 },
411   { O_EXCLAMATION_MARK, NULL, 0, NULL, 0, 78, 78, 78 },
412
413   { -1 },
414 };
415
416 // entries.
417 /* type given for each element;
418  * GD_TYPE_ELEMENT represents a combo box of gdash objects.
419  * GD_TAB&LABEL represents a notebook tab or a label.
420  * others are self-explanatory.
421  */
422 const GdStructDescriptor gd_cave_properties[] =
423 {
424   // default data
425   {"", GD_TAB, 0, N_("Cave data")},
426   {"Name", GD_TYPE_STRING, 0, N_("Name"), STRUCT_OFFSET(GdCave, name), 1, N_("Name of game")},
427   {"Description", GD_TYPE_STRING, 0, N_("Description"), STRUCT_OFFSET(GdCave, description), 1, N_("Some words about the game")},
428   {"Author", GD_TYPE_STRING, 0, N_("Author"), STRUCT_OFFSET(GdCave, author), 1, N_("Name of author")},
429   {"Date", GD_TYPE_STRING, 0, N_("Date"), STRUCT_OFFSET(GdCave, date), 1, N_("Date of creation")},
430   {"WWW", GD_TYPE_STRING, 0, N_("WWW"), STRUCT_OFFSET(GdCave, www), 1, N_("Web page or e-mail address")},
431   {"Difficulty", GD_TYPE_STRING, 0, N_("Difficulty"), STRUCT_OFFSET(GdCave, difficulty), 1, N_("Difficulty (informative)")},
432
433   {"Selectable", GD_TYPE_BOOLEAN, 0, N_("Selectable as start"), STRUCT_OFFSET(GdCave, selectable), 1, N_("This sets whether the game can be started at this cave.")},
434   {"Intermission", GD_TYPE_BOOLEAN, GD_ALWAYS_SAVE, N_("Intermission"), STRUCT_OFFSET(GdCave, intermission), 1, N_("Intermission caves are usually small and fast caves, which are not required to be solved. The player will not lose a life if he is not successful. The game always proceeds to the next cave.")},
435   {"IntermissionProperties.instantlife", GD_TYPE_BOOLEAN, 0, N_("   Instant life"), STRUCT_OFFSET(GdCave, intermission_instantlife), 1, N_("If true, an extra life is given to the player, when the intermission cave is reached.")},
436   {"IntermissionProperties.rewardlife", GD_TYPE_BOOLEAN, 0, N_("   Reward life"), STRUCT_OFFSET(GdCave, intermission_rewardlife), 1, N_("If true, an extra life is given to the player, when the intermission cave is successfully finished.")},
437   {"Size", GD_TYPE_INT, GD_ALWAYS_SAVE, N_("Width"), STRUCT_OFFSET(GdCave, w), 1, N_("Width of cave. The standard size for a cave is 40x22, and 20x12 for an intermission."), 12, 128},
438   {"Size", GD_TYPE_INT, GD_ALWAYS_SAVE, N_("Height"), STRUCT_OFFSET(GdCave, h), 1, N_("Height of cave. The standard size for a cave is 40x22, and 20x12 for an intermission."), 12, 128},
439   {"Size", GD_TYPE_INT, GD_ALWAYS_SAVE|GD_DONT_SHOW_IN_EDITOR, N_("Visible, left"), STRUCT_OFFSET(GdCave, x1), 1, N_("Visible parts of the cave, upper left and lower right corner."), 0, 127},
440   {"Size", GD_TYPE_INT, GD_ALWAYS_SAVE|GD_DONT_SHOW_IN_EDITOR, N_("Visible, upper"), STRUCT_OFFSET(GdCave, y1), 1, N_("Visible parts of the cave, upper left and lower right corner."), 0, 127},
441   {"Size", GD_TYPE_INT, GD_ALWAYS_SAVE|GD_DONT_SHOW_IN_EDITOR, N_("Visible, right"), STRUCT_OFFSET(GdCave, x2), 1, N_("Visible parts of the cave, upper left and lower right corner."), 0, 127},
442   {"Size", GD_TYPE_INT, GD_ALWAYS_SAVE|GD_DONT_SHOW_IN_EDITOR, N_("Visible, lower"), STRUCT_OFFSET(GdCave, y2), 1, N_("Visible parts of the cave, upper left and lower right corner."), 0, 127},
443   {"Charset", GD_TYPE_STRING, 0, N_("Character set"), STRUCT_OFFSET(GdCave, charset), 1, N_("Theme used for displaying the game. Not used by GDash.")},
444   {"Fontset", GD_TYPE_STRING, 0, N_("Font set"), STRUCT_OFFSET(GdCave, fontset), 1, N_("Font used during the game. Not used by GDash.")},
445
446   // notes - a tab on its own
447   {"Story", GD_TYPE_LONGSTRING, 0, N_("Story"), STRUCT_OFFSET(GdCave, story), 1, N_("Story for the cave. It will be shown when the cave is played.")},
448
449   // remark - also a tab on its own
450   {"Remark", GD_TYPE_LONGSTRING, 0, N_("Remark"), STRUCT_OFFSET(GdCave, remark), 1, N_("Remark (informative). Can contain supplementary information about the design of the cave. It is not shown during the game, only when the user requests the cave info dialog, so can also contain spoilers and hints.")},
451
452   {"", GD_TAB, 0, N_("Colors")},
453   {"Colors", GD_TYPE_COLOR, GD_ALWAYS_SAVE, N_("Border color"), STRUCT_OFFSET(GdCave, colorb), 1, N_("Border color for C64 graphics. Only for compatibility, not used by GDash.")},
454   {"Colors", GD_TYPE_COLOR, GD_ALWAYS_SAVE, N_("Background color"), STRUCT_OFFSET(GdCave, color0), 1, N_("Background color for C64 graphics")},
455   {"Colors", GD_TYPE_COLOR, GD_ALWAYS_SAVE, N_("Color 1 (dirt)"), STRUCT_OFFSET(GdCave, color1), 1, N_("Foreground color 1 for C64 graphics")},
456   {"Colors", GD_TYPE_COLOR, GD_ALWAYS_SAVE, N_("Color 2 (steel wall)"), STRUCT_OFFSET(GdCave, color2), 1, N_("Foreground color 2 for C64 graphics")},
457   {"Colors", GD_TYPE_COLOR, GD_ALWAYS_SAVE, N_("Color 3 (brick wall)"), STRUCT_OFFSET(GdCave, color3), 1, N_("Foreground color 3 for C64 graphics")},
458   {"Colors", GD_TYPE_COLOR, GD_ALWAYS_SAVE, N_("Amoeba color"), STRUCT_OFFSET(GdCave, color4), 1, N_("Amoeba color for C64 graphics")},
459   {"Colors", GD_TYPE_COLOR, GD_ALWAYS_SAVE, N_("Slime color"), STRUCT_OFFSET(GdCave, color5), 1, N_("Slime color for C64 graphics")},
460
461   // difficulty
462   {"", GD_TAB, 0, N_("Difficulty")},
463   {"", GD_LABEL, GD_SHOW_LEVEL_LABEL, N_("Diamonds")},
464   {"DiamondsRequired", GD_TYPE_INT, GD_ALWAYS_SAVE, N_("Diamonds needed"), CAVE_OFFSET(level_diamonds[0]), 5, N_("Here zero means automatically count diamonds before level start. If negative, the value is subtracted from that. This is useful for totally random caves."), -100, 999},
465   {"DiamondValue", GD_TYPE_INT, GD_ALWAYS_SAVE, N_("Score for diamonds"), CAVE_OFFSET(diamond_value), 1, N_("Number of points per diamond collected, before opening the exit."), 0, 100},
466   {"DiamondValue", GD_TYPE_INT, GD_ALWAYS_SAVE, N_("Score for extra diamonds"), CAVE_OFFSET(extra_diamond_value), 1, N_("Number of points per diamond collected, after opening the exit."), 0, 100},
467   {"", GD_LABEL, 0, N_("Time")},
468   {"CaveTime", GD_TYPE_INT, GD_ALWAYS_SAVE, N_("Time (s)"), CAVE_OFFSET(level_time[0]), 5, N_("Time available to solve cave, in seconds."), 1, 999},
469   {"CaveMaxTime", GD_TYPE_INT, 0, N_("Maximum time (s)"), CAVE_OFFSET(max_time), 1, N_("If you reach this time by collecting too many clocks, the timer will overflow."), 60, 999},
470   {"TimeValue", GD_TYPE_INT, 0, N_("Score for time"), CAVE_OFFSET(level_timevalue[0]), 5, N_("Points for each seconds remaining, when the player exits the level."), 0, 50},
471   {"CaveScheduling", GD_TYPE_SCHEDULING, GD_ALWAYS_SAVE, N_("Scheduling type"), CAVE_OFFSET(scheduling), 1, N_("This flag sets whether the game uses an emulation of the original timing (c64-style), or a more modern milliseconds-based timing. The original game used a delay (empty loop) based timing of caves; this is selected by setting this to BD1, BD2, Construction Kit or Crazy Dream 7. This is a compatibility setting only; milliseconds-based timing is recommended for every new cave.")},
472   {"PALTiming", GD_TYPE_BOOLEAN, 0, N_("PAL timing"), CAVE_OFFSET(pal_timing), 1, N_("On the PAL version of the C64 computer, the timer was actually slower than normal seconds. This flag is used to compensate for this. If enabled, one game second will last 1.2 real seconds. Most original games were authored for the PAL version. This is a compatibility setting for imported caves; it is not recommended to enable it for newly authored ones.")},
473   {"FrameTime", GD_TYPE_INT, GD_ALWAYS_SAVE, N_("   Speed (ms)"), CAVE_OFFSET(level_speed[0]), 5, N_("Number of milliseconds between game frames. Used when milliseconds-based timing is active, ie. C64 scheduling is off."), 50, 500},
474   {"HatchingDelay", GD_TYPE_INT, 0, N_("   Hatching delay (frames)"), CAVE_OFFSET(level_hatching_delay_frame[0]), 5, N_("This value sets how much the cave will move until the player enters the cave, and is expressed in frames. This is used for the milliseconds-based scheduling."), 1, 40},
475   {"CaveDelay", GD_TYPE_INT, GD_ALWAYS_SAVE, N_("   Delay (C64-style)"), CAVE_OFFSET(level_ckdelay[0]), 5, N_("The length of the delay loop between game frames. Used when milliseconds-based timing is inactive, ie. some kind of C64 or Atari scheduling is selected."), 0, 32},
476   {"HatchingTime", GD_TYPE_INT, 0, N_("   Hatching time (seconds)"), CAVE_OFFSET(level_hatching_delay_time[0]), 5, N_("This value sets how much the cave will move until the player enters the cave. This is used for the C64-like schedulings."), 1, 40},
477
478   // initial fill
479   {"RandSeed", GD_TYPE_INT, GD_DONT_SHOW_IN_EDITOR, NULL /* random seed value */, CAVE_OFFSET(level_rand[0]), 5, NULL, -1, 255},
480   {"InitialBorder", GD_TYPE_ELEMENT, GD_DONT_SHOW_IN_EDITOR, NULL /* Initial border */, CAVE_OFFSET(initial_border), 1, NULL},
481   {"InitialFill", GD_TYPE_ELEMENT, GD_DONT_SHOW_IN_EDITOR, NULL /* Initial fill */, CAVE_OFFSET(initial_fill), 1, NULL},
482   {"RandomFill", GD_TYPE_ELEMENT, GD_DONT_SHOW_IN_EDITOR, NULL /* Random fill 1 */, CAVE_OFFSET(random_fill[0]), 1, NULL},
483   {"RandomFill", GD_TYPE_INT, GD_DONT_SHOW_IN_EDITOR, NULL /* Probability 1 */, CAVE_OFFSET(random_fill_probability[0]), 1, NULL, 0, 255},
484   {"RandomFill", GD_TYPE_ELEMENT, GD_DONT_SHOW_IN_EDITOR, NULL /* Random fill 2 */, CAVE_OFFSET(random_fill[1]), 1, NULL},
485   {"RandomFill", GD_TYPE_INT, GD_DONT_SHOW_IN_EDITOR, NULL /* Probability 2 */, CAVE_OFFSET(random_fill_probability[1]), 1, NULL, 0, 255},
486   {"RandomFill", GD_TYPE_ELEMENT, GD_DONT_SHOW_IN_EDITOR, NULL /* Random fill 3 */, CAVE_OFFSET(random_fill[2]), 1, NULL},
487   {"RandomFill", GD_TYPE_INT, GD_DONT_SHOW_IN_EDITOR, NULL /* Probability 3 */, CAVE_OFFSET(random_fill_probability[2]), 1, NULL, 0, 255},
488   {"RandomFill", GD_TYPE_ELEMENT, GD_DONT_SHOW_IN_EDITOR, NULL /* Random fill 4 */, CAVE_OFFSET(random_fill[3]), 1, NULL},
489   {"RandomFill", GD_TYPE_INT, GD_DONT_SHOW_IN_EDITOR, NULL /* Probability 4 */, CAVE_OFFSET(random_fill_probability[3]), 1, NULL, 0, 255},
490
491   // PLAYER
492   {"", GD_TAB, 0, N_("Player")},
493
494   // player
495   {"", GD_LABEL, 0, N_("Player movements")},
496   {"DiagonalMovement", GD_TYPE_BOOLEAN, 0, N_("Diagonal movements"), CAVE_OFFSET(diagonal_movements), 1, N_("Controls if the player can move diagonally.")},
497   {"ActiveGuyIsFirst", GD_TYPE_BOOLEAN, 0, N_("Uppermost player active"), CAVE_OFFSET(active_is_first_found), 1, N_("In 1stB, cave is scrolled to the uppermost and leftmost player found, whereas in the original game to the last one. Chasing stones also follow the active player.")},
498   {"SnapEffect", GD_TYPE_ELEMENT, 0, N_("Snap element"), CAVE_OFFSET(snap_element), 1, N_("Snapping (pressing fire while moving) usually creates space, but it can create any other element.")},
499   {"PushingBoulderProb", GD_TYPE_PROBABILITY, 0, N_("Probability of pushing (%)"), CAVE_OFFSET(pushing_stone_prob), 1, N_("Chance of player managing to push a stone, every game cycle he tries. This is the normal probability.")},
500   {"", GD_LABEL, 0, N_("Sweet")},
501   {"PushingBoulderProb", GD_TYPE_PROBABILITY, 0, N_("Probability of pushing (%)"), CAVE_OFFSET(pushing_stone_prob_sweet), 1, N_("Chance of player managing to push a stone, every game cycle he tries. This is used after eating sweet.")},
502   {"PushingMegaStonesAfterSweet", GD_TYPE_BOOLEAN, 0, N_("Mega stones pushable"), CAVE_OFFSET(mega_stones_pushable_with_sweet), 1, N_("If it is true, mega stones can be pushed after eating sweet.")},
503
504   // rocket launcher
505   {"", GD_LABEL, 0, N_("Rocket launcher")},
506   {"RocketLauncher.infinite", GD_TYPE_BOOLEAN, 0, N_("Infinite rockets"), CAVE_OFFSET(infinite_rockets), 1, N_("If it is true, the player is able to launch an infinite number of rockets. Otherwise every rocket launcher contains only a single rocket.")},
507
508   // pneumatic hammer
509   {"", GD_LABEL, 0, N_("Pneumatic hammer")},
510   {"PneumaticHammer.frames", GD_TYPE_INT, 0, N_("Time for hammer (frames)"), CAVE_OFFSET(pneumatic_hammer_frame), 1, N_("This is the number of game frames, a pneumatic hammer is required to break a wall."), 1, 100},
511   {"PneumaticHammer.wallsreappear", GD_TYPE_BOOLEAN, 0, N_("Hammered walls reappear"), CAVE_OFFSET(hammered_walls_reappear), 1, N_("If this is set to true, walls broken with a pneumatic hammer will reappear later.")},
512   {"PneumaticHammer.wallsreappearframes", GD_TYPE_INT, 0, N_("   Timer for reappear (frames)"), CAVE_OFFSET(hammered_wall_reappear_frame), 1, N_("This sets the number of game frames, after hammered walls reappear, when the above setting is true."), 1, 200},
513
514   // clock
515   {"", GD_LABEL, GD_SHOW_LEVEL_LABEL, N_("Clock")},
516   {"BonusTime", GD_TYPE_INT, 0, N_("Time bonus (s)"), CAVE_OFFSET(level_bonus_time), 5, N_("Bonus time when a clock is collected."), -100, 100},
517
518   // voodoo
519   {"", GD_LABEL, 0, N_("Voodoo Doll")},
520   {"DummyProperties.diamondcollector", GD_TYPE_BOOLEAN, 0, N_("Can collect diamonds"), CAVE_OFFSET(voodoo_collects_diamonds), 1, N_("Controls if a voodoo doll can collect diamonds for the player.")},
521   {"DummyProperties.penalty", GD_TYPE_BOOLEAN, 0, N_("Dies if hit by a stone"), CAVE_OFFSET(voodoo_dies_by_stone), 1, N_("Controls if the voodoo doll dies if it is hit by a stone. Then the player gets a time penalty, and it is turned to a gravestone surrounded by steel wall.")},
522   {"DummyProperties.destructable", GD_TYPE_BOOLEAN, 0, N_("Disappear in explosion"), CAVE_OFFSET(voodoo_disappear_in_explosion), 1, N_("Controls if the voodoo can be destroyed by an explosion nearby. If not, it is converted to a gravestone, and you get a time penalty. If yes, the voodoo simply disappears.")},
523   {"DummyProperties.alwayskillsplayer", GD_TYPE_BOOLEAN, 0, N_("Any way hurt, player explodes"), CAVE_OFFSET(voodoo_any_hurt_kills_player), 1, N_("If this setting is enabled, the player will explode if the voodoo is hurt in any possible way, ie. touched by a firefly, hit by a stone or an explosion.")},
524   {"PenaltyTime", GD_TYPE_INT, 0, N_("Time penalty (s)"), CAVE_OFFSET(level_penalty_time), 5, N_("Penalty time when the voodoo is destroyed by a stone."), 0, 100},
525
526   // AMOEBA
527   {"", GD_TAB, 0, N_("Amoeba")},
528   {"AmoebaProperties.immediately", GD_TYPE_BOOLEAN, 0, N_("Timer started immediately"), CAVE_OFFSET(amoeba_timer_started_immediately), 1, N_("If this flag is enabled, the amoeba slow growth timer will start at the beginning of the cave, regardless of the amoeba being let free or not. This can make a big difference when playing the cave!")},
529   {"AmoebaProperties.waitforhatching", GD_TYPE_BOOLEAN, 0, N_("Timer waits for hatching"), CAVE_OFFSET(amoeba_timer_wait_for_hatching), 1, N_("This determines if the amoeba timer starts before the player appearing. Amoeba can always be activated before that; but if this is set to true, the timer will not start. This setting is for compatiblity for some old imported caves. As the player is usually born within a few seconds, changing this setting makes not much difference. It is not advised to change it, set the slow growth time to fit your needs instead.")},
530
531   // amoeba
532   {"", GD_LABEL, GD_SHOW_LEVEL_LABEL, N_("Amoeba")},
533   {"AmoebaThreshold", GD_TYPE_RATIO, 0, N_("Threshold (cells)"), CAVE_OFFSET(level_amoeba_threshold), 5, N_("If the amoeba grows more than this fraction of the cave, it is considered too big and it converts to the element specified below."), 0, 16383},
534   {"AmoebaTime", GD_TYPE_INT, 0, N_("Slow growth time (s)"), CAVE_OFFSET(level_amoeba_time), 5, N_("After this time, amoeba will grow very quickly."), 0, 999},
535   {"AmoebaGrowthProb", GD_TYPE_PROBABILITY, 0, N_("Growth ratio, slow (%)"), CAVE_OFFSET(amoeba_growth_prob), 1, N_("This sets the speed at which a slow amoeba grows.")},
536   {"AmoebaGrowthProb", GD_TYPE_PROBABILITY, 0, N_("Growth ratio, fast (%)"), CAVE_OFFSET(amoeba_fast_growth_prob), 1, N_("This sets the speed at which a fast amoeba grows.")},
537   {"AMOEBABOULDEReffect", GD_TYPE_EFFECT, 0, N_("If too big, converts to"), CAVE_OFFSET(amoeba_too_big_effect), 1, N_("Controls which element an overgrown amoeba converts to.")},
538   {"AMOEBADIAMONDeffect", GD_TYPE_EFFECT, 0, N_("If enclosed, converts to"), CAVE_OFFSET(amoeba_enclosed_effect), 1, N_("Controls which element an enclosed amoeba converts to.")},
539   {"", GD_LABEL, GD_SHOW_LEVEL_LABEL, N_("Amoeba 2")},
540   {"Amoeba2Threshold", GD_TYPE_RATIO, 0, N_("Threshold (cells)"), CAVE_OFFSET(level_amoeba_2_threshold), 5, N_("If the amoeba grows more than this fraction of the cave, it is considered too big and it converts to the element specified below."), 0, 16383},
541   {"Amoeba2Time", GD_TYPE_INT, 0, N_("Slow growth time (s)"), CAVE_OFFSET(level_amoeba_2_time), 5, N_("After this time, amoeba will grow very quickly."), 0, 999},
542   {"Amoeba2GrowthProb", GD_TYPE_PROBABILITY, 0, N_("Growth ratio, slow (%)"), CAVE_OFFSET(amoeba_2_growth_prob), 1, N_("This sets the speed at which a slow amoeba grows.")},
543   {"Amoeba2GrowthProb", GD_TYPE_PROBABILITY, 0, N_("Growth ratio, fast (%)"), CAVE_OFFSET(amoeba_2_fast_growth_prob), 1, N_("This sets the speed at which a fast amoeba grows.")},
544   {"Amoeba2Properties.explode", GD_TYPE_BOOLEAN, 0, N_("Explodes by amoeba"), CAVE_OFFSET(amoeba_2_explodes_by_amoeba), 1, N_("If this setting is enabled, an amoeba 2 will explode if it is touched by a normal amoeba.")},
545   {"AMOEBA2EXPLOSIONeffect", GD_TYPE_EFFECT, 0, N_("   Explosion ends in"), CAVE_OFFSET(amoeba_2_explosion_effect), 1, N_("An amoeba 2 explodes to this element, when touched by the original amoeba.")},
546   {"AMOEBA2BOULDEReffect", GD_TYPE_EFFECT, 0, N_("If too big, converts to"), CAVE_OFFSET(amoeba_2_too_big_effect), 1, N_("Controls which element an overgrown amoeba converts to.")},
547   {"AMOEBA2DIAMONDeffect", GD_TYPE_EFFECT, 0, N_("If enclosed, converts to"), CAVE_OFFSET(amoeba_2_enclosed_effect), 1, N_("Controls which element an enclosed amoeba converts to.")},
548   {"AMOEBA2LOOKSLIKEeffect", GD_TYPE_EFFECT, 0, N_("Looks like"), CAVE_OFFSET(amoeba_2_looks_like), 1, N_("Amoeba 2 can look like any other element. Hint: it can also look like a normal amoeba. Or it can look like slime, and then you have two different colored amoebas!")},
549
550   // magic wall
551   {"", GD_TAB, 0, N_("Magic Wall")},
552   {"", GD_LABEL, GD_SHOW_LEVEL_LABEL, N_("Timing")},
553   {"MagicWallTime", GD_TYPE_INT, 0, N_("Milling time (s)"), CAVE_OFFSET(level_magic_wall_time), 5, N_("Magic wall will stop after this time, and it cannot be activated again."), 0, 999},
554   {"MagicWallProperties.zeroisinfinite", GD_TYPE_BOOLEAN, 0, N_("Milling time 0 is infinite"), CAVE_OFFSET(magic_timer_zero_is_infinite), 1, N_("This determines if the magic wall timer 0 is interpreted as infinite.")},
555   {"MagicWallProperties.waitforhatching", GD_TYPE_BOOLEAN, 0, N_("Timer waits for hatching"), CAVE_OFFSET(magic_timer_wait_for_hatching), 1, N_("This determines if the magic wall timer starts before the player appearing. Magic can always be activated before that; but if this is set to true, the timer will not start.")},
556   {"MagicWallProperties.convertamoeba", GD_TYPE_BOOLEAN, 0, N_("Stops amoeba"), CAVE_OFFSET(magic_wall_stops_amoeba), 1, N_("When the magic wall is activated, it can convert amoeba into diamonds.")},
557   {"MagicWallProperties.breakscan", GD_TYPE_BOOLEAN, 0, N_("BD1 amoeba bug"), CAVE_OFFSET(magic_wall_breakscan), 1, N_("This setting emulates the BD1 bug, where a stone or a diamond falling into a magic wall sometimes caused the active amoeba to convert into a diamond. The rule is: if all amoeba cells above or left to the point where the stone or the diamond falls into the magic wall are enclosed, the amoeba is converted. The timing implications of the bug are not emulated.")},
558   {"", GD_LABEL, 0, N_("Conversions")},
559   {"MagicWallProperties", GD_TYPE_ELEMENT, 0, N_("Diamond to"), CAVE_OFFSET(magic_diamond_to), 1, N_("As a special effect, magic walls can convert diamonds to any other element.")},
560   {"MagicWallProperties", GD_TYPE_ELEMENT, 0, N_("Stone to"), CAVE_OFFSET(magic_stone_to), 1, N_("As a special effect, magic walls can convert stones to any other element.")},
561   {"MagicWallProperties.megastoneto", GD_TYPE_ELEMENT, 0, N_("Mega stone to"), CAVE_OFFSET(magic_mega_stone_to), 1, N_("If a mega stone falls into the magic wall, it will drop this element.")},
562   {"MagicWallProperties.nitropackto", GD_TYPE_ELEMENT, 0, N_("Nitro pack to"), CAVE_OFFSET(magic_nitro_pack_to), 1, N_("If a nitro pack falls into the magic wall, it will be turned to this element.")},
563   {"MagicWallProperties.nutto", GD_TYPE_ELEMENT, 0, N_("Nut to"), CAVE_OFFSET(magic_nut_to), 1, N_("As a special effect, magic walls can convert nuts to any other element.")},
564   {"MagicWallProperties.flyingstoneto", GD_TYPE_ELEMENT, 0, N_("Flying stone to"), CAVE_OFFSET(magic_flying_stone_to), 1, N_("If a flying stone climbs up into the magic wall, it will be turned to this element. Remember that flying stones enter the magic wall from its bottom, not from the top!")},
565   {"MagicWallProperties.flyingdiamondto", GD_TYPE_ELEMENT, 0, N_("Flying diamonds to"), CAVE_OFFSET(magic_flying_diamond_to), 1, N_("If a flying diamond enters the magic wall, it will be turned to this element. Remember that flying diamonds enter the magic wall from its bottom, not from the top!")},
566
567   // slime
568   {"", GD_TAB, 0, N_("Slime")},
569   {"", GD_LABEL, GD_SHOW_LEVEL_LABEL, N_("Permeability")},
570   {"", GD_TYPE_BOOLEAN, GD_DONT_SAVE, N_("Predictable"), CAVE_OFFSET(slime_predictable), 1, N_("Controls if the predictable random generator is used for slime. It is required for compatibility with some older caves.")},
571
572   // permeabilities are "always" saved; and according to the predictability, one of them is removed.
573   {"SlimePermeability", GD_TYPE_PROBABILITY, GD_ALWAYS_SAVE, N_("Permeability (unpredictable, %)"), CAVE_OFFSET(level_slime_permeability[0]), 5, N_("This controls the rate at which elements go through the slime. Higher values represent higher probability of passing. This one is for unpredictable slime.")},
574   {"SlimePermeabilityC64", GD_TYPE_INT, GD_ALWAYS_SAVE, N_("Permeability (predictable, bits)"), CAVE_OFFSET(level_slime_permeability_c64[0]), 5, N_("This controls the rate at which elements go through the slime. This one is for predictable slime, and the value is used for a bitwise AND function. The values used by the C64 engines are 0, 128, 192, 224, 240, 248, 252, 254 and 255."), 0, 255},
575   {"SlimePredictableC64.seed", GD_TYPE_INT, 0, N_("Random seed (predictable)"), CAVE_OFFSET(level_slime_seed_c64), 5, N_("The random number seed for predictable slime. Use -1 to leave on its default. Not recommended to change. Does not affect unpredictable slime."), -1, 65535},
576   {"", GD_LABEL, 0, N_("Passing elements")},
577   {"SlimeProperties", GD_TYPE_ELEMENT, 0, N_("Eats this..."), CAVE_OFFSET(slime_eats_1), 1, N_("Slime can let other elements than stone and diamond go through. It always lets a waiting or a chasing stone pass, though. Also, flying diamonds and stones, as well as bladders are always passed.")},
578   {"SlimeProperties", GD_TYPE_ELEMENT, 0, N_("  ... and converts to"), CAVE_OFFSET(slime_converts_1), 1, N_("Slime can let other elements than stone and diamond go through. It always lets a waiting or a chasing stone pass, though. Also, flying diamonds and stones, as well as bladders are always passed.")},
579   {"SlimeProperties", GD_TYPE_ELEMENT, 0, N_("Eats this..."), CAVE_OFFSET(slime_eats_2), 1, N_("Slime can let other elements than stone and diamond go through. It always lets a waiting or a chasing stone pass, though. Also, flying diamonds and stones, as well as bladders are always passed.")},
580   {"SlimeProperties", GD_TYPE_ELEMENT, 0, N_("  ... and converts to"), CAVE_OFFSET(slime_converts_2), 1, N_("Slime can let other elements than stone and diamond go through. It always lets a waiting or a chasing stone pass, though. Also, flying diamonds and stones, as well as bladders are always passed.")},
581   {"SlimeProperties", GD_TYPE_ELEMENT, 0, N_("Eats this..."), CAVE_OFFSET(slime_eats_3), 1, N_("Slime can let other elements than stone and diamond go through. It always lets a waiting or a chasing stone pass, though. Also, flying diamonds and stones, as well as bladders are always passed.")},
582   {"SlimeProperties", GD_TYPE_ELEMENT, 0, N_("  ... and converts to"), CAVE_OFFSET(slime_converts_3), 1, N_("Slime can let other elements than stone and diamond go through. It always lets a waiting or a chasing stone pass, though. Also, flying diamonds and stones, as well as bladders are always passed.")},
583
584   // ACTIVE 2
585   {"", GD_TAB, 0, N_("Other elements")},
586
587   // acid
588   {"", GD_LABEL, 0, N_("Acid")},
589   {"AcidProperties", GD_TYPE_ELEMENT, 0, N_("Eats this element"), CAVE_OFFSET(acid_eats_this), 1, N_("The element which acid eats. If it cannot find any, it simply disappears.")},
590   {"AcidProperties", GD_TYPE_PROBABILITY, 0, N_("Spread ratio (%)"), CAVE_OFFSET(acid_spread_ratio), 1, N_("The probability at which an acid will explode and eat neighbouring elements.")},
591   {"ACIDEffect", GD_TYPE_EFFECT, 0, N_("Leaves this behind"), CAVE_OFFSET(acid_turns_to), 1, N_("If acid converts to an explosion puff on spreading or any other element.")},
592
593   // biter
594   {"", GD_LABEL, 0, N_("Biter")},
595   {"BiterProperties", GD_TYPE_INT, 0, N_("Delay (frame)"), CAVE_OFFSET(biter_delay_frame), 1, N_("Number of frames biters wait between movements."), 0, 3},
596   {"BiterProperties", GD_TYPE_ELEMENT, 0, N_("Eats this"), CAVE_OFFSET(biter_eat), 1, N_("Biters eat this element. (They always eat dirt.)")},
597
598   // bladder
599   {"", GD_LABEL, 0, N_("Bladder")},
600   {"BladderProperties", GD_TYPE_ELEMENT, 0, N_("Converts to clock by touching"), CAVE_OFFSET(bladder_converts_by), 1, NULL},
601
602   // expanding wall
603   {"", GD_LABEL, 0, N_("Expanding wall")},
604   {"ExpandingWallDirection.changed", GD_TYPE_BOOLEAN, 0, N_("Direction changed"), CAVE_OFFSET(expanding_wall_changed), 1, N_("If this option is enabled, the direction of growing for the horizontal and vertical expanding wall is switched. As you can use both horizontal and vertical expanding walls in a cave, it is not recommended to change this setting, as it might be confusing. You should rather select the type with the correct direction from the element box when drawing the cave.")},
605
606   // replicator
607   {"", GD_LABEL, 0, N_("Replicator")},
608   {"ReplicatorActive", GD_TYPE_BOOLEAN, 0, N_("Active at start"), CAVE_OFFSET(replicators_active), 1, N_("Whether the replicators are turned on or off at the cave start.")},
609   {"ReplicatorDelayFrame", GD_TYPE_INT, 0, N_("Delay (frame)"), CAVE_OFFSET(replicator_delay_frame), 1, N_("Number of frames to wait between replicating elements."), 0, 100},
610
611   // conveyor belt
612   {"", GD_LABEL, 0, N_("Conveyor belt")},
613   {"ConveyorBeltActive", GD_TYPE_BOOLEAN, 0, N_("Active at start"), CAVE_OFFSET(conveyor_belts_active), 1, N_("Whether the conveyor belts are moving when the cave starts.")},
614   {"ConveyorBeltDirection.changed", GD_TYPE_BOOLEAN, 0, N_("Direction changed"), CAVE_OFFSET(conveyor_belts_direction_changed), 1, N_("If the conveyor belts' movement is changed, ie. they are running in the opposite direction. As you can freely use left and right going versions of the conveyor belt in a cave, it is not recommended to change this setting, rather you should select the correct one from the element box when drawing.")},
615
616   // water
617   {"", GD_LABEL, 0, N_("Water")},
618   {"WaterProperties.doesnotflowdown", GD_TYPE_BOOLEAN, 0, N_("Does not flow downwards"), CAVE_OFFSET(water_does_not_flow_down), 1, N_("In CrDr, the water element had the odd property that it did not flow downwards, only in other directions. This flag emulates this behaviour.")},
619
620   // nut
621   {"", GD_LABEL, 0, N_("Nut")},
622   {"Nut.whencrushed", GD_TYPE_ELEMENT, 0, N_("Turns to when crushed"), CAVE_OFFSET(nut_turns_to_when_crushed), 1, N_("Normally, a nut contains a diamond. If you crush it with a stone, the diamond will appear after the usual nut explosion sequence. This setting can be used to change the element the nut contains.")},
623
624   // EFFECTS 1
625   {"", GD_TAB, 0, N_("Effects")},
626
627   // cave effects
628   {"", GD_LABEL, 0, N_("Stone and diamond effects")},
629   {"BOULDERfallingeffect", GD_TYPE_EFFECT, 0, N_("Falling stones convert to"), CAVE_OFFSET(stone_falling_effect), 1, N_("When a stone begins falling, it converts to this element.")},
630   {"BOULDERbouncingeffect", GD_TYPE_EFFECT, 0, N_("Bouncing stones convert to"), CAVE_OFFSET(stone_bouncing_effect), 1, N_("When a stone stops falling and rolling, it converts to this element.")},
631   {"DIAMONDfallingeffect", GD_TYPE_EFFECT, 0, N_("Falling diamonds convert to"), CAVE_OFFSET(diamond_falling_effect), 1, N_("When a diamond begins falling, it converts to this element.")},
632   {"DIAMONDbouncingeffect", GD_TYPE_EFFECT, 0, N_("Bouncing diamonds convert to"), CAVE_OFFSET(diamond_bouncing_effect), 1, N_("When a diamond stops falling and rolling, it converts to this element.")},
633
634   {"", GD_LABEL, 0, N_("Creature explosion effects")},
635   {"FireflyExplodeTo", GD_TYPE_ELEMENT, 0, N_("Fireflies explode to"), CAVE_OFFSET(firefly_explode_to), 1, N_("When a firefly explodes, it will create this element. Change this setting wisely. The firefly is a traditional element which is expected to explode to empty space.")},
636   {"AltFireflyExplodeTo", GD_TYPE_ELEMENT, 0, N_("Alt. fireflies explode to"), CAVE_OFFSET(alt_firefly_explode_to), 1, N_("When an alternative firefly explodes, it will create this element. Use this setting wisely. Do not create a firefly which explodes to stones, for example: use the stonefly instead.")},
637   {"ButterflyExplodeTo", GD_TYPE_ELEMENT, 0, N_("Butterflies explode to"), CAVE_OFFSET(butterfly_explode_to), 1, N_("When a butterfly explodes, it will create this element. Use this setting wisely. Butterflies should explode to diamonds. If you need a creature which explodes to space, use the firefly instead.")},
638   {"AltButterflyExplodeTo", GD_TYPE_ELEMENT, 0, N_("Alt. butterflies explode to"), CAVE_OFFSET(alt_butterfly_explode_to), 1, N_("When an alternative butterfly explodes, it will create this element. Use this setting wisely.")},
639   {"StoneflyExplodeTo", GD_TYPE_ELEMENT, 0, N_("Stoneflies explode to"), CAVE_OFFSET(stonefly_explode_to), 1, N_("When a stonefly explodes, it will create this element.")},
640   {"DragonflyExplodeTo", GD_TYPE_ELEMENT, 0, N_("Dragonflies explode to"), CAVE_OFFSET(dragonfly_explode_to), 1, N_("When a dragonfly explodes, it will create this element.")},
641
642   {"", GD_LABEL, 0, N_("Explosion effects")},
643   {"EXPLOSIONEffect", GD_TYPE_EFFECT, 0, N_("Explosions end in"), CAVE_OFFSET(explosion_effect), 1, N_("This element appears in places where an explosion finishes.")},
644   {"DIAMONDBIRTHEffect", GD_TYPE_EFFECT, 0, N_("Diamond births end in"), CAVE_OFFSET(diamond_birth_effect), 1, N_("When a diamond birth animation reaches its end, it will leave this element there. This can be used to change the element butterflies explode to.")},
645   {"BOMBEXPLOSIONeffect", GD_TYPE_EFFECT, 0, N_("Bombs explosions end in"), CAVE_OFFSET(bomb_explosion_effect), 1, N_("Use this setting to select the element the exploding bomb creates.")},
646   {"NITROEXPLOSIONeffect", GD_TYPE_EFFECT, 0, N_("Nitro explosions end in"), CAVE_OFFSET(nitro_explosion_effect), 1, N_("The nitro explosions can create some element other than space.")},
647
648   // EFFECTS 2
649   {"", GD_TAB, 0, N_("More effects")},
650
651   // visual effects
652   {"", GD_LABEL, 0, N_("Visual effects")},
653   {"EXPANDINGWALLLOOKSLIKEeffect", GD_TYPE_EFFECT, 0, N_("Expanding wall looks like"), CAVE_OFFSET(expanding_wall_looks_like), 1, N_("This is a compatibility setting for old caves. If you need an expanding wall which looks like steel, you should rather choose the expanding steel wall from the element box.")},
654   {"DIRTLOOKSLIKEeffect", GD_TYPE_EFFECT, 0, N_("Dirt looks like"), CAVE_OFFSET(dirt_looks_like), 1, N_("Compatibility setting. Use it wisely! Anything other than Dirt 2 (which can be used to emulate the Dirt Mod) is not recommended.")},
655
656   // creature effects
657   {"", GD_LABEL, 0, N_("Creature movement")},
658   {"EnemyDirectionProperties.startbackwards", GD_TYPE_BOOLEAN, 0, N_("Start backwards"), CAVE_OFFSET(creatures_backwards), 1, N_("Whether the direction creatures travel will already be switched at the cave start.")},
659   {"EnemyDirectionProperties.time", GD_TYPE_INT, 0, N_("Automatically turn (s)"), CAVE_OFFSET(creatures_direction_auto_change_time), 1, N_("If this is greater than zero, creatures will automatically change direction in every x seconds."), 0, 999},
660   {"EnemyDirectionProperties.changeathatching", GD_TYPE_BOOLEAN, 0, N_("Auto turn on hatching"), CAVE_OFFSET(creatures_direction_auto_change_on_start), 1, N_("If this is set to true, creatures also turn at the start signal. If false, the first change in direction occurs only later.")},
661
662   // gravity
663   {"", GD_LABEL, 0, N_("Gravitation change")},
664   {"Gravitation", GD_TYPE_DIRECTION, 0, N_("Direction"), CAVE_OFFSET(gravity), 1, N_("The direction where stones and diamonds fall.")},
665   {"GravitationSwitchActive", GD_TYPE_BOOLEAN, 0, N_("Switch active at start"), CAVE_OFFSET(gravity_switch_active), 1, N_("If set to true, the gravitation switch will be already activated, when the cave is started, as if a pot has already been collected.")},
666   {"SkeletonsForPot", GD_TYPE_INT, 0, N_("Skeletons needed for pot"), CAVE_OFFSET(skeletons_needed_for_pot), 1, N_("The number of skeletons to be collected to be able to use a pot."), 0, 50},
667   {"GravitationChangeDelay", GD_TYPE_INT, 0, N_("Gravitation switch delay"), CAVE_OFFSET(gravity_change_time), 1, N_("The gravitation changes after a while using the gravitation switch. This option sets the number of seconds to wait."), 1, 60},
668
669   // SOUND
670   {"", GD_TAB, 0, N_("Sound")},
671   {"", GD_LABEL, 0, N_("Sound for elements")},
672   {"Diamond.sound", GD_TYPE_BOOLEAN, 0, N_("Diamond"), CAVE_OFFSET(diamond_sound), 1, N_("If true, falling diamonds will have sound.")},
673   {"Stone.sound", GD_TYPE_BOOLEAN, 0, N_("Stone"), CAVE_OFFSET(stone_sound), 1, N_("If true, falling and pushed stones will have sound.")},
674   {"Nut.sound", GD_TYPE_BOOLEAN, 0, N_("Nut"), CAVE_OFFSET(nut_sound), 1, N_("If true, falling and cracked nuts have sound.")},
675   {"NitroPack.sound", GD_TYPE_BOOLEAN, 0, N_("Nitro pack"), CAVE_OFFSET(nitro_sound), 1, N_("If true, falling and pushed nitro packs will have sound.")},
676   {"ExpandingWall.sound", GD_TYPE_BOOLEAN, 0, N_("Expanding wall"), CAVE_OFFSET(expanding_wall_sound), 1, N_("If true, expanding wall will have sound.")},
677   {"FallingWall.sound", GD_TYPE_BOOLEAN, 0, N_("Falling wall"), CAVE_OFFSET(falling_wall_sound), 1, N_("If true, falling wall will have sound.")},
678   {"AmoebaProperties.sound", GD_TYPE_BOOLEAN, 0, N_("Amoeba"), CAVE_OFFSET(amoeba_sound), 1, N_("Controls if the living amoeba has sound or not.")},
679   {"MagicWallProperties.sound", GD_TYPE_BOOLEAN, 0, N_("Magic wall"), CAVE_OFFSET(magic_wall_sound), 1, N_("If true, the activated magic wall will have sound.")},
680   {"SlimeProperties.sound", GD_TYPE_BOOLEAN, 0, N_("Slime"), CAVE_OFFSET(slime_sound), 1, N_("If true, the elements passing slime will have sound.")},
681   {"LavaProperties.sound", GD_TYPE_BOOLEAN, 0, N_("Lava"), CAVE_OFFSET(lava_sound), 1, N_("If true, the elements sinking in lava will have sound.")},
682   {"ReplicatorProperties.sound", GD_TYPE_BOOLEAN, 0, N_("Replicator"), CAVE_OFFSET(replicator_sound), 1, N_("If true, the new element appearing under the replicator will make sound.")},
683   {"AcidProperties.sound", GD_TYPE_BOOLEAN, 0, N_("Acid"), CAVE_OFFSET(acid_spread_sound), 1, N_("If true, the acid spreading will have sound.")},
684   {"BiterProperties.sound", GD_TYPE_BOOLEAN, 0, N_("Biter"), CAVE_OFFSET(biter_sound), 1, N_("Biters eating something or pushing a stone will have sound.")},
685   {"BladderProperties.sound", GD_TYPE_BOOLEAN, 0, N_("Bladder"), CAVE_OFFSET(bladder_sound), 1, N_("Bladders moving and being pushed can have sound.")},
686   {"WaterProperties.sound", GD_TYPE_BOOLEAN, 0, N_("Water"), CAVE_OFFSET(water_sound), 1, N_("If true, the cave containing water will have sound.")},
687   {"PneumaticHammer.sound", GD_TYPE_BOOLEAN, 0, N_("Pneumatic hammer"), CAVE_OFFSET(pneumatic_hammer_sound), 1, N_("If true, using the pneumatic hammer will have sound.")},
688   {"BladderSpender.sound", GD_TYPE_BOOLEAN, 0, N_("Bladder spender"), CAVE_OFFSET(bladder_spender_sound), 1, N_("If true, the bladder spender will make sound, when the bladder appears.")},
689   {"BladderConvert.sound", GD_TYPE_BOOLEAN, 0, N_("Bladder convert"), CAVE_OFFSET(bladder_convert_sound), 1, N_("If true, the bladder converting to a clock will make sound.")},
690   {"", GD_LABEL, 0, N_("Event sounds")},
691   {"GravityChange.sound", GD_TYPE_BOOLEAN, 0, N_("Gravity change"), CAVE_OFFSET(gravity_change_sound), 1, N_("If true, the gravity changing will make sound.")},
692   {"EnemyDirectionProperties.sound", GD_TYPE_BOOLEAN, 0, N_("Creature direction change"), CAVE_OFFSET(creature_direction_auto_change_sound), 1, N_("If this is set to true, creatures changing direction will be signaled by a sound.")},
693
694   // COMPATIBILITY
695   {"", GD_TAB, 0, N_("Compatibility")},
696   {"", GD_LABEL, 0, N_("Skeleton")},
697   {"SkeletonsWorthDiamonds", GD_TYPE_INT, GD_COMPATIBILITY_SETTING, N_("Skeletons worth diamonds"), CAVE_OFFSET(skeletons_worth_diamonds), 1, N_("The number of diamonds each skeleton is worth. Normally skeletons are used for letting the player use the pot! They are not intended to be used as a second kind of diamond."), 0, 10},
698   {"", GD_LABEL, 0, N_("Borders")},
699   {"BorderProperties.lineshift", GD_TYPE_BOOLEAN, 0, N_("Line shifting border"), CAVE_OFFSET(lineshift), 1, N_("If this is set to true, the player exiting on either side will appear one row lower or upper on the other side.")},
700   {"BorderProperties.objectwraparound", GD_TYPE_BOOLEAN, 0, N_("Objects wrap around"), CAVE_OFFSET(wraparound_objects), 1, N_("If true, objects will wrap around the cave borders as well, ie. if you drag a line to the left, part of it will appear on the right hand side of the cave. The drawing in this case is also affected by the line shifting border property. If that one is enabled, too, crossing the left hand side or right hand side boundary will decrement or increment the row, and crossing the top or the bottom boundary will have no effect at all.")},
701   {"BorderProperties.scan", GD_TYPE_BOOLEAN, 0, N_("Scan first and last row"), CAVE_OFFSET(border_scan_first_and_last), 1, N_("Elements move on first and last row, too. Usually those rows are the border. The games created by the original editor were not allowed to put anything but steel wall there, so it was not apparent that the borders were not processed by the engine. Some old caves need this for compatibility; it is not recommended to change this setting for newly designed caves, though.")},
702   {"", GD_LABEL, 0, N_("Other")},
703   {"ShortExplosions", GD_TYPE_BOOLEAN, 0, N_("Short explosions"), CAVE_OFFSET(short_explosions), 1, N_("In 1stB and newer engines, explosions were longer, they took five cave frames to complete, as opposed to four frames in the original.")},
704   {"GravityAffectsAll", GD_TYPE_BOOLEAN, 0, N_("Gravity change affects everything"), CAVE_OFFSET(gravity_affects_all), 1, N_("If this is enabled, changing the gravity will also affect bladders (moving and pushing), bladder spenders, falling walls and waiting stones. Otherwise, those elements behave as gravity was always pointing downwards. This is a compatibility setting which is not recommended to change. It is intended for imported caves.")},
705
706   {NULL}  // end of array
707 };
708
709 // entries.
710 // type given for each element
711 const GdStructDescriptor gd_replay_properties[] =
712 {
713   // default data
714   {"", GD_TAB, 0, N_("Replay")},
715   {"Level", GD_TYPE_INT, 0, NULL, STRUCT_OFFSET(GdReplay, level), 1, NULL},
716   {"RandomSeed", GD_TYPE_INT, 0, NULL, STRUCT_OFFSET(GdReplay, seed), 1, NULL},
717   // {"Saved", GD_TYPE_BOOLEAN, 0, NULL, STRUCT_OFFSET(GdReplay, saved), 1, NULL},
718   // no need to state in bdcff, as saved replays are saved ones :)
719   {"Player", GD_TYPE_STRING, 0, NULL, STRUCT_OFFSET(GdReplay, player_name), 1, NULL},
720   {"Date", GD_TYPE_STRING, 0, NULL, STRUCT_OFFSET(GdReplay, date), 1, NULL},
721   {"Comment", GD_TYPE_LONGSTRING, 0, NULL, STRUCT_OFFSET(GdReplay, comment), 1, NULL},
722   {"RecordedWith", GD_TYPE_STRING, 0, NULL, STRUCT_OFFSET(GdReplay, recorded_with), 1, NULL},
723   {"Score", GD_TYPE_INT, 0, NULL, STRUCT_OFFSET(GdReplay, score), 1, NULL},
724   {"Duration", GD_TYPE_INT, 0, NULL, STRUCT_OFFSET(GdReplay, duration), 1, NULL},
725   {"Success", GD_TYPE_BOOLEAN, 0, NULL, STRUCT_OFFSET(GdReplay, success), 1, NULL},
726   {"Checksum", GD_TYPE_INT, 0, NULL, STRUCT_OFFSET(GdReplay, checksum), 1, NULL},
727
728   {NULL}  // end of array
729 };
730
731 GdPropertyDefault gd_cave_defaults_gdash[] =
732 {
733   // default data
734   {CAVE_OFFSET(selectable), TRUE},
735   {CAVE_OFFSET(intermission), FALSE},
736   {CAVE_OFFSET(intermission_instantlife), FALSE},
737   {CAVE_OFFSET(intermission_rewardlife), TRUE},
738   {CAVE_OFFSET(w), 40},
739   {CAVE_OFFSET(h), 22},
740   {CAVE_OFFSET(x1), 0},
741   {CAVE_OFFSET(y1), 0},
742   {CAVE_OFFSET(x2), 39},
743   {CAVE_OFFSET(y2), 21},
744   {CAVE_OFFSET(colorb), 0},
745   {CAVE_OFFSET(color0), 0},
746   {CAVE_OFFSET(color1), 8},
747   {CAVE_OFFSET(color2), 11},
748   {CAVE_OFFSET(color3), 1},
749   {CAVE_OFFSET(color4), 5},
750   {CAVE_OFFSET(color5), 6},
751
752   // difficulty
753   {CAVE_OFFSET(level_diamonds[0]), 10},
754   {CAVE_OFFSET(diamond_value), 0},
755   {CAVE_OFFSET(extra_diamond_value), 0},
756   {CAVE_OFFSET(level_time[0]), 999},
757   {CAVE_OFFSET(max_time), 999},
758   {CAVE_OFFSET(pal_timing), FALSE},
759   {CAVE_OFFSET(level_timevalue[0]), 1},
760   {CAVE_OFFSET(scheduling), GD_SCHEDULING_MILLISECONDS},
761   {CAVE_OFFSET(level_ckdelay[0]), 0},
762   {CAVE_OFFSET(level_hatching_delay_time[0]), 2},
763   {CAVE_OFFSET(level_speed[0]), 200},
764   {CAVE_OFFSET(level_hatching_delay_frame[0]), 21},
765   {CAVE_OFFSET(level_rand[0]), 0},
766
767   // initial fill
768   {CAVE_OFFSET(initial_border), O_STEEL},
769   {CAVE_OFFSET(initial_fill), O_DIRT},
770   {CAVE_OFFSET(random_fill[0]), O_DIRT},
771   {CAVE_OFFSET(random_fill_probability[0]), 0},
772   {CAVE_OFFSET(random_fill[1]), O_DIRT},
773   {CAVE_OFFSET(random_fill_probability[1]), 0},
774   {CAVE_OFFSET(random_fill[2]), O_DIRT},
775   {CAVE_OFFSET(random_fill_probability[2]), 0},
776   {CAVE_OFFSET(random_fill[3]), O_DIRT},
777   {CAVE_OFFSET(random_fill_probability[3]), 0},
778
779   // PLAYER
780   {CAVE_OFFSET(diagonal_movements), FALSE},
781   {CAVE_OFFSET(active_is_first_found), TRUE},
782   {CAVE_OFFSET(snap_element), O_SPACE},
783   {CAVE_OFFSET(pushing_stone_prob), 250000},
784   {CAVE_OFFSET(pushing_stone_prob_sweet), 1000000},
785   {CAVE_OFFSET(level_bonus_time), 30},
786   {CAVE_OFFSET(pneumatic_hammer_frame), 5},
787   {CAVE_OFFSET(hammered_walls_reappear), FALSE},
788   {CAVE_OFFSET(hammered_wall_reappear_frame), 100},
789   {CAVE_OFFSET(voodoo_collects_diamonds), FALSE},
790   {CAVE_OFFSET(voodoo_disappear_in_explosion), TRUE},
791   {CAVE_OFFSET(voodoo_dies_by_stone), FALSE},
792   {CAVE_OFFSET(voodoo_any_hurt_kills_player), FALSE},
793   {CAVE_OFFSET(level_penalty_time), 30},
794
795   // magic wall
796   {CAVE_OFFSET(level_magic_wall_time), 999},
797   {CAVE_OFFSET(magic_diamond_to), O_STONE_F},
798   {CAVE_OFFSET(magic_stone_to), O_DIAMOND_F},
799   {CAVE_OFFSET(magic_mega_stone_to), O_NITRO_PACK_F},
800   {CAVE_OFFSET(magic_nitro_pack_to), O_MEGA_STONE_F},
801   {CAVE_OFFSET(magic_nut_to), O_NUT_F},
802   {CAVE_OFFSET(magic_flying_stone_to), O_FLYING_DIAMOND_F},
803   {CAVE_OFFSET(magic_flying_diamond_to), O_FLYING_STONE_F},
804   {CAVE_OFFSET(magic_wall_stops_amoeba), TRUE},
805   {CAVE_OFFSET(magic_timer_zero_is_infinite), TRUE},
806   {CAVE_OFFSET(magic_timer_wait_for_hatching), FALSE},
807
808   // amoeba
809   {CAVE_OFFSET(amoeba_timer_started_immediately), TRUE},
810   {CAVE_OFFSET(amoeba_timer_wait_for_hatching), FALSE},
811
812   {CAVE_OFFSET(level_amoeba_threshold), 200},
813   {CAVE_OFFSET(amoeba_growth_prob), 31250},
814   {CAVE_OFFSET(amoeba_fast_growth_prob), 250000},
815   {CAVE_OFFSET(level_amoeba_time), 999},
816   {CAVE_OFFSET(amoeba_timer_started_immediately), TRUE},
817   {CAVE_OFFSET(amoeba_timer_wait_for_hatching), FALSE},
818   {CAVE_OFFSET(amoeba_too_big_effect), O_STONE},
819   {CAVE_OFFSET(amoeba_enclosed_effect), O_DIAMOND},
820
821   // amoeba
822   {CAVE_OFFSET(level_amoeba_2_threshold), 200},
823   {CAVE_OFFSET(amoeba_2_growth_prob), 31250},
824   {CAVE_OFFSET(amoeba_2_fast_growth_prob), 250000},
825   {CAVE_OFFSET(level_amoeba_2_time), 999},
826   {CAVE_OFFSET(amoeba_2_too_big_effect), O_STONE},
827   {CAVE_OFFSET(amoeba_2_enclosed_effect), O_DIAMOND},
828   {CAVE_OFFSET(amoeba_2_explodes_by_amoeba), TRUE},
829   {CAVE_OFFSET(amoeba_2_looks_like), O_AMOEBA_2},
830   {CAVE_OFFSET(amoeba_2_explosion_effect), O_SPACE},
831
832   // water
833   {CAVE_OFFSET(water_does_not_flow_down), FALSE},
834
835   // nut
836   {CAVE_OFFSET(nut_turns_to_when_crushed), O_NUT_EXPL_1},
837
838   // replicator
839   {CAVE_OFFSET(replicator_delay_frame), 4},
840   {CAVE_OFFSET(replicators_active), TRUE},
841
842   // conveyor belt
843   {CAVE_OFFSET(conveyor_belts_active), TRUE},
844   {CAVE_OFFSET(conveyor_belts_direction_changed), FALSE},
845
846   // slime
847   {CAVE_OFFSET(slime_predictable), TRUE},
848   {CAVE_OFFSET(level_slime_seed_c64), -1},
849   {CAVE_OFFSET(level_slime_permeability_c64), 0},
850   {CAVE_OFFSET(level_slime_permeability), 1000000},
851   {CAVE_OFFSET(slime_eats_1), O_DIAMOND},
852   {CAVE_OFFSET(slime_converts_1), O_DIAMOND_F},
853   {CAVE_OFFSET(slime_eats_2), O_STONE},
854   {CAVE_OFFSET(slime_converts_2), O_STONE_F},
855   {CAVE_OFFSET(slime_eats_3), O_NUT},
856   {CAVE_OFFSET(slime_converts_3), O_NUT_F},
857
858   // acid
859   {CAVE_OFFSET(acid_eats_this), O_DIRT},
860   {CAVE_OFFSET(acid_spread_ratio), 31250},
861   {CAVE_OFFSET(acid_turns_to), O_EXPLODE_3},
862
863   // biter
864   {CAVE_OFFSET(biter_delay_frame), 0},
865   {CAVE_OFFSET(biter_eat), O_DIAMOND},
866
867   // bladder
868   {CAVE_OFFSET(bladder_converts_by), O_VOODOO},
869
870   // SOUND
871   {CAVE_OFFSET(amoeba_sound), TRUE},
872   {CAVE_OFFSET(magic_wall_sound), TRUE},
873   {CAVE_OFFSET(slime_sound), TRUE},
874   {CAVE_OFFSET(lava_sound), TRUE},
875   {CAVE_OFFSET(replicator_sound), TRUE},
876   {CAVE_OFFSET(acid_spread_sound), TRUE},
877   {CAVE_OFFSET(biter_sound), TRUE},
878   {CAVE_OFFSET(bladder_sound), TRUE},
879   {CAVE_OFFSET(water_sound), TRUE},
880   {CAVE_OFFSET(stone_sound), TRUE},
881   {CAVE_OFFSET(nut_sound), TRUE},
882   {CAVE_OFFSET(diamond_sound), TRUE},
883   {CAVE_OFFSET(falling_wall_sound), TRUE},
884   {CAVE_OFFSET(expanding_wall_sound), TRUE},
885   {CAVE_OFFSET(nitro_sound), TRUE},
886   {CAVE_OFFSET(pneumatic_hammer_sound), TRUE},
887   {CAVE_OFFSET(bladder_spender_sound), TRUE},
888   {CAVE_OFFSET(bladder_convert_sound), TRUE},
889   {CAVE_OFFSET(gravity_change_sound), TRUE},
890   {CAVE_OFFSET(creature_direction_auto_change_sound), TRUE},
891
892   // creature effects
893   {CAVE_OFFSET(creatures_backwards), FALSE},
894   {CAVE_OFFSET(creatures_direction_auto_change_time), 0},
895   {CAVE_OFFSET(creatures_direction_auto_change_on_start), FALSE},
896
897   // cave effects
898   {CAVE_OFFSET(explosion_effect), O_SPACE},
899   {CAVE_OFFSET(diamond_birth_effect), O_DIAMOND},
900   {CAVE_OFFSET(bomb_explosion_effect), O_BRICK},
901   {CAVE_OFFSET(nitro_explosion_effect), O_SPACE},
902   {CAVE_OFFSET(firefly_explode_to), O_EXPLODE_1},
903   {CAVE_OFFSET(alt_firefly_explode_to), O_EXPLODE_1},
904   {CAVE_OFFSET(butterfly_explode_to), O_PRE_DIA_1},
905   {CAVE_OFFSET(alt_butterfly_explode_to), O_PRE_DIA_1},
906   {CAVE_OFFSET(stonefly_explode_to), O_PRE_STONE_1},
907   {CAVE_OFFSET(dragonfly_explode_to), O_EXPLODE_1},
908
909   {CAVE_OFFSET(stone_falling_effect), O_STONE_F},
910   {CAVE_OFFSET(stone_bouncing_effect), O_STONE},
911   {CAVE_OFFSET(diamond_falling_effect), O_DIAMOND_F},
912   {CAVE_OFFSET(diamond_bouncing_effect), O_DIAMOND},
913
914   // visual effects
915   {CAVE_OFFSET(expanding_wall_looks_like), O_BRICK},
916   {CAVE_OFFSET(dirt_looks_like), O_DIRT},
917
918   // gravity
919   {CAVE_OFFSET(gravity), GD_MV_DOWN},
920   {CAVE_OFFSET(gravity_switch_active), FALSE},
921   {CAVE_OFFSET(skeletons_needed_for_pot), 5},
922   {CAVE_OFFSET(gravity_change_time), 10},
923
924   // COMPATIBILITY
925   {CAVE_OFFSET(border_scan_first_and_last), TRUE},
926   {CAVE_OFFSET(lineshift), FALSE},
927   {CAVE_OFFSET(wraparound_objects), FALSE},
928   {CAVE_OFFSET(short_explosions), TRUE},
929   {CAVE_OFFSET(skeletons_worth_diamonds), 0},
930   {CAVE_OFFSET(gravity_affects_all), TRUE},
931
932   {-1},
933 };
934
935 // return new element, which appears after elem is hammered.
936 // returns o_none, if elem is invalid for hammering.
937 GdElement gd_element_get_hammered(GdElement elem)
938 {
939   switch (elem)
940   {
941     // what is under the pneumatic hammer?
942     case O_WALLED_KEY_1:
943       return O_KEY_1;
944
945     case O_WALLED_KEY_2:
946       return O_KEY_2;
947
948     case O_WALLED_KEY_3:
949       return O_KEY_3;
950
951     case O_WALLED_DIAMOND:
952       return O_DIAMOND;
953
954     case O_BRICK:
955     case O_BRICK_SLOPED_UP_RIGHT:
956     case O_BRICK_SLOPED_UP_LEFT:
957     case O_BRICK_SLOPED_DOWN_RIGHT:
958     case O_BRICK_SLOPED_DOWN_LEFT:
959     case O_BRICK_NON_SLOPED:
960     case O_MAGIC_WALL:
961     case O_STEEL_EXPLODABLE:
962     case O_EXPANDING_WALL:
963     case O_V_EXPANDING_WALL:
964     case O_H_EXPANDING_WALL:
965     case O_FALLING_WALL:
966     case O_FALLING_WALL_F:
967       return O_SPACE;
968
969     default:
970       return O_NONE;
971   }
972 }
973
974 void gd_cave_db_init(void)
975 {
976   int i;
977   HashTable *pointers;
978   boolean lowercase_names = TRUE;
979
980   // TRANSLATORS: some languages (for example, german) do not have lowercase nouns.
981   // When gdash generates the list of lowercase element names, this has to be
982   // taken into account. Therefore we have a string, which must be changed
983   // by the translator to select the behavior.
984   // For example, the name of the element is "Brick wall", as in a button, it has to be
985   // written with an uppercase initial. But if "Line of brick wall", the B is changed to b.
986   // However, this is not allowed in some languages, for example, German.
987   // So one writes "Ziegelmauer", and "Linie aus Ziegelmauer", the Z is not changed to z.
988   // Set the translated string to "lowercase-element-names-yes", if your language
989   // allows writing nouns with lowercase initials. Set it to "lowercase-element-names-no",
990   // if not: for example, german. Do not translate the string, but set the behavior!
991
992   if (strEqual(_("lowercase-element-names-yes"), "lowercase-element-names-no"))
993     lowercase_names = FALSE;
994
995   // check element database for faults.
996   for (i = 0; gd_elements[i].element != -1; i++)
997   {
998     if (gd_elements[i].element != i)
999       Error("element: i:0x%x != 0x%x", i, gd_elements[i].element);
1000
1001     // if it has a name, create a lowercase name (of the translated one).
1002     // will be used by the editor
1003     if (gd_elements[i].name)
1004     {
1005       if (lowercase_names)
1006         // the function allocates a new string, but it is needed as long as the app is running
1007         gd_elements[i].lowercase_name = getStringToLower(gettext(gd_elements[i].name));
1008       else
1009         // only translate, no lowercase.
1010         gd_elements[i].lowercase_name = gettext(gd_elements[i].name);
1011     }
1012
1013     // we do not like generated pixbufs for games. only those that are in the png.
1014     if (ABS(gd_elements[i].image_game) > GD_NUM_OF_CELLS_X * GD_NUM_OF_CELLS_Y)
1015       Error("game pixbuf for element %x (%s) bigger than png size", i, gd_elements[i].name);
1016
1017     if (gd_elements[i].image < 0)
1018       Error("editor pixbuf for element %x (%s) should not be animated", i, gd_elements[i].name);
1019
1020     if (gd_elements[i].properties & P_CAN_BE_HAMMERED && gd_element_get_hammered((GdElement) i) == O_NONE)
1021       Error("element %x (%s) can be hammered, but get_hammered_element does not define another one", i, gd_elements[i].name);
1022   }
1023
1024   /*
1025     NOT REALLY NEEDED ANYMORE, as the enum takes care of it.
1026     maybe to show that there is an unnecessary one.
1027   */
1028   /*
1029     g_print("Free pixbuf indexes: ");
1030     for (i = GD_NUM_OF_CELLS_X*GD_NUM_OF_CELLS_Y; i<GD_NUM_OF_CELLS; i++)
1031     {
1032     if (!cell_used[i])
1033     g_print("%d ", i);
1034     }
1035     g_print("\n");
1036   */
1037
1038   // uncomment this, to show free element->character characters.
1039   /*
1040     gd_create_char_to_element_table();
1041     g_print("Free characters: ");
1042     for (i = 32; i < 128; i++)
1043     if (gd_char_to_element[i] == O_UNKNOWN)
1044     g_print("%c", i);
1045     g_print("\n");
1046   */
1047
1048   // check the cave property database for faults.
1049   pointers = create_hashtable(get_hash_from_integer, hash_key_integers_are_equal, NULL, NULL);
1050
1051   for (i = 0; gd_cave_properties[i].identifier != NULL; i++)
1052   {
1053     GdType type = gd_cave_properties[i].type;
1054
1055     switch (type)
1056     {
1057       case GD_LABEL:
1058       case GD_TAB:
1059         // some lines are used for the user interface. these should not have an identifier.
1060         if (strcmp(gd_cave_properties[i].identifier, "") != 0)
1061         {
1062           Error ("ui lines in cave properties should not have identifiers: %s",
1063                  gd_cave_properties[i].identifier);
1064         }
1065         break;
1066
1067       case GD_TYPE_STRING:
1068         // check if any of the properties are designated as string arrays.
1069         // they are not supported in file read/write and operations,
1070         // also they do not even make any sense!
1071         if (gd_cave_properties[i].count != 1)
1072         {
1073           Error ("string arrays have no sense in cave properties: %s",
1074                  gd_cave_properties[i].identifier);
1075         }
1076         break;
1077
1078       case GD_TYPE_LONGSTRING:
1079         if (gd_cave_properties[i].count != 1)
1080         {
1081           Error ("longstring arrays have no sense cave properties: %s",
1082                  gd_cave_properties[i].identifier);
1083         }
1084         break;
1085
1086       case GD_TYPE_EFFECT:
1087         // the same applies for effects.
1088         if (gd_cave_properties[i].count != 1)
1089         {
1090           Error ("effect arrays not supported in cave properties: %s",
1091                  gd_cave_properties[i].identifier);
1092         }
1093         break;
1094
1095       case GD_TYPE_COLOR:
1096         // the same applies for effects.
1097         if (gd_cave_properties[i].count != 1)
1098         {
1099           Error ("color arrays not supported in cave properties: %s",
1100                  gd_cave_properties[i].identifier);
1101         }
1102         break;
1103
1104       default:
1105         break;
1106     }
1107
1108     if (type != GD_LABEL && (gd_cave_properties[i].flags & GD_SHOW_LEVEL_LABEL))
1109     {
1110       Error ("show_level_label only for labels: line %d", i);
1111     }
1112
1113     if (type != GD_LABEL && type != GD_TAB)
1114     {
1115       const char *another_prop;
1116
1117       // other types
1118       // check if its pointer is not the same as another one's
1119       // +1 is added so it is never zero
1120       if (!(gd_cave_properties[i].flags & GD_DONT_SAVE) && strcmp(gd_cave_properties[i].identifier, "") == 0)
1121       {
1122         Error ("property should have a bdcff identifier: line %d, name %s",
1123                i, gd_cave_properties[i].name);
1124       }
1125
1126       another_prop = hashtable_search(pointers, INT_TO_PTR(gd_cave_properties[i].offset + 1));
1127
1128       if (another_prop != NULL)
1129       {
1130         Error("property %s has the same pointer as property %s",
1131               gd_cave_properties[i].identifier, another_prop);
1132       }
1133       else
1134       {
1135         // value is the identifier, so we can report the OLD one if the check fails
1136         hashtable_insert(pointers, INT_TO_PTR(gd_cave_properties[i].offset + 1),
1137                          gd_cave_properties[i].identifier);
1138       }
1139     }
1140   }
1141
1142   hashtable_destroy(pointers);
1143 }