]>
git.zerfleddert.de Git - micropolis/blob - src/sim/s_sim.c
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.
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.
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/>.
21 * ADDITIONAL TERMS per GNU GPL Section 7
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.
29 * Any propagation or conveyance of this program must include this
30 * copyright notice and these terms.
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.
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.
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
69 short CrimeRamp
, PolluteRamp
;
70 short RValve
, CValve
, IValve
;
71 short ResCap
, ComCap
, IndCap
;
80 short NewPower
; /* post */
85 short DoInitialEval
= 0;
89 /* comefrom: doEditWindow scoreDoer doMapInFront graphDoer doNilEvent */
97 if (++Spdcycle
> 1023)
100 if (SimSpeed
== 1 && Spdcycle
% 5)
103 if (SimSpeed
== 2 && Spdcycle
% 3)
106 if (++Fcycle
> 1023) Fcycle
= 0;
107 /* if (InitSimLoad) Fcycle = 0; */
108 Simulate(Fcycle
& 15);
112 /* comefrom: SimFrame */
115 static short SpdPwr
[4] = { 1, 2, 4, 5 };
116 static short SpdPtl
[4] = { 1, 2, 7, 17 };
117 static short SpdCri
[4] = { 1, 1, 8, 18 };
118 static short SpdPop
[4] = { 1, 1, 9, 19 };
119 static short SpdFir
[4] = { 1, 1, 10, 20 };
127 if (++Scycle
> 1023) Scycle
= 0; /* this is cosmic */
133 AvCityTax
+= CityTax
; /* post */
134 if (!(Scycle
& 1)) SetValves();
138 MapScan(0, 1 * WORLD_X
/ 8);
141 MapScan(1 * WORLD_X
/ 8, 2 * WORLD_X
/ 8);
144 MapScan(2 * WORLD_X
/ 8, 3 * WORLD_X
/ 8);
147 MapScan(3 * WORLD_X
/ 8, 4 * WORLD_X
/ 8);
150 MapScan(4 * WORLD_X
/ 8, 5 * WORLD_X
/ 8);
153 MapScan(5 * WORLD_X
/ 8, 6 * WORLD_X
/ 8);
156 MapScan(6 * WORLD_X
/ 8, 7 * WORLD_X
/ 8);
159 MapScan(7 * WORLD_X
/ 8, WORLD_X
);
162 if (!(CityTime
% CENSUSRATE
)) TakeCensus();
163 if (!(CityTime
% (CENSUSRATE
* 12))) Take2Census();
165 if (!(CityTime
% TAXFREQ
)) {
171 if (!(Scycle
% 5)) DecROGMem();
173 NewMapFlags
[TDMAP
] = 1;
174 NewMapFlags
[RDMAP
] = 1;
175 NewMapFlags
[ALMAP
] = 1;
176 NewMapFlags
[REMAP
] = 1;
177 NewMapFlags
[COMAP
] = 1;
178 NewMapFlags
[INMAP
] = 1;
179 NewMapFlags
[DYMAP
] = 1;
183 if (!(Scycle
% SpdPwr
[x
])) {
185 NewMapFlags
[PRMAP
] = 1;
186 NewPower
= 1; /* post-release change */
190 if (!(Scycle
% SpdPtl
[x
])) PTLScan();
193 if (!(Scycle
% SpdCri
[x
])) CrimeScan();
196 if (!(Scycle
% SpdPop
[x
])) PopDenScan();
199 if (!(Scycle
% SpdFir
[x
])) FireAnalysis();
206 /* comefrom: Simulate */
212 if (InitSimLoad
== 2) /* if new city */
215 if (InitSimLoad
== 1) /* if city just loaded */
221 MapScan(0, WORLD_X
); /* XXX are you sure ??? */
224 NewPower
= 1; /* post rel */
237 /* comefrom: SimLoadInit */
240 register short x
, y
, z
;
242 for (x
= 0; x
< WORLD_X
; x
++)
243 for (y
= 0; y
< WORLD_Y
; y
++) {
255 /* comefrom: Simulate */
256 DecTrafficMem(void) /* tends to empty TrfDensity */
258 register short x
, y
, z
;
260 for (x
= 0; x
< HWLDX
; x
++)
261 for (y
= 0; y
< HWLDY
; y
++)
262 if (z
= TrfDensity
[x
][y
]) {
264 if (z
> 200) TrfDensity
[x
][y
] = z
- 34;
265 else TrfDensity
[x
][y
] = z
- 24;
267 else TrfDensity
[x
][y
] = 0;
272 /* comefrom: Simulate */
273 DecROGMem(void) /* tends to empty RateOGMem */
275 register short x
, y
, z
;
277 for (x
= 0; x
< SmX
; x
++)
278 for (y
= 0; y
< SmY
; y
++) {
280 if (z
== 0) continue;
283 if (z
> 200) RateOGMem
[x
][y
] = 200; /* prevent overflow */
288 if (z
< -200) RateOGMem
[x
][y
] = -200;
294 /* comefrom: DoSimInit */
301 for (x
= 0; x
< 240; x
++) {
323 /* This clears powermem */
326 NewPower
= 1; /* post rel */
332 /* comefrom: DoSimInit */
335 static short DisTab
[9] = { 0, 2, 10, 5, 20, 3, 5, 5, 2 * 48};
336 static short ScoreWaitTab
[9] = { 0, 30 * 48, 5 * 48, 5 * 48, 10 * 48,
337 5 * 48, 10 * 48, 5 * 48, 10 * 48 };
341 EMarket
= (float)MiscHis
[1];
348 CrimeRamp
= MiscHis
[10];
349 PolluteRamp
= MiscHis
[11];
350 LVAverage
= MiscHis
[12];
351 CrimeAverage
= MiscHis
[13];
352 PolluteAverage
= MiscHis
[14];
353 GameLevel
= MiscHis
[15];
355 if (CityTime
< 0) CityTime
= 0;
356 if (!EMarket
) EMarket
= 4.0;
357 if ((GameLevel
> 2) || (GameLevel
< 0)) GameLevel
= 0;
358 SetGameLevel(GameLevel
);
362 CityClass
= MiscHis
[16];
363 CityScore
= MiscHis
[17];
365 if ((CityClass
> 5) || (CityClass
< 0)) CityClass
= 0;
366 if ((CityScore
> 999) || (CityScore
< 1)) CityScore
= 500;
372 AvCityTax
= (CityTime
% 48) * 7; /* post */
374 for (z
= 0; z
< PWRMAPSIZE
; z
++)
375 PowerMap
[z
] = ~0; /* set power Map */
378 if (ScenarioID
> 8) ScenarioID
= 0;
381 DisasterEvent
= ScenarioID
;
382 DisasterWait
= DisTab
[DisasterEvent
];
383 ScoreType
= DisasterEvent
;
384 ScoreWait
= ScoreWaitTab
[DisasterEvent
];
391 PoliceEffect
= 1000; /*post*/
397 /* comefrom: InitSimMemory SimLoadInit */
407 if ((GameLevel > 2) || (GameLevel < 0)) GameLevel = 0;
408 setGameLevel(GameLevel);
413 /* comefrom: Simulate DoSimInit */
416 static short TaxTable
[21] = {
417 200, 150, 120, 100, 80, 50, 30, 0, -10, -40, -100,
418 -150, -200, -250, -300, -350, -400, -450, -500, -550, -600 };
419 float Employment
, Migration
, Births
, LaborBase
, IntMarket
;
420 float Rratio
, Cratio
, Iratio
, temp
;
421 float NormResPop
, PjResPop
, PjComPop
, PjIndPop
;
424 MiscHis
[1] = (short)EMarket
;
431 MiscHis
[10] = CrimeRamp
;
432 MiscHis
[11] = PolluteRamp
;
433 MiscHis
[12] = LVAverage
;
434 MiscHis
[13] = CrimeAverage
;
435 MiscHis
[14] = PolluteAverage
;
436 MiscHis
[15] = GameLevel
;
437 MiscHis
[16] = CityClass
;
438 MiscHis
[17] = CityScore
;
440 NormResPop
= ResPop
/ 8;
441 LastTotalPop
= TotalPop
;
442 TotalPop
= NormResPop
+ ComPop
+ IndPop
;
444 if (NormResPop
) Employment
= ((ComHis
[1] + IndHis
[1]) / NormResPop
);
447 Migration
= NormResPop
* (Employment
- 1);
448 Births
= NormResPop
* (.02); /* Birth Rate */
449 PjResPop
= NormResPop
+ Migration
+ Births
; /* Projected Res.Pop */
451 if (temp
= (ComHis
[1] + IndHis
[1])) LaborBase
= (ResHis
[1] / temp
);
453 if (LaborBase
> 1.3) LaborBase
= 1.3;
454 if (LaborBase
< 0) LaborBase
= 0; /* LB > 1 - .1 */
456 for (z
= 0; z
< 2; z
++)
457 temp
= ResHis
[z
] + ComHis
[z
] + IndHis
[z
];
458 IntMarket
= (NormResPop
+ ComPop
+ IndPop
) / 3.7;
460 PjComPop
= IntMarket
* LaborBase
;
462 z
= GameLevel
; /* New ExtMarket */
476 PjIndPop
= IndPop
* LaborBase
* temp
;
477 if (PjIndPop
< 5) PjIndPop
= 5;
479 if (NormResPop
) Rratio
= (PjResPop
/ NormResPop
); /* projected -vs- actual */
481 if (ComPop
) Cratio
= (PjComPop
/ ComPop
);
482 else Cratio
= PjComPop
;
483 if (IndPop
) Iratio
= (PjIndPop
/ IndPop
);
484 else Iratio
= PjIndPop
;
486 if (Rratio
> 2) Rratio
= 2;
487 if (Cratio
> 2) Cratio
= 2;
488 if (Iratio
> 2) Iratio
= 2;
490 z
= CityTax
+ GameLevel
;
492 Rratio
= ((Rratio
-1) * 600) + TaxTable
[z
]; /* global tax/Glevel effects */
493 Cratio
= ((Cratio
-1) * 600) + TaxTable
[z
];
494 Iratio
= ((Iratio
-1) * 600) + TaxTable
[z
];
496 if (Rratio
> 0) /* ratios are velocity changes to valves */
497 if (RValve
< 2000) RValve
+= Rratio
;
499 if (RValve
> -2000) RValve
+= Rratio
;
501 if (CValve
< 1500) CValve
+= Cratio
;
503 if (CValve
> -1500) CValve
+= Cratio
;
505 if (IValve
< 1500) IValve
+= Iratio
;
507 if (IValve
> -1500) IValve
+= Iratio
;
509 if (RValve
> 2000) RValve
= 2000;
510 if (RValve
< -2000) RValve
= -2000;
511 if (CValve
> 1500) CValve
= 1500;
512 if (CValve
< -1500) CValve
= -1500;
513 if (IValve
> 1500) IValve
= 1500;
514 if (IValve
< -1500) IValve
= -1500;
516 if ((ResCap
) && (RValve
> 0)) RValve
= 0; /* Stad, Prt, Airprt */
517 if ((ComCap
) && (CValve
> 0)) CValve
= 0;
518 if ((IndCap
) && (IValve
> 0)) IValve
= 0;
523 /* comefrom: Simulate DoSimInit */
526 register short x
, y
, z
;
549 PowerStackNum
= z
; /* Reset before Mapscan */
550 for (x
= 0; x
< SmX
; x
++)
551 for (y
= 0; y
< SmY
; y
++) {
558 /* comefrom: Simulate */
563 /* put census#s in Historical Graphs and scroll data */
567 for (x
= 118; x
>= 0; x
--) {
568 if ((ResHis
[x
+ 1] = ResHis
[x
]) > ResHisMax
) ResHisMax
= ResHis
[x
];
569 if ((ComHis
[x
+ 1] = ComHis
[x
]) > ComHisMax
) ComHisMax
= ComHis
[x
];
570 if ((IndHis
[x
+ 1] = IndHis
[x
]) > IndHisMax
) IndHisMax
= IndHis
[x
];
571 CrimeHis
[x
+ 1] = CrimeHis
[x
];
572 PollutionHis
[x
+ 1] = PollutionHis
[x
];
573 MoneyHis
[x
+ 1] = MoneyHis
[x
];
576 Graph10Max
= ResHisMax
;
577 if (ComHisMax
> Graph10Max
) Graph10Max
= ComHisMax
;
578 if (IndHisMax
> Graph10Max
) Graph10Max
= IndHisMax
;
580 ResHis
[0] = ResPop
/ 8;
584 CrimeRamp
+= (CrimeAverage
- CrimeRamp
) / 4;
585 CrimeHis
[0] = CrimeRamp
;
587 PolluteRamp
+= (PolluteAverage
- PolluteRamp
) / 4;
588 PollutionHis
[0] = PolluteRamp
;
590 x
= (CashFlow
/ 20) + 128; /* scale to 0..255 */
592 if (x
> 255) x
= 255;
595 if (CrimeHis
[0] > 255) CrimeHis
[0] = 255;
596 if (PollutionHis
[0] > 255) PollutionHis
[0] = 255;
598 ChangeCensus(); /* XXX: if 10 year graph view */
600 if (HospPop
< (ResPop
>>8)) NeedHosp
= TRUE
;
601 if (HospPop
> (ResPop
>>8)) NeedHosp
= -1;
602 if (HospPop
== (ResPop
>>8)) NeedHosp
= FALSE
;
604 if (ChurchPop
< (ResPop
>>8)) NeedChurch
= TRUE
;
605 if (ChurchPop
> (ResPop
>>8)) NeedChurch
= -1;
606 if (ChurchPop
== (ResPop
>>8)) NeedChurch
= FALSE
;
610 /* comefrom: Simulate */
611 Take2Census(void) /* Long Term Graphs */
618 for (x
= 238; x
>= 120; x
--) {
619 if ((ResHis
[x
+ 1] = ResHis
[x
]) > Res2HisMax
) Res2HisMax
= ResHis
[x
];
620 if ((ComHis
[x
+ 1] = ComHis
[x
]) > Com2HisMax
) Com2HisMax
= ComHis
[x
];
621 if ((IndHis
[x
+ 1] = IndHis
[x
]) > Ind2HisMax
) Ind2HisMax
= IndHis
[x
];
622 CrimeHis
[x
+ 1] = CrimeHis
[x
];
623 PollutionHis
[x
+ 1] = PollutionHis
[x
];
624 MoneyHis
[x
+ 1] = MoneyHis
[x
];
626 Graph120Max
= Res2HisMax
;
627 if (Com2HisMax
> Graph120Max
) Graph120Max
= Com2HisMax
;
628 if (Ind2HisMax
> Graph120Max
) Graph120Max
= Ind2HisMax
;
630 ResHis
[120] = ResPop
/ 8;
631 ComHis
[120] = ComPop
;
632 IndHis
[120] = IndPop
;
633 CrimeHis
[120] = CrimeHis
[0] ;
634 PollutionHis
[120] = PollutionHis
[0];
635 MoneyHis
[120] = MoneyHis
[0];
636 ChangeCensus(); /* XXX: if 120 year graph view */
640 /* comefrom: Simulate */
643 static float RLevels
[3] = { 0.7, 0.9, 1.2 };
644 static float FLevels
[3] = { 1.4, 1.2, 0.8 };
648 if (!TaxFlag
) { /* if the Tax Port is clear */
649 /* XXX: do something with z */
650 z
= AvCityTax
/ 48; /* post */
652 PoliceFund
= PolicePop
* 100;
653 FireFund
= FireStPop
* 100;
654 RoadFund
= (RoadTotal
+ (RailTotal
* 2)) * RLevels
[GameLevel
];
655 TaxFund
= (((QUAD
)TotalPop
* LVAverage
) / 120) *
656 CityTax
* FLevels
[GameLevel
];
657 if (TotalPop
) { /* if there are people to tax */
658 CashFlow
= TaxFund
- (PoliceFund
+ FireFund
+ RoadFund
);
670 UpdateFundEffects(void)
673 RoadEffect
= (short)(((float)RoadSpend
/
674 (float)RoadFund
) * 32.0);
679 PoliceEffect
= (short)(((float)PoliceSpend
/
680 (float)PoliceFund
) * 1000.0);
685 FireEffect
= (short)(((float)FireSpend
/
686 (float)FireFund
) * 1000.0);
694 /* comefrom: Simulate DoSimInit */
695 MapScan(int x1
, int x2
)
699 for (x
= x1
; x
< x2
; x
++) {
700 for (y
= 0; y
< WORLD_Y
; y
++) {
701 if (CChr
= Map
[x
][y
]) {
702 CChr9
= CChr
& LOMASK
; /* Mask off status bits */
703 if (CChr9
>= FLOOD
) {
706 if (CChr9
< ROADBASE
) {
707 if (CChr9
>= FIREBASE
) {
709 if (!(Rand16() & 3)) DoFire(); /* 1 in 4 times */
712 if (CChr9
< RADTILE
) DoFlood();
717 if (NewPower
&& (CChr
& CONDBIT
))
720 if ((CChr9
>= ROADBASE
) &&
721 (CChr9
< POWERBASE
)) {
726 if (CChr
& ZONEBIT
) { /* process Zones */
731 if ((CChr9
>= RAILBASE
) &&
736 if ((CChr9
>= SOMETINYEXP
) &&
737 (CChr9
<= LASTTINYEXP
)) /* clear AniRubble */
738 Map
[x
][y
] = RUBBLE
+ (Rand16() & 3) + BULLBIT
;
746 /* comefrom: MapScan */
750 GenerateTrain(SMapX
, SMapY
);
751 if (RoadEffect
< 30) /* Deteriorating Rail */
752 if (!(Rand16() & 511))
753 if (!(CChr
& CONDBIT
))
754 if (RoadEffect
< (Rand16() & 31)) {
755 if (CChr9
< (RAILBASE
+ 2))
756 Map
[SMapX
][SMapY
] = RIVER
;
758 Map
[SMapX
][SMapY
] = RUBBLE
+ (Rand16() & 3) + BULLBIT
;
764 /* comefrom: MapScan */
767 if (!(Rand16() & 4095)) Map
[SMapX
][SMapY
] = 0; /* Radioactive decay */
771 /* comefrom: MapScan */
774 register short Density
, tden
, z
;
775 static short DenTab
[3] = { ROADBASE
, LTRFBASE
, HTRFBASE
};
778 /* GenerateBus(SMapX, SMapY); */
779 if (RoadEffect
< 30) /* Deteriorating Roads */
780 if (!(Rand16() & 511))
781 if (!(CChr
& CONDBIT
))
782 if (RoadEffect
< (Rand16() & 31)) {
783 if (((CChr9
& 15) < 2) || ((CChr9
& 15) == 15))
784 Map
[SMapX
][SMapY
] = RIVER
;
786 Map
[SMapX
][SMapY
] = RUBBLE
+ (Rand16() & 3) + BULLBIT
;
790 if (!(CChr
& BURNBIT
)) { /* If Bridge */
792 if (DoBridge()) return;
794 if (CChr9
< LTRFBASE
) tden
= 0;
795 else if (CChr9
< HTRFBASE
) tden
= 1;
801 Density
= (TrfDensity
[SMapX
>>1][SMapY
>>1]) >>6; /* Set Traf Density */
802 if (Density
> 1) Density
--;
803 if (tden
!= Density
) { /* tden 0..2 */
804 z
= ((CChr9
- ROADBASE
) & 15) + DenTab
[Density
];
805 z
+= CChr
& (ALLBITS
- ANIMBIT
);
806 if (Density
) z
+= ANIMBIT
;
807 Map
[SMapX
][SMapY
] = z
;
812 /* comefrom: MapScan */
815 static short HDx
[7] = { -2, 2, -2, -1, 0, 1, 2 };
816 static short HDy
[7] = { -1, -1, 0, 0, 0, 0, 0 };
817 static short HBRTAB
[7] = {
818 HBRDG1
| BULLBIT
, HBRDG3
| BULLBIT
, HBRDG0
| BULLBIT
,
819 RIVER
, BRWH
| BULLBIT
, RIVER
, HBRDG2
| BULLBIT
};
820 static short HBRTAB2
[7] = {
821 RIVER
, RIVER
, HBRIDGE
| BULLBIT
, HBRIDGE
| BULLBIT
, HBRIDGE
| BULLBIT
,
822 HBRIDGE
| BULLBIT
, HBRIDGE
| BULLBIT
};
823 static short VDx
[7] = { 0, 1, 0, 0, 0, 0, 1 };
824 static short VDy
[7] = { -2, -2, -1, 0, 1, 2, 2 };
825 static short VBRTAB
[7] = {
826 VBRDG0
| BULLBIT
, VBRDG1
| BULLBIT
, RIVER
, BRWV
| BULLBIT
,
827 RIVER
, VBRDG2
| BULLBIT
, VBRDG3
| BULLBIT
};
828 static short VBRTAB2
[7] = {
829 VBRIDGE
| BULLBIT
, RIVER
, VBRIDGE
| BULLBIT
, VBRIDGE
| BULLBIT
,
830 VBRIDGE
| BULLBIT
, VBRIDGE
| BULLBIT
, RIVER
};
831 register z
, x
, y
, MPtem
;
833 if (CChr9
== BRWV
) { /* Vertical bridge close */
834 if ((!(Rand16() & 3)) &&
835 (GetBoatDis() > 340))
836 for (z
= 0; z
< 7; z
++) { /* Close */
839 if (TestBounds(x
, y
))
840 if ((Map
[x
][y
] & LOMASK
) == (VBRTAB
[z
] & LOMASK
))
841 Map
[x
][y
] = VBRTAB2
[z
];
845 if (CChr9
== BRWH
) { /* Horizontal bridge close */
846 if ((!(Rand16() & 3)) &&
847 (GetBoatDis() > 340))
848 for (z
= 0; z
< 7; z
++) { /* Close */
851 if (TestBounds(x
, y
))
852 if ((Map
[x
][y
] & LOMASK
) == (HBRTAB
[z
] & LOMASK
))
853 Map
[x
][y
] = HBRTAB2
[z
];
858 if ((GetBoatDis() < 300) || (!(Rand16() & 7))) {
860 if (SMapX
< (WORLD_X
- 1))
861 if (Map
[SMapX
+ 1][SMapY
] == CHANNEL
) { /* Vertical open */
862 for (z
= 0; z
< 7; z
++) {
865 if (TestBounds(x
, y
)) {
867 if ((MPtem
== CHANNEL
) ||
868 ((MPtem
& 15) == (VBRTAB2
[z
] & 15)))
869 Map
[x
][y
] = VBRTAB
[z
];
877 if (Map
[SMapX
][SMapY
- 1] == CHANNEL
) { /* Horizontal open */
878 for (z
= 0; z
< 7; z
++) {
881 if (TestBounds(x
, y
)) {
883 if (((MPtem
& 15) == (HBRTAB2
[z
] & 15)) ||
885 Map
[x
][y
] = HBRTAB
[z
];
900 register int dist
, mx
, my
, dx
, dy
;
904 mx
= (SMapX
<<4) + 8;
905 my
= (SMapY
<<4) + 8;
907 for (sprite
= sim
->sprite
; sprite
!= NULL
; sprite
= sprite
->next
) {
908 if ((sprite
->type
== SHI
) &&
909 (sprite
->frame
!= 0)) {
910 if ((dx
= sprite
->x
+ sprite
->x_hot
- mx
) < 0) dx
= -dx
;
911 if ((dy
= sprite
->y
+ sprite
->y_hot
- my
) < 0) dy
= -dy
;
913 if (dx
< dist
) dist
= dx
;
920 /* comefrom: MapScan */
923 static short DX
[4] = { -1, 0, 1, 0 };
924 static short DY
[4] = { 0, -1, 0, 1 };
925 register short z
, Xtem
, Ytem
, Rate
, c
;
927 for (z
= 0; z
< 4; z
++) {
928 if (!(Rand16() & 7)) {
929 Xtem
= SMapX
+ DX
[z
];
930 Ytem
= SMapY
+ DY
[z
];
931 if (TestBounds(Xtem
, Ytem
)) {
935 FireZone(Xtem
, Ytem
, c
);
936 if ((c
& LOMASK
) > IZB
) { /* Explode */
937 MakeExplosionAt((Xtem
<<4) + 8, (Ytem
<<4) + 8);
940 Map
[Xtem
][Ytem
] = FIRE
+ (Rand16() & 3) + ANIMBIT
;
945 z
= FireRate
[SMapX
>>3][SMapY
>>3];
949 if (z
> 20) Rate
= 2;
950 if (z
> 100) Rate
= 1;
953 Map
[SMapX
][SMapY
] = RUBBLE
+ (Rand16() & 3) + BULLBIT
;
957 /* comefrom: DoFire MakeFlood */
958 FireZone(int Xloc
, int Yloc
, int ch
)
960 register short Xtem
, Ytem
;
963 RateOGMem
[Xloc
>>3][Yloc
>>3] -= 20;
974 for (x
= -1; x
< XYmax
; x
++)
975 for (y
= -1; y
< XYmax
; y
++) {
978 if ((Xtem
< 0) || (Xtem
> (WORLD_X
- 1)) ||
979 (Ytem
< 0) || (Ytem
> (WORLD_Y
- 1)))
981 if ((short)(Map
[Xtem
][Ytem
] & LOMASK
) >= ROADBASE
) /* post release */
982 Map
[Xtem
][Ytem
] |= BULLBIT
;
987 /* comefrom: DoSPZone DoHospChur */
988 RepairZone(short ZCent
, short zsize
)
991 register short x
, y
, ThCh
;
995 for (y
= -1; y
< zsize
; y
++)
996 for (x
= -1; x
< zsize
; x
++) {
1000 if (TestBounds(xx
, yy
)) {
1002 if (ThCh
& ZONEBIT
) continue;
1003 if (ThCh
& ANIMBIT
) continue;
1004 ThCh
= ThCh
& LOMASK
;
1005 if ((ThCh
< RUBBLE
) || (ThCh
>= ROADBASE
)) {
1006 Map
[xx
][yy
] = ZCent
- 3 - zsize
+ cnt
+ CONDBIT
+ BURNBIT
;
1013 /* comefrom: DoZone */
1014 DoSPZone(short PwrOn
)
1016 static short MltdwnTab
[3] = { 30000, 20000, 10000 }; /* simadj */
1023 if (!(CityTime
& 7))
1024 RepairZone(POWERPLANT
, 4); /* post */
1026 CoalSmoke(SMapX
, SMapY
);
1030 if (!NoDisasters
&& !Rand(MltdwnTab
[GameLevel
])) {
1031 DoMeltdown(SMapX
, SMapY
);
1035 if (!(CityTime
& 7))
1036 RepairZone(NUCLEAR
, 4); /* post */
1042 if (!(CityTime
& 7))
1043 RepairZone(FIRESTATION
, 3); /* post */
1046 z
= FireEffect
; /* if powered get effect */
1048 z
= FireEffect
>>1; /* from the funding ratio */
1051 z
= z
>>1; /* post FD's need roads */
1053 FireStMap
[SMapX
>>3][SMapY
>>3] += z
;
1058 if (!(CityTime
& 7))
1059 RepairZone(POLICESTATION
, 3); /* post */
1064 z
= PoliceEffect
>>1;
1067 z
= z
>>1; /* post PD's need roads */
1069 PoliceMap
[SMapX
>>3][SMapY
>>3] += z
;
1074 if (!(CityTime
& 15))
1075 RepairZone(STADIUM
, 4);
1077 if (!((CityTime
+ SMapX
+ SMapY
) & 31)) { /* post release */
1078 DrawStadium(FULLSTADIUM
);
1079 Map
[SMapX
+ 1][SMapY
] = FOOTBALLGAME1
+ ANIMBIT
;
1080 Map
[SMapX
+ 1][SMapY
+ 1] = FOOTBALLGAME2
+ ANIMBIT
;
1086 if (!((CityTime
+ SMapX
+ SMapY
) & 7)) /* post release */
1087 DrawStadium(STADIUM
);
1092 if (!(CityTime
& 7))
1093 RepairZone(AIRPORT
, 6);
1095 if (PwrOn
) { /* post */
1096 if ((Map
[SMapX
+ 1][SMapY
- 1] & LOMASK
) == RADAR
)
1097 Map
[SMapX
+ 1][SMapY
- 1] = RADAR
+ ANIMBIT
+ CONDBIT
+ BURNBIT
;
1099 Map
[SMapX
+ 1][SMapY
- 1] = RADAR
+ CONDBIT
+ BURNBIT
;
1107 if ((CityTime
& 15) == 0) {
1108 RepairZone(PORT
, 4);
1111 (GetSprite(SHI
) == NULL
)) {
1119 /* comefrom: DoSPZone */
1125 for (y
= (SMapY
- 1); y
< (SMapY
+ 3); y
++)
1126 for (x
= (SMapX
- 1); x
< (SMapX
+ 3); x
++)
1127 Map
[x
][y
] = (z
++) | BNCNBIT
;
1128 Map
[SMapX
][SMapY
] |= ZONEBIT
| PWRBIT
;
1132 /* comefrom: DoSPZone */
1136 GeneratePlane(SMapX
, SMapY
);
1140 GenerateCopter(SMapX
, SMapY
);
1144 /* comefrom: DoSPZone */
1145 CoalSmoke(int mx
, int my
)
1147 static short SmTb
[4] = { COALSMOKE1
, COALSMOKE2
, COALSMOKE3
, COALSMOKE4
};
1148 static short dx
[4] = { 1, 2, 1, 2 };
1149 static short dy
[4] = { -1, -1, 0, 0 };
1152 for (x
= 0; x
< 4; x
++)
1153 Map
[mx
+ dx
[x
]][my
+ dy
[x
]] =
1154 SmTb
[x
] | ANIMBIT
| CONDBIT
| PWRBIT
| BURNBIT
;
1158 /* comefrom: DoSPZone MakeMeltdown */
1159 DoMeltdown(int SX
, int SY
)
1161 register x
, y
, z
, t
;
1163 MeltX
= SX
; MeltY
= SY
;
1165 MakeExplosion(SX
- 1, SY
- 1);
1166 MakeExplosion(SX
- 1, SY
+ 2);
1167 MakeExplosion(SX
+ 2, SY
- 1);
1168 MakeExplosion(SX
+ 2, SY
+ 2);
1170 for (x
= (SX
- 1); x
< (SX
+ 3); x
++)
1171 for (y
= (SY
- 1); y
< (SY
+ 3); y
++)
1172 Map
[x
][y
] = FIRE
+ (Rand16() & 3) + ANIMBIT
;
1174 for (z
= 0; z
< 200; z
++) {
1175 x
= SX
- 20 + Rand(40);
1176 y
= SY
- 15 + Rand(30);
1177 if ((x
< 0) || (x
>= WORLD_X
) ||
1178 (y
< 0) || (y
>= WORLD_Y
))
1183 if ((t
& BURNBIT
) || (t
== 0))
1184 Map
[x
][y
] = RADTILE
;
1188 SendMesAt(-43, SX
, SY
);
1192 #define RANDOM_RANGE 0xffff
1197 int maxMultiple
, rnum
;
1200 maxMultiple
= RANDOM_RANGE
/ range
;
1201 maxMultiple
*= range
;
1202 while ((rnum
= Rand16()) >= maxMultiple
)
1204 return (rnum
% range
);
1211 return (sim_rand());
1229 struct timeval time
;
1231 gettimeofday(&time
, NULL
);
1233 SeedRand(time
.tv_usec
^ time
.tv_sec
^ sim_rand());