fixed tree node navigation bug (when stepping up empty sub-trees)
[rocksndiamonds.git] / src / game_em / convert.c
1 /* 2007-04-04 08:33:37
2  *
3  * convert intermediate cave format to internal cave structure for
4  * use in logic(). initializes entire internal structure.
5  */
6
7 #include "main_em.h"
8
9
10 static const short map[CAVE_TILE_MAX] =
11 {
12   [Cblank]              = Xblank,
13   [Cgrass]              = Xgrass,
14   [Cdirt]               = Xdirt,
15   [Cplant]              = Xplant,
16   [Cwall_1]             = Xwall_1,
17   [Cwall_2]             = Xwall_2,
18   [Cwall_3]             = Xwall_3,
19   [Cwall_4]             = Xwall_4,
20   [Croundwall_1]        = Xroundwall_1,
21   [Croundwall_2]        = Xroundwall_2,
22   [Croundwall_3]        = Xroundwall_3,
23   [Croundwall_4]        = Xroundwall_4,
24   [Csteel_1]            = Xsteel_1,
25   [Csteel_2]            = Xsteel_2,
26   [Csteel_3]            = Xsteel_3,
27   [Csteel_4]            = Xsteel_4,
28   [Candroid]            = Xandroid,
29   [Ceater_n]            = Xeater_n,
30   [Ceater_e]            = Xeater_e,
31   [Ceater_s]            = Xeater_s,
32   [Ceater_w]            = Xeater_w,
33   [Calien]              = Xalien,
34   [Cbug_1_n]            = Xbug_1_n,
35   [Cbug_1_e]            = Xbug_1_e,
36   [Cbug_1_s]            = Xbug_1_s,
37   [Cbug_1_w]            = Xbug_1_w,
38   [Cbug_2_n]            = Xbug_2_n,
39   [Cbug_2_e]            = Xbug_2_e,
40   [Cbug_2_s]            = Xbug_2_s,
41   [Cbug_2_w]            = Xbug_2_w,
42   [Ctank_1_n]           = Xtank_1_n,
43   [Ctank_1_e]           = Xtank_1_e,
44   [Ctank_1_s]           = Xtank_1_s,
45   [Ctank_1_w]           = Xtank_1_w,
46   [Ctank_2_n]           = Xtank_2_n,
47   [Ctank_2_e]           = Xtank_2_e,
48   [Ctank_2_s]           = Xtank_2_s,
49   [Ctank_2_w]           = Xtank_2_w,
50   [Cemerald]            = Xemerald,
51   [Cdiamond]            = Xdiamond,
52   [Cstone]              = Xstone,
53   [Cbomb]               = Xbomb,
54   [Cnut]                = Xnut,
55   [Cspring]             = Xspring,
56   [Cspring_e]           = Xspring_e,
57   [Cspring_w]           = Xspring_w,
58   [Cpush_emerald_e]     = Xpush_emerald_e,
59   [Cpush_emerald_w]     = Xpush_emerald_w,
60   [Cpush_diamond_e]     = Xpush_diamond_e,
61   [Cpush_diamond_w]     = Xpush_diamond_w,
62   [Cpush_stone_e]       = Xpush_stone_e,
63   [Cpush_stone_w]       = Xpush_stone_w,
64   [Cpush_bomb_e]        = Xpush_bomb_e,
65   [Cpush_bomb_w]        = Xpush_bomb_w,
66   [Cpush_nut_e]         = Xpush_nut_e,
67   [Cpush_nut_w]         = Xpush_nut_w,
68   [Cpush_spring_e]      = Xpush_spring_e,
69   [Cpush_spring_w]      = Xpush_spring_w,
70   [Cdynamite]           = Xdynamite,
71   [Cdynamite_1]         = Xdynamite_1,
72   [Cdynamite_2]         = Xdynamite_2,
73   [Cdynamite_3]         = Xdynamite_3,
74   [Cdynamite_4]         = Xdynamite_4,
75   [Ckey_1]              = Xkey_1,
76   [Ckey_2]              = Xkey_2,
77   [Ckey_3]              = Xkey_3,
78   [Ckey_4]              = Xkey_4,
79   [Ckey_5]              = Xkey_5,
80   [Ckey_6]              = Xkey_6,
81   [Ckey_7]              = Xkey_7,
82   [Ckey_8]              = Xkey_8,
83   [Cdoor_1]             = Xdoor_1,
84   [Cdoor_2]             = Xdoor_2,
85   [Cdoor_3]             = Xdoor_3,
86   [Cdoor_4]             = Xdoor_4,
87   [Cdoor_5]             = Xdoor_5,
88   [Cdoor_6]             = Xdoor_6,
89   [Cdoor_7]             = Xdoor_7,
90   [Cdoor_8]             = Xdoor_8,
91   [Cfake_door_1]        = Xfake_door_1,
92   [Cfake_door_2]        = Xfake_door_2,
93   [Cfake_door_3]        = Xfake_door_3,
94   [Cfake_door_4]        = Xfake_door_4,
95   [Cfake_door_5]        = Xfake_door_5,
96   [Cfake_door_6]        = Xfake_door_6,
97   [Cfake_door_7]        = Xfake_door_7,
98   [Cfake_door_8]        = Xfake_door_8,
99   [Cballoon]            = Xballoon,
100   [Cball_1]             = Xball_1,
101   [Cball_2]             = Xball_2,
102   [Camoeba_1]           = Xamoeba_1,
103   [Camoeba_2]           = Xamoeba_2,
104   [Camoeba_3]           = Xamoeba_3,
105   [Camoeba_4]           = Xamoeba_4,
106   [Camoeba_5]           = Xamoeba_5,
107   [Camoeba_6]           = Xamoeba_6,
108   [Camoeba_7]           = Xamoeba_7,
109   [Camoeba_8]           = Xamoeba_8,
110   [Cdrip]               = Xdrip,
111   [Cwonderwall]         = Xwonderwall,
112   [Cwheel]              = Xwheel,
113   [Cswitch]             = Xswitch,
114   [Cbumper]             = Xbumper,
115   [Cacid_nw]            = Xacid_nw,
116   [Cacid_ne]            = Xacid_ne,
117   [Cacid_sw]            = Xacid_sw,
118   [Cacid_s]             = Xacid_s,
119   [Cacid_se]            = Xacid_se,
120   [Cacid_1]             = Xacid_1,
121   [Cacid_2]             = Xacid_2,
122   [Cacid_3]             = Xacid_3,
123   [Cacid_4]             = Xacid_4,
124   [Cacid_5]             = Xacid_5,
125   [Cacid_6]             = Xacid_6,
126   [Cacid_7]             = Xacid_7,
127   [Cacid_8]             = Xacid_8,
128   [Cfake_acid_1]        = Xfake_acid_1,
129   [Cfake_acid_2]        = Xfake_acid_2,
130   [Cfake_acid_3]        = Xfake_acid_3,
131   [Cfake_acid_4]        = Xfake_acid_4,
132   [Cfake_acid_5]        = Xfake_acid_5,
133   [Cfake_acid_6]        = Xfake_acid_6,
134   [Cfake_acid_7]        = Xfake_acid_7,
135   [Cfake_acid_8]        = Xfake_acid_8,
136   [Cfake_blank]         = Xfake_blank,
137   [Cfake_grass]         = Xfake_grass,
138   [Cfake_amoeba]        = Xfake_amoeba,
139   [Clenses]             = Xlenses,
140   [Cmagnify]            = Xmagnify,
141   [Csand]               = Xsand,
142   [Csand_stone]         = Xsand_stone,
143   [Cslide_ns]           = Xslide_ns,
144   [Cslide_ew]           = Xslide_ew,
145   [Cwind_n]             = Xwind_n,
146   [Cwind_e]             = Xwind_e,
147   [Cwind_s]             = Xwind_s,
148   [Cwind_w]             = Xwind_w,
149   [Cwind_any]           = Xwind_any,
150   [Cwind_stop]          = Xwind_stop,
151   [Cexit]               = Xexit,
152   [Cexit_1]             = Xexit_1,
153   [Cexit_2]             = Xexit_2,
154   [Cexit_3]             = Xexit_3,
155   [Cpause]              = Xpause,
156   [Cdecor_1]            = Xdecor_1,
157   [Cdecor_2]            = Xdecor_2,
158   [Cdecor_3]            = Xdecor_3,
159   [Cdecor_4]            = Xdecor_4,
160   [Cdecor_5]            = Xdecor_5,
161   [Cdecor_6]            = Xdecor_6,
162   [Cdecor_7]            = Xdecor_7,
163   [Cdecor_8]            = Xdecor_8,
164   [Cdecor_9]            = Xdecor_9,
165   [Cdecor_10]           = Xdecor_10,
166   [Cdecor_11]           = Xdecor_11,
167   [Cdecor_12]           = Xdecor_12,
168   [Calpha_0]            = Xalpha_0,
169   [Calpha_1]            = Xalpha_1,
170   [Calpha_2]            = Xalpha_2,
171   [Calpha_3]            = Xalpha_3,
172   [Calpha_4]            = Xalpha_4,
173   [Calpha_5]            = Xalpha_5,
174   [Calpha_6]            = Xalpha_6,
175   [Calpha_7]            = Xalpha_7,
176   [Calpha_8]            = Xalpha_8,
177   [Calpha_9]            = Xalpha_9,
178   [Calpha_excla]        = Xalpha_excla,
179   [Calpha_apost]        = Xalpha_apost,
180   [Calpha_comma]        = Xalpha_comma,
181   [Calpha_minus]        = Xalpha_minus,
182   [Calpha_perio]        = Xalpha_perio,
183   [Calpha_colon]        = Xalpha_colon,
184   [Calpha_quest]        = Xalpha_quest,
185   [Calpha_a]            = Xalpha_a,
186   [Calpha_b]            = Xalpha_b,
187   [Calpha_c]            = Xalpha_c,
188   [Calpha_d]            = Xalpha_d,
189   [Calpha_e]            = Xalpha_e,
190   [Calpha_f]            = Xalpha_f,
191   [Calpha_g]            = Xalpha_g,
192   [Calpha_h]            = Xalpha_h,
193   [Calpha_i]            = Xalpha_i,
194   [Calpha_j]            = Xalpha_j,
195   [Calpha_k]            = Xalpha_k,
196   [Calpha_l]            = Xalpha_l,
197   [Calpha_m]            = Xalpha_m,
198   [Calpha_n]            = Xalpha_n,
199   [Calpha_o]            = Xalpha_o,
200   [Calpha_p]            = Xalpha_p,
201   [Calpha_q]            = Xalpha_q,
202   [Calpha_r]            = Xalpha_r,
203   [Calpha_s]            = Xalpha_s,
204   [Calpha_t]            = Xalpha_t,
205   [Calpha_u]            = Xalpha_u,
206   [Calpha_v]            = Xalpha_v,
207   [Calpha_w]            = Xalpha_w,
208   [Calpha_x]            = Xalpha_x,
209   [Calpha_y]            = Xalpha_y,
210   [Calpha_z]            = Xalpha_z,
211   [Calpha_arrow_e]      = Xalpha_arrow_e,
212   [Calpha_arrow_w]      = Xalpha_arrow_w,
213   [Calpha_copyr]        = Xalpha_copyr
214 };
215
216 int map_em_element_C_to_X(int element_em_cave)
217 {
218   if (element_em_cave < 0 || element_em_cave >= CAVE_TILE_MAX)
219   {
220     Warn("invalid EM cave element %d", element_em_cave);
221
222     return Xblank;
223   }
224
225   return map[element_em_cave];
226 }
227
228 int map_em_element_X_to_C(int element_em_game)
229 {
230   static unsigned short map_reverse[GAME_TILE_MAX];
231   static boolean map_reverse_initialized = FALSE;
232
233   if (!map_reverse_initialized)
234   {
235     int i;
236
237     // return "Cblank" for all undefined elements in mapping array
238     for (i = 0; i < GAME_TILE_MAX; i++)
239       map_reverse[i] = Cblank;
240
241     for (i = 0; i < CAVE_TILE_MAX; i++)
242       map_reverse[map[i]] = i;
243
244     map_reverse_initialized = TRUE;
245   }
246
247   if (element_em_game < 0 || element_em_game >= GAME_TILE_MAX)
248   {
249     Warn("invalid EM game element %d", element_em_game);
250
251     return Cblank;
252   }
253
254   int element_em_cave = map_reverse[element_em_game];
255
256   if (element_em_cave == Cblank && element_em_game != Xblank)
257     Warn("unknown EM game element %d", element_em_game);
258
259   return element_em_cave;
260 }
261
262 void prepare_em_level(void)
263 {
264   int i, j, x, y;
265   int players_left;
266   boolean team_mode;
267
268   /* reset all runtime variables to their initial values */
269
270   game_init_cave_buffers();
271
272   lev.width  = cav.width;
273   lev.height = cav.height;
274
275   lev.left = CAVE_BUFFER_XOFFSET;
276   lev.top  = CAVE_BUFFER_YOFFSET;
277   lev.right = lev.left + lev.width;
278   lev.bottom = lev.top + lev.height;
279
280   lev.infinite = game_em.use_wrap_around;
281   lev.infinite_true = cav.infinite_true;
282
283   if (lev.infinite)
284   {
285     /* add linked cave buffer columns for wrap-around movement */
286     for (x = 0; x < lev.left; x++)
287     {
288       int offset = (lev.infinite_true ? 0 : 1);
289
290       lev.cavecol[x] = &lev.cavecol[lev.width + x][-offset];
291       lev.nextcol[x] = &lev.nextcol[lev.width + x][-offset];
292       lev.drawcol[x] = &lev.drawcol[lev.width + x][-offset];
293       lev.boomcol[x] = &lev.boomcol[lev.width + x][-offset];
294
295       lev.cavecol[lev.right + x] = &lev.cavecol[lev.left + x][offset];
296       lev.nextcol[lev.right + x] = &lev.nextcol[lev.left + x][offset];
297       lev.drawcol[lev.right + x] = &lev.drawcol[lev.left + x][offset];
298       lev.boomcol[lev.right + x] = &lev.boomcol[lev.left + x][offset];
299     }
300   }
301
302   for (x = 0; x < lev.width; x++)
303     for (y = 0; y < lev.height; y++)
304       lev.cave[lev.left + x][lev.top + y] = map[cav.cave[x][y]];
305
306   for (x = lev.left; x < lev.right; x++)
307     for (y = lev.top; y < lev.bottom; y++)
308       lev.next[x][y] = lev.draw[x][y] = lev.cave[x][y];
309
310   lev.time = cav.time_seconds;
311   lev.gems_needed = cav.gems_needed;
312   lev.score = 0;
313
314   lev.testmode = cav.testmode;
315
316   if (lev.testmode)
317   {
318     lev.time = 0;
319     lev.gems_needed = 0;
320   }
321
322   lev.eater_score       = cav.eater_score;
323   lev.alien_score       = cav.alien_score;
324   lev.bug_score         = cav.bug_score;
325   lev.tank_score        = cav.tank_score;
326   lev.emerald_score     = cav.emerald_score;
327   lev.diamond_score     = cav.diamond_score;
328   lev.nut_score         = cav.nut_score;
329   lev.slurp_score       = cav.slurp_score;
330   lev.dynamite_score    = cav.dynamite_score;
331   lev.key_score         = cav.key_score;
332   lev.lenses_score      = cav.lenses_score;
333   lev.magnify_score     = cav.magnify_score;
334   lev.exit_score        = cav.exit_score;
335
336   lev.amoeba_time = cav.amoeba_time;
337
338   lev.android_move_time = cav.android_move_time;
339   lev.android_move_cnt  = cav.android_move_time;
340
341   lev.android_clone_time = cav.android_clone_time;
342   lev.android_clone_cnt  = cav.android_clone_time;
343
344   lev.ball_time   = cav.ball_time;
345   lev.ball_cnt    = cav.ball_time;
346   lev.ball_active = cav.ball_active;
347   lev.ball_random = cav.ball_random;
348   lev.ball_pos    = 0;
349
350   lev.eater_pos = 0;
351   lev.shine_cnt = 0;
352
353   lev.lenses_time = cav.lenses_time;
354   lev.lenses_cnt  = cav.lenses_active ? cav.lenses_time : 0;
355
356   lev.magnify_time = cav.magnify_time;
357   lev.magnify_cnt  = cav.magnify_active ? cav.magnify_time : 0;
358
359   lev.wheel_time = cav.wheel_time;
360   lev.wheel_cnt  = cav.wheel_active ? cav.wheel_time : 0;
361   lev.wheel_x    = cav.wheel_x + lev.left;
362   lev.wheel_y    = cav.wheel_y + lev.top;
363
364   lev.wind_time      = cav.wind_time;
365   lev.wind_cnt       = cav.wind_time;
366   lev.wind_direction = cav.wind_direction;
367
368   lev.wonderwall_time   = cav.wonderwall_time;
369   lev.wonderwall_active = cav.wonderwall_active;
370
371   lev.killed_out_of_time = FALSE;
372
373   lev.num_eater_arrays = cav.num_eater_arrays;
374   lev.num_ball_arrays  = cav.num_ball_arrays;
375
376   for (i = 0; i < 8; i++)
377     for (j = 0; j < 9; j++)
378       lev.eater_array[i][j] = map[cav.eater_array[i][j]];
379
380   for (i = 0; i < 8; i++)
381     for (j = 0; j < 8; j++)
382       lev.ball_array[i][j] = map[cav.ball_array[i][j]];
383
384   for (i = 0; i < GAME_TILE_MAX; i++)
385     lev.android_array[i] = map[cav.android_array[i]];
386
387   lev.home_initial = 0;
388
389   /* check for players in this level */
390   for (i = 0; i < MAX_PLAYERS; i++)
391   {
392     ply[i].exists = FALSE;
393     ply[i].alive = FALSE;
394
395     if (cav.player_x[i] != -1 &&
396         cav.player_y[i] != -1)
397     {
398       ply[i].exists = TRUE;
399
400       lev.home_initial++;
401     }
402   }
403
404   team_mode = getTeamMode_EM();
405
406   if (!team_mode)
407     lev.home_initial = 1;
408
409   lev.home = lev.home_initial;
410   players_left = lev.home_initial;
411
412   /* assign active players */
413   for (i = 0; i < MAX_PLAYERS; i++)
414   {
415     if (ply[i].exists && isActivePlayer_EM(i))
416     {
417       if (players_left)
418       {
419         ply[i].alive = TRUE;
420         players_left--;
421       }
422     }
423   }
424
425   /* remove inactive players */
426   for (i = 0; i < MAX_PLAYERS; i++)
427   {
428     if (ply[i].exists && !ply[i].alive)
429     {
430       int x = cav.player_x[i];
431       int y = cav.player_y[i];
432
433       lev.cave[lev.left + x][lev.top + y] = Xblank;
434       lev.next[lev.left + x][lev.top + y] = Xblank;
435       lev.draw[lev.left + x][lev.top + y] = Xblank;
436     }
437   }
438
439   for (i = 0; i < MAX_PLAYERS; i++)
440   {
441     ply[i].num = i;
442     ply[i].anim = PLY_still;
443
444     ply[i].x = cav.player_x[i] + lev.left;
445     ply[i].y = cav.player_y[i] + lev.top;
446     ply[i].prev_x = ply[i].x;
447     ply[i].prev_y = ply[i].y;
448
449     ply[i].dynamite     = 0;
450     ply[i].dynamite_cnt = 0;
451     ply[i].keys         = 0;
452
453     ply[i].last_move_dir = MV_NONE;
454
455     ply[i].joy_n        = FALSE;
456     ply[i].joy_e        = FALSE;
457     ply[i].joy_s        = FALSE;
458     ply[i].joy_w        = FALSE;
459     ply[i].joy_snap     = FALSE;
460     ply[i].joy_drop     = FALSE;
461     ply[i].joy_stick    = FALSE;
462   }
463
464   // the following engine variables are initialized to version-specific values
465   // in function InitGameEngine() (src/game.c):
466   //
467   // - game_em.use_single_button (default: TRUE)
468   // - game_em.use_snap_key_bug (default: FALSE)
469   // - game_em.use_random_bug (default: FALSE)
470   // - game_em.use_old_explosions (default: FALSE)
471   // - game_em.use_old_android (default: FALSE)
472   // - game_em.use_old_push_elements (default: FALSE)
473   // - game_em.use_old_push_into_acid (default: FALSE)
474   // - game_em.use_wrap_around (default: TRUE)
475
476   game_em.level_solved = FALSE;
477   game_em.game_over = FALSE;
478
479   game_em.any_player_moving = FALSE;
480   game_em.any_player_snapping = FALSE;
481
482   game_em.last_moving_player = 0;       /* default: first player */
483
484   for (i = 0; i < MAX_PLAYERS; i++)
485     game_em.last_player_direction[i] = MV_NONE;
486
487   lev.exit_x = lev.exit_y = -1; /* kludge for playing player exit sound */
488 }