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