rnd-20100316-1-src
[rocksndiamonds.git] / src / game_sp / SnikSnaks.c
1 // ----------------------------------------------------------------------------
2 // SnikSnaks.c
3 // ----------------------------------------------------------------------------
4
5 #include "SnikSnaks.h"
6
7
8 static void subDrawSnikSnakFromAbove(int, int);
9 static void subDrawSnikSnakFromBelow(int, int);
10 static void subDrawSnikSnakFromLeft(int, int);
11 static void subDrawSnikSnakFromRight(int, int);
12 static void subDrawSnikSnakTurnLeft(int, int);
13 static void subDrawSnikSnakTurnRight(int, int);
14 static void subSnikSnakFromAbove(int, int);
15 static void subSnikSnakFromBelow(int, int);
16 static void subSnikSnakFromLeft(int, int);
17 static void subSnikSnakFromRight(int, int);
18 static void subSnikSnakTurnLeft(int, int);
19 static void subSnikSnakTurnRight(int, int);
20
21 // static char *VB_Name = "modSnikSnak";
22
23 // --- Option Explicit
24 // ==========================================================================
25 //                              SUBROUTINE
26 // Animate/move Snik-Snaks
27 // ==========================================================================
28
29 void subAnimateSnikSnaks(int si)
30 {
31   int bx, Tmp;
32
33   if (SnikSnaksElectronsFrozen == 1)
34     return;
35
36 #if 1
37   /* (not sure why this was removed -- this broke several level solutions) */
38   if (LowByte(PlayField16[si]) != fiSnikSnak)
39     return;
40 #endif
41
42   // If LowByte(PlayField16(si)) <> fiSnikSnak Then Exit Function
43   // Debug.Assert (LowByte(PlayField16[si]) == fiSnikSnak);
44
45   bx = HighByte(PlayField16[si]);
46   Tmp = bx / 8;
47   switch (Tmp)
48   {
49     case 0:
50       subSnikSnakTurnLeft(si, bx); // turning, bx=0 -> point N, bx = 1 -> point NW etc.
51       break;
52
53     case 1:
54       subSnikSnakTurnRight(si, bx); // turn right
55       break;
56
57     case 2:
58       subSnikSnakFromBelow(si, bx); // access si from below
59       break;
60
61     case 3:
62       subSnikSnakFromRight(si, bx); // access si from right
63       break;
64
65     case 4:
66       subSnikSnakFromAbove(si, bx); // access si from above
67       break;
68
69     case 5:
70       subSnikSnakFromLeft(si, bx); // access si from left
71       break;
72
73     default:
74       // Debug.Assert(False);
75       break;
76   }
77 }
78
79 void subDrawAnimatedSnikSnaks(int si)
80 {
81   int bx, Tmp;
82
83   // If SnikSnaksElectronsFrozen = 1 Then Exit Function
84
85   if (LowByte(PlayField16[si]) != fiSnikSnak)
86     return;
87
88   bx = HighByte(PlayField16[si]);
89   Tmp = bx / 8;
90   switch (Tmp)
91   {
92     case 0:
93       subDrawSnikSnakTurnLeft(si, bx); // turning, bx=0 -> point N, bx = 1 -> point NW etc.
94       break;
95
96     case 1:
97       subDrawSnikSnakTurnRight(si, bx); // turn right
98       break;
99
100     case 2:
101       subDrawSnikSnakFromBelow(si, bx); // access si from below
102       break;
103
104     case 3:
105       subDrawSnikSnakFromRight(si, bx); // access si from right
106       break;
107
108     case 4:
109       subDrawSnikSnakFromAbove(si, bx); // access si from above
110       break;
111
112     case 5:
113       subDrawSnikSnakFromLeft(si, bx); // access si from left
114       break;
115   }
116 }
117
118 static void subSnikSnakTurnLeft(int si, int bx)
119 {
120   int ax, ah, bl;
121
122   ax = (TimerVar & 3);
123   if (ax != 0)
124   {
125     if (ax == 3)
126       goto loc_g_7622;
127
128     return;
129   } // loc_g_75E0:
130
131   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
132   subDrawSnikSnakTurnLeft(si, bx);
133   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
134
135   bx = (bx + 1) & 0x7;
136   MovHighByte(&PlayField16[si], bx);
137
138   return;
139
140 locMayExplode760A:
141   ah = HighByte(ax);
142   if (ah == 0x1B)
143     return;
144
145   if (ah == 0x19)
146     return;
147
148   if (ah == 0x18)
149     return;
150
151   if (ah == 0x1A)
152     return;
153
154   ExplodeFieldSP(si); // Explode
155
156   return;
157
158 loc_g_7622:
159   bl = HighByte(PlayField16[si]);
160   if (bl == 0)
161     goto loc_g_763B;
162
163   if (bl == 2)
164     goto loc_g_765E;
165
166   if (bl == 4)
167     goto loc_g_7681;
168
169   if (bl == 6)
170     goto loc_g_76A7;
171
172   return;
173
174 loc_g_763B: // pointing up
175   ax = PlayField16[si - FieldWidth];
176   if (ax == 0) // above is empty -> go up
177     goto loc_g_764E;
178
179   if (LowByte(ax) == fiMurphy) // above is murphy -> explode
180     goto locMayExplode760A;
181
182   return;
183
184 loc_g_764E: // above is empty -> go up
185   PlayField16[si] = 0x1BB;
186   si = si - FieldWidth;
187   PlayField16[si] = 0x1011;
188
189   return;
190
191 loc_g_765E: // pointing left
192   ax = PlayField16[si - 1];
193   if (ax == 0) // left is empty -> go there
194     goto loc_g_7671;
195
196   if (LowByte(ax) == fiMurphy) // left is murphy -> explode
197     goto locMayExplode760A;
198
199   return;
200
201 loc_g_7671: // left is empty -> go there
202   PlayField16[si] = 0x2BB;
203   si = si - 1;
204   PlayField16[si] = 0x1811;
205
206   return;
207
208 loc_g_7681: // pointing down
209   ax = PlayField16[si + FieldWidth];
210   if (ax == 0) // below is empty -> go down
211     goto loc_g_7697;
212
213   if (LowByte(ax) == fiMurphy) // below is murphy -> explode
214     goto locMayExplode760A;
215
216   return;
217
218 loc_g_7697: // below is empty -> go down
219   PlayField16[si] = 0x3BB;
220   si = si + FieldWidth;
221   PlayField16[si] = 0x2011;
222
223   return;
224
225 loc_g_76A7: // pointing Right
226   ax = PlayField16[si + 1];
227   if (ax == 0) // right is empty -> go there
228     goto loc_g_76BD;
229
230   if (LowByte(ax) == fiMurphy) // right is murphy -> explode
231     goto locMayExplode760A;
232
233   return;
234
235 loc_g_76BD: // right is empty -> go there
236   PlayField16[si] = 0x4BB;
237   si = si + 1;
238   PlayField16[si] = 0x2811;
239 }
240
241 static void subSnikSnakTurnRight(int si, int bx)
242 {
243   int ax, ah, bl;
244
245   ax = (TimerVar & 3);
246   if (ax != 0)
247   {
248     if (ax == 3)
249       goto loc_g_771F;
250
251     return;
252   } // loc_g_76DB:
253
254   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
255   subDrawSnikSnakTurnRight(si, bx);
256   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
257
258   bx = ((bx + 1) & 0x7) | 8;
259   MovHighByte(&PlayField16[si], bx);
260
261   return;
262
263 locMayExplode7707:
264   ah = HighByte(ax);
265   if (ah == 0x1B)
266     return;
267
268   if (ah == 0x19)
269     return;
270
271   if (ah == 0x18)
272     return;
273
274   if (ah == 0x1A)
275     return;
276
277   ExplodeFieldSP(si); // Explode
278
279   return;
280
281 loc_g_771F:
282   bl = HighByte(PlayField16[si]);
283   if (bl == 0x8)
284     goto loc_g_7738;
285
286   if (bl == 0xA)
287     goto loc_g_77A4;
288
289   if (bl == 0xC)
290     goto loc_g_777E;
291
292   if (bl == 0xE)
293     goto loc_g_775B;
294
295   return;
296
297 loc_g_7738: // pointing up
298   ax = PlayField16[si - FieldWidth];
299   if (ax == 0) // above is empty -> go up
300     goto loc_g_774B;
301
302   if (LowByte(ax) == fiMurphy) // above is murphy -> explode
303     goto locMayExplode7707;
304
305   return;
306
307 loc_g_774B: // above is empty -> go up
308   PlayField16[si] = 0x1BB;
309   si = si - FieldWidth;
310   PlayField16[si] = 0x1011;
311
312   return;
313
314 loc_g_775B: // pointing left
315   ax = PlayField16[si - 1];
316   if (ax == 0) // left is empty -> go there
317     goto loc_g_776E;
318
319   if (LowByte(ax) == fiMurphy) // left is murphy -> explode
320     goto locMayExplode7707;
321
322   return;
323
324 loc_g_776E: // left is empty -> go there
325   PlayField16[si] = 0x2BB;
326   si = si - 1;
327   PlayField16[si] = 0x1811;
328
329   return;
330
331 loc_g_777E: // pointing down
332   ax = PlayField16[si + FieldWidth];
333   if (ax == 0) // below is empty -> go down
334     goto loc_g_7794;
335
336   if (LowByte(ax) == fiMurphy) // below is murphy -> explode
337     goto locMayExplode7707;
338
339   return;
340
341 loc_g_7794: // below is empty -> go down
342   PlayField16[si] = 0x3BB;
343   si = si + FieldWidth;
344   PlayField16[si] = 0x2011;
345
346   return;
347
348 loc_g_77A4: // pointing Right
349   ax = PlayField16[si + 1];
350   if (ax == 0) // right is empty -> go there
351     goto loc_g_77BA;
352
353   if (LowByte(ax) == fiMurphy) // right is murphy -> explode
354     goto locMayExplode7707;
355
356   return;
357
358 loc_g_77BA: // right is empty -> go there
359   PlayField16[si] = 0x4BB;
360   si = si + 1;
361   PlayField16[si] = 0x2811;
362 }
363
364 static void subSnikSnakFromBelow(int si, int bx)
365 {
366   int ax, bl;
367
368   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
369   subDrawSnikSnakFromBelow(si, bx);
370   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
371   bx = bx - 0xF;  // get and increment sequence#
372
373   bl = LowByte(bx);
374   if (bl == 7 && LowByte(PlayField16[si + FieldWidth]) != fiExplosion)
375   {
376     PlayField16[si + FieldWidth] = 0; // sniknak left that field
377   }
378
379   if (bl < 8) // sniksnak still goes up
380   {
381     bl = bl + 0x10;
382     MovHighByte(&PlayField16[si], bl);
383
384     return;
385   } // loc_g_7813
386
387   PlayField16[si] = 0x11; // sequence#=8 -> arrived at the new field
388   ax = PlayField16[si - 1]; // check left field
389   if (ax == 0 || LowByte(ax) == fiMurphy) // check for empty or murphy
390   {
391     MovHighByte(&PlayField16[si], 1); // start to turn left
392
393     return;
394   } // loc_g_7826: and 'loc_g_7833:
395
396   ax = PlayField16[si - FieldWidth]; // cannot turn left -> check above
397   if (ax == 0) // check if empty
398   {
399     PlayField16[si] = 0x1BB; // mark as "sniksnak leaving"
400     si = si - FieldWidth; // go up!
401     PlayField16[si] = 0x1011;
402
403     return;
404   } // loc_g_784A:
405
406   if (LowByte(ax) == fiMurphy) // check for murphy above
407   {
408     ExplodeFieldSP(si); // Explode
409
410     return;
411   } // loc_g_7855:
412
413   ax = PlayField16[si + 1]; // check right field
414   if (ax == 0 || LowByte(ax) == fiMurphy) // check for empty or murphy
415   {
416     MovHighByte(&PlayField16[si], 9); // start to turn right
417
418     return;
419   } // loc_g_7862: and 'loc_g_786F:
420
421   // else: no way to go, start turning around
422   MovHighByte(&PlayField16[si], 1);
423 }
424
425 static void subSnikSnakFromRight(int si, int bx)
426 {
427   int ax, bl;
428
429   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
430   subDrawSnikSnakFromRight(si, bx);
431   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
432   bx = bx - 0x17;  // get and increment sequence#
433
434   bl = LowByte(bx);
435   if (bl == 7 && LowByte(PlayField16[si + 1]) != fiExplosion)
436   {
437     PlayField16[si + 1] = 0; // sniknak left that field
438   } // loc_g_78AC:
439
440   if (bl < 8) // sniksnak still goes left
441   {
442     bl = bl + 0x18;
443     MovHighByte(&PlayField16[si], bl);
444
445     return;
446   } // loc_g_78B9:
447
448   PlayField16[si] = 0x11; // sequence#=8 -> arrived at the new field
449   ax = PlayField16[si + FieldWidth]; // check below
450   if (ax == 0 || LowByte(ax) == fiMurphy) // empty or murphy?
451   {
452     MovHighByte(&PlayField16[si], 3); // yes -> turn left down
453
454     return;
455   } // loc_g_78CC: and 'loc_g_78D9:
456
457   ax = PlayField16[si - 1]; // check left, etc ... see the comments on subSnikSnakFromBelow()
458   if (ax == 0)
459   {
460     PlayField16[si] = 0x2BB;
461     si = si - 1;                // 1 field left
462     PlayField16[si] = 0x1811;
463
464     return;
465   } // loc_g_78F0:
466
467   if (LowByte(ax) == fiMurphy)
468   {
469     ExplodeFieldSP(si);      // Explode
470
471     return;
472   } // loc_g_78FB:
473
474   ax = PlayField16[si - FieldWidth]; // check above
475   if (ax == 0 || LowByte(ax) == fiMurphy)
476   {
477     MovHighByte(&PlayField16[si], 0xF);
478
479     return;
480   } // loc_g_7908:loc_g_7915:
481
482   MovHighByte(&PlayField16[si], 3);
483 }
484
485 static void subSnikSnakFromAbove(int si, int bx)
486 {
487   int ax, bl;
488
489   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
490   subDrawSnikSnakFromAbove(si, bx);
491   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
492   bx = bx - 0x1F;  // get and increment sequence#
493
494   bl = LowByte(bx);
495   if (bl == 7 && LowByte(PlayField16[si - FieldWidth]) != fiExplosion)
496   {
497     PlayField16[si - FieldWidth] = 0; // sniknak left that field
498   }
499
500   if (bl < 8) // sniksnak still goes down
501   {
502     bl = bl + 0x20;
503     MovHighByte(&PlayField16[si], bl);
504
505     return;
506   } // loc_g_7813
507
508   PlayField16[si] = 0x11; // sequence#=8 -> arrived at the new field
509   ax = PlayField16[si + 1]; // check right
510   if (ax == 0 || LowByte(ax) == fiMurphy)
511   {
512     MovHighByte(&PlayField16[si], 5);
513
514     return;
515   } // loc_g_7986:
516
517   ax = PlayField16[si + FieldWidth]; // check below
518   if (ax == 0)
519   {
520     PlayField16[si] = 0x3BB;
521     si = si + FieldWidth;                 // 1 field down
522     PlayField16[si] = 0x2011;
523
524     return;
525   } // loc_g_799D:
526
527   if (LowByte(ax) == fiMurphy)
528   {
529     ExplodeFieldSP(si);        // Explode
530
531     return;
532   } // loc_g_79A8:
533
534   ax = PlayField16[si - 1]; // check left
535   if (ax == 0 || LowByte(ax) == fiMurphy)
536   {
537     MovHighByte(&PlayField16[si], 0xD);
538
539     return;
540   } // loc_g_79C2:
541
542   MovHighByte(&PlayField16[si], 5);
543 }
544
545 static void subSnikSnakFromLeft(int si, int bx)
546 {
547   int ax, bl;
548
549   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
550   subDrawSnikSnakFromLeft(si, bx);
551   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
552   bx = bx - 0x27;  // get and increment sequence#
553
554   bl = LowByte(bx);
555   if (bl == 7 && LowByte(PlayField16[si - 1]) != fiExplosion)
556   {
557     PlayField16[si - 1] = 0; // sniknak left that field
558   }
559
560   if (bl < 8) // sniksnak still goes right
561   {
562     bl = bl + 0x28;
563     MovHighByte(&PlayField16[si], bl);
564
565     return;
566   } // loc_g_78B9:
567
568   PlayField16[si] = 0x11; // sequence#=8 -> arrived at the new field
569   ax = PlayField16[si - FieldWidth]; // check above
570   if (ax == 0 || LowByte(ax) == fiMurphy)
571   {
572     MovHighByte(&PlayField16[si], 7);
573
574     return;
575   } // loc_g_7A2D:
576
577   ax = PlayField16[si + 1]; // check right(straight on)
578   if (ax == 0)
579   {
580     PlayField16[si] = 0x4BB;
581     si = si + 1;                   // 1 field right
582     PlayField16[si] = 0x2811;
583
584     return;
585   } // loc_g_7A44:
586
587   if (LowByte(ax) == fiMurphy)
588   {
589     ExplodeFieldSP(si);    // Explode
590
591     return;
592   } // loc_g_7A4F:
593
594   ax = PlayField16[si + FieldWidth]; // check below
595   if (ax == 0 || LowByte(ax) == fiMurphy)
596   {
597     MovHighByte(&PlayField16[si], 0xB);
598
599     return;
600   } // loc_g_7A69:
601
602   MovHighByte(&PlayField16[si], 7);
603 }
604
605 static void subDrawSnikSnakTurnLeft(int si, int bx)
606 {
607   int pos = ((bx + 7) % 8) / 2;
608
609   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
610   GfxGraphic[GetX(si)][GetY(si)] = aniSnikSnakTurningLeft[pos];
611   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
612 }
613
614 static void subDrawSnikSnakTurnRight(int si, int bx)
615 {
616   int pos = ((bx - 1) % 8) / 2;
617
618   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
619   GfxGraphic[GetX(si)][GetY(si)] = aniSnikSnakTurningRight[pos];
620   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
621 }
622
623 static void subDrawSnikSnakFromBelow(int si, int bx)
624 {
625   int X, Y;
626
627   bx = bx - 0xF; // get and anti-increment sequence#
628
629   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
630   X = GetStretchX(si);
631   Y = GetStretchY(si + FieldWidth);
632   DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
633   DDSpriteBuffer_BltImg(X, Y - bx * TwoPixels, aniSnikSnakUp, bx);
634   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
635 }
636
637 static void subDrawSnikSnakFromRight(int si, int bx)
638 {
639   int X, Y;
640
641   bx = bx - 0x17; // get and increment sequence#
642
643   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
644   X = GetStretchX(si + 1);
645   Y = GetStretchY(si);
646   DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
647   DDSpriteBuffer_BltImg(X - bx * TwoPixels, Y, aniSnikSnakLeft, bx);
648   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
649 }
650
651 static void subDrawSnikSnakFromAbove(int si, int bx)
652 {
653   int X, Y;
654
655   bx = bx - 0x1F; // get and increment sequence#
656
657   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
658   X = GetStretchX(si);
659   Y = GetStretchY(si - FieldWidth);
660   DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
661   DDSpriteBuffer_BltImg(X, Y + bx * TwoPixels, aniSnikSnakDown, bx);
662   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
663 }
664
665 static void subDrawSnikSnakFromLeft(int si, int bx)
666 {
667   int X, Y;
668
669   bx = bx - 0x27; // get and increment sequence#
670
671   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
672   X = GetStretchX(si - 1);
673   Y = GetStretchY(si);
674   DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
675   DDSpriteBuffer_BltImg(X + bx * TwoPixels, Y, aniSnikSnakRight, bx);
676   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
677 }