]>
git.zerfleddert.de Git - micropolis/blob - src/sim/s_sim.c
9d0e4c6f004983c0be40b750d3a8f6a4b182e3d9
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;
88 void CoalSmoke(int mx
, int my
);
90 void DrawStadium(int z
);
97 void MapScan(int x1
, int x2
);
98 void CollectTax(void);
99 void Take2Census(void);
100 void TakeCensus(void);
101 void ClearCensus(void);
102 void SetValves(void);
103 void SetCommonInits(void);
104 void SimLoadInit(void);
105 void InitSimMemory(void);
106 void DecROGMem(void);
107 void DecTrafficMem(void);
108 void Simulate(int mod16
);
110 /* comefrom: doEditWindow scoreDoer doMapInFront graphDoer doNilEvent */
116 if (++Spdcycle
> 1023)
119 if (SimSpeed
== 1 && Spdcycle
% 5)
122 if (SimSpeed
== 2 && Spdcycle
% 3)
125 if (++Fcycle
> 1023) Fcycle
= 0;
126 /* if (InitSimLoad) Fcycle = 0; */
127 Simulate(Fcycle
& 15);
131 /* comefrom: SimFrame */
135 static short SpdPwr
[4] = { 1, 2, 4, 5 };
136 static short SpdPtl
[4] = { 1, 2, 7, 17 };
137 static short SpdCri
[4] = { 1, 1, 8, 18 };
138 static short SpdPop
[4] = { 1, 1, 9, 19 };
139 static short SpdFir
[4] = { 1, 1, 10, 20 };
147 if (++Scycle
> 1023) Scycle
= 0; /* this is cosmic */
153 AvCityTax
+= CityTax
; /* post */
154 if (!(Scycle
& 1)) SetValves();
158 MapScan(0, 1 * WORLD_X
/ 8);
161 MapScan(1 * WORLD_X
/ 8, 2 * WORLD_X
/ 8);
164 MapScan(2 * WORLD_X
/ 8, 3 * WORLD_X
/ 8);
167 MapScan(3 * WORLD_X
/ 8, 4 * WORLD_X
/ 8);
170 MapScan(4 * WORLD_X
/ 8, 5 * WORLD_X
/ 8);
173 MapScan(5 * WORLD_X
/ 8, 6 * WORLD_X
/ 8);
176 MapScan(6 * WORLD_X
/ 8, 7 * WORLD_X
/ 8);
179 MapScan(7 * WORLD_X
/ 8, WORLD_X
);
182 if (!(CityTime
% CENSUSRATE
)) TakeCensus();
183 if (!(CityTime
% (CENSUSRATE
* 12))) Take2Census();
185 if (!(CityTime
% TAXFREQ
)) {
191 if (!(Scycle
% 5)) DecROGMem();
193 NewMapFlags
[TDMAP
] = 1;
194 NewMapFlags
[RDMAP
] = 1;
195 NewMapFlags
[ALMAP
] = 1;
196 NewMapFlags
[REMAP
] = 1;
197 NewMapFlags
[COMAP
] = 1;
198 NewMapFlags
[INMAP
] = 1;
199 NewMapFlags
[DYMAP
] = 1;
203 if (!(Scycle
% SpdPwr
[x
])) {
205 NewMapFlags
[PRMAP
] = 1;
206 NewPower
= 1; /* post-release change */
210 if (!(Scycle
% SpdPtl
[x
])) PTLScan();
213 if (!(Scycle
% SpdCri
[x
])) CrimeScan();
216 if (!(Scycle
% SpdPop
[x
])) PopDenScan();
219 if (!(Scycle
% SpdFir
[x
])) FireAnalysis();
226 /* comefrom: Simulate */
233 if (InitSimLoad
== 2) /* if new city */
236 if (InitSimLoad
== 1) /* if city just loaded */
242 MapScan(0, WORLD_X
); /* XXX are you sure ??? */
245 NewPower
= 1; /* post rel */
258 /* comefrom: SimLoadInit */
262 register short x
, y
, z
;
264 for (x
= 0; x
< WORLD_X
; x
++)
265 for (y
= 0; y
< WORLD_Y
; y
++) {
277 /* comefrom: Simulate */
279 DecTrafficMem(void) /* tends to empty TrfDensity */
281 register short x
, y
, z
;
283 for (x
= 0; x
< HWLDX
; x
++)
284 for (y
= 0; y
< HWLDY
; y
++)
285 if ((z
= TrfDensity
[x
][y
])) {
287 if (z
> 200) TrfDensity
[x
][y
] = z
- 34;
288 else TrfDensity
[x
][y
] = z
- 24;
290 else TrfDensity
[x
][y
] = 0;
295 /* comefrom: Simulate */
297 DecROGMem(void) /* tends to empty RateOGMem */
299 register short x
, y
, z
;
301 for (x
= 0; x
< SmX
; x
++)
302 for (y
= 0; y
< SmY
; y
++) {
304 if (z
== 0) continue;
307 if (z
> 200) RateOGMem
[x
][y
] = 200; /* prevent overflow */
312 if (z
< -200) RateOGMem
[x
][y
] = -200;
318 /* comefrom: DoSimInit */
326 for (x
= 0; x
< 240; x
++) {
348 /* This clears powermem */
351 NewPower
= 1; /* post rel */
357 /* comefrom: DoSimInit */
361 static short DisTab
[9] = { 0, 2, 10, 5, 20, 3, 5, 5, 2 * 48};
362 static short ScoreWaitTab
[9] = { 0, 30 * 48, 5 * 48, 5 * 48, 10 * 48,
363 5 * 48, 10 * 48, 5 * 48, 10 * 48 };
367 EMarket
= (float)MiscHis
[1];
374 CrimeRamp
= MiscHis
[10];
375 PolluteRamp
= MiscHis
[11];
376 LVAverage
= MiscHis
[12];
377 CrimeAverage
= MiscHis
[13];
378 PolluteAverage
= MiscHis
[14];
379 GameLevel
= MiscHis
[15];
381 if (CityTime
< 0) CityTime
= 0;
382 if (!EMarket
) EMarket
= 4.0;
383 if ((GameLevel
> 2) || (GameLevel
< 0)) GameLevel
= 0;
384 SetGameLevel(GameLevel
);
388 CityClass
= MiscHis
[16];
389 CityScore
= MiscHis
[17];
391 if ((CityClass
> 5) || (CityClass
< 0)) CityClass
= 0;
392 if ((CityScore
> 999) || (CityScore
< 1)) CityScore
= 500;
398 AvCityTax
= (CityTime
% 48) * 7; /* post */
400 for (z
= 0; z
< PWRMAPSIZE
; z
++)
401 PowerMap
[z
] = ~0; /* set power Map */
404 if (ScenarioID
> 8) ScenarioID
= 0;
407 DisasterEvent
= ScenarioID
;
408 DisasterWait
= DisTab
[DisasterEvent
];
409 ScoreType
= DisasterEvent
;
410 ScoreWait
= ScoreWaitTab
[DisasterEvent
];
417 PoliceEffect
= 1000; /*post*/
423 /* comefrom: InitSimMemory SimLoadInit */
434 if ((GameLevel > 2) || (GameLevel < 0)) GameLevel = 0;
435 setGameLevel(GameLevel);
440 /* comefrom: Simulate DoSimInit */
444 static short TaxTable
[21] = {
445 200, 150, 120, 100, 80, 50, 30, 0, -10, -40, -100,
446 -150, -200, -250, -300, -350, -400, -450, -500, -550, -600 };
447 float Employment
, Migration
, Births
, LaborBase
, IntMarket
;
448 float Rratio
, Cratio
, Iratio
, temp
;
449 float NormResPop
, PjResPop
, PjComPop
, PjIndPop
;
452 MiscHis
[1] = (short)EMarket
;
459 MiscHis
[10] = CrimeRamp
;
460 MiscHis
[11] = PolluteRamp
;
461 MiscHis
[12] = LVAverage
;
462 MiscHis
[13] = CrimeAverage
;
463 MiscHis
[14] = PolluteAverage
;
464 MiscHis
[15] = GameLevel
;
465 MiscHis
[16] = CityClass
;
466 MiscHis
[17] = CityScore
;
468 NormResPop
= ResPop
/ 8;
469 LastTotalPop
= TotalPop
;
470 TotalPop
= NormResPop
+ ComPop
+ IndPop
;
472 if (NormResPop
) Employment
= ((ComHis
[1] + IndHis
[1]) / NormResPop
);
475 Migration
= NormResPop
* (Employment
- 1);
476 Births
= NormResPop
* (.02); /* Birth Rate */
477 PjResPop
= NormResPop
+ Migration
+ Births
; /* Projected Res.Pop */
479 if ((temp
= (ComHis
[1] + IndHis
[1]))) LaborBase
= (ResHis
[1] / temp
);
481 if (LaborBase
> 1.3) LaborBase
= 1.3;
482 if (LaborBase
< 0) LaborBase
= 0; /* LB > 1 - .1 */
484 for (z
= 0; z
< 2; z
++)
485 temp
= ResHis
[z
] + ComHis
[z
] + IndHis
[z
];
486 IntMarket
= (NormResPop
+ ComPop
+ IndPop
) / 3.7;
488 PjComPop
= IntMarket
* LaborBase
;
490 z
= GameLevel
; /* New ExtMarket */
504 PjIndPop
= IndPop
* LaborBase
* temp
;
505 if (PjIndPop
< 5) PjIndPop
= 5;
507 if (NormResPop
) Rratio
= (PjResPop
/ NormResPop
); /* projected -vs- actual */
509 if (ComPop
) Cratio
= (PjComPop
/ ComPop
);
510 else Cratio
= PjComPop
;
511 if (IndPop
) Iratio
= (PjIndPop
/ IndPop
);
512 else Iratio
= PjIndPop
;
514 if (Rratio
> 2) Rratio
= 2;
515 if (Cratio
> 2) Cratio
= 2;
516 if (Iratio
> 2) Iratio
= 2;
518 z
= CityTax
+ GameLevel
;
520 Rratio
= ((Rratio
-1) * 600) + TaxTable
[z
]; /* global tax/Glevel effects */
521 Cratio
= ((Cratio
-1) * 600) + TaxTable
[z
];
522 Iratio
= ((Iratio
-1) * 600) + TaxTable
[z
];
524 if (Rratio
> 0) /* ratios are velocity changes to valves */
525 if (RValve
< 2000) RValve
+= Rratio
;
527 if (RValve
> -2000) RValve
+= Rratio
;
529 if (CValve
< 1500) CValve
+= Cratio
;
531 if (CValve
> -1500) CValve
+= Cratio
;
533 if (IValve
< 1500) IValve
+= Iratio
;
535 if (IValve
> -1500) IValve
+= Iratio
;
537 if (RValve
> 2000) RValve
= 2000;
538 if (RValve
< -2000) RValve
= -2000;
539 if (CValve
> 1500) CValve
= 1500;
540 if (CValve
< -1500) CValve
= -1500;
541 if (IValve
> 1500) IValve
= 1500;
542 if (IValve
< -1500) IValve
= -1500;
544 if ((ResCap
) && (RValve
> 0)) RValve
= 0; /* Stad, Prt, Airprt */
545 if ((ComCap
) && (CValve
> 0)) CValve
= 0;
546 if ((IndCap
) && (IValve
> 0)) IValve
= 0;
551 /* comefrom: Simulate DoSimInit */
555 register short x
, y
, z
;
578 PowerStackNum
= z
; /* Reset before Mapscan */
579 for (x
= 0; x
< SmX
; x
++)
580 for (y
= 0; y
< SmY
; y
++) {
587 /* comefrom: Simulate */
593 /* put census#s in Historical Graphs and scroll data */
597 for (x
= 118; x
>= 0; x
--) {
598 if ((ResHis
[x
+ 1] = ResHis
[x
]) > ResHisMax
) ResHisMax
= ResHis
[x
];
599 if ((ComHis
[x
+ 1] = ComHis
[x
]) > ComHisMax
) ComHisMax
= ComHis
[x
];
600 if ((IndHis
[x
+ 1] = IndHis
[x
]) > IndHisMax
) IndHisMax
= IndHis
[x
];
601 CrimeHis
[x
+ 1] = CrimeHis
[x
];
602 PollutionHis
[x
+ 1] = PollutionHis
[x
];
603 MoneyHis
[x
+ 1] = MoneyHis
[x
];
606 Graph10Max
= ResHisMax
;
607 if (ComHisMax
> Graph10Max
) Graph10Max
= ComHisMax
;
608 if (IndHisMax
> Graph10Max
) Graph10Max
= IndHisMax
;
610 ResHis
[0] = ResPop
/ 8;
614 CrimeRamp
+= (CrimeAverage
- CrimeRamp
) / 4;
615 CrimeHis
[0] = CrimeRamp
;
617 PolluteRamp
+= (PolluteAverage
- PolluteRamp
) / 4;
618 PollutionHis
[0] = PolluteRamp
;
620 x
= (CashFlow
/ 20) + 128; /* scale to 0..255 */
622 if (x
> 255) x
= 255;
625 if (CrimeHis
[0] > 255) CrimeHis
[0] = 255;
626 if (PollutionHis
[0] > 255) PollutionHis
[0] = 255;
628 ChangeCensus(); /* XXX: if 10 year graph view */
630 if (HospPop
< (ResPop
>>8)) NeedHosp
= TRUE
;
631 if (HospPop
> (ResPop
>>8)) NeedHosp
= -1;
632 if (HospPop
== (ResPop
>>8)) NeedHosp
= FALSE
;
634 if (ChurchPop
< (ResPop
>>8)) NeedChurch
= TRUE
;
635 if (ChurchPop
> (ResPop
>>8)) NeedChurch
= -1;
636 if (ChurchPop
== (ResPop
>>8)) NeedChurch
= FALSE
;
640 /* comefrom: Simulate */
642 Take2Census(void) /* Long Term Graphs */
649 for (x
= 238; x
>= 120; x
--) {
650 if ((ResHis
[x
+ 1] = ResHis
[x
]) > Res2HisMax
) Res2HisMax
= ResHis
[x
];
651 if ((ComHis
[x
+ 1] = ComHis
[x
]) > Com2HisMax
) Com2HisMax
= ComHis
[x
];
652 if ((IndHis
[x
+ 1] = IndHis
[x
]) > Ind2HisMax
) Ind2HisMax
= IndHis
[x
];
653 CrimeHis
[x
+ 1] = CrimeHis
[x
];
654 PollutionHis
[x
+ 1] = PollutionHis
[x
];
655 MoneyHis
[x
+ 1] = MoneyHis
[x
];
657 Graph120Max
= Res2HisMax
;
658 if (Com2HisMax
> Graph120Max
) Graph120Max
= Com2HisMax
;
659 if (Ind2HisMax
> Graph120Max
) Graph120Max
= Ind2HisMax
;
661 ResHis
[120] = ResPop
/ 8;
662 ComHis
[120] = ComPop
;
663 IndHis
[120] = IndPop
;
664 CrimeHis
[120] = CrimeHis
[0] ;
665 PollutionHis
[120] = PollutionHis
[0];
666 MoneyHis
[120] = MoneyHis
[0];
667 ChangeCensus(); /* XXX: if 120 year graph view */
671 /* comefrom: Simulate */
675 static float RLevels
[3] = { 0.7, 0.9, 1.2 };
676 static float FLevels
[3] = { 1.4, 1.2, 0.8 };
680 if (!TaxFlag
) { /* if the Tax Port is clear */
681 /* XXX: do something with z */
682 z
= AvCityTax
/ 48; /* post */
684 PoliceFund
= PolicePop
* 100;
685 FireFund
= FireStPop
* 100;
686 RoadFund
= (RoadTotal
+ (RailTotal
* 2)) * RLevels
[GameLevel
];
687 TaxFund
= (((QUAD
)TotalPop
* LVAverage
) / 120) *
688 CityTax
* FLevels
[GameLevel
];
689 if (TotalPop
) { /* if there are people to tax */
690 CashFlow
= TaxFund
- (PoliceFund
+ FireFund
+ RoadFund
);
703 UpdateFundEffects(void)
706 RoadEffect
= (short)(((float)RoadSpend
/
707 (float)RoadFund
) * 32.0);
712 PoliceEffect
= (short)(((float)PoliceSpend
/
713 (float)PoliceFund
) * 1000.0);
718 FireEffect
= (short)(((float)FireSpend
/
719 (float)FireFund
) * 1000.0);
727 /* comefrom: Simulate DoSimInit */
729 MapScan(int x1
, int x2
)
733 for (x
= x1
; x
< x2
; x
++) {
734 for (y
= 0; y
< WORLD_Y
; y
++) {
735 if ((CChr
= Map
[x
][y
])) {
736 CChr9
= CChr
& LOMASK
; /* Mask off status bits */
737 if (CChr9
>= FLOOD
) {
740 if (CChr9
< ROADBASE
) {
741 if (CChr9
>= FIREBASE
) {
743 if (!(Rand16() & 3)) DoFire(); /* 1 in 4 times */
746 if (CChr9
< RADTILE
) DoFlood();
751 if (NewPower
&& (CChr
& CONDBIT
))
754 if ((CChr9
>= ROADBASE
) &&
755 (CChr9
< POWERBASE
)) {
760 if (CChr
& ZONEBIT
) { /* process Zones */
765 if ((CChr9
>= RAILBASE
) &&
770 if ((CChr9
>= SOMETINYEXP
) &&
771 (CChr9
<= LASTTINYEXP
)) /* clear AniRubble */
772 Map
[x
][y
] = RUBBLE
+ (Rand16() & 3) + BULLBIT
;
780 /* comefrom: MapScan */
785 GenerateTrain(SMapX
, SMapY
);
786 if (RoadEffect
< 30) /* Deteriorating Rail */
787 if (!(Rand16() & 511))
788 if (!(CChr
& CONDBIT
))
789 if (RoadEffect
< (Rand16() & 31)) {
790 if (CChr9
< (RAILBASE
+ 2))
791 Map
[SMapX
][SMapY
] = RIVER
;
793 Map
[SMapX
][SMapY
] = RUBBLE
+ (Rand16() & 3) + BULLBIT
;
799 /* comefrom: MapScan */
803 if (!(Rand16() & 4095)) Map
[SMapX
][SMapY
] = 0; /* Radioactive decay */
807 /* comefrom: MapScan */
811 register short Density
, tden
, z
;
812 static short DenTab
[3] = { ROADBASE
, LTRFBASE
, HTRFBASE
};
815 /* GenerateBus(SMapX, SMapY); */
816 if (RoadEffect
< 30) /* Deteriorating Roads */
817 if (!(Rand16() & 511))
818 if (!(CChr
& CONDBIT
))
819 if (RoadEffect
< (Rand16() & 31)) {
820 if (((CChr9
& 15) < 2) || ((CChr9
& 15) == 15))
821 Map
[SMapX
][SMapY
] = RIVER
;
823 Map
[SMapX
][SMapY
] = RUBBLE
+ (Rand16() & 3) + BULLBIT
;
827 if (!(CChr
& BURNBIT
)) { /* If Bridge */
829 if (DoBridge()) return;
831 if (CChr9
< LTRFBASE
) tden
= 0;
832 else if (CChr9
< HTRFBASE
) tden
= 1;
838 Density
= (TrfDensity
[SMapX
>>1][SMapY
>>1]) >>6; /* Set Traf Density */
839 if (Density
> 1) Density
--;
840 if (tden
!= Density
) { /* tden 0..2 */
841 z
= ((CChr9
- ROADBASE
) & 15) + DenTab
[Density
];
842 z
+= CChr
& (ALLBITS
- ANIMBIT
);
843 if (Density
) z
+= ANIMBIT
;
844 Map
[SMapX
][SMapY
] = z
;
849 /* comefrom: MapScan */
853 static short HDx
[7] = { -2, 2, -2, -1, 0, 1, 2 };
854 static short HDy
[7] = { -1, -1, 0, 0, 0, 0, 0 };
855 static short HBRTAB
[7] = {
856 HBRDG1
| BULLBIT
, HBRDG3
| BULLBIT
, HBRDG0
| BULLBIT
,
857 RIVER
, BRWH
| BULLBIT
, RIVER
, HBRDG2
| BULLBIT
};
858 static short HBRTAB2
[7] = {
859 RIVER
, RIVER
, HBRIDGE
| BULLBIT
, HBRIDGE
| BULLBIT
, HBRIDGE
| BULLBIT
,
860 HBRIDGE
| BULLBIT
, HBRIDGE
| BULLBIT
};
861 static short VDx
[7] = { 0, 1, 0, 0, 0, 0, 1 };
862 static short VDy
[7] = { -2, -2, -1, 0, 1, 2, 2 };
863 static short VBRTAB
[7] = {
864 VBRDG0
| BULLBIT
, VBRDG1
| BULLBIT
, RIVER
, BRWV
| BULLBIT
,
865 RIVER
, VBRDG2
| BULLBIT
, VBRDG3
| BULLBIT
};
866 static short VBRTAB2
[7] = {
867 VBRIDGE
| BULLBIT
, RIVER
, VBRIDGE
| BULLBIT
, VBRIDGE
| BULLBIT
,
868 VBRIDGE
| BULLBIT
, VBRIDGE
| BULLBIT
, RIVER
};
869 register int z
, x
, y
, MPtem
;
871 if (CChr9
== BRWV
) { /* Vertical bridge close */
872 if ((!(Rand16() & 3)) &&
873 (GetBoatDis() > 340))
874 for (z
= 0; z
< 7; z
++) { /* Close */
877 if (TestBounds(x
, y
))
878 if ((Map
[x
][y
] & LOMASK
) == (VBRTAB
[z
] & LOMASK
))
879 Map
[x
][y
] = VBRTAB2
[z
];
883 if (CChr9
== BRWH
) { /* Horizontal bridge close */
884 if ((!(Rand16() & 3)) &&
885 (GetBoatDis() > 340))
886 for (z
= 0; z
< 7; z
++) { /* Close */
889 if (TestBounds(x
, y
))
890 if ((Map
[x
][y
] & LOMASK
) == (HBRTAB
[z
] & LOMASK
))
891 Map
[x
][y
] = HBRTAB2
[z
];
896 if ((GetBoatDis() < 300) || (!(Rand16() & 7))) {
898 if (SMapX
< (WORLD_X
- 1))
899 if (Map
[SMapX
+ 1][SMapY
] == CHANNEL
) { /* Vertical open */
900 for (z
= 0; z
< 7; z
++) {
903 if (TestBounds(x
, y
)) {
905 if ((MPtem
== CHANNEL
) ||
906 ((MPtem
& 15) == (VBRTAB2
[z
] & 15)))
907 Map
[x
][y
] = VBRTAB
[z
];
915 if (Map
[SMapX
][SMapY
- 1] == CHANNEL
) { /* Horizontal open */
916 for (z
= 0; z
< 7; z
++) {
919 if (TestBounds(x
, y
)) {
921 if (((MPtem
& 15) == (HBRTAB2
[z
] & 15)) ||
923 Map
[x
][y
] = HBRTAB
[z
];
938 register int dist
, mx
, my
, dx
, dy
;
942 mx
= (SMapX
<<4) + 8;
943 my
= (SMapY
<<4) + 8;
945 for (sprite
= sim
->sprite
; sprite
!= NULL
; sprite
= sprite
->next
) {
946 if ((sprite
->type
== SHI
) &&
947 (sprite
->frame
!= 0)) {
948 if ((dx
= sprite
->x
+ sprite
->x_hot
- mx
) < 0) dx
= -dx
;
949 if ((dy
= sprite
->y
+ sprite
->y_hot
- my
) < 0) dy
= -dy
;
951 if (dx
< dist
) dist
= dx
;
958 /* comefrom: MapScan */
962 static short DX
[4] = { -1, 0, 1, 0 };
963 static short DY
[4] = { 0, -1, 0, 1 };
964 register short z
, Xtem
, Ytem
, Rate
, c
;
966 for (z
= 0; z
< 4; z
++) {
967 if (!(Rand16() & 7)) {
968 Xtem
= SMapX
+ DX
[z
];
969 Ytem
= SMapY
+ DY
[z
];
970 if (TestBounds(Xtem
, Ytem
)) {
974 FireZone(Xtem
, Ytem
, c
);
975 if ((c
& LOMASK
) > IZB
) { /* Explode */
976 MakeExplosionAt((Xtem
<<4) + 8, (Ytem
<<4) + 8);
979 Map
[Xtem
][Ytem
] = FIRE
+ (Rand16() & 3) + ANIMBIT
;
984 z
= FireRate
[SMapX
>>3][SMapY
>>3];
988 if (z
> 20) Rate
= 2;
989 if (z
> 100) Rate
= 1;
992 Map
[SMapX
][SMapY
] = RUBBLE
+ (Rand16() & 3) + BULLBIT
;
996 /* comefrom: DoFire MakeFlood */
998 FireZone(int Xloc
, int Yloc
, int ch
)
1000 register short Xtem
, Ytem
;
1003 RateOGMem
[Xloc
>>3][Yloc
>>3] -= 20;
1014 for (x
= -1; x
< XYmax
; x
++)
1015 for (y
= -1; y
< XYmax
; y
++) {
1018 if ((Xtem
< 0) || (Xtem
> (WORLD_X
- 1)) ||
1019 (Ytem
< 0) || (Ytem
> (WORLD_Y
- 1)))
1021 if ((short)(Map
[Xtem
][Ytem
] & LOMASK
) >= ROADBASE
) /* post release */
1022 Map
[Xtem
][Ytem
] |= BULLBIT
;
1027 /* comefrom: DoSPZone DoHospChur */
1029 RepairZone(short ZCent
, short zsize
)
1032 register short x
, y
, ThCh
;
1036 for (y
= -1; y
< zsize
; y
++)
1037 for (x
= -1; x
< zsize
; x
++) {
1041 if (TestBounds(xx
, yy
)) {
1043 if (ThCh
& ZONEBIT
) continue;
1044 if (ThCh
& ANIMBIT
) continue;
1045 ThCh
= ThCh
& LOMASK
;
1046 if ((ThCh
< RUBBLE
) || (ThCh
>= ROADBASE
)) {
1047 Map
[xx
][yy
] = ZCent
- 3 - zsize
+ cnt
+ CONDBIT
+ BURNBIT
;
1054 /* comefrom: DoZone */
1056 DoSPZone(short PwrOn
)
1058 static short MltdwnTab
[3] = { 30000, 20000, 10000 }; /* simadj */
1065 if (!(CityTime
& 7))
1066 RepairZone(POWERPLANT
, 4); /* post */
1068 CoalSmoke(SMapX
, SMapY
);
1072 if (!NoDisasters
&& !Rand(MltdwnTab
[GameLevel
])) {
1073 DoMeltdown(SMapX
, SMapY
);
1077 if (!(CityTime
& 7))
1078 RepairZone(NUCLEAR
, 4); /* post */
1084 if (!(CityTime
& 7))
1085 RepairZone(FIRESTATION
, 3); /* post */
1088 z
= FireEffect
; /* if powered get effect */
1090 z
= FireEffect
>>1; /* from the funding ratio */
1093 z
= z
>>1; /* post FD's need roads */
1095 FireStMap
[SMapX
>>3][SMapY
>>3] += z
;
1100 if (!(CityTime
& 7))
1101 RepairZone(POLICESTATION
, 3); /* post */
1106 z
= PoliceEffect
>>1;
1109 z
= z
>>1; /* post PD's need roads */
1111 PoliceMap
[SMapX
>>3][SMapY
>>3] += z
;
1116 if (!(CityTime
& 15))
1117 RepairZone(STADIUM
, 4);
1119 if (!((CityTime
+ SMapX
+ SMapY
) & 31)) { /* post release */
1120 DrawStadium(FULLSTADIUM
);
1121 Map
[SMapX
+ 1][SMapY
] = FOOTBALLGAME1
+ ANIMBIT
;
1122 Map
[SMapX
+ 1][SMapY
+ 1] = FOOTBALLGAME2
+ ANIMBIT
;
1128 if (!((CityTime
+ SMapX
+ SMapY
) & 7)) /* post release */
1129 DrawStadium(STADIUM
);
1134 if (!(CityTime
& 7))
1135 RepairZone(AIRPORT
, 6);
1137 if (PwrOn
) { /* post */
1138 if ((Map
[SMapX
+ 1][SMapY
- 1] & LOMASK
) == RADAR
)
1139 Map
[SMapX
+ 1][SMapY
- 1] = RADAR
+ ANIMBIT
+ CONDBIT
+ BURNBIT
;
1141 Map
[SMapX
+ 1][SMapY
- 1] = RADAR
+ CONDBIT
+ BURNBIT
;
1149 if ((CityTime
& 15) == 0) {
1150 RepairZone(PORT
, 4);
1153 (GetSprite(SHI
) == NULL
)) {
1161 /* comefrom: DoSPZone */
1168 for (y
= (SMapY
- 1); y
< (SMapY
+ 3); y
++)
1169 for (x
= (SMapX
- 1); x
< (SMapX
+ 3); x
++)
1170 Map
[x
][y
] = (z
++) | BNCNBIT
;
1171 Map
[SMapX
][SMapY
] |= ZONEBIT
| PWRBIT
;
1175 /* comefrom: DoSPZone */
1180 GeneratePlane(SMapX
, SMapY
);
1184 GenerateCopter(SMapX
, SMapY
);
1188 /* comefrom: DoSPZone */
1190 CoalSmoke(int mx
, int my
)
1192 static short SmTb
[4] = { COALSMOKE1
, COALSMOKE2
, COALSMOKE3
, COALSMOKE4
};
1193 static short dx
[4] = { 1, 2, 1, 2 };
1194 static short dy
[4] = { -1, -1, 0, 0 };
1197 for (x
= 0; x
< 4; x
++)
1198 Map
[mx
+ dx
[x
]][my
+ dy
[x
]] =
1199 SmTb
[x
] | ANIMBIT
| CONDBIT
| PWRBIT
| BURNBIT
;
1203 /* comefrom: DoSPZone MakeMeltdown */
1205 DoMeltdown(int SX
, int SY
)
1207 register int x
, y
, z
, t
;
1209 MeltX
= SX
; MeltY
= SY
;
1211 MakeExplosion(SX
- 1, SY
- 1);
1212 MakeExplosion(SX
- 1, SY
+ 2);
1213 MakeExplosion(SX
+ 2, SY
- 1);
1214 MakeExplosion(SX
+ 2, SY
+ 2);
1216 for (x
= (SX
- 1); x
< (SX
+ 3); x
++)
1217 for (y
= (SY
- 1); y
< (SY
+ 3); y
++)
1218 Map
[x
][y
] = FIRE
+ (Rand16() & 3) + ANIMBIT
;
1220 for (z
= 0; z
< 200; z
++) {
1221 x
= SX
- 20 + Rand(40);
1222 y
= SY
- 15 + Rand(30);
1223 if ((x
< 0) || (x
>= WORLD_X
) ||
1224 (y
< 0) || (y
>= WORLD_Y
))
1229 if ((t
& BURNBIT
) || (t
== 0))
1230 Map
[x
][y
] = RADTILE
;
1234 SendMesAt(-43, SX
, SY
);
1238 #define RANDOM_RANGE 0xffff
1243 int maxMultiple
, rnum
;
1246 maxMultiple
= RANDOM_RANGE
/ range
;
1247 maxMultiple
*= range
;
1248 while ((rnum
= Rand16()) >= maxMultiple
)
1250 return (rnum
% range
);
1257 return (sim_rand());
1276 struct timeval time
;
1278 gettimeofday(&time
, NULL
);
1280 SeedRand(time
.tv_usec
^ time
.tv_sec
^ sim_rand());