Micropolis
micropolis.cpp
Go to the documentation of this file.
1/* micropolis.cpp
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
77
78
79#include "micropolis.h"
80
81
83
84
89 populationDensityMap(0),
90 trafficDensityMap(0),
91 pollutionDensityMap(0),
92 landValueMap(0),
93 crimeRateMap(0),
94 terrainDensityMap(0),
95 tempMap1(0),
96 tempMap2(0),
97 tempMap3(0),
98 powerGridMap(0),
99 rateOfGrowthMap(0),
100 fireStationMap(0),
101 fireStationEffectMap(0),
102 policeStationMap(0),
103 policeStationEffectMap(0),
104 comRateMap(0)
105{
107}
108
109
112{
113 destroy();
114 setCallback(NULL, emscripten::val::null());
115}
116
117
118void Micropolis::setCallback(Callback *callback0, emscripten::val callbackVal0)
119{
120 if (callback != NULL) {
121 delete callback;
122 }
123 callback = callback0;
124 callbackVal = callbackVal0;
125}
126
127
130{
131 printf("init");
132
134 // allocate.cpp
135
136 // short roadTotal;
137 roadTotal = 0;
138
139 // short railTotal;
140 railTotal = 0;
141
142 // short firePop;
143 firePop = 0;
144
145 // short resPop;
146 resPop = 0;
147
148 // short comPop;
149 comPop = 0;
150
151 // short indPop;
152 indPop = 0;
153
154 // short totalPop;
155 totalPop = 0;
156
157 // short totalPopLast;
158 totalPopLast = 0;
159
160 // short resZonePop;
161 resZonePop = 0;
162
163 // short comZonePop;
164 comZonePop = 0;
165
166 // short indZonePop;
167 indZonePop = 0;
168
169 // short totalZonePop;
170 totalZonePop = 0;
171
172 // short hospitalPop;
173 hospitalPop = 0;
174
175 // short churchPop;
176 churchPop = 0;
177
178 // short faith;
179 faith = 0;
180
181 // short stadiumPop;
182 stadiumPop = 0;
183
184 // short policeStationPop;
186
187 // short fireStationPop;
188 fireStationPop = 0;
189
190 // short coalPowerPop;
191 coalPowerPop = 0;
192
193 // short nuclearPowerPop;
194 nuclearPowerPop = 0;
195
196 // short seaportPop;
197 seaportPop = 0;
198
199 // short airportPop;
200 airportPop = 0;
201
202 // short needHospital;
203 needHospital = 0;
204
205 // short needChurch;
206 needChurch = 0;
207
208 // short crimeAverage;
209 crimeAverage = 0;
210
211 // short pollutionAverage;
213
214 // short landValueAverage;
216
217 // Quad cityTime;
218 cityTime = 0;
219
220 // Quad cityMonth;
221 cityMonth = 0;
222
223 // Quad cityYear;
224 cityYear = 0;
225
226 // short startingYear;
227 startingYear = 0;
228
229 // short resHist10Max;
230 resHist10Max = 0;
231
232 // short resHist120Max;
233 resHist120Max = 0;
234
235 // short comHist10Max;
236 comHist10Max = 0;
237
238 // short comHist120Max;
239 comHist120Max = 0;
240
241 // short indHist10Max;
242 indHist10Max = 0;
243
244 // short indHist120Max;
245 indHist120Max = 0;
246
247 censusChanged = false;
248
249 // Quad roadSpend;
250 roadSpend = 0;
251
252 // Quad policeSpend;
253 policeSpend = 0;
254
255 // Quad fireSpend;
256 fireSpend = 0;
257
258 // Quad roadFund;
259 roadFund = 0;
260
261 // Quad policeFund;
262 policeFund = 0;
263
264 // Quad fireFund;
265 fireFund = 0;
266
267 roadEffect = 0;
268 policeEffect = 0;
269 fireEffect = 0;
270
271 // Quad taxFund;
272 taxFund = 0;
273
274 // short cityTax;
275 cityTax = 0;
276
277 // bool taxFlag;
278 taxFlag = false;
279
293
294
296 // budget.cpp
297
298
299 // float roadPercent;
300 roadPercent = (float)0.0;
301
302 // float policePercent;
303 policePercent = (float)0.0;
304
305 // float firePercent;
306 firePercent = (float)0.0;
307
308 // Quad roadValue;
309 roadValue = 0;
310
311 // Quad policeValue;
312 policeValue = 0;
313
314 // Quad fireValue;
315 fireValue = 0;
316
317 // int mustDrawBudget;
318 mustDrawBudget = 0;
319
320
322 // disasters.cpp
323
324
325 // short floodCount;
326 floodCount = 0;
327
328
330 // evaluate.cpp
331
332
333 // short cityYes;
334 cityYes = 0;
335
336 // short problemVotes[PROBNUM]; /* these are the votes for each */
337 memset(problemVotes, 0, sizeof(short) * PROBNUM);
338
339 // short problemOrder[CVP_PROBLEM_COMPLAINTS]; /* sorted index to above */
340 memset(problemOrder, 0, sizeof(short) * CVP_PROBLEM_COMPLAINTS);
341
342 // Quad cityPop;
343 cityPop = 0;
344
345 // Quad cityPopDelta;
346 cityPopDelta = 0;
347
348 // Quad cityAssessedValue;
350
352
353 // short cityScore;
354 cityScore = 0;
355
356 // short cityScoreDelta;
357 cityScoreDelta = 0;
358
359 // short trafficAverage;
360 trafficAverage = 0;
361
362
364 // generate.cpp
365
366
367 // int TreeLevel; /* level for tree creation */
368 terrainTreeLevel = -1;
369
370 // int LakeLevel; /* level for lake creation */
371 terrainLakeLevel = -1;
372
373 // int CurveLevel; /* level for river curviness */
375
376 // int CreateIsland; /* -1 => 10%, 0 => never, 1 => always */
378
379
381 // graph.cpp
382
383
384 graph10Max = 0;
385 graph120Max = 0;
386
387
389 // main.cpp
390
391 // int simLoops;
392 simLoops = 0;
393
394 // int simPasses;
395 simPasses = 0;
396
397 // int simPass;
398 simPass = 0;
399
400 simPaused = false; // Simulation is running
401
402 // int simPausedSpeed;
403 simPausedSpeed = 0;
404
405 // int heatSteps;
406 heatSteps = 0;
407
408 // int heatFlow;
409 heatFlow = -7;
410
411 // int heatRule;
412 heatRule = 0;
413
414 // int heatWrap;
415 heatWrap = 3;
416
417 // std::string cityFileName;
418 cityFileName = "";
419
420 // std::string cityName;
421 cityName = "";
422
423 // bool tilesAnimated;
424 tilesAnimated = false;
425
426 // bool doAnimaton;
427 doAnimation = true;
428
429 // bool doMessages;
430 doMessages = true;
431
432 // bool doNotices;
433 doNotices = true;
434
435 // short *cellSrc;
436 cellSrc = NULL;
437
438 // short *cellDst;
439 cellDst = NULL;
440
441
443 // message.cpp
444
445
446 // Quad cityPopLast;
447 cityPopLast = 0;
448
449 // short categoryLast;
450 categoryLast = 0;
451
452 autoGoto = false;
453
454
456 // power.cpp
457
458
460
461 // Position powerStackXY[POWER_STACK_SIZE];
462 for (int i = 0; i < POWER_STACK_SIZE; i++) {
463 powerStackXY[i] = Position();
464 }
465
466
468 // random.cpp
469
470
471 // UQuad nextRandom;
472 nextRandom = 1;
473
474
476 // scan.cpp
477
478 // short newMap;
479 newMap = 0;
480
481 // short newMapFlags[MAP_TYPE_COUNT];
482 memset(newMapFlags, 0, sizeof(short) * MAP_TYPE_COUNT);
483
484 // short cityCenterX;
485 cityCenterX = 0;
486
487 // short cityCenterY;
488 cityCenterY = 0;
489
490 // short pollutionMaxX;
491 pollutionMaxX = 0;
492
493 // short pollutionMaxY;
494 pollutionMaxY = 0;
495
496 // short crimeMaxX;
497 crimeMaxX = 0;
498
499 // short crimeMaxY;
500 crimeMaxY = 0;
501
502 // Quad donDither;
503 donDither = 0;
504
505
507 // simulate.cpp
508
509
510 valveFlag = false;
511
512 // short crimeRamp;
513 crimeRamp = 0;
514
515 // short pollutionRamp;
516 pollutionRamp = 0;
517
518 resCap = false; // Do not block residential growth
519 comCap = false; // Do not block commercial growth
520 indCap = false; // Do not block industrial growth
521
522 // short cashFlow;
523 cashFlow = 0;
524
525 // float externalMarket;
526 externalMarket = (float)4.0;
527
529
530 // short disasterWait;
531 disasterWait = 0;
532
534
535 // short scoreWait;
536 scoreWait = 0;
537
538 // short poweredZoneCount;
540
541 // short unpoweredZoneCount;
543
544 newPower = false;
545
546 // short cityTaxAverage;
547 cityTaxAverage = 0;
548
549 // short simCycle;
550 simCycle = 0;
551
552 // short phaseCycle;
553 phaseCycle = 0;
554
555 // short speedCycle;
556 speedCycle = 0;
557
558 // bool doInitialEval
559 doInitialEval = false;
560
561 // int mapSerial;
562 mapSerial = 1;
563
564 // short resValve;
565 resValve = 0;
566
567 // short comValve;
568 comValve = 0;
569
570 // short indValve;
571 indValve = 0;
572
573
575 // sprite.cpp
576
577
578 //SimSprite *spriteList;
579 spriteList = NULL;
580
581 // SimSprite *freeSprites;
582 freeSprites = NULL;
583
584 // SimSprite *globalSprites[SPRITE_COUNT];
585 memset(globalSprites, 0, sizeof(SimSprite *) * SPRITE_COUNT);
586
587 // int absDist;
588 absDist = 0;
589
590 // short spriteCycle;
591 spriteCycle = 0;
592
593
595 // stubs.cpp
596
597
598 // Quad totalFunds;
599 totalFunds = 0;
600
601 autoBulldoze = true;
602
603 autoBudget = true;
604
606
607 // short initSimLoad;
608 initSimLoad = 0;
609
611
612 // short simSpeed;
613 simSpeed = 0;
614
615 // short simSpeedMeta;
616 simSpeedMeta = 0;
617
618 enableSound = false;
619
620 enableDisasters = true;
621
622 evalChanged = false;
623
624 // short blinkFlag;
625 blinkFlag = 0;
626
627
629 // traffic.cpp
630
631
632 // short curMapStackPointer;
634
635 // Position curMapStackXY[MAX_TRAFFIC_DISTANCE+1];
636 for (int i = 0; i < MAX_TRAFFIC_DISTANCE + 1; i++) {
637 curMapStackXY[i] = Position();
638 }
639
640 // short trafMaxX, trafMaxY;
641 trafMaxX = 0;
642 trafMaxY = 0;
643
644
646 // update.cpp
647
648
649 mustUpdateFunds = false;
650
651 mustUpdateOptions = false;
652
653 // Quad cityTimeLast;
654 cityTimeLast = 0;
655
656 // Quad cityYearLast;
657 cityYearLast = 0;
658
659 // Quad cityMonthLast;
660 cityMonthLast = 0;
661
662 // Quad totalFundsLast;
663 totalFundsLast = 0;
664
665 // Quad resLast;
666 resLast = 0;
667
668 // Quad comLast;
669 comLast = 0;
670
671 // Quad indLast;
672 indLast = 0;
673
674 simInit();
675 doSimInit();
676
677}
678
679
680void Micropolis::destroy()
681{
682
684
685 // TODO: Clean up all other stuff:
686
687}
688
689
697static bool testDirectory(const std::string& dir, const std::string &envVar)
698{
699 struct stat statbuf;
700
701 if (stat(dir.c_str(), &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
702
703 return true;
704 }
705
706 fprintf(stderr, "Can't find the directory \"%s\"!\n", dir.c_str());
707 fprintf(stderr,
708 "The environment variable \"%s\" should name a directory.\n",
709 envVar.c_str());
710
711 return false;
712}
713
714
717{
718 setEnableSound(true); // Enable sound
719 mustUpdateOptions = true; // Update options displayed at user
721 startingYear = 1900;
722 simPasses = 1;
723 simPass = 0;
724 setAutoGoto(true); // Enable auto-goto
725 setCityTax(7);
726 cityTime = 50;
727 setEnableDisasters(true); // Enable disasters
728 setAutoBulldoze(true); // Enable auto bulldoze
729 setAutoBudget(true); // Enable auto-budget
730 blinkFlag = 1;
731 changeEval();
732 simPaused = false; // Simulation is running
733 simLoops = 0;
734 initSimLoad = 2;
735
736 initGraphs();
737 initFundingLevel();
740 clearMap();
742 setFunds(5000);
744 setSpeed(3);
745 setPasses(1);
746}
747
748
755{
756 blinkFlag = ((tickCount() % 60) < 30) ? 1 : -1;
757
758 if (simSpeed && !heatSteps) {
759 tilesAnimated = false;
760 }
761
762 doUpdateHeads();
763 graphDoer();
764 updateBudget();
765 scoreDoer();
766}
767
768
777{
778 int x, y;
779 static int a = 0;
780 short *src, *dst;
781 int fl = heatFlow;
782
783 const int SRCCOL = WORLD_H + 2;
784 const int DSTCOL = WORLD_H;
785
786 if (cellSrc == NULL) {
787 cellSrc = (short *)newPtr((WORLD_W + 2) * (WORLD_H + 2) * sizeof (short));
788 cellDst = (short *)&map[0][0];
789 }
790
791 src = cellSrc + SRCCOL + 1;
792 dst = cellDst;
793
794 /*
795 * Copy wrapping edges:
796 *
797 * 0 ff f0 f1 ... fe ff f0
798 *
799 * 1 0f 00 01 ... 0e 0f 00
800 * 2 1f 10 11 ... 1e 1f 10
801 * .. .. .. .. .. ..
802 * ef e0 e1 ... ee ef e0
803 * h ff f0 f1 ... fe ff f0
804 *
805 * h+1 0f 00 01 ... 0e 0f 00
806 *
807 * wrap value: effect:
808 * 0 no effect
809 * 1 copy future=>past, no wrap
810 * 2 no copy, wrap edges
811 * 3 copy future=>past, wrap edges
812 * 4 copy future=>past, same edges
813 */
814
815 switch (heatWrap) {
816 case 0:
817 break;
818 case 1:
819 for (x = 0; x < WORLD_W; x++) {
820 memcpy(src, dst, WORLD_H * sizeof (short));
821 src += SRCCOL;
822 dst += DSTCOL;
823 }
824 break;
825 case 2:
826 for (x = 0; x < WORLD_W; x++) {
827 src[-1] = src[WORLD_H - 1];
828 src[WORLD_H] = src[0];
829 src += SRCCOL;
830 dst += DSTCOL;
831 }
832 memcpy(
833 cellSrc,
834 cellSrc + (SRCCOL * WORLD_W),
835 SRCCOL * sizeof (short));
836 memcpy(
837 cellSrc + SRCCOL * (WORLD_W + 1),
838 cellSrc + SRCCOL,
839 SRCCOL * sizeof (short));
840 break;
841 case 3:
842 for (x = 0; x < WORLD_W; x++) {
843 memcpy(src, dst, WORLD_H * sizeof (short));
844 src[-1] = src[WORLD_H - 1];
845 src[WORLD_H] = src[0];
846 src += SRCCOL;
847 dst += DSTCOL;
848 }
849 memcpy(
850 cellSrc,
851 cellSrc + (SRCCOL * WORLD_W),
852 SRCCOL * sizeof (short));
853 memcpy(
854 cellSrc + SRCCOL * (WORLD_W + 1),
855 cellSrc + SRCCOL,
856 SRCCOL * sizeof (short));
857 break;
858 case 4:
859 src[0] =
860 dst[0];
861 src[1 + WORLD_H] =
862 dst[WORLD_H - 1];
863 src[(1 + WORLD_W) * SRCCOL] =
864 dst[(WORLD_W - 1) * DSTCOL];
865 src[((2 + WORLD_W) * SRCCOL) - 1] =
866 dst[(WORLD_W * WORLD_H) - 1];
867 for (x = 0; x < WORLD_W; x++) {
868 memcpy(src, dst, WORLD_H * sizeof (short));
869 src[-1] = src[0];
870 src[WORLD_H] = src[WORLD_H - 1];
871 src += SRCCOL;
872 dst += DSTCOL;
873 }
874 memcpy(
875 cellSrc + (SRCCOL * (WORLD_W + 1)),
876 cellSrc + (SRCCOL * WORLD_W),
877 SRCCOL * sizeof (short));
878 memcpy(
879 cellSrc,
880 cellSrc + SRCCOL,
881 SRCCOL * sizeof (short));
882 break;
883 default:
884 NOT_REACHED();
885 break;
886 }
887
888
889#define CLIPPER_LOOP_BODY(CODE) \
890 src = cellSrc; dst = cellDst; \
891 for (x = 0; x < WORLD_W;) { \
892 short nw, n, ne, w, c, e, sw, s, se; \
893 src = cellSrc + (x * SRCCOL); \
894 dst = cellDst + (x * DSTCOL); \
895 w = src[0]; c = src[SRCCOL]; e = src[2 * SRCCOL]; \
896 sw = src[1]; s = src[SRCCOL + 1]; se = src[(2 * SRCCOL) + 1]; \
897 for (y = 0; y < WORLD_H; y++) { \
898 nw = w; w = sw; sw = src[2]; \
899 n = c; c = s; s = src[SRCCOL + 2]; \
900 ne = e; e = se; se = src[(2 * SRCCOL) + 2]; \
901 { CODE } \
902 src++; dst++; \
903 } \
904 x++; \
905 src = cellSrc + ((x + 1) * SRCCOL) - 3; \
906 dst = cellDst + ((x + 1) * DSTCOL) - 1; \
907 nw = src[1]; n = src[SRCCOL + 1]; ne = src[(2 * SRCCOL) + 1]; \
908 w = src[2]; c = src[SRCCOL + 2]; e = src[(2 * SRCCOL) + 2]; \
909 for (y = WORLD_H - 1; y >= 0; y--) { \
910 sw = w; w = nw; nw = src[0]; \
911 s = c; c = n; n = src[SRCCOL]; \
912 se = e; e = ne; ne = src[2 * SRCCOL]; \
913 { CODE } \
914 src--; dst--; \
915 } \
916 x++; \
917 }
918
919
920 switch (heatRule) {
921
922 case 0:
923
924#define HEAT \
925 a += nw + n + ne + w + e + sw + s + se + fl; \
926 dst[0] = ((a >> 3) & LOMASK) | ANIMBIT | BURNBIT | BULLBIT; \
927 a &= 7;
928
929 CLIPPER_LOOP_BODY(HEAT);
930 break;
931
932 case 1:
933
934#define ECOMASK 0x3fc
935#define ECO \
936 { \
937 c -= fl; n -= fl; s -= fl; e -= fl; w -= fl; \
938 ne -= fl; nw -= fl; se -= fl; sw -= fl; \
939 /* anneal */ \
940 int sum = \
941 (c&1) + (n&1) + (s&1) + (e&1) + (w&1) + \
942 (ne&1) + (nw&1) + (se&1) + (sw&1), cell; \
943 if (((sum > 5) || (sum == 4))) { \
944 /* brian's brain */ \
945 cell = \
946 ((c <<1) & (0x3fc)) | \
947 (((((c >>1)&3) == 0) && \
948 (((n&2) + (s&2) + (e&2) + (w&2) + \
949 (ne&2) + (nw&2) + (se&2) + (sw&2)) == (2 <<1)) \
950 ) ? 2 : 0) | \
951 1; \
952 cell &= 0x00f; \
953 } else { \
954 /* anti-life */ \
955 sum = \
956 ((n&2) + (s&2) + (e&2) + (w&2) + \
957 (ne&2) + (nw&2) + (se&2) + (sw&2)) >>1; \
958 cell = \
959 (((c ^ 2) <<1) & ECOMASK) | \
960 ((c&2) \
961 ? ((sum != 5) ? 2 : 0) \
962 : (((sum != 5) && (sum != 6)) ? 2 : 0)); \
963 cell &= 0x00f; \
964 } \
965 dst[0] = \
966 ((fl + cell) & LOMASK) | ANIMBIT | BURNBIT | BULLBIT; \
967 c += fl; n += fl; s += fl; e += fl; w += fl; \
968 ne += fl; nw += fl; se += fl; sw += fl; \
969 }
970
971 CLIPPER_LOOP_BODY(ECO);
972
973 break;
974
975 default:
976 NOT_REACHED();
977 break;
978 }
979}
980
981
982void Micropolis::simLoop(bool doSim)
983{
984 if (heatSteps) {
985 int j;
986
987 for (j = 0; j < heatSteps; j++) {
988 simHeat();
989 }
990
991 moveObjects();
992 simulateRobots();
993
994 newMap = 1;
995
996 } else {
997 if (doSim) {
998 simFrame();
999 }
1000
1001 moveObjects();
1002 simulateRobots();
1003 }
1004
1005 simLoops++;
1006}
1007
1008
1015{
1016 if (simSpeed) {
1017 for (simPass = 0; simPass < simPasses; simPass++) {
1018 simLoop(true);
1019 }
1020 }
1021 simUpdate();
1022}
1023
1024
1025void Micropolis::simulateRobots()
1026{
1027 callback->simulateRobots(this, callbackVal);
1028}
1029
1030
1035void Micropolis::spend(int dollars)
1036{
1037 setFunds(totalFunds - dollars);
1038}
1039
1040
1048void Micropolis::setFunds(int dollars)
1049{
1050 totalFunds = dollars;
1051 updateFunds();
1052}
1053
1054
1062{
1063 struct timeval time;
1064 gettimeofday(&time, 0);
1065 return (Quad)((time.tv_sec * 60) + (time.tv_usec * 60) / 1000000);
1066}
1067
1068
1075{
1076 return (Ptr)malloc(size);
1077}
1078
1079
1084void Micropolis::freePtr(void *data)
1085{
1086 free(data);
1087}
1088
1089
1096{
1097 callback->startScenario(this, callbackVal, scenario);
1098}
1099
1100
1105{
1106 callback->startGame(this, callbackVal);
1107}
1108
1109
1115{
1116 makeSound("city", "ExplosionLow"); // Make the sound all over.
1117
1118 callback->startEarthquake(this, callbackVal, strength);
1119}
1120
1121
1124{
1125 mapSerial++;
1126 callback->updateMap(this, callbackVal);
1127}
1128
1129
1140void Micropolis::makeSound(const std::string &channel,
1141 const std::string &sound,
1142 int x, int y)
1143{
1144 if (enableSound) {
1145 callback->makeSound(this, callbackVal, channel, sound, x, y);
1146 }
1147}
1148
1149
1157int Micropolis::getTile(int x, int y)
1158{
1159 if (!testBounds(x, y)) {
1160 return DIRT;
1161 }
1162
1163 return map[x][y];
1164}
1165
1166
1174void Micropolis::setTile(int x, int y, int tile)
1175{
1176 if (!testBounds(x, y)) {
1177 return;
1178 }
1179
1180 map[x][y] = (unsigned short)tile;
1181}
1182
1183
1190{
1191 return (void *)mapBase;
1192}
1193
1194
1204{
1205 return powerGridMap.worldGet(x, y);
1206}
1207
1208
1217void Micropolis::setPowerGrid(int x, int y, int power)
1218{
1219 powerGridMap.worldSet(x, y, power);
1220}
1221
1222
1230{
1231 return (void *)powerGridMap.getBase();
1232}
1233
1234
1244{
1245 return populationDensityMap.get(x, y);
1246}
1247
1248
1257void Micropolis::setPopulationDensity(int x, int y, int density)
1258{
1259 populationDensityMap.set(x, y, density);
1260}
1261
1262
1273
1274
1284{
1285 return rateOfGrowthMap.get(x, y);
1286}
1287
1288
1297void Micropolis::setRateOfGrowth(int x, int y, int rate)
1298{
1299 rateOfGrowthMap.set(x, y, rate);
1300}
1301
1302
1310{
1311 return (void *)rateOfGrowthMap.getBase();
1312}
1313
1314
1324{
1325 return trafficDensityMap.get(x, y);
1326}
1327
1328
1337void Micropolis::setTrafficDensity(int x, int y, int density)
1338{
1339 trafficDensityMap.set(x, y, density);
1340}
1341
1342
1350{
1351 return (void *)trafficDensityMap.getBase();
1352}
1353
1354
1364{
1365 return pollutionDensityMap.get(x, y);
1366}
1367
1368
1377void Micropolis::setPollutionDensity(int x, int y, int density)
1378{
1379 pollutionDensityMap.set(x, y, density);
1380}
1381
1382
1393
1394
1404{
1405 return crimeRateMap.get(x, y);
1406}
1407
1408
1417void Micropolis::setCrimeRate(int x, int y, int rate)
1418{
1419 crimeRateMap.set(x, y, rate);
1420}
1421
1422
1430{
1431 return (void *)crimeRateMap.getBase();
1432}
1433
1434
1444{
1445 return landValueMap.get(x, y);
1446}
1447
1448
1457void Micropolis::setLandValue(int x, int y, int value)
1458{
1459 landValueMap.set(x, y, value);
1460}
1461
1462
1470{
1471 return (void *)landValueMap.getBase();
1472}
1473
1474
1484{
1485 return fireStationEffectMap.get(x, y);
1486}
1487
1488
1497void Micropolis::setFireCoverage(int x, int y, int coverage)
1498{
1499 fireStationEffectMap.set(x, y, coverage);
1500}
1501
1502
1510{
1511 return (void *)fireStationEffectMap.getBase();
1512}
1513
1523{
1524 return policeStationEffectMap.get(x, y);
1525}
1526
1527
1536void Micropolis::setPoliceCoverage(int x, int y, int coverage)
1537{
1538 policeStationEffectMap.set(x, y, coverage);
1539}
1540
1541
1552
1553
1554long Micropolis::getMapAddress()
1555{
1556 return (long)mapBase;
1557}
1558
1559
1560long Micropolis::getMapSize()
1561{
1562 return (long)(WORLD_W * WORLD_H * sizeof (short));
1563}
1564
1565
1566long Micropolis::getMopAddress()
1567{
1568 return (long)mopBase;
1569}
1570
1571
1572long Micropolis::getMopSize()
1573{
1574 return (long)(WORLD_W * WORLD_H * sizeof (short));
1575}
1576
1577
DATA worldGet(int x, int y) const
Definition map_type.h:316
void set(int x, int y, DATA val)
Definition map_type.h:248
void clear()
Definition map_type.h:222
DATA * getBase()
Definition map_type.h:233
DATA get(int x, int y) const
Definition map_type.h:265
void worldSet(int x, int y, DATA val)
Definition map_type.h:297
short crimeMaxX
X coordinate of most criminal area. Not used.
Quad roadEffect
void setGameLevelFunds(GameLevel level)
SimSprite * spriteList
List of active sprites.
int terrainCreateIsland
short problemVotes[PROBNUM]
int getCrimeRate(int x, int y)
float firePercent
void * getPopulationDensityMapBuffer()
bool doInitialEval
Need to perform initial city evaluation.
int mustDrawBudget
void changeEval()
Definition evaluate.cpp:507
short indPop
Definition micropolis.h:997
MapShort8 policeStationEffectMap
short stadiumPop
Number of stadiums.
void resetMapState()
void initGraphs()
Definition graph.cpp:142
short indZonePop
Number of industrial zones.
void setTile(int x, int y, int tile)
void setPoliceCoverage(int x, int y, int coverage)
Scenario scoreType
The type of score table to use.
short blinkFlag
void simUpdate()
short indHist10Max
short crimeAverage
int terrainTreeLevel
Quad cityPopDelta
GameLevel gameLevel
Difficulty level of the game (0..2)
Scenario scenario
Scenario being played.
void setPollutionDensity(int x, int y, int density)
int getTrafficDensity(int x, int y)
short poweredZoneCount
Number of powered tiles in all zone.
Quad policeEffect
Quad tickCount()
void setTrafficDensity(int x, int y, int density)
Callback * callback
Definition micropolis.h:955
int powerStackPointer
Stack counter, points to top-most item.
short graph10Max
MapByte1 powerGridMap
bool tilesAnimated
MapByte2 crimeRateMap
Crime rate map.
std::string cityFileName
Filename of the last loaded city.
void * getRateOfGrowthMapBuffer()
Quad policeValue
MapByte4 terrainDensityMap
SimSprite * freeSprites
Pool of free SimSprite objects.
short unpoweredZoneCount
Number of unpowered tiles in all zones.
void updateBudget()
Definition budget.cpp:327
void * getTrafficDensityMapBuffer()
void scoreDoer()
Definition evaluate.cpp:515
short newMapFlags[MAP_TYPE_COUNT]
short churchPop
Number of churches.
bool evalChanged
The evaluation window should be shown to the user.
short firePop
Definition micropolis.h:976
void graphDoer()
Definition graph.cpp:132
Position powerStackXY[POWER_STACK_SIZE]
short faith
Faith bias.
int terrainCurveLevel
float roadPercent
MapShort8 comRateMap
short cityCenterY
Y coordinate of city center.
void simInit()
MapShort8 fireStationEffectMap
void * getLandValueMapBuffer()
void * getCrimeRateMapBuffer()
short resPop
Definition micropolis.h:983
Position curMapStackXY[MAX_TRAFFIC_DISTANCE+1]
Position stack.
short pollutionMaxY
Y coordinate of most polluted area.
void moveObjects()
Definition sprite.cpp:553
void setAutoGoto(bool value)
bool doAnimation
short problemOrder[CVP_PROBLEM_COMPLAINTS]
void * getPowerGridMapBuffer()
bool enableDisasters
Enable disasters.
short cityScoreDelta
int getRateOfGrowth(int x, int y)
Quad cityPopLast
Population of last city class check.
short graph120Max
short scoreWait
Time to wait before computing the score.
short pollutionMaxX
X coordinate of most polluted area.
void * getPoliceCoverageMapBuffer()
short totalZonePop
short resZonePop
Number of residential zones.
short pollutionAverage
short trafMaxY
Y coordinate of a position with heavy traffic.
short resHist120Max
bool indCap
Block industrial growth.
Quad fireEffect
void resetEditorState()
short totalPopLast
bool resCap
Block residential growth.
void * getMapBuffer()
short trafMaxX
X coordinate of a position with heavy traffic.
short airportPop
std::string cityName
Name of the city.
void setFunds(int dollars)
short policeStationPop
void updateFunds()
Definition update.cpp:127
void setAutoBulldoze(bool value)
short disasterWait
Count-down timer for the disaster.
void setEnableSound(bool value)
int getPoliceCoverage(int x, int y)
bool mustUpdateOptions
Options displayed at user need updating.
void setEnableDisasters(bool value)
int getFireCoverage(int x, int y)
MapShort8 fireStationMap
short cityCenterX
X coordinate of city center.
short totalPop
short cityYes
int getLandValue(int x, int y)
Quad cityAssessedValue
short landValueAverage
unsigned short * map[WORLD_W]
bool doMessages
void setFireCoverage(int x, int y, int coverage)
void initMapArrays()
Definition allocate.cpp:88
void simHeat()
short coalPowerPop
void doStartGame()
short hospitalPop
Number of hospitals.
bool censusChanged
int terrainLakeLevel
short trafficAverage
int mapSerial
The invalidateMaps method increases the map serial number every time the maps changes.
short comHist10Max
void destroyMapArrays()
Definition allocate.cpp:121
short startingYear
bool enableSound
Enable sound.
Scenario disasterEvent
The disaster for which a count-down is running.
unsigned short * mapBase
MapShort8 policeStationMap
void makeSound(const std::string &channel, const std::string &sound, int x=-1, int y=-1)
MapByte2 pollutionDensityMap
Pollution density map.
MapByte2 trafficDensityMap
Traffic density map.
bool autoBudget
int getTile(int x, int y)
short cityScore
short categoryLast
City class of last city class check.
bool comCap
Block commercial growth.
int getPollutionDensity(int x, int y)
Quad policeSpend
void * getFireCoverageMapBuffer()
CityClass cityClass
City class, affected by city population.
short nuclearPowerPop
void spend(int dollars)
static bool testBounds(int wx, int wy)
void invalidateMaps()
short floodCount
void clearMap()
Definition generate.cpp:175
void setPopulationDensity(int x, int y, int density)
short fireStationPop
void doStartScenario(int scenario)
void freePtr(void *data)
Ptr newPtr(int size)
void * getPollutionDensityMapBuffer()
short curMapStackPointer
short comPop
Definition micropolis.h:990
int getPowerGrid(int x, int y)
short needHospital
int getPopulationDensity(const Position &pos, MapTile tile)
Definition scan.cpp:198
MapByte2 populationDensityMap
Population density map.
void initWillStuff()
MapByte2 landValueMap
Land value map.
Quad policeFund
short needChurch
MapShort8 rateOfGrowthMap
void setRateOfGrowth(int x, int y, int rate)
void setCrimeRate(int x, int y, int rate)
short cityTax
void setPowerGrid(int x, int y, int power)
short railTotal
Definition micropolis.h:971
short crimeMaxY
Y coordinate of most criminal area. Not used.
short comZonePop
Number of commercial zones.
short seaportPop
short roadTotal
Definition micropolis.h:964
float policePercent
Quad totalFunds
Funds of the player.
short comHist120Max
bool autoBulldoze
void doEarthquake(int strength)
void doSimInit()
Definition simulate.cpp:288
short resHist10Max
short indHist120Max
void setAutoBudget(bool value)
void setLandValue(int x, int y, int value)
static const int WORLD_H
Definition map_type.h:95
static const int WORLD_W
Definition map_type.h:90
static bool testDirectory(const std::string &dir, const std::string &envVar)
Header file for Micropolis game engine.
@ SC_NONE
No scenario (free playing)
Definition micropolis.h:699
static const int POWER_STACK_SIZE
Definition micropolis.h:226
@ MAP_TYPE_COUNT
Number of map types.
Definition micropolis.h:323
@ DIRT
Clear tile.
Definition micropolis.h:382
#define NOT_REACHED()
Definition micropolis.h:848
@ CC_VILLAGE
Village.
Definition micropolis.h:752
@ LEVEL_EASY
Simple game level.
Definition micropolis.h:764
@ CVP_PROBLEM_COMPLAINTS
Number of problems to complain about.
Definition micropolis.h:745
@ SPRITE_COUNT
Number of sprite objects.
Definition micropolis.h:340
static const int MAX_TRAFFIC_DISTANCE
Definition micropolis.h:248