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