]> git.zerfleddert.de Git - micropolis/blame - src/sim/s_zone.c
rename setenv and unsetenv to not clash with functions provided by libc
[micropolis] / src / sim / s_zone.c
CommitLineData
6a5fa4e0
MG
1/* s_zone.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/* Zone Stuff */
66
67
68DoZone(void)
69{
70 short ZonePwrFlg;
71
72 ZonePwrFlg = SetZPower(); /* Set Power Bit in Map from PowerMap */
73 if (ZonePwrFlg) PwrdZCnt++;
74 else unPwrdZCnt++;
75
76 if (CChr9 > PORTBASE) { /* do Special Zones */
77 DoSPZone(ZonePwrFlg);
78 return;
79 }
80 if (CChr9 < HOSPITAL) {
81 DoResidential(ZonePwrFlg);
82 return;
83 }
84 if (CChr9 < COMBASE) {
85 DoHospChur();
86 return;
87 }
88 if (CChr9 < INDBASE) {
89 DoCommercial(ZonePwrFlg);
90 return;
91 }
92 DoIndustrial(ZonePwrFlg);
93 return;
94}
95
96
97DoHospChur(void)
98{
99 if (CChr9 == HOSPITAL) {
100 HospPop++;
101 if (!(CityTime & 15)) RepairZone (HOSPITAL, 3); /*post*/
102 if (NeedHosp == -1)
103 if (!Rand(20))
104 ZonePlop(RESBASE);
105 }
106 if (CChr9 == CHURCH) {
107 ChurchPop++;
108 if (!(CityTime & 15)) RepairZone (CHURCH, 3); /*post*/
109 if (NeedChurch == -1)
110 if (!Rand(20))
111 ZonePlop(RESBASE);
112 }
113}
114
115
116#define T 1
117#define F 0
118#define ASCBIT (ANIMBIT | CONDBIT | BURNBIT)
119#define REGBIT (CONDBIT | BURNBIT)
120
121SetSmoke(int ZonePower)
122{
123 static short AniThis[8] = { T, F, T, T, F, F, T, T };
124 static short DX1[8] = { -1, 0, 1, 0, 0, 0, 0, 1 };
125 static short DY1[8] = { -1, 0, -1, -1, 0, 0, -1, -1 };
126 static short DX2[8] = { -1, 0, 1, 1, 0, 0, 1, 1 };
127 static short DY2[8] = { -1, 0, 0, -1, 0, 0, -1, 0 };
128 static short AniTabA[8] = { 0, 0, 32, 40, 0, 0, 48, 56 };
129 static short AniTabB[8] = { 0, 0, 36, 44, 0, 0, 52, 60 };
130 static short AniTabC[8] = { IND1, 0, IND2, IND4, 0, 0, IND6, IND8 };
131 static short AniTabD[8] = { IND1, 0, IND3, IND5, 0, 0, IND7, IND9 };
132 register short z;
133
134 if (CChr9 < IZB) return;
135 z = (CChr9 - IZB) >>3;
136 z = z & 7;
137 if (AniThis[z]) {
138 int xx = SMapX + DX1[z];
139 int yy = SMapY + DY1[z];
140 if (TestBounds(xx, yy)) {
141 if (ZonePower) {
142 if ((Map[xx][yy] & LOMASK) == AniTabC[z]) {
143 Map[xx][yy] =
144 ASCBIT | (SMOKEBASE + AniTabA[z]);
145 Map[xx][yy] =
146 ASCBIT | (SMOKEBASE + AniTabB[z]);
147 }
148 } else {
149 if ((Map[xx][yy] & LOMASK) > AniTabC[z]) {
150 Map[xx][yy] =
151 REGBIT | AniTabC[z];
152 Map[xx][yy] =
153 REGBIT | AniTabD[z];
154 }
155 }
156 }
157 }
158}
159
160
161DoIndustrial(int ZonePwrFlg)
162{
163 short tpop, zscore, TrfGood;
164
165 IndZPop++;
166 SetSmoke(ZonePwrFlg);
167 tpop = IZPop(CChr9);
168 IndPop += tpop;
169 if (tpop > Rand(5)) TrfGood = MakeTraf(2);
170 else TrfGood = TRUE;
171
172 if (TrfGood == -1) {
173 DoIndOut(tpop, Rand16() & 1);
174 return;
175 }
176
177 if (!(Rand16() & 7)) {
178 zscore = IValve + EvalInd(TrfGood);
179 if (!ZonePwrFlg) zscore = -500;
180 if ((zscore > -350) &&
181 (((short)(zscore - 26380)) > ((short)Rand16Signed()))) {
182 DoIndIn(tpop, Rand16() & 1);
183 return;
184 }
185 if ((zscore < 350) &&
186 (((short)(zscore + 26380)) < ((short)Rand16Signed())))
187 DoIndOut(tpop, Rand16() & 1);
188 }
189}
190
191
192DoCommercial(int ZonePwrFlg)
193{
194 register short tpop, TrfGood;
195 short zscore, locvalve,value;
196
197 ComZPop++;
198 tpop = CZPop(CChr9);
199 ComPop += tpop;
200 if (tpop > Rand(5)) TrfGood = MakeTraf(1);
201 else TrfGood = TRUE;
202
203 if (TrfGood == -1) {
204 value = GetCRVal();
205 DoComOut(tpop, value);
206 return;
207 }
208
209 if (!(Rand16() & 7)) {
210 locvalve = EvalCom(TrfGood);
211 zscore = CValve + locvalve;
212 if (!ZonePwrFlg) zscore = -500;
213
214 if (TrfGood &&
215 (zscore > -350) &&
216 (((short)(zscore - 26380)) > ((short)Rand16Signed()))) {
217 value = GetCRVal();
218 DoComIn(tpop, value);
219 return;
220 }
221 if ((zscore < 350) &&
222 (((short)(zscore + 26380)) < ((short)Rand16Signed()))) {
223 value = GetCRVal();
224 DoComOut(tpop, value);
225 }
226 }
227}
228
229
230DoResidential(int ZonePwrFlg)
231{
232 short tpop, zscore, locvalve, value, TrfGood;
233
234 ResZPop++;
235 if (CChr9 == FREEZ) tpop = DoFreePop();
236 else tpop = RZPop(CChr9);
237
238 ResPop += tpop;
239 if (tpop > Rand(35)) TrfGood = MakeTraf(0);
240 else TrfGood = TRUE;
241
242 if (TrfGood == -1) {
243 value = GetCRVal();
244 DoResOut(tpop, value);
245 return;
246 }
247
248 if ((CChr9 == FREEZ) || (!(Rand16() & 7))) {
249 locvalve = EvalRes(TrfGood);
250 zscore = RValve + locvalve;
251 if (!ZonePwrFlg) zscore = -500;
252
253 if ((zscore > -350) &&
254 (((short)(zscore - 26380)) > ((short)Rand16Signed()))) {
255 if ((!tpop) && (!(Rand16() & 3))) {
256 MakeHosp();
257 return;
258 }
259 value = GetCRVal();
260 DoResIn(tpop, value);
261 return;
262 }
263 if ((zscore < 350) &&
264 (((short)(zscore + 26380)) < ((short)Rand16Signed()))) {
265 value = GetCRVal();
266 DoResOut(tpop, value);
267 }
268 }
269}
270
271
272MakeHosp(void)
273{
274 if (NeedHosp > 0) {
275 ZonePlop(HOSPITAL - 4);
276 NeedHosp = FALSE;
277 return;
278 }
279 if (NeedChurch > 0) {
280 ZonePlop(CHURCH - 4);
281 NeedChurch = FALSE;
282 return;
283 }
284}
285
286
287GetCRVal(void)
288{
289 register short LVal;
290
291 LVal = LandValueMem[SMapX >>1][SMapY >>1];
292 LVal -= PollutionMem[SMapX >>1][SMapY >>1];
293 if (LVal < 30) return (0);
294 if (LVal < 80) return (1);
295 if (LVal < 150) return (2);
296 return (3);
297}
298
299
300DoResIn(int pop, int value)
301{
302 short z;
303
304 z = PollutionMem[SMapX >>1][SMapY >>1];
305 if (z > 128) return;
306
307 if (CChr9 == FREEZ) {
308 if (pop < 8) {
309 BuildHouse(value);
310 IncROG(1);
311 return;
312 }
313 if (PopDensity[SMapX >>1][SMapY >>1] > 64) {
314 ResPlop(0, value);
315 IncROG(8);
316 return;
317 }
318 return;
319 }
320 if (pop < 40) {
321 ResPlop((pop / 8) - 1, value);
322 IncROG(8);
323 }
324}
325
326
327DoComIn(int pop, int value)
328{
329 register short z;
330
331 z = LandValueMem[SMapX >>1][SMapY >>1];
332 z = z >>5;
333 if (pop > z) return;
334
335 if (pop < 5) {
336 ComPlop(pop, value);
337 IncROG(8);
338 }
339}
340
341
342DoIndIn(int pop, int value)
343{
344 if (pop < 4) {
345 IndPlop(pop, value);
346 IncROG(8);
347 }
348}
349
350
351IncROG(int amount)
352{
353 RateOGMem[SMapX>>3][SMapY>>3] += amount<<2;
354}
355
356
357DoResOut(int pop, int value)
358{
359 static short Brdr[9] = {0,3,6,1,4,7,2,5,8};
360 register short x, y, loc, z;
361
362 if (!pop) return;
363 if (pop > 16) {
364 ResPlop(((pop - 24) / 8), value);
365 IncROG(-8);
366 return;
367 }
368 if (pop == 16) {
369 IncROG(-8);
370 Map[SMapX][SMapY] = (FREEZ | BLBNCNBIT | ZONEBIT);
371 for (x = SMapX - 1; x <= SMapX + 1; x++)
372 for (y = SMapY - 1; y <= SMapY + 1; y++)
373 if (x >= 0 && x < WORLD_X &&
374 y >= 0 && y < WORLD_Y) {
375 if ((Map[x][y] & LOMASK) != FREEZ)
376 Map[x][y] = LHTHR + value +
377 Rand(2) + BLBNCNBIT;
378 }
379 }
380 if (pop < 16) {
381 IncROG(-1);
382 z = 0;
383 for (x = SMapX - 1; x <= SMapX + 1; x++)
384 for (y = SMapY - 1; y <= SMapY + 1; y++) {
385 if (x >= 0 && x < WORLD_X &&
386 y >= 0 && y < WORLD_Y) {
387 loc = Map[x][y] & LOMASK;
388 if ((loc >= LHTHR) && (loc <= HHTHR)) {
389 Map[x][y] = Brdr[z] +
390 BLBNCNBIT + FREEZ - 4;
391 return;
392 }
393 }
394 z++;
395 }
396 }
397}
398
399
400DoComOut(int pop, int value)
401{
402 if (pop > 1) {
403 ComPlop(pop - 2, value);
404 IncROG(-8);
405 return;
406 }
407 if (pop == 1) {
408 ZonePlop(COMBASE);
409 IncROG(-8);
410 }
411}
412
413
414DoIndOut(int pop, int value)
415{
416 if (pop > 1) {
417 IndPlop(pop - 2, value);
418 IncROG(-8);
419 return;
420 }
421 if (pop == 1) {
422 ZonePlop(INDCLR - 4);
423 IncROG(-8);
424 }
425}
426
427
428RZPop(int Ch9)
429{
430 short CzDen;
431
432 CzDen = (((Ch9 - RZB) / 9) % 4);
433 return ((CzDen * 8) + 16);
434}
435
436
437CZPop(int Ch9)
438{
439 short CzDen;
440
441 if (Ch9 == COMCLR) return (0);
442 CzDen = (((Ch9 - CZB) / 9) % 5) + 1;
443 return (CzDen);
444}
445
446
447IZPop(int Ch9)
448{
449 short CzDen;
450
451 if (Ch9 == INDCLR) return (0);
452 CzDen = (((Ch9 - IZB) / 9) % 4) + 1;
453 return (CzDen);
454}
455
456
457BuildHouse(int value)
458{
459 short z, score, hscore, BestLoc;
460 static short ZeX[9] = { 0,-1, 0, 1,-1, 1,-1, 0, 1};
461 static short ZeY[9] = { 0,-1,-1,-1, 0, 0, 1, 1, 1};
462
463 BestLoc = 0;
464 hscore = 0;
465 for (z = 1; z < 9; z++) {
466 int xx = SMapX + ZeX[z];
467 int yy = SMapY + ZeY[z];
468 if (TestBounds(xx, yy)) {
469 score = EvalLot(xx, yy);
470 if (score != 0) {
471 if (score > hscore) {
472 hscore = score;
473 BestLoc = z;
474 }
475 if ((score == hscore) && !(Rand16() & 7))
476 BestLoc = z;
477 }
478 }
479 }
480 if (BestLoc) {
481 int xx = SMapX + ZeX[BestLoc];
482 int yy = SMapY + ZeY[BestLoc];
483 if (TestBounds(xx, yy)) {
484 Map[xx][yy] = HOUSE + BLBNCNBIT + Rand(2) + (value * 3);
485 }
486 }
487}
488
489
490ResPlop (int Den, int Value)
491{
492 short base;
493
494 base = (((Value * 4) + Den) * 9) + RZB - 4;
495 ZonePlop(base);
496}
497
498
499ComPlop (int Den, int Value)
500{
501 short base;
502
503 base = (((Value * 5) + Den) * 9) + CZB - 4;
504 ZonePlop(base);
505}
506
507
508IndPlop (int Den, int Value)
509{
510 short base;
511
512 base = (((Value * 4) + Den) * 9) + (IZB - 4);
513 ZonePlop (base);
514}
515
516
517EvalLot (int x, int y)
518{
519 short z, score;
520 static short DX[4] = { 0, 1, 0,-1};
521 static short DY[4] = {-1, 0, 1, 0};
522
523 /* test for clear lot */
524 z = Map[x][y] & LOMASK;
525 if (z && ((z < RESBASE) || (z > RESBASE + 8)))
526 return (-1);
527 score = 1;
528 for (z = 0; z < 4; z++) {
529 int xx = x + DX[z];
530 int yy = y + DY[z];
531 if (TestBounds(xx, yy) &&
532 Map[xx][yy] &&
533 ((Map[xx][yy] & LOMASK) <= LASTROAD)) {
534 score++; /* look for road */
535 }
536 }
537 return (score);
538}
539
540
541ZonePlop (int base)
542{
543 short z, x;
544 static short Zx[9] = {-1, 0, 1,-1, 0, 1,-1, 0, 1};
545 static short Zy[9] = {-1,-1,-1, 0, 0, 0, 1, 1, 1};
546
547 for (z = 0; z < 9; z++) { /* check for fire */
548 int xx = SMapX + Zx[z];
549 int yy = SMapY + Zy[z];
550 if (TestBounds(xx, yy)) {
551 x = Map[xx][yy] & LOMASK;
552 if ((x >= FLOOD) && (x < ROADBASE)) return (FALSE);
553 }
554 }
555 for (z = 0; z < 9; z++) {
556 int xx = SMapX + Zx[z];
557 int yy = SMapY + Zy[z];
558 if (TestBounds(xx, yy)) {
559 Map[xx][yy] = base + BNCNBIT;
560 }
561 base++;
562 }
563 CChr = Map[SMapX][SMapY];
564 SetZPower();
565 Map[SMapX][SMapY] |= ZONEBIT + BULLBIT;
566}
567
568
569EvalRes (int traf)
570{
571 register short Value;
572
573 if (traf < 0) return (-3000);
574
575 Value = LandValueMem[SMapX >>1][SMapY >>1];
576 Value -= PollutionMem[SMapX >>1][SMapY >>1];
577
578 if (Value < 0) Value = 0; /* Cap at 0 */
579 else Value = Value <<5;
580
581 if (Value > 6000) Value = 6000; /* Cap at 6000 */
582
583 Value = Value - 3000;
584 return (Value);
585}
586
587
588EvalCom (int traf)
589{
590 short Value;
591
592 if (traf < 0) return (-3000);
593 Value = ComRate[SMapX >>3][SMapY >>3];
594 return (Value);
595}
596
597
598EvalInd (int traf)
599{
600 if (traf < 0) return (-1000);
601 return (0);
602}
603
604
605DoFreePop (void)
606{
607 short count;
608 register short loc, x, y;
609
610 count = 0;
611 for (x = SMapX - 1; x <= SMapX + 1; x++)
612 for (y = SMapY - 1; y <= SMapY + 1; y++) {
613 if (x >= 0 && x < WORLD_X &&
614 y >= 0 && y < WORLD_Y) {
615 loc = Map[x][y] & LOMASK;
616 if ((loc >= LHTHR) && (loc <= HHTHR))
617 count++;
618 }
619 }
620 return (count);
621}
622
623
624SetZPower(void) /* set bit in MapWord depending on powermap */
625{
626 short z;
627 QUAD PowerWrd;
628
629/* TestPowerBit was taking alot of time so I inlined it. -Don */
630
631#if 0
632
633 if (z = TestPowerBit())
634 Map[SMapX][SMapY] = CChr | PWRBIT;
635 else
636 Map[SMapX][SMapY] = CChr & (~PWRBIT);
637 return (z);
638
639#else
640
641 if ((CChr9 == NUCLEAR) ||
642 (CChr9 == POWERPLANT) ||
643 (
644#if 1
645 (PowerWrd = POWERWORD(SMapX, SMapY)),
646#else
647 (PowerWrd = (SMapX >>4) + (SMapY <<3)),
648#endif
649 ((PowerWrd < PWRMAPSIZE) &&
650 (PowerMap[PowerWrd] & (1 << (SMapX & 15)))))) {
651 Map[SMapX][SMapY] = CChr | PWRBIT;
652 return 1;
653 } else {
654 Map[SMapX][SMapY] = CChr & (~PWRBIT);
655 return 0;
656 }
657
658#endif
659}
Impressum, Datenschutz