|
|
1.1 root 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 [email protected].
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:
68: DoZone(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:
97: DoHospChur(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:
121: SetSmoke(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:
161: DoIndustrial(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:
192: DoCommercial(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:
230: DoResidential(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:
272: MakeHosp(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:
287: GetCRVal(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:
300: DoResIn(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:
327: DoComIn(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:
342: DoIndIn(int pop, int value)
343: {
344: if (pop < 4) {
345: IndPlop(pop, value);
346: IncROG(8);
347: }
348: }
349:
350:
351: IncROG(int amount)
352: {
353: RateOGMem[SMapX>>3][SMapY>>3] += amount<<2;
354: }
355:
356:
357: DoResOut(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:
400: DoComOut(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:
414: DoIndOut(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:
428: RZPop(int Ch9)
429: {
430: short CzDen;
431:
432: CzDen = (((Ch9 - RZB) / 9) % 4);
433: return ((CzDen * 8) + 16);
434: }
435:
436:
437: CZPop(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:
447: IZPop(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:
457: BuildHouse(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:
490: ResPlop (int Den, int Value)
491: {
492: short base;
493:
494: base = (((Value * 4) + Den) * 9) + RZB - 4;
495: ZonePlop(base);
496: }
497:
498:
499: ComPlop (int Den, int Value)
500: {
501: short base;
502:
503: base = (((Value * 5) + Den) * 9) + CZB - 4;
504: ZonePlop(base);
505: }
506:
507:
508: IndPlop (int Den, int Value)
509: {
510: short base;
511:
512: base = (((Value * 4) + Den) * 9) + (IZB - 4);
513: ZonePlop (base);
514: }
515:
516:
517: EvalLot (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:
541: ZonePlop (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:
569: EvalRes (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:
588: EvalCom (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:
598: EvalInd (int traf)
599: {
600: if (traf < 0) return (-1000);
601: return (0);
602: }
603:
604:
605: DoFreePop (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:
624: SetZPower(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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.