added checkbox to player settings in editor if first player solves level
[rocksndiamonds.git] / src / game_sp / Zonk.c
1 // ----------------------------------------------------------------------------
2 // Zonk.c
3 // ----------------------------------------------------------------------------
4
5 #include "Zonk.h"
6
7
8 void subCleanUpForZonksAbove(int si);
9
10
11 // static char *VB_Name = "modZonk";
12 // --- Option Explicit
13
14 // ==========================================================================
15 //                              SUBROUTINE
16 // Animate Zonks (falling)
17 // ==========================================================================
18
19 void subAnimateZonks(int si)
20 {
21   int tFld;
22
23   // PseudoRegisters:
24   // int ax, bx, cx, dx, di, X, Y;
25   int ax, bx, dx, X, Y;
26   // int ah, bh, ch, dh, al, bl, cl, dl;
27   int al, bl;
28
29   tFld = PlayField16[si];
30   if ((tFld & 0xFF) != fiZonk)
31     return;
32
33   if (tFld == fiZonk)
34   {
35     if (FreezeZonks == 2) // Do Zonks fall? (debug)
36       return;
37
38     ax = PlayField16[si + FieldWidth]; // select case playfield16(si+60)
39     if (ax == 0)
40       goto loc_g_0D64;
41
42     if (ax == fiZonk)
43       goto loc_g_0D35;
44
45     if (ax == fiInfotron)
46       goto loc_g_0D35;
47
48     if (ax == fiRAM)
49       goto loc_g_0D35;
50
51     return;
52
53 loc_g_0D35: //        Case fiZonk, fiInfotron, fiRAM
54     ax = PlayField16[si + FieldWidth - 1];
55     if (ax == 0 || ax == 0x8888 || ax == 0xAAAA)
56       goto loc_g_0D6B;
57
58 loc_g_0D4C:
59     ax = PlayField16[si + FieldWidth + 1];
60     if (ax == 0 || ax == 0x8888 || ax == 0xAAAA)
61       goto loc_g_0D81;
62
63     return;
64
65 loc_g_0D64: //       Case fiSpace
66     MovHighByte(&PlayField16[si], 0x40);
67     goto loc_g_0DA5;
68
69 loc_g_0D6B: // roll left?
70     if (PlayField16[si - 1] == 0)
71       goto loc_g_0D74;
72
73     goto loc_g_0D4C;
74
75 loc_g_0D74:
76     MovHighByte(&PlayField16[si], 0x50);
77     PlayField16[si - 1] = 0x8888;
78     goto loc_g_0DA5;
79
80 loc_g_0D81: // roll right?
81     if (PlayField16[si + 1] == 0)
82       goto loc_g_0D98;
83
84     if (PlayField16[si + 1] != 0x9999) // wow right is different from left!
85       return;
86
87     if (LowByte(PlayField16[si - FieldWidth + 1]) != 1)
88       return;
89
90 loc_g_0D98:
91     MovHighByte(&PlayField16[si], 0x60);
92     PlayField16[si + 1] = 0x8888;
93   } // tFld = fiZonk
94
95 loc_g_0DA5:
96   // from now on the zonk is definitely moving,
97   // maybe the sequence is in an advanced frame
98   // or just beeing initialized due to the code above
99   bl = HighByte(PlayField16[si]);
100   bx = 0;
101   MovLowByte(&bx, bl);
102   al = bl & 0xF0;
103   if (al == 0x10) // zonk comes falling from above
104     goto loc_g_0DE8;
105
106   if (al == 0x20) // zonk comes rolling from right to left
107     goto loc_g_0F83;
108
109   if (al == 0x30) // zonk comes rolling from left to right
110     goto loc_g_0FE8;
111
112   if (FreezeZonks == 2)
113     return;
114
115   if (al == 0x40) // zonk falls straight down
116     goto loc_g_104D;
117
118   if (al == 0x50) // zonk rolls left
119     goto loc_g_107B;
120
121   if (al == 0x60) // zonk rolls right
122     goto loc_g_10E9;
123
124   if (al == 0x70) // intermediate state
125     goto loc_g_1157;
126
127   return;
128
129 loc_g_0DE8: // zonk comes falling from above
130   //      To Do: draw zonk falling from above
131   //      according to position in (bl And &H07)
132   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
133   X = GetStretchX(si);
134   Y = GetStretchY(si - FieldWidth);
135   dx = bl & 0x7;
136   DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
137   DDSpriteBuffer_BltImg(X, Y + TwoPixels * (dx + 1), aniZonk, dx);
138   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
139
140   bl = HighByte(PlayField16[si]) + 1;
141   if (bl == 0x16)
142   {
143     MovHighByte(&PlayField16[si], bl);
144     subCleanUpForZonksAbove(si - FieldWidth);
145     return;
146   } // loc_g_0E2B:
147
148   if (bl < 0x18)
149   {
150     MovHighByte(&PlayField16[si], bl);
151     return;
152   } // loc_g_0E35:
153
154   MovHighByte(&PlayField16[si], 0); // zonk arrived at the field
155   if ((FreezeZonks & 0xFF) == 2)
156     return;
157
158   // loc_g_0E42:     // now check if the zonk may go on falling somehow
159   ax = PlayField16[si + FieldWidth];
160   if (ax == 0) // below is empty!-> go on falling 'loc_g_0E4C:
161     goto loc_g_0EDD;
162
163   if (ax == 0x9999) // below is only temporarily used ' loc_g_0E57:
164     goto loc_g_0EDD;
165
166   if ((ax & 0xFF) == fiMurphy) // Murphy dies 'loc_g_0E61:
167     goto loc_g_0F14;
168
169   if ((ax & 0xFF) == fiSnikSnak) // SnikSnak dies 'loc_g_0E6B:
170     goto loc_g_0F6E;
171
172   if (ax == 0x2BB) // loc_g_0E76:
173     goto loc_g_0F36;
174
175   if (ax == 0x4BB) // loc_g_0E81:
176     goto loc_g_0F52;
177
178   if ((ax & 0xFF) == fiElectron) // Electron cracked! 'loc_g_0E8B:
179     goto loc_g_0F6E;
180
181   if (ax == fiOrangeDisk) // OrangeDisk explodes 'loc_g_0E95:
182     goto loc_g_0F75;
183
184   // play the zonk sound, 'cause zonk hits something "hard"
185   subSoundFX(si, fiZonk, actImpact);
186
187   if (! (ax == fiZonk || ax == fiInfotron || ax == fiRAM))
188     return;
189
190   // loc_g_0EAE: ' Zonk rolls somewhere
191   ax = PlayField16[si + FieldWidth - 1];
192   if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) // may roll left
193     goto loc_g_0EEA;
194
195   ax = PlayField16[si + FieldWidth + 1];
196   if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) // may roll right
197     goto loc_g_0F00;
198
199   return;
200
201 loc_g_0EDD:     // go on falling down?
202   PlayField16[si] = 0x7001; // go into intermediate waitstate
203   PlayField16[si + FieldWidth] = 0x9999; // mark as "zonk waiting to access"
204   return;
205
206 loc_g_0EEA:     // test if zonk may roll left
207   // This if(if true) jumps up far above
208   // to the according rountine for fixed zonks!
209   if (PlayField16[si - 1] != 0) // Remarkable!!! ' loc_g_0EF4:
210     goto loc_g_0D4C;
211
212   MovHighByte(&PlayField16[si], 0x50); // zonk rolls left
213   PlayField16[si - 1] = 0x8888; // mark as zonk accessing?
214   return;
215
216 loc_g_0F00:     // test if zonk may roll right
217   if (PlayField16[si + 1] != 0) // loc_g_0F08:
218     return;
219
220   MovHighByte(&PlayField16[si], 0x60); // zonk rolls right
221   PlayField16[si + 1] = 0x8888; // mark as zonk accessing?
222   return;
223
224 loc_g_0F14:     // Murphy dies, but not in any case
225   bl = HighByte(PlayField16[si + FieldWidth]);
226   if (bl == 0xE || bl == 0xF || bl == 0x28)
227     return;
228
229   if (bl == 0x29 || bl == 0x25 || bl == 0x26)
230     return;
231
232 loc_g_0F36:     // ??
233   ax = LowByte(PlayField16[si + FieldWidth - 1]);
234   if (ax == fiElectron) // loc_g_0F43:
235     PlayField16[si + FieldWidth] = fiElectron;
236
237   if (ax != 0x1F)
238     PlayField16[si + FieldWidth - 1] = 0;
239
240   goto loc_g_0F6E;
241
242 loc_g_0F52:     // ??
243   ax = LowByte(PlayField16[si + FieldWidth + 1]);
244   if (ax == fiElectron) // loc_g_0F5F:
245     PlayField16[si + FieldWidth] = fiElectron;
246
247   if (ax != 0x1F)
248     PlayField16[si + FieldWidth + 1] = 0;
249
250   goto loc_g_0F6E;
251
252 loc_g_0F6E:     // someone dies/explodes
253   si = si + FieldWidth;                 // 1 field down
254   ExplodeFieldSP(si);               // Explode
255   return;
256
257 loc_g_0F75:     // OrangeDisk explodes next cycle
258   si = si + FieldWidth;                 // 1 field down
259   PlayField8[si] = fiHardWare;
260   return;
261
262 loc_g_0F83: // zonk comes rolling from right to left
263   //  To Do: draw zonk rolling from right
264   //  according to position in (bl And &H07)
265   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
266   X = GetStretchX(si + 1);
267   Y = GetStretchY(si);
268   dx = (bl & 0x7) + 1;
269   DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
270   DDSpriteBuffer_BltImg(X - (TwoPixels * dx), Y, aniZonkRollLeft, dx - 1);
271   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
272
273   bl = HighByte(PlayField16[si]) + 1; // get and increment sequence#
274   if (bl == 0x24)
275     PlayField16[si + 1] = 0xAAAA;
276
277   if (bl == 0x26)
278   {
279     MovHighByte(&PlayField16[si], bl);
280     subCleanUpForZonksAbove(si + 1);
281   }
282   else if (bl < 0x28)
283   {
284     MovHighByte(&PlayField16[si], bl);
285   }
286   else
287   {
288     PlayField16[si] = 0xFFFF;
289     si = si + FieldWidth;                 // 1 field down
290     PlayField16[si] = 0x1001; // convert rolling zonk to a falling zonk
291   }
292
293   return;
294
295 loc_g_0FE8: // zonk comes rolling from left to right
296   //  To Do: draw zonk rolling from left
297   //  according to position in (bl And &H07)
298   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
299   X = GetStretchX(si - 1);
300   Y = GetStretchY(si);
301   dx = (bl & 0x7) + 1;
302   DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
303   DDSpriteBuffer_BltImg(X + (TwoPixels * dx), Y, aniZonkRollRight, dx - 1);
304   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
305
306   bl = HighByte(PlayField16[si]) + 1;
307   if (bl == 0x34)
308     PlayField16[si - 1] = 0xAAAA;
309
310   if (bl == 0x36)
311   {
312     MovHighByte(&PlayField16[si], bl);
313     subCleanUpForZonksAbove(si - 1);
314   }
315   else if (bl < 0x38)
316   {
317     MovHighByte(&PlayField16[si], bl);
318   }
319   else
320   {
321     PlayField16[si] = 0xFFFF;
322     si = si + FieldWidth;                   // 1 field down
323     PlayField16[si] = 0x1001; // convert rolling zonk to a falling zonk
324   }
325
326   return;
327
328 loc_g_104D: // zonk falls straight down
329   bl = bl + 1;
330   if (bl < 0x42)
331   {
332     MovHighByte(&PlayField16[si], bl);
333   }
334   else if (PlayField16[si + FieldWidth] != 0)
335   {
336     bl = bl - 1; // stay waiting
337     MovHighByte(&PlayField16[si], bl);
338   }
339   else
340   {
341     PlayField16[si] = 0xFFFF; // mark as "zonk leaving"
342     si = si + FieldWidth;                 // 1 field down
343     PlayField16[si] = 0x1001; // go falling
344   }
345
346   return;
347
348 loc_g_107B: // zonk rolls left
349   //  To Do: draw zonk rolling to left
350   //  according to position in (bl And &H0F)
351   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
352   X = GetStretchX(si);
353   Y = GetStretchY(si);
354   dx = (bl & 0xF) + 1;
355   DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
356   DDSpriteBuffer_BltImg(X - (TwoPixels * dx), Y, aniZonkRollLeft, dx - 1);
357   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
358
359   bl = HighByte(PlayField16[si]) + 1; // retrieve and increment sequence#
360   if (bl < 0x52)
361   {
362     MovHighByte(&PlayField16[si], bl);
363     return;
364   }
365
366   if (PlayField16[si + FieldWidth - 1] != 0)
367     goto loc_g_10E2;
368
369   if (PlayField16[si - 1] != 0)
370   {
371     if (PlayField16[si - 1] != 0x8888)
372       goto loc_g_10E2;
373   } // loc_g_10C8:
374
375   PlayField16[si] = 0xFFFF;
376   si = si - 1;                   // 1 field left
377   PlayField16[si] = 0x2201;
378   PlayField16[si + FieldWidth] = 0xFFFF;
379   return;
380
381 loc_g_10E2: // stay waiting
382   bl = bl - 1;
383   MovHighByte(&PlayField16[si], bl);
384   return;
385
386 loc_g_10E9: // zonk rolls right
387   //  To Do: draw zonk rolling to right
388   //  according to position in (bl And &H07)
389   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
390   X = GetStretchX(si);
391   Y = GetStretchY(si);
392   dx = (bl & 0x7) + 1;
393   DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
394   DDSpriteBuffer_BltImg(X + (TwoPixels * dx), Y, aniZonkRollRight, dx - 1);
395   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
396
397   bl = HighByte(PlayField16[si]) + 1;
398   if (bl < 0x62)
399   {
400     MovHighByte(&PlayField16[si], bl);
401     return;
402   }
403
404   if (PlayField16[si + FieldWidth + 1] != 0)
405     goto loc_g_1150;
406
407   if (PlayField16[si + 1] != 0)
408   {
409     if (PlayField16[si + 1] != 0x8888)
410       goto loc_g_1150;
411   }
412
413   PlayField16[si] = 0xFFFF;
414   si = si + 1;
415   PlayField16[si] = 0x3201;
416   PlayField16[si + FieldWidth] = 0xFFFF;
417   return;
418
419 loc_g_1150: // stay waiting
420   bl = bl - 1;
421   MovHighByte(&PlayField16[si], bl);
422   return;
423
424 loc_g_1157: // intermediate state
425   ax = PlayField16[si + FieldWidth];
426   if (ax == 0 || ax == 0x9999)
427   {
428     PlayField16[si] = 0xFFFF;
429     si = si + FieldWidth;                 // 1 field down
430     PlayField16[si] = 0x1001; // start falling down
431     goto loc_g_0DE8;
432   }
433
434   return;
435 } // subAnimateZonks endp
436
437 void subCleanUpForZonksAbove(int si)
438 {
439   int ax;
440
441   if (LowByte(PlayField16[si]) != fiExplosion)
442     PlayField16[si] = 0;
443
444   if (PlayField16[si - FieldWidth] != 0)
445   {
446     if (PlayField16[si - FieldWidth] != 0x9999)
447       return;
448
449     if (LowByte(PlayField16[si - 2 * FieldWidth]) != fiInfotron)
450       return;
451   } // loc_g_1674:
452
453   if (PlayField16[si - FieldWidth - 1] != fiZonk)
454   {
455     if (PlayField16[si - FieldWidth + 1] != fiZonk)
456       return;
457
458     goto loc_g_16A7;
459   }
460
461   ax = PlayField16[si - 1];
462   if (ax == fiZonk || ax == fiInfotron || ax == fiRAM)
463   {
464     PlayField16[si - FieldWidth - 1] = 0x6001;
465     PlayField16[si - FieldWidth] = 0x8888;
466     return;
467   }
468
469   if (PlayField16[si - FieldWidth + 1] != fiZonk)
470     return;
471
472 loc_g_16A7:
473   ax = PlayField16[si + 1];
474   if (ax == fiZonk || ax == fiInfotron || ax == fiRAM)
475   {
476     PlayField16[si - FieldWidth + 1] = 0x5001;
477     PlayField16[si - FieldWidth] = 0x8888;
478   }
479
480   return;
481 } // subCleanUpForZonksAbove