added boundary checks for sound/music ID for some sound and music functions
[rocksndiamonds.git] / src / game_sp / InitGameConditions.c
1 // ----------------------------------------------------------------------------
2 // InitGameConditions.c
3 // ----------------------------------------------------------------------------
4
5 #include "InitGameConditions.h"
6
7
8 // ==========================================================================
9 //                              SUBROUTINE
10 // Init game conditions (variables)
11 // ==========================================================================
12
13 void subInitGameConditions()
14 {
15   MurphyVarFaceLeft = 0;
16   KillMurphyFlag = 0;                   // no "kill Murphy"
17   ExitToMenuFlag = 0;
18   LeadOutCounter = 0;                   // quit flag: lead-out counter
19   RedDiskCount = 0;                     // Red disk counter
20
21   YawnSleepCounter = 0;                 // Wake up sleeping Murphy
22
23   ExplosionShake = 0;                   // Force explosion flag off
24   ExplosionShakeMurphy = 0;             // Force explosion flag off
25
26   TerminalMaxCycles = 0x7F;
27   YellowDisksExploded = 0;
28
29   TimerVar = 0;
30
31   SnikSnaksElectronsFrozen = 0;         // Snik-Snaks and Electrons move!
32
33   SplitMoveFlag = 0;                    // Reset Split-through-ports
34   RedDiskReleasePhase = 0;              // (re-)enable red disk release
35   RedDiskReleaseMurphyPos = 0;          // Red disk was released here
36 }
37
38
39 // ==========================================================================
40 //                              SUBROUTINE
41 // Locate Murphy and init location.
42 // ==========================================================================
43
44 void InitMurphyPos()
45 {
46   int si;
47
48   for (si = 0; si < LevelMax; si++)
49     if (PlayField16[si] == fiMurphy)
50       break;
51
52   InitMurphyPosB(si);
53
54   MurphyPosIndex = si;
55 }
56
57 void InitMurphyPosB(int si)
58 {
59   MurphyScreenXPos = MurphyXPos = GetStretchX(si); // Murphy's screen x-position
60   MurphyScreenYPos = MurphyYPos = GetStretchY(si); // Murphy's screen y-position
61
62   // To Do: draw Murphy in location ax
63   DDSpriteBuffer_BltImg(MurphyScreenXPos, MurphyScreenYPos, aniMurphy, 0);
64
65   subCalculateScreenScrollPos();           // calculate screen start addrs
66
67   if (AutoScrollFlag)
68   {
69     if (bPlaying)
70       SoftScrollTo(ScreenScrollXPos, ScreenScrollYPos, 1000, 25);
71     else
72       ScrollTo(ScreenScrollXPos, ScreenScrollYPos);
73   }
74 }
75
76
77 // ==========================================================================
78 //                              SUBROUTINE
79 // Convert to easy symbols and reset Infotron count If not ThenVer62
80 // ==========================================================================
81
82 int subConvertToEasySymbols()
83 {
84   int ax, bx, cx, dx, i;
85   int al;
86
87   bx = 0;
88   dx = 0;
89   cx = LevelMax + 1;
90   i = 0;
91
92 loc_g_26C9:
93   ax = PlayField16[i];
94   al = LowByte(ax);
95   if (al == 0xF1) // converted explosion?
96   {
97     MovLowByte(&PlayField16[i], 0x1F);      // restore explosions
98     goto loc_g_2778;
99   }
100
101   if (LowByte(GameBusyFlag) != 1) // free screen write?
102   {
103     if (ax == fiInfotron) // Infotron? -> yes--count!
104       goto loc_g_2704;
105
106     if (ax == fiSnikSnak) // Snik Snak? -> yes--rearrange
107       goto loc_g_2713;
108
109     if (ax == fiElectron) // Electron? -> yes--rearrange
110       goto loc_g_2741;
111   }
112
113   // test for fancy RAM Chips:
114   if (ax == fiRAMLeft || ax == fiRAMRight)
115     goto loc_g_2707;
116
117   if (ax == fiRAMTop || ax == fiRAMBottom)
118     goto loc_g_2707;
119
120   if (ax < fiHWFirst) // All but deco hardware?
121     goto loc_g_26F8;
122
123   if (ax < fiRAMTop) // Decorative hardware?
124     goto loc_g_270D;
125
126 loc_g_26F8:
127   if (ax < fiSpPortRight) // Gravity change ports only?
128     goto loc_g_2778;
129
130   if (ax < fiSnikSnak) // Gravity change port! 'loc_g_2702:
131     goto loc_g_276F;
132
133   goto loc_g_2778;
134
135 loc_g_2704:                                     // INFOTRON
136   dx = dx + 1;                      // Count Infotrons
137   goto loc_g_2778;
138
139 loc_g_2707:                                     // DECO RAM CHIPS
140   PlayField16[i] = fiRAM; // Convert to standard RAM chip
141   goto loc_g_2778;
142
143 loc_g_270D:                                     // DECO HARDWARE
144   PlayField16[i] = fiHardWare; // Convert to standard hardware
145   goto loc_g_2778;
146
147 loc_g_2713:                                     // SNIK-SNAK
148   if (PlayField16[i - 1] != 0) // 1 field left empty? -> no--try up
149     goto loc_g_271F;
150
151   MovHighByte(&PlayField16[i], 1); // turn left, step = NorthWest
152   goto loc_g_2778;
153
154 loc_g_271F:
155   if (PlayField16[i - FieldWidth] != 0) // 1 field up empty? -> no--try right
156     goto loc_g_2730;
157
158   PlayField16[i - FieldWidth] = 0x1011; // SnikSnak accessing from below, step = 0
159   PlayField16[i] = 0xFFFF;
160   goto loc_g_2778;
161
162 loc_g_2730:
163   if (PlayField16[i + 1] != 0) // 1 field right empty? -> point up
164     goto loc_g_2778;
165
166   PlayField16[i + 1] = 0x2811; // SnikSnak accessing from left, step = 0
167   PlayField16[i] = 0xFFFF;
168   goto loc_g_2778;
169
170 loc_g_2741:                                     // ELECTRON
171   if (PlayField16[i - 1] != 0) // 1 field left empty? -> no--try up
172     goto loc_g_274D;
173
174   MovHighByte(&PlayField16[i], 1);
175   goto loc_g_2778;
176
177 loc_g_274D:
178   if (PlayField16[i - FieldWidth] != 0) // 1 field up empty? -> no--try right
179     goto loc_g_275E;
180
181   PlayField16[i - FieldWidth] = 0x1018; // 1 field up
182   PlayField16[i] = 0xFFFF;
183   goto loc_g_2778;
184
185 loc_g_275E:
186   if (PlayField16[i + 1] != 0) // 1 field right empty? -> no--point down
187     goto loc_g_2778;
188
189   PlayField16[i + 1] = 0x2818;
190   PlayField16[i] = 0xFFFF;
191   goto loc_g_2778;
192
193 loc_g_276F:                                     // GRAVITY CHANGING PORTS
194   PlayField16[i] = (ax - 4) | 0x100;    // Convert to standard ports
195   goto loc_g_2778;
196
197 loc_g_2778:
198   i = i + 1;                   // Next field
199   bx = bx + 1;
200   cx = cx - 1;
201   if (0 < cx) // Until all done 'loc_g_2782:
202     goto loc_g_26C9;
203
204   return dx;    // return InfotronCount
205 }
206
207
208 // ==========================================================================
209 //                              SUBROUTINE
210 // Reset Infotron count.  Call immediately after subConvertToEasySymbols
211 // ==========================================================================
212
213 void ResetInfotronsNeeded(int dx)
214 {
215   if (LInfo.InfotronsNeeded != 0)               // Jump If equal (autodetect)
216     dx = LInfo.InfotronsNeeded;
217
218   InfotronsNeeded = LowByte(dx);                // Remaining Infotrons needed
219   TotalInfotronsNeeded = InfotronsNeeded;       // Number of Infotrons needed
220 }
221
222
223 // ==========================================================================
224 //                              SUBROUTINE
225 // Fetch and initialize a level
226 // ==========================================================================
227
228 void subFetchAndInitLevelB()
229 {
230   subFetchAndInitLevelA();
231 }
232
233 void subFetchAndInitLevelA()
234 {
235   GameBusyFlag = 0;                             // restore scissors too
236   subFetchAndInitLevel();                       // fetch and initialize a level
237   GameBusyFlag = 1;                             // no free screen write
238
239   DemoKeyCode = 0;                              // delete last demo key!
240 }
241
242 void subFetchAndInitLevel()
243 {
244   int InfoCountInLevel;
245
246   PrepareLevel();                               // initialize level data
247
248   GameBusyFlag = -GameBusyFlag;                 // make != 1
249   InfoCountInLevel = subConvertToEasySymbols(); // convert to easy symbols
250   GameBusyFlag = -GameBusyFlag;                 // restore
251
252   subDisplayLevel();                            // paint (init) game field
253
254   ResetInfotronsNeeded(InfoCountInLevel);       // and reset Infotron count
255
256   subInitGameConditions();                      // init game conditions (vars)
257
258   InitMurphyPos();                              // locate Murphy + screen pos
259 }