]>
Commit | Line | Data |
---|---|---|
6a5fa4e0 MG |
1 | /* s_msg.c |
2 | * | |
3 | * Micropolis, Unix Version. This game was released for the Unix platform | |
4 | * in or about 1990 and has been modified for inclusion in the One Laptop | |
5 | * Per Child program. Copyright (C) 1989 - 2007 Electronic Arts Inc. If | |
6 | * you need assistance with this program, you may contact: | |
7 | * http://wiki.laptop.org/go/Micropolis or email micropolis@laptop.org. | |
8 | * | |
9 | * This program is free software: you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License as published by | |
11 | * the Free Software Foundation, either version 3 of the License, or (at | |
12 | * your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, but | |
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * General Public License for more details. You should have received a | |
18 | * copy of the GNU General Public License along with this program. If | |
19 | * not, see <http://www.gnu.org/licenses/>. | |
20 | * | |
21 | * ADDITIONAL TERMS per GNU GPL Section 7 | |
22 | * | |
23 | * No trademark or publicity rights are granted. This license does NOT | |
24 | * give you any right, title or interest in the trademark SimCity or any | |
25 | * other Electronic Arts trademark. You may not distribute any | |
26 | * modification of this program using the trademark SimCity or claim any | |
27 | * affliation or association with Electronic Arts Inc. or its employees. | |
28 | * | |
29 | * Any propagation or conveyance of this program must include this | |
30 | * copyright notice and these terms. | |
31 | * | |
32 | * If you convey this program (or any modifications of it) and assume | |
33 | * contractual liability for the program to recipients of it, you agree | |
34 | * to indemnify Electronic Arts for any liability that those contractual | |
35 | * assumptions impose on Electronic Arts. | |
36 | * | |
37 | * You may not misrepresent the origins of this program; modified | |
38 | * versions of the program must be marked as such and not identified as | |
39 | * the original program. | |
40 | * | |
41 | * This disclaimer supplements the one included in the General Public | |
42 | * License. TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS | |
43 | * PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY | |
44 | * OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF | |
45 | * SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS | |
46 | * DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES, | |
47 | * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY, | |
48 | * FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY | |
49 | * RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING, | |
50 | * USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT AGAINST | |
51 | * INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL | |
52 | * MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE | |
53 | * UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE | |
54 | * WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE | |
55 | * CORRECTED. NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR | |
56 | * ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY. SOME | |
57 | * JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED | |
58 | * WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A | |
59 | * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY | |
60 | * NOT APPLY TO YOU. | |
61 | */ | |
62 | #include "sim.h" | |
63 | ||
64 | ||
65 | QUAD LastCityPop; | |
66 | short LastCategory; | |
67 | short LastPicNum; | |
68 | short autoGo; | |
69 | short HaveLastMessage = 0; | |
70 | char LastMessage[256]; | |
6f214ac0 MG |
71 | |
72 | void DoAutoGoto(short x, short y, char *msg); | |
73 | void DoShowPicture(short id); | |
74 | void DoLoseGame(void); | |
75 | void SetMessageField(char *str); | |
76 | void DoScenarioScore(int type); | |
77 | void CheckGrowth(void); | |
78 | ||
6a5fa4e0 MG |
79 | |
80 | /* comefrom: Simulate */ | |
6f214ac0 | 81 | void |
6a5fa4e0 MG |
82 | SendMessages(void) |
83 | { | |
6f214ac0 | 84 | register int z; |
6a5fa4e0 MG |
85 | short PowerPop; |
86 | float TM; | |
87 | ||
88 | if ((ScenarioID) && (ScoreType) && (ScoreWait)) { | |
89 | ScoreWait--; | |
90 | if (!ScoreWait) | |
91 | DoScenarioScore(ScoreType); | |
92 | } | |
93 | ||
94 | CheckGrowth(); | |
95 | ||
96 | TotalZPop = ResZPop + ComZPop + IndZPop; | |
97 | PowerPop = NuclearPop + CoalPop; | |
98 | ||
99 | z = CityTime & 63; | |
100 | ||
101 | switch(z) { | |
102 | ||
103 | case 1: | |
104 | if ((TotalZPop >>2) >= ResZPop) | |
105 | SendMes(1); /* need Res */ | |
106 | break; | |
107 | case 5: | |
108 | if ((TotalZPop >>3) >= ComZPop) | |
109 | SendMes(2); /* need Com */ | |
110 | break; | |
111 | case 10: | |
112 | if ((TotalZPop >>3) >= IndZPop) | |
113 | SendMes(3); /* need Ind */ | |
114 | break; | |
115 | case 14: | |
116 | if ((TotalZPop > 10) && ((TotalZPop <<1) > RoadTotal)) | |
117 | SendMes(4); | |
118 | break; | |
119 | case 18: | |
120 | if ((TotalZPop > 50) && (TotalZPop > RailTotal)) | |
121 | SendMes(5); | |
122 | break; | |
123 | case 22: | |
124 | if ((TotalZPop > 10) && (PowerPop == 0)) | |
125 | SendMes(6); /* need Power */ | |
126 | break; | |
127 | case 26: | |
128 | if ((ResPop > 500) && (StadiumPop == 0)) { | |
129 | SendMes(7); /* need Stad */ | |
130 | ResCap = 1; | |
131 | } | |
132 | else | |
133 | ResCap = 0; | |
134 | break; | |
135 | case 28: | |
136 | if ((IndPop > 70) && (PortPop == 0)) { | |
137 | SendMes(8); | |
138 | IndCap = 1; | |
139 | } | |
140 | else IndCap = 0; | |
141 | break; | |
142 | case 30: | |
143 | if ((ComPop > 100) && (APortPop == 0)) { | |
144 | SendMes(9); | |
145 | ComCap = 1; | |
146 | } | |
147 | else ComCap = 0; | |
148 | break; | |
149 | case 32: | |
150 | TM = unPwrdZCnt + PwrdZCnt; /* dec score for unpowered zones */ | |
151 | if (TM) | |
152 | if ((PwrdZCnt / TM) < .7) | |
153 | SendMes(15); | |
154 | break; | |
155 | case 35: | |
156 | if (PolluteAverage > /* 80 */ 60) | |
157 | SendMes(-10); | |
158 | break; | |
159 | case 42: | |
160 | if (CrimeAverage > 100) | |
161 | SendMes(-11); | |
162 | break; | |
163 | case 45: | |
164 | if ((TotalPop > 60) && (FireStPop == 0)) | |
165 | SendMes(13); | |
166 | break; | |
167 | case 48: | |
168 | if ((TotalPop > 60) && (PolicePop == 0)) | |
169 | SendMes(14); | |
170 | break; | |
171 | case 51: | |
172 | if (CityTax > 12) | |
173 | SendMes(16); | |
174 | break; | |
175 | case 54: | |
176 | if ((RoadEffect < 20) && (RoadTotal > 30)) | |
177 | SendMes(17); | |
178 | break; | |
179 | case 57: | |
180 | if ((FireEffect < 700) && (TotalPop > 20)) | |
181 | SendMes(18); | |
182 | break; | |
183 | case 60: | |
184 | if ((PoliceEffect < 700) && (TotalPop > 20)) | |
185 | SendMes(19); | |
186 | break; | |
187 | case 63: | |
188 | if (TrafficAverage > 60) | |
189 | SendMes(-12); | |
190 | break; | |
191 | } | |
192 | } | |
193 | ||
194 | ||
195 | /* comefrom: SendMessages */ | |
6f214ac0 | 196 | void |
6a5fa4e0 MG |
197 | CheckGrowth(void) |
198 | { | |
199 | QUAD ThisCityPop; | |
200 | short z; | |
201 | ||
202 | if (!(CityTime & 3)) { | |
203 | z = 0; | |
204 | ThisCityPop = ((ResPop) + (ComPop * 8L) + (IndPop * 8L)) * 20L; | |
205 | if (LastCityPop) { | |
206 | if ((LastCityPop < 2000) && (ThisCityPop >= 2000)) z = 35; | |
207 | if ((LastCityPop < 10000) && (ThisCityPop >= 10000)) z = 36; | |
208 | if ((LastCityPop < 50000L) && (ThisCityPop >= 50000L)) z = 37; | |
209 | if ((LastCityPop < 100000L) && (ThisCityPop >= 100000L)) z = 38; | |
210 | if ((LastCityPop < 500000L) && (ThisCityPop >= 500000L)) z = 39; | |
211 | } | |
212 | if (z) | |
213 | if (z != LastCategory) { | |
214 | SendMes(-z); | |
215 | LastCategory = z; | |
216 | } | |
217 | LastCityPop = ThisCityPop; | |
218 | } | |
219 | } | |
220 | ||
221 | ||
222 | /* comefrom: SendMessages */ | |
6f214ac0 | 223 | void |
6a5fa4e0 MG |
224 | DoScenarioScore(int type) |
225 | { | |
226 | short z; | |
227 | ||
228 | z = -200; /* you lose */ | |
229 | switch(type) { | |
230 | case 1: /* Dullsville */ | |
231 | if (CityClass >= 4) z = -100; | |
232 | break; | |
233 | case 2: /* San Francisco */ | |
234 | if (CityClass >= 4) z = -100; | |
235 | break; | |
236 | case 3: /* Hamburg */ | |
237 | if (CityClass >= 4) z = -100; | |
238 | break; | |
239 | case 4: /* Bern */ | |
240 | if (TrafficAverage < 80) z = -100; | |
241 | break; | |
242 | case 5: /* Tokyo */ | |
243 | if (CityScore > 500) z = -100; | |
244 | break; | |
245 | case 6: /* Detroit */ | |
246 | if (CrimeAverage < 60) z = -100; | |
247 | break; | |
248 | case 7: /* Boston */ | |
249 | if (CityScore > 500) z = -100; | |
250 | break; | |
251 | case 8: /* Rio de Janeiro */ | |
252 | if (CityScore > 500) z = -100; | |
253 | break; | |
254 | } | |
255 | ClearMes(); | |
256 | SendMes(z); | |
257 | ||
258 | if (z == -200) | |
259 | DoLoseGame(); | |
260 | } | |
261 | ||
262 | ||
6f214ac0 | 263 | void |
6a5fa4e0 MG |
264 | ClearMes(void) |
265 | { | |
266 | MessagePort = 0; | |
267 | MesX = 0; | |
268 | MesY = 0; | |
269 | LastPicNum = 0; | |
270 | } | |
271 | ||
272 | ||
273 | /* comefrom: MakeEarthquake MakeFire MakeFire MakeFlood SendMessages | |
274 | CheckGrowth DoScenarioScore DoPowerScan */ | |
6f214ac0 | 275 | int |
6a5fa4e0 MG |
276 | SendMes(int Mnum) |
277 | { | |
278 | if (Mnum < 0) { | |
279 | if (Mnum != LastPicNum) { | |
280 | MessagePort = Mnum; | |
281 | MesX = 0; | |
282 | MesY = 0; | |
283 | LastPicNum = Mnum; | |
284 | return (1); | |
285 | } | |
286 | } else { | |
287 | if (!(MessagePort)) { | |
288 | MessagePort = Mnum; | |
289 | MesX = 0; | |
290 | MesY = 0; | |
291 | return(1); | |
292 | } | |
293 | } | |
294 | return(0); | |
295 | } | |
296 | ||
297 | ||
298 | /* comefrom: DoExplosion DoCopter ExplodeObject */ | |
299 | void SendMesAt(short Mnum, short x, short y) | |
300 | { | |
301 | if (SendMes(Mnum)) { | |
302 | MesX = x; | |
303 | MesY = y; | |
304 | } | |
305 | } | |
306 | ||
307 | ||
6f214ac0 | 308 | void |
6a5fa4e0 MG |
309 | doMessage(void) |
310 | { | |
311 | char messageStr[256]; | |
312 | short pictId; | |
313 | short firstTime; | |
314 | ||
315 | messageStr[0] = 0; | |
316 | ||
317 | if (MessagePort) { | |
318 | MesNum = MessagePort; | |
319 | MessagePort = 0; | |
320 | LastMesTime = TickCount(); | |
321 | firstTime = 1; | |
322 | } else { | |
323 | firstTime = 0; | |
324 | if (MesNum == 0) return; | |
325 | if (MesNum < 0) { | |
326 | MesNum = -MesNum; | |
327 | LastMesTime = TickCount(); | |
328 | } else if ((TickCount() - LastMesTime) > (60 * 30)) { | |
329 | MesNum = 0; | |
330 | return; | |
331 | } | |
332 | } | |
333 | if (firstTime) { | |
334 | switch ((MesNum < 0) ? -MesNum : MesNum) { | |
335 | case 12: | |
336 | if (Rand(5) == 1) { | |
337 | MakeSound("city", "HonkHonk-Med"); | |
338 | } else if (Rand(5) == 1) { | |
339 | MakeSound("city", "HonkHonk-Low"); | |
340 | } else if (Rand(5) == 1) { | |
341 | MakeSound("city", "HonkHonk-High"); | |
342 | } | |
343 | break; | |
344 | case 11: | |
345 | case 20: | |
346 | case 22: | |
347 | case 23: | |
348 | case 24: | |
349 | case 25: | |
350 | case 26: | |
351 | case 27: | |
352 | MakeSound("city", "Siren"); | |
353 | break; | |
354 | case 21: | |
bf4857d3 | 355 | MakeSound("city", "Monster"); |
6a5fa4e0 MG |
356 | break; |
357 | case 30: | |
358 | MakeSound("city", "Explosion-Low"); | |
359 | MakeSound("city", "Siren"); | |
360 | break; | |
361 | case 43: | |
362 | MakeSound("city", "Explosion-High"); | |
363 | MakeSound("city", "Explosion-Low"); | |
364 | MakeSound("city", "Siren"); | |
365 | break; | |
366 | case 44: | |
367 | MakeSound("city", "Siren"); | |
368 | break; | |
369 | } | |
370 | } | |
371 | ||
372 | if (MesNum >= 0) { | |
373 | if (MesNum == 0) | |
374 | return; | |
375 | ||
376 | if (MesNum > 60) { | |
377 | MesNum = 0; | |
378 | return; | |
379 | } | |
380 | ||
381 | GetIndString(messageStr, 301, MesNum); | |
382 | if (MesX || MesY) { | |
383 | /* TODO: draw goto button */ | |
384 | } | |
385 | ||
386 | if (autoGo && (MesX || MesY)) { | |
387 | DoAutoGoto(MesX, MesY, messageStr); | |
388 | MesX = 0; | |
389 | MesY = 0; | |
390 | } else { | |
391 | SetMessageField(messageStr); | |
392 | } | |
393 | ||
394 | } else { /* picture message */ | |
395 | pictId = -(MesNum); | |
396 | ||
397 | if (pictId < 43) | |
398 | GetIndString(messageStr, 301, pictId); | |
399 | else | |
400 | messageStr[0] = '\0'; | |
401 | ||
402 | DoShowPicture(pictId); | |
403 | ||
404 | MessagePort = pictId; /* resend text message */ | |
405 | ||
406 | if (autoGo && (MesX || MesY)) { | |
407 | ||
408 | DoAutoGoto(MesX, MesY, messageStr); | |
409 | MesX = 0; | |
410 | MesY = 0; | |
411 | } | |
412 | } | |
413 | } | |
414 | ||
415 | ||
6f214ac0 | 416 | void |
6a5fa4e0 MG |
417 | DoAutoGoto(short x, short y, char *msg) |
418 | { | |
419 | char buf[256]; | |
420 | ||
421 | SetMessageField(msg); | |
422 | sprintf(buf, "UIAutoGoto %d %d", x, y); | |
423 | Eval(buf); | |
424 | } | |
425 | ||
426 | ||
6f214ac0 | 427 | void |
6a5fa4e0 MG |
428 | SetMessageField(char *str) |
429 | { | |
430 | char buf[256]; | |
431 | ||
432 | if (!HaveLastMessage || | |
433 | strcmp(LastMessage, str)) { | |
434 | strcpy(LastMessage, str); | |
435 | HaveLastMessage = 1; | |
436 | sprintf(buf, "UISetMessage {%s}", str); | |
437 | Eval(buf); | |
438 | } | |
439 | } | |
440 | ||
441 | ||
6f214ac0 | 442 | void |
6a5fa4e0 MG |
443 | DoShowPicture(short id) |
444 | { | |
445 | char buf[256]; | |
446 | ||
447 | sprintf(buf, "UIShowPicture %d", id); | |
448 | Eval(buf); | |
449 | } | |
450 | ||
451 | ||
6f214ac0 MG |
452 | void |
453 | DoLoseGame(void) | |
6a5fa4e0 MG |
454 | { |
455 | Eval("UILoseGame"); | |
456 | } | |
457 | ||
458 | ||
6f214ac0 MG |
459 | void |
460 | DoWinGame(void) | |
6a5fa4e0 MG |
461 | { |
462 | Eval("UIWinGame"); | |
463 | } | |
464 | ||
465 |