]>
Commit | Line | Data |
---|---|---|
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]; | |
71 | int DoAutoGoto(short x, short y, char *msg); | |
72 | int DoShowPicture(short id); | |
73 | ||
74 | /* comefrom: Simulate */ | |
75 | SendMessages(void) | |
76 | { | |
77 | register z; | |
78 | short PowerPop; | |
79 | float TM; | |
80 | ||
81 | if ((ScenarioID) && (ScoreType) && (ScoreWait)) { | |
82 | ScoreWait--; | |
83 | if (!ScoreWait) | |
84 | DoScenarioScore(ScoreType); | |
85 | } | |
86 | ||
87 | CheckGrowth(); | |
88 | ||
89 | TotalZPop = ResZPop + ComZPop + IndZPop; | |
90 | PowerPop = NuclearPop + CoalPop; | |
91 | ||
92 | z = CityTime & 63; | |
93 | ||
94 | switch(z) { | |
95 | ||
96 | case 1: | |
97 | if ((TotalZPop >>2) >= ResZPop) | |
98 | SendMes(1); /* need Res */ | |
99 | break; | |
100 | case 5: | |
101 | if ((TotalZPop >>3) >= ComZPop) | |
102 | SendMes(2); /* need Com */ | |
103 | break; | |
104 | case 10: | |
105 | if ((TotalZPop >>3) >= IndZPop) | |
106 | SendMes(3); /* need Ind */ | |
107 | break; | |
108 | case 14: | |
109 | if ((TotalZPop > 10) && ((TotalZPop <<1) > RoadTotal)) | |
110 | SendMes(4); | |
111 | break; | |
112 | case 18: | |
113 | if ((TotalZPop > 50) && (TotalZPop > RailTotal)) | |
114 | SendMes(5); | |
115 | break; | |
116 | case 22: | |
117 | if ((TotalZPop > 10) && (PowerPop == 0)) | |
118 | SendMes(6); /* need Power */ | |
119 | break; | |
120 | case 26: | |
121 | if ((ResPop > 500) && (StadiumPop == 0)) { | |
122 | SendMes(7); /* need Stad */ | |
123 | ResCap = 1; | |
124 | } | |
125 | else | |
126 | ResCap = 0; | |
127 | break; | |
128 | case 28: | |
129 | if ((IndPop > 70) && (PortPop == 0)) { | |
130 | SendMes(8); | |
131 | IndCap = 1; | |
132 | } | |
133 | else IndCap = 0; | |
134 | break; | |
135 | case 30: | |
136 | if ((ComPop > 100) && (APortPop == 0)) { | |
137 | SendMes(9); | |
138 | ComCap = 1; | |
139 | } | |
140 | else ComCap = 0; | |
141 | break; | |
142 | case 32: | |
143 | TM = unPwrdZCnt + PwrdZCnt; /* dec score for unpowered zones */ | |
144 | if (TM) | |
145 | if ((PwrdZCnt / TM) < .7) | |
146 | SendMes(15); | |
147 | break; | |
148 | case 35: | |
149 | if (PolluteAverage > /* 80 */ 60) | |
150 | SendMes(-10); | |
151 | break; | |
152 | case 42: | |
153 | if (CrimeAverage > 100) | |
154 | SendMes(-11); | |
155 | break; | |
156 | case 45: | |
157 | if ((TotalPop > 60) && (FireStPop == 0)) | |
158 | SendMes(13); | |
159 | break; | |
160 | case 48: | |
161 | if ((TotalPop > 60) && (PolicePop == 0)) | |
162 | SendMes(14); | |
163 | break; | |
164 | case 51: | |
165 | if (CityTax > 12) | |
166 | SendMes(16); | |
167 | break; | |
168 | case 54: | |
169 | if ((RoadEffect < 20) && (RoadTotal > 30)) | |
170 | SendMes(17); | |
171 | break; | |
172 | case 57: | |
173 | if ((FireEffect < 700) && (TotalPop > 20)) | |
174 | SendMes(18); | |
175 | break; | |
176 | case 60: | |
177 | if ((PoliceEffect < 700) && (TotalPop > 20)) | |
178 | SendMes(19); | |
179 | break; | |
180 | case 63: | |
181 | if (TrafficAverage > 60) | |
182 | SendMes(-12); | |
183 | break; | |
184 | } | |
185 | } | |
186 | ||
187 | ||
188 | /* comefrom: SendMessages */ | |
189 | CheckGrowth(void) | |
190 | { | |
191 | QUAD ThisCityPop; | |
192 | short z; | |
193 | ||
194 | if (!(CityTime & 3)) { | |
195 | z = 0; | |
196 | ThisCityPop = ((ResPop) + (ComPop * 8L) + (IndPop * 8L)) * 20L; | |
197 | if (LastCityPop) { | |
198 | if ((LastCityPop < 2000) && (ThisCityPop >= 2000)) z = 35; | |
199 | if ((LastCityPop < 10000) && (ThisCityPop >= 10000)) z = 36; | |
200 | if ((LastCityPop < 50000L) && (ThisCityPop >= 50000L)) z = 37; | |
201 | if ((LastCityPop < 100000L) && (ThisCityPop >= 100000L)) z = 38; | |
202 | if ((LastCityPop < 500000L) && (ThisCityPop >= 500000L)) z = 39; | |
203 | } | |
204 | if (z) | |
205 | if (z != LastCategory) { | |
206 | SendMes(-z); | |
207 | LastCategory = z; | |
208 | } | |
209 | LastCityPop = ThisCityPop; | |
210 | } | |
211 | } | |
212 | ||
213 | ||
214 | /* comefrom: SendMessages */ | |
215 | DoScenarioScore(int type) | |
216 | { | |
217 | short z; | |
218 | ||
219 | z = -200; /* you lose */ | |
220 | switch(type) { | |
221 | case 1: /* Dullsville */ | |
222 | if (CityClass >= 4) z = -100; | |
223 | break; | |
224 | case 2: /* San Francisco */ | |
225 | if (CityClass >= 4) z = -100; | |
226 | break; | |
227 | case 3: /* Hamburg */ | |
228 | if (CityClass >= 4) z = -100; | |
229 | break; | |
230 | case 4: /* Bern */ | |
231 | if (TrafficAverage < 80) z = -100; | |
232 | break; | |
233 | case 5: /* Tokyo */ | |
234 | if (CityScore > 500) z = -100; | |
235 | break; | |
236 | case 6: /* Detroit */ | |
237 | if (CrimeAverage < 60) z = -100; | |
238 | break; | |
239 | case 7: /* Boston */ | |
240 | if (CityScore > 500) z = -100; | |
241 | break; | |
242 | case 8: /* Rio de Janeiro */ | |
243 | if (CityScore > 500) z = -100; | |
244 | break; | |
245 | } | |
246 | ClearMes(); | |
247 | SendMes(z); | |
248 | ||
249 | if (z == -200) | |
250 | DoLoseGame(); | |
251 | } | |
252 | ||
253 | ||
254 | ClearMes(void) | |
255 | { | |
256 | MessagePort = 0; | |
257 | MesX = 0; | |
258 | MesY = 0; | |
259 | LastPicNum = 0; | |
260 | } | |
261 | ||
262 | ||
263 | /* comefrom: MakeEarthquake MakeFire MakeFire MakeFlood SendMessages | |
264 | CheckGrowth DoScenarioScore DoPowerScan */ | |
265 | SendMes(int Mnum) | |
266 | { | |
267 | if (Mnum < 0) { | |
268 | if (Mnum != LastPicNum) { | |
269 | MessagePort = Mnum; | |
270 | MesX = 0; | |
271 | MesY = 0; | |
272 | LastPicNum = Mnum; | |
273 | return (1); | |
274 | } | |
275 | } else { | |
276 | if (!(MessagePort)) { | |
277 | MessagePort = Mnum; | |
278 | MesX = 0; | |
279 | MesY = 0; | |
280 | return(1); | |
281 | } | |
282 | } | |
283 | return(0); | |
284 | } | |
285 | ||
286 | ||
287 | /* comefrom: DoExplosion DoCopter ExplodeObject */ | |
288 | void SendMesAt(short Mnum, short x, short y) | |
289 | { | |
290 | if (SendMes(Mnum)) { | |
291 | MesX = x; | |
292 | MesY = y; | |
293 | } | |
294 | } | |
295 | ||
296 | ||
297 | doMessage(void) | |
298 | { | |
299 | char messageStr[256]; | |
300 | short pictId; | |
301 | short firstTime; | |
302 | ||
303 | messageStr[0] = 0; | |
304 | ||
305 | if (MessagePort) { | |
306 | MesNum = MessagePort; | |
307 | MessagePort = 0; | |
308 | LastMesTime = TickCount(); | |
309 | firstTime = 1; | |
310 | } else { | |
311 | firstTime = 0; | |
312 | if (MesNum == 0) return; | |
313 | if (MesNum < 0) { | |
314 | MesNum = -MesNum; | |
315 | LastMesTime = TickCount(); | |
316 | } else if ((TickCount() - LastMesTime) > (60 * 30)) { | |
317 | MesNum = 0; | |
318 | return; | |
319 | } | |
320 | } | |
321 | if (firstTime) { | |
322 | switch ((MesNum < 0) ? -MesNum : MesNum) { | |
323 | case 12: | |
324 | if (Rand(5) == 1) { | |
325 | MakeSound("city", "HonkHonk-Med"); | |
326 | } else if (Rand(5) == 1) { | |
327 | MakeSound("city", "HonkHonk-Low"); | |
328 | } else if (Rand(5) == 1) { | |
329 | MakeSound("city", "HonkHonk-High"); | |
330 | } | |
331 | break; | |
332 | case 11: | |
333 | case 20: | |
334 | case 22: | |
335 | case 23: | |
336 | case 24: | |
337 | case 25: | |
338 | case 26: | |
339 | case 27: | |
340 | MakeSound("city", "Siren"); | |
341 | break; | |
342 | case 21: | |
343 | MakeSound("city", "Monster -speed [MonsterSpeed]"); | |
344 | break; | |
345 | case 30: | |
346 | MakeSound("city", "Explosion-Low"); | |
347 | MakeSound("city", "Siren"); | |
348 | break; | |
349 | case 43: | |
350 | MakeSound("city", "Explosion-High"); | |
351 | MakeSound("city", "Explosion-Low"); | |
352 | MakeSound("city", "Siren"); | |
353 | break; | |
354 | case 44: | |
355 | MakeSound("city", "Siren"); | |
356 | break; | |
357 | } | |
358 | } | |
359 | ||
360 | if (MesNum >= 0) { | |
361 | if (MesNum == 0) | |
362 | return; | |
363 | ||
364 | if (MesNum > 60) { | |
365 | MesNum = 0; | |
366 | return; | |
367 | } | |
368 | ||
369 | GetIndString(messageStr, 301, MesNum); | |
370 | if (MesX || MesY) { | |
371 | /* TODO: draw goto button */ | |
372 | } | |
373 | ||
374 | if (autoGo && (MesX || MesY)) { | |
375 | DoAutoGoto(MesX, MesY, messageStr); | |
376 | MesX = 0; | |
377 | MesY = 0; | |
378 | } else { | |
379 | SetMessageField(messageStr); | |
380 | } | |
381 | ||
382 | } else { /* picture message */ | |
383 | pictId = -(MesNum); | |
384 | ||
385 | if (pictId < 43) | |
386 | GetIndString(messageStr, 301, pictId); | |
387 | else | |
388 | messageStr[0] = '\0'; | |
389 | ||
390 | DoShowPicture(pictId); | |
391 | ||
392 | MessagePort = pictId; /* resend text message */ | |
393 | ||
394 | if (autoGo && (MesX || MesY)) { | |
395 | ||
396 | DoAutoGoto(MesX, MesY, messageStr); | |
397 | MesX = 0; | |
398 | MesY = 0; | |
399 | } | |
400 | } | |
401 | } | |
402 | ||
403 | ||
404 | DoAutoGoto(short x, short y, char *msg) | |
405 | { | |
406 | char buf[256]; | |
407 | ||
408 | SetMessageField(msg); | |
409 | sprintf(buf, "UIAutoGoto %d %d", x, y); | |
410 | Eval(buf); | |
411 | } | |
412 | ||
413 | ||
414 | SetMessageField(char *str) | |
415 | { | |
416 | char buf[256]; | |
417 | ||
418 | if (!HaveLastMessage || | |
419 | strcmp(LastMessage, str)) { | |
420 | strcpy(LastMessage, str); | |
421 | HaveLastMessage = 1; | |
422 | sprintf(buf, "UISetMessage {%s}", str); | |
423 | Eval(buf); | |
424 | } | |
425 | } | |
426 | ||
427 | ||
428 | DoShowPicture(short id) | |
429 | { | |
430 | char buf[256]; | |
431 | ||
432 | sprintf(buf, "UIShowPicture %d", id); | |
433 | Eval(buf); | |
434 | } | |
435 | ||
436 | ||
437 | DoLoseGame() | |
438 | { | |
439 | Eval("UILoseGame"); | |
440 | } | |
441 | ||
442 | ||
443 | DoWinGame() | |
444 | { | |
445 | Eval("UIWinGame"); | |
446 | } | |
447 | ||
448 |