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 {
106  setCallback(new ConsoleCallback(), emscripten::val::null());
107  init();
108 }
109 
110 
113 {
114  setCallback(NULL, emscripten::val::null());
115  destroy();
116 }
117 
118 
119 void Micropolis::setCallback(Callback *callback0, emscripten::val callbackVal0)
120 {
121  if (callback != NULL) {
122  delete callback;
123  }
124  callback = callback0;
125  callbackVal = callbackVal0;
126 }
127 
128 
131 {
132 
134  // allocate.cpp
135 
136 
137  // short roadTotal;
138  roadTotal = 0;
139 
140  // short railTotal;
141  railTotal = 0;
142 
143  // short firePop;
144  firePop = 0;
145 
146  // short resPop;
147  resPop = 0;
148 
149  // short comPop;
150  comPop = 0;
151 
152  // short indPop;
153  indPop = 0;
154 
155  // short totalPop;
156  totalPop = 0;
157 
158  // short totalPopLast;
159  totalPopLast = 0;
160 
161  // short resZonePop;
162  resZonePop = 0;
163 
164  // short comZonePop;
165  comZonePop = 0;
166 
167  // short indZonePop;
168  indZonePop = 0;
169 
170  // short totalZonePop;
171  totalZonePop = 0;
172 
173  // short hospitalPop;
174  hospitalPop = 0;
175 
176  // short churchPop;
177  churchPop = 0;
178 
179  // short faith;
180  faith = 0;
181 
182  // short stadiumPop;
183  stadiumPop = 0;
184 
185  // short policeStationPop;
186  policeStationPop = 0;
187 
188  // short fireStationPop;
189  fireStationPop = 0;
190 
191  // short coalPowerPop;
192  coalPowerPop = 0;
193 
194  // short nuclearPowerPop;
195  nuclearPowerPop = 0;
196 
197  // short seaportPop;
198  seaportPop = 0;
199 
200  // short airportPop;
201  airportPop = 0;
202 
203  // short needHospital;
204  needHospital = 0;
205 
206  // short needChurch;
207  needChurch = 0;
208 
209  // short crimeAverage;
210  crimeAverage = 0;
211 
212  // short pollutionAverage;
213  pollutionAverage = 0;
214 
215  // short landValueAverage;
216  landValueAverage = 0;
217 
218  // Quad cityTime;
219  cityTime = 0;
220 
221  // Quad cityMonth;
222  cityMonth = 0;
223 
224  // Quad cityYear;
225  cityYear = 0;
226 
227  // short startingYear;
228  startingYear = 0;
229 
230  // short *map[WORLD_W];
231  memset(map, 0, sizeof(short *) * WORLD_W);
232 
233  // short resHist10Max;
234  resHist10Max = 0;
235 
236  // short resHist120Max;
237  resHist120Max = 0;
238 
239  // short comHist10Max;
240  comHist10Max = 0;
241 
242  // short comHist120Max;
243  comHist120Max = 0;
244 
245  // short indHist10Max;
246  indHist10Max = 0;
247 
248  // short indHist120Max;
249  indHist120Max = 0;
250 
251  censusChanged = false;
252 
253  // Quad roadSpend;
254  roadSpend = 0;
255 
256  // Quad policeSpend;
257  policeSpend = 0;
258 
259  // Quad fireSpend;
260  fireSpend = 0;
261 
262  // Quad roadFund;
263  roadFund = 0;
264 
265  // Quad policeFund;
266  policeFund = 0;
267 
268  // Quad fireFund;
269  fireFund = 0;
270 
271  roadEffect = 0;
272  policeEffect = 0;
273  fireEffect = 0;
274 
275  // Quad taxFund;
276  taxFund = 0;
277 
278  // short cityTax;
279  cityTax = 0;
280 
281  // bool taxFlag;
282  taxFlag = false;
283 
296  comRateMap.clear();
297 
298  // unsigned short *mapBase;
299  mapBase = NULL;
300 
301  // short *resHist;
302  resHist = NULL;
303 
304  // short *comHist;
305  comHist = NULL;
306 
307  // short *indHist;
308  indHist = NULL;
309 
310  // short *moneyHist;
311  moneyHist = NULL;
312 
313  // short *pollutionHist;
314  pollutionHist = NULL;
315 
316  // short *crimeHist;
317  crimeHist = NULL;
318 
319  // short *miscHist;
320  miscHist = NULL;
321 
322 
324  // budget.cpp
325 
326 
327  // float roadPercent;
328  roadPercent = (float)0.0;
329 
330  // float policePercent;
331  policePercent = (float)0.0;
332 
333  // float firePercent;
334  firePercent = (float)0.0;
335 
336  // Quad roadValue;
337  roadValue = 0;
338 
339  // Quad policeValue;
340  policeValue = 0;
341 
342  // Quad fireValue;
343  fireValue = 0;
344 
345  // int mustDrawBudget;
346  mustDrawBudget = 0;
347 
348 
350  // disasters.cpp
351 
352 
353  // short floodCount;
354  floodCount = 0;
355 
356 
358  // evaluate.cpp
359 
360 
361  // short cityYes;
362  cityYes = 0;
363 
364  // short problemVotes[PROBNUM]; /* these are the votes for each */
365  memset(problemVotes, 0, sizeof(short) * PROBNUM);
366 
367  // short problemOrder[CVP_PROBLEM_COMPLAINTS]; /* sorted index to above */
368  memset(problemOrder, 0, sizeof(short) * CVP_PROBLEM_COMPLAINTS);
369 
370  // Quad cityPop;
371  cityPop = 0;
372 
373  // Quad cityPopDelta;
374  cityPopDelta = 0;
375 
376  // Quad cityAssessedValue;
377  cityAssessedValue = 0;
378 
380 
381  // short cityScore;
382  cityScore = 0;
383 
384  // short cityScoreDelta;
385  cityScoreDelta = 0;
386 
387  // short trafficAverage;
388  trafficAverage = 0;
389 
390 
392  // generate.cpp
393 
394 
395  // int TreeLevel; /* level for tree creation */
396  terrainTreeLevel = -1;
397 
398  // int LakeLevel; /* level for lake creation */
399  terrainLakeLevel = -1;
400 
401  // int CurveLevel; /* level for river curviness */
402  terrainCurveLevel = -1;
403 
404  // int CreateIsland; /* -1 => 10%, 0 => never, 1 => always */
405  terrainCreateIsland = -1;
406 
407 
409  // graph.cpp
410 
411 
412  graph10Max = 0;
413  graph120Max = 0;
414 
415 
417  // main.cpp
418 
419  // int simLoops;
420  simLoops = 0;
421 
422  // int simPasses;
423  simPasses = 0;
424 
425  // int simPass;
426  simPass = 0;
427 
428  simPaused = false; // Simulation is running
429 
430  // int simPausedSpeed;
431  simPausedSpeed = 3;
432 
433  // int heatSteps;
434  heatSteps = 0;
435 
436  // int heatFlow;
437  heatFlow = -7;
438 
439  // int heatRule;
440  heatRule = 0;
441 
442  // int heatWrap;
443  heatWrap = 3;
444 
445  // std::string cityFileName;
446  cityFileName = "";
447 
448  // std::string cityName;
449  cityName = "";
450 
451  // bool tilesAnimated;
452  tilesAnimated = false;
453 
454  // bool doAnimaton;
455  doAnimation = true;
456 
457  // bool doMessages;
458  doMessages = true;
459 
460  // bool doNotices;
461  doNotices = true;
462 
463  // short *cellSrc;
464  cellSrc = NULL;
465 
466  // short *cellDst;
467  cellDst = NULL;
468 
469 
471  // message.cpp
472 
473 
474  // Quad cityPopLast;
475  cityPopLast = 0;
476 
477  // short categoryLast;
478  categoryLast = 0;
479 
480  autoGoto = false;
481 
482 
484  // power.cpp
485 
486 
487  powerStackPointer = 0;
488 
489  // Position powerStackXY[POWER_STACK_SIZE];
490  for (int i = 0; i < POWER_STACK_SIZE; i++) {
491  powerStackXY[i] = Position();
492  }
493 
494 
496  // random.cpp
497 
498 
499  // UQuad nextRandom;
500  nextRandom = 1;
501 
502 
504  // scan.cpp
505 
506  // short newMap;
507  newMap = 0;
508 
509  // short newMapFlags[MAP_TYPE_COUNT];
510  memset(newMapFlags, 0, sizeof(short) * MAP_TYPE_COUNT);
511 
512  // short cityCenterX;
513  cityCenterX = 0;
514 
515  // short cityCenterY;
516  cityCenterY = 0;
517 
518  // short pollutionMaxX;
519  pollutionMaxX = 0;
520 
521  // short pollutionMaxY;
522  pollutionMaxY = 0;
523 
524  // short crimeMaxX;
525  crimeMaxX = 0;
526 
527  // short crimeMaxY;
528  crimeMaxY = 0;
529 
530  // Quad donDither;
531  donDither = 0;
532 
533 
535  // simulate.cpp
536 
537 
538  valveFlag = false;
539 
540  // short crimeRamp;
541  crimeRamp = 0;
542 
543  // short pollutionRamp;
544  pollutionRamp = 0;
545 
546  resCap = false; // Do not block residential growth
547  comCap = false; // Do not block commercial growth
548  indCap = false; // Do not block industrial growth
549 
550  // short cashFlow;
551  cashFlow = 0;
552 
553  // float externalMarket;
554  externalMarket = (float)4.0;
555 
557 
558  // short disasterWait;
559  disasterWait = 0;
560 
561  scoreType = SC_NONE;
562 
563  // short scoreWait;
564  scoreWait = 0;
565 
566  // short poweredZoneCount;
567  poweredZoneCount = 0;
568 
569  // short unpoweredZoneCount;
570  unpoweredZoneCount = 0;
571 
572  newPower = false;
573 
574  // short cityTaxAverage;
575  cityTaxAverage = 0;
576 
577  // short simCycle;
578  simCycle = 0;
579 
580  // short phaseCycle;
581  phaseCycle = 0;
582 
583  // short speedCycle;
584  speedCycle = 0;
585 
586  // bool doInitialEval
587  doInitialEval = false;
588 
589  // int mapSerial;
590  mapSerial = 1;
591 
592  // short resValve;
593  resValve = 0;
594 
595  // short comValve;
596  comValve = 0;
597 
598  // short indValve;
599  indValve = 0;
600 
601 
603  // sprite.cpp
604 
605 
606  //SimSprite *spriteList;
607  spriteList = NULL;
608 
609  // SimSprite *freeSprites;
610  freeSprites = NULL;
611 
612  // SimSprite *globalSprites[SPRITE_COUNT];
613  memset(globalSprites, 0, sizeof(SimSprite *) * SPRITE_COUNT);
614 
615  // int absDist;
616  absDist = 0;
617 
618  // short spriteCycle;
619  spriteCycle = 0;
620 
621 
623  // stubs.cpp
624 
625 
626  // Quad totalFunds;
627  totalFunds = 0;
628 
629  autoBulldoze = true;
630 
631  autoBudget = true;
632 
634 
635  // short initSimLoad;
636  initSimLoad = 0;
637 
638  scenario = SC_NONE;
639 
640  // short simSpeed;
641  simSpeed = 0;
642 
643  // short simSpeedMeta;
644  simSpeedMeta = 0;
645 
646  enableSound = false;
647 
648  enableDisasters = true;
649 
650  evalChanged = false;
651 
652  // short blinkFlag;
653  blinkFlag = 0;
654 
655 
657  // traffic.cpp
658 
659 
660  // short curMapStackPointer;
661  curMapStackPointer = 0;
662 
663  // Position curMapStackXY[MAX_TRAFFIC_DISTANCE+1];
664  for (int i = 0; i < MAX_TRAFFIC_DISTANCE + 1; i++) {
665  curMapStackXY[i] = Position();
666  }
667 
668  // short trafMaxX, trafMaxY;
669  trafMaxX = 0;
670  trafMaxY = 0;
671 
672 
674  // update.cpp
675 
676 
677  mustUpdateFunds = false;
678 
679  mustUpdateOptions = false;
680 
681  // Quad cityTimeLast;
682  cityTimeLast = 0;
683 
684  // Quad cityYearLast;
685  cityYearLast = 0;
686 
687  // Quad cityMonthLast;
688  cityMonthLast = 0;
689 
690  // Quad totalFundsLast;
691  totalFundsLast = 0;
692 
693  // Quad resLast;
694  resLast = 0;
695 
696  // Quad comLast;
697  comLast = 0;
698 
699  // Quad indLast;
700  indLast = 0;
701 
702  simInit();
703 
704 }
705 
706 
707 void Micropolis::destroy()
708 {
709 
711 
712  // TODO: Clean up all other stuff:
713 
714 }
715 
716 
724 static bool testDirectory(const std::string& dir, const std::string &envVar)
725 {
726  struct stat statbuf;
727 
728  if (stat(dir.c_str(), &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
729 
730  return true;
731  }
732 
733  fprintf(stderr, "Can't find the directory \"%s\"!\n", dir.c_str());
734  fprintf(stderr,
735  "The environment variable \"%s\" should name a directory.\n",
736  envVar.c_str());
737 
738  return false;
739 }
740 
741 
744 {
745  setEnableSound(true); // Enable sound
746  mustUpdateOptions = true; // Update options displayed at user
747  scenario = SC_NONE;
748  startingYear = 1900;
749  simPasses = 1;
750  simPass = 0;
751  setAutoGoto(true); // Enable auto-goto
752  setCityTax(7);
753  cityTime = 50;
754  setEnableDisasters(true); // Enable disasters
755  setAutoBulldoze(true); // Enable auto bulldoze
756  setAutoBudget(true); // Enable auto-budget
757  blinkFlag = 1;
758  simSpeed = 3;
759  changeEval();
760  simPaused = false; // Simulation is running
761  simLoops = 0;
762  initSimLoad = 2;
763 
764  initMapArrays();
765  initGraphs();
766  initFundingLevel();
767  resetMapState();
769  clearMap();
770  initWillStuff();
771  setFunds(5000);
773  setSpeed(0);
774  setPasses(1);
775 }
776 
777 
784 {
785  //printf("simUpdate\n");
786  blinkFlag = ((tickCount() % 60) < 30) ? 1 : -1;
787 
788  if (simSpeed && !heatSteps) {
789  tilesAnimated = false;
790  }
791 
792  doUpdateHeads();
793  graphDoer();
794  updateBudget();
795  scoreDoer();
796 }
797 
798 
807 {
808  int x, y;
809  static int a = 0;
810  short *src, *dst;
811  int fl = heatFlow;
812 
813  const int SRCCOL = WORLD_H + 2;
814  const int DSTCOL = WORLD_H;
815 
816 
817  if (cellSrc == NULL) {
818  cellSrc = (short *)newPtr((WORLD_W + 2) * (WORLD_H + 2) * sizeof (short));
819  cellDst = (short *)&map[0][0];
820  }
821 
822  src = cellSrc + SRCCOL + 1;
823  dst = cellDst;
824 
825  /*
826  * Copy wrapping edges:
827  *
828  * 0 ff f0 f1 ... fe ff f0
829  *
830  * 1 0f 00 01 ... 0e 0f 00
831  * 2 1f 10 11 ... 1e 1f 10
832  * .. .. .. .. .. ..
833  * ef e0 e1 ... ee ef e0
834  * h ff f0 f1 ... fe ff f0
835  *
836  * h+1 0f 00 01 ... 0e 0f 00
837  *
838  * wrap value: effect:
839  * 0 no effect
840  * 1 copy future=>past, no wrap
841  * 2 no copy, wrap edges
842  * 3 copy future=>past, wrap edges
843  * 4 copy future=>past, same edges
844  */
845 
846  switch (heatWrap) {
847  case 0:
848  break;
849  case 1:
850  for (x = 0; x < WORLD_W; x++) {
851  memcpy(src, dst, WORLD_H * sizeof (short));
852  src += SRCCOL;
853  dst += DSTCOL;
854  }
855  break;
856  case 2:
857  for (x = 0; x < WORLD_W; x++) {
858  src[-1] = src[WORLD_H - 1];
859  src[WORLD_H] = src[0];
860  src += SRCCOL;
861  dst += DSTCOL;
862  }
863  memcpy(
864  cellSrc,
865  cellSrc + (SRCCOL * WORLD_W),
866  SRCCOL * sizeof (short));
867  memcpy(
868  cellSrc + SRCCOL * (WORLD_W + 1),
869  cellSrc + SRCCOL,
870  SRCCOL * sizeof (short));
871  break;
872  case 3:
873  for (x = 0; x < WORLD_W; x++) {
874  memcpy(src, dst, WORLD_H * sizeof (short));
875  src[-1] = src[WORLD_H - 1];
876  src[WORLD_H] = src[0];
877  src += SRCCOL;
878  dst += DSTCOL;
879  }
880  memcpy(
881  cellSrc,
882  cellSrc + (SRCCOL * WORLD_W),
883  SRCCOL * sizeof (short));
884  memcpy(
885  cellSrc + SRCCOL * (WORLD_W + 1),
886  cellSrc + SRCCOL,
887  SRCCOL * sizeof (short));
888  break;
889  case 4:
890  src[0] =
891  dst[0];
892  src[1 + WORLD_H] =
893  dst[WORLD_H - 1];
894  src[(1 + WORLD_W) * SRCCOL] =
895  dst[(WORLD_W - 1) * DSTCOL];
896  src[((2 + WORLD_W) * SRCCOL) - 1] =
897  dst[(WORLD_W * WORLD_H) - 1];
898  for (x = 0; x < WORLD_W; x++) {
899  memcpy(src, dst, WORLD_H * sizeof (short));
900  src[-1] = src[0];
901  src[WORLD_H] = src[WORLD_H - 1];
902  src += SRCCOL;
903  dst += DSTCOL;
904  }
905  memcpy(
906  cellSrc + (SRCCOL * (WORLD_W + 1)),
907  cellSrc + (SRCCOL * WORLD_W),
908  SRCCOL * sizeof (short));
909  memcpy(
910  cellSrc,
911  cellSrc + SRCCOL,
912  SRCCOL * sizeof (short));
913  break;
914  default:
915  NOT_REACHED();
916  break;
917  }
918 
919 
920 #define CLIPPER_LOOP_BODY(CODE) \
921  src = cellSrc; dst = cellDst; \
922  for (x = 0; x < WORLD_W;) { \
923  short nw, n, ne, w, c, e, sw, s, se; \
924  src = cellSrc + (x * SRCCOL); \
925  dst = cellDst + (x * DSTCOL); \
926  w = src[0]; c = src[SRCCOL]; e = src[2 * SRCCOL]; \
927  sw = src[1]; s = src[SRCCOL + 1]; se = src[(2 * SRCCOL) + 1]; \
928  for (y = 0; y < WORLD_H; y++) { \
929  nw = w; w = sw; sw = src[2]; \
930  n = c; c = s; s = src[SRCCOL + 2]; \
931  ne = e; e = se; se = src[(2 * SRCCOL) + 2]; \
932  { CODE } \
933  src++; dst++; \
934  } \
935  x++; \
936  src = cellSrc + ((x + 1) * SRCCOL) - 3; \
937  dst = cellDst + ((x + 1) * DSTCOL) - 1; \
938  nw = src[1]; n = src[SRCCOL + 1]; ne = src[(2 * SRCCOL) + 1]; \
939  w = src[2]; c = src[SRCCOL + 2]; e = src[(2 * SRCCOL) + 2]; \
940  for (y = WORLD_H - 1; y >= 0; y--) { \
941  sw = w; w = nw; nw = src[0]; \
942  s = c; c = n; n = src[SRCCOL]; \
943  se = e; e = ne; ne = src[2 * SRCCOL]; \
944  { CODE } \
945  src--; dst--; \
946  } \
947  x++; \
948  }
949 
950 
951  switch (heatRule) {
952 
953  case 0:
954 
955 #define HEAT \
956  a += nw + n + ne + w + e + sw + s + se + fl; \
957  dst[0] = ((a >> 3) & LOMASK) | ANIMBIT | BURNBIT | BULLBIT; \
958  a &= 7;
959 
960  CLIPPER_LOOP_BODY(HEAT);
961  break;
962 
963  case 1:
964 
965 #define ECOMASK 0x3fc
966 #define ECO \
967  { \
968  c -= fl; n -= fl; s -= fl; e -= fl; w -= fl; \
969  ne -= fl; nw -= fl; se -= fl; sw -= fl; \
970  /* anneal */ \
971  int sum = \
972  (c&1) + (n&1) + (s&1) + (e&1) + (w&1) + \
973  (ne&1) + (nw&1) + (se&1) + (sw&1), cell; \
974  if (((sum > 5) || (sum == 4))) { \
975  /* brian's brain */ \
976  cell = \
977  ((c <<1) & (0x3fc)) | \
978  (((((c >>1)&3) == 0) && \
979  (((n&2) + (s&2) + (e&2) + (w&2) + \
980  (ne&2) + (nw&2) + (se&2) + (sw&2)) == (2 <<1)) \
981  ) ? 2 : 0) | \
982  1; \
983  } else { \
984  /* anti-life */ \
985  sum = \
986  ((n&2) + (s&2) + (e&2) + (w&2) + \
987  (ne&2) + (nw&2) + (se&2) + (sw&2)) >>1; \
988  cell = \
989  (((c ^ 2) <<1) & ECOMASK) | \
990  ((c&2) \
991  ? ((sum != 5) ? 2 : 0) \
992  : (((sum != 5) && (sum != 6)) ? 2 : 0)); \
993  } \
994  dst[0] = \
995  ((fl + cell) & LOMASK) | ANIMBIT | BURNBIT | BULLBIT; \
996  c += fl; n += fl; s += fl; e += fl; w += fl; \
997  ne += fl; nw += fl; se += fl; sw += fl; \
998  }
999 
1000  CLIPPER_LOOP_BODY(ECO);
1001 
1002  break;
1003 
1004  default:
1005  NOT_REACHED();
1006  break;
1007  }
1008 }
1009 
1010 
1011 void Micropolis::simLoop(bool doSim)
1012 {
1013  if (heatSteps) {
1014  int j;
1015 
1016  for (j = 0; j < heatSteps; j++) {
1017  simHeat();
1018  }
1019 
1020  moveObjects();
1021  simulateRobots();
1022 
1023  newMap = 1;
1024 
1025  } else {
1026  if (doSim) {
1027  simFrame();
1028  }
1029 
1030  moveObjects();
1031  simulateRobots();
1032  }
1033 
1034  simLoops++;
1035 }
1036 
1037 
1044 {
1045  if (simSpeed) {
1046  for (simPass = 0; simPass < simPasses; simPass++) {
1047  simLoop(true);
1048  }
1049  }
1050  simUpdate();
1051 }
1052 
1053 
1054 void Micropolis::simulateRobots()
1055 {
1056  callback->simulateRobots(this, callbackVal);
1057 }
1058 
1059 
1064 void Micropolis::spend(int dollars)
1065 {
1066  setFunds(totalFunds - dollars);
1067 }
1068 
1069 
1077 void Micropolis::setFunds(int dollars)
1078 {
1079  totalFunds = dollars;
1080  updateFunds();
1081 }
1082 
1083 
1091 {
1092  struct timeval time;
1093  gettimeofday(&time, 0);
1094  return (Quad)((time.tv_sec * 60) + (time.tv_usec * 60) / 1000000);
1095 }
1096 
1097 
1103 Ptr Micropolis::newPtr(int size)
1104 {
1105  return (Ptr)malloc(size);
1106 }
1107 
1108 
1113 void Micropolis::freePtr(void *data)
1114 {
1115  free(data);
1116 }
1117 
1118 
1125 {
1126  callback->startScenario(this, callbackVal, scenario);
1127 }
1128 
1129 
1134 {
1135  callback->startGame(this, callbackVal);
1136 }
1137 
1138 
1145 {
1146  simPaused = false; // Simulation is running.
1147  simPausedSpeed = 0;
1148  simPass = 0;
1149  simPasses = 1;
1150  heatSteps = 0; // Disable cellular automata machine.
1151  setSpeed(0);
1152 }
1153 
1154 
1159 void Micropolis::doEarthquake(int strength)
1160 {
1161  makeSound("city", "ExplosionLow"); // Make the sound all over.
1162 
1163  callback->startEarthquake(this, callbackVal, strength);
1164 }
1165 
1166 
1169 {
1170  mapSerial++;
1171  callback->updateMap(this, callbackVal);
1172 }
1173 
1174 
1185 void Micropolis::makeSound(const std::string &channel,
1186  const std::string &sound,
1187  int x, int y)
1188 {
1189  if (enableSound) {
1190  callback->makeSound(this, callbackVal, channel, sound, x, y);
1191  }
1192 }
1193 
1194 
1202 int Micropolis::getTile(int x, int y)
1203 {
1204  if (!testBounds(x, y)) {
1205  return DIRT;
1206  }
1207 
1208  return map[x][y];
1209 }
1210 
1211 
1219 void Micropolis::setTile(int x, int y, int tile)
1220 {
1221  if (!testBounds(x, y)) {
1222  return;
1223  }
1224 
1225  map[x][y] = (unsigned short)tile;
1226 }
1227 
1228 
1235 {
1236  return (void *)mapBase;
1237 }
1238 
1239 
1248 int Micropolis::getPowerGrid(int x, int y)
1249 {
1250  return powerGridMap.worldGet(x, y);
1251 }
1252 
1253 
1262 void Micropolis::setPowerGrid(int x, int y, int power)
1263 {
1264  powerGridMap.worldSet(x, y, power);
1265 }
1266 
1267 
1275 {
1276  return (void *)powerGridMap.getBase();
1277 }
1278 
1279 
1289 {
1290  return populationDensityMap.get(x, y);
1291 }
1292 
1293 
1302 void Micropolis::setPopulationDensity(int x, int y, int density)
1303 {
1304  populationDensityMap.set(x, y, density);
1305 }
1306 
1307 
1315 {
1316  return (void *)populationDensityMap.getBase();
1317 }
1318 
1319 
1329 {
1330  return rateOfGrowthMap.get(x, y);
1331 }
1332 
1333 
1342 void Micropolis::setRateOfGrowth(int x, int y, int rate)
1343 {
1344  rateOfGrowthMap.set(x, y, rate);
1345 }
1346 
1347 
1355 {
1356  return (void *)rateOfGrowthMap.getBase();
1357 }
1358 
1359 
1369 {
1370  return trafficDensityMap.get(x, y);
1371 }
1372 
1373 
1382 void Micropolis::setTrafficDensity(int x, int y, int density)
1383 {
1384  trafficDensityMap.set(x, y, density);
1385 }
1386 
1387 
1395 {
1396  return (void *)trafficDensityMap.getBase();
1397 }
1398 
1399 
1409 {
1410  return pollutionDensityMap.get(x, y);
1411 }
1412 
1413 
1422 void Micropolis::setPollutionDensity(int x, int y, int density)
1423 {
1424  pollutionDensityMap.set(x, y, density);
1425 }
1426 
1427 
1435 {
1436  return (void *)pollutionDensityMap.getBase();
1437 }
1438 
1439 
1448 int Micropolis::getCrimeRate(int x, int y)
1449 {
1450  return crimeRateMap.get(x, y);
1451 }
1452 
1453 
1462 void Micropolis::setCrimeRate(int x, int y, int rate)
1463 {
1464  crimeRateMap.set(x, y, rate);
1465 }
1466 
1467 
1475 {
1476  return (void *)crimeRateMap.getBase();
1477 }
1478 
1479 
1488 int Micropolis::getLandValue(int x, int y)
1489 {
1490  return landValueMap.get(x, y);
1491 }
1492 
1493 
1502 void Micropolis::setLandValue(int x, int y, int value)
1503 {
1504  landValueMap.set(x, y, value);
1505 }
1506 
1507 
1515 {
1516  return (void *)landValueMap.getBase();
1517 }
1518 
1519 
1529 {
1530  return fireStationEffectMap.get(x, y);
1531 }
1532 
1533 
1542 void Micropolis::setFireCoverage(int x, int y, int coverage)
1543 {
1544  fireStationEffectMap.set(x, y, coverage);
1545 }
1546 
1547 
1555 {
1556  return (void *)fireStationEffectMap.getBase();
1557 }
1558 
1568 {
1569  return policeStationEffectMap.get(x, y);
1570 }
1571 
1572 
1581 void Micropolis::setPoliceCoverage(int x, int y, int coverage)
1582 {
1583  policeStationEffectMap.set(x, y, coverage);
1584 }
1585 
1586 
1594 {
1595  return (void *)policeStationEffectMap.getBase();
1596 }
1597 
1598 
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.
Definition: micropolis.h:2050
Quad roadEffect
Definition: micropolis.h:1201
void setGameLevelFunds(GameLevel level)
Definition: utilities.cpp:208
SimSprite * spriteList
List of active sprites.
Definition: micropolis.h:2213
int terrainCreateIsland
Definition: micropolis.h:1735
short problemVotes[PROBNUM]
Definition: micropolis.h:1559
int getCrimeRate(int x, int y)
float firePercent
Definition: micropolis.h:1443
void * getPopulationDensityMapBuffer()
bool doInitialEval
Need to perform initial city evaluation.
Definition: micropolis.h:2120
Quad roadFund
Definition: micropolis.h:1182
int mustDrawBudget
Definition: micropolis.h:1463
void changeEval()
Definition: evaluate.cpp:507
short indPop
Definition: micropolis.h:996
MapShort8 policeStationEffectMap
Definition: micropolis.h:1322
short stadiumPop
Number of stadiums.
Definition: micropolis.h:1025
void resetMapState()
Definition: initialize.cpp:131
void initGraphs()
Definition: graph.cpp:142
short indZonePop
Number of industrial zones.
Definition: micropolis.h:1015
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.
Definition: micropolis.h:2104
short blinkFlag
Definition: micropolis.h:2355
bool taxFlag
Definition: micropolis.h:1237
void simUpdate()
Definition: micropolis.cpp:783
short indHist10Max
Definition: micropolis.h:1145
short crimeAverage
Definition: micropolis.h:1063
int terrainTreeLevel
Definition: micropolis.h:1717
Quad cityPopDelta
Definition: micropolis.h:1581
GameLevel gameLevel
Difficulty level of the game (0..2)
Definition: micropolis.h:2334
Scenario scenario
Scenario being played.
Definition: micropolis.h:2338
void setPollutionDensity(int x, int y, int density)
Quad fireFund
Definition: micropolis.h:1196
int getTrafficDensity(int x, int y)
short poweredZoneCount
Number of powered tiles in all zone.
Definition: micropolis.h:2107
Quad policeEffect
Definition: micropolis.h:1206
Quad tickCount()
short * resHist
Definition: micropolis.h:1341
void setTrafficDensity(int x, int y, int density)
Callback * callback
Definition: micropolis.h:954
int powerStackPointer
Stack counter, points to top-most item.
Definition: micropolis.h:1993
short graph10Max
Definition: micropolis.h:1807
MapByte1 powerGridMap
Definition: micropolis.h:1281
bool tilesAnimated
Definition: micropolis.h:1881
MapByte2 crimeRateMap
Crime rate map.
Definition: micropolis.h:1248
std::string cityFileName
Filename of the last loaded city.
Definition: micropolis.h:1904
void * getRateOfGrowthMapBuffer()
Quad policeValue
Definition: micropolis.h:1453
MapByte4 terrainDensityMap
Definition: micropolis.h:1255
SimSprite * freeSprites
Pool of free SimSprite objects.
Definition: micropolis.h:2231
short unpoweredZoneCount
Number of unpowered tiles in all zones.
Definition: micropolis.h:2108
void updateBudget()
Definition: budget.cpp:327
void * getTrafficDensityMapBuffer()
void scoreDoer()
Definition: evaluate.cpp:515
short newMapFlags[MAP_TYPE_COUNT]
Definition: micropolis.h:2042
short churchPop
Number of churches.
Definition: micropolis.h:1023
bool evalChanged
The evaluation window should be shown to the user.
Definition: micropolis.h:2350
short firePop
Definition: micropolis.h:975
void simTick()
void graphDoer()
Definition: graph.cpp:132
Position powerStackXY[POWER_STACK_SIZE]
Definition: micropolis.h:1996
short * moneyHist
Definition: micropolis.h:1356
Quad cityTime
Definition: micropolis.h:1092
Quad fireSpend
Definition: micropolis.h:1175
short faith
Faith bias.
Definition: micropolis.h:1024
int terrainCurveLevel
Definition: micropolis.h:1729
float roadPercent
Definition: micropolis.h:1427
MapShort8 comRateMap
Definition: micropolis.h:1330
short cityCenterY
Y coordinate of city center.
Definition: micropolis.h:2045
void simInit()
Definition: micropolis.cpp:743
MapShort8 fireStationEffectMap
Definition: micropolis.h:1306
void * getLandValueMapBuffer()
void * getCrimeRateMapBuffer()
short resPop
Definition: micropolis.h:982
Position curMapStackXY[MAX_TRAFFIC_DISTANCE+1]
Position stack.
Definition: micropolis.h:2603
short pollutionMaxY
Y coordinate of most polluted area.
Definition: micropolis.h:2048
void moveObjects()
Definition: sprite.cpp:553
void setAutoGoto(bool value)
Definition: utilities.cpp:356
bool doAnimation
Definition: micropolis.h:1887
short problemOrder[CVP_PROBLEM_COMPLAINTS]
Definition: micropolis.h:1567
void * getPowerGridMapBuffer()
bool enableDisasters
Enable disasters.
Definition: micropolis.h:2346
short cityScoreDelta
Definition: micropolis.h:1611
short newMap
Definition: micropolis.h:2039
int getRateOfGrowth(int x, int y)
Quad cityPopLast
Population of last city class check.
Definition: micropolis.h:1951
Quad roadValue
Definition: micropolis.h:1448
Quad fireValue
Definition: micropolis.h:1458
void initGame()
short graph120Max
Definition: micropolis.h:1812
short scoreWait
Time to wait before computing the score.
Definition: micropolis.h:2105
short pollutionMaxX
X coordinate of most polluted area.
Definition: micropolis.h:2047
void * getPoliceCoverageMapBuffer()
short totalZonePop
Definition: micropolis.h:1020
short resZonePop
Number of residential zones.
Definition: micropolis.h:1013
short pollutionAverage
Definition: micropolis.h:1072
Quad donDither
Definition: micropolis.h:2056
short trafMaxY
Y coordinate of a position with heavy traffic.
Definition: micropolis.h:2606
short resHist120Max
Definition: micropolis.h:1130
bool indCap
Block industrial growth.
Definition: micropolis.h:2095
Quad fireEffect
Definition: micropolis.h:1211
void resetEditorState()
Definition: initialize.cpp:141
short totalPopLast
Definition: micropolis.h:1011
bool resCap
Block residential growth.
Definition: micropolis.h:2093
void * getMapBuffer()
short trafMaxX
X coordinate of a position with heavy traffic.
Definition: micropolis.h:2605
short * crimeHist
Definition: micropolis.h:1366
short * pollutionHist
Definition: micropolis.h:1361
short airportPop
Definition: micropolis.h:1055
Quad taxFund
Definition: micropolis.h:1219
std::string cityName
Name of the city.
Definition: micropolis.h:1909
void setFunds(int dollars)
Quad roadSpend
Definition: micropolis.h:1165
short policeStationPop
Definition: micropolis.h:1030
void updateFunds()
Definition: update.cpp:127
void setAutoBulldoze(bool value)
Definition: utilities.cpp:342
short disasterWait
Count-down timer for the disaster.
Definition: micropolis.h:2102
void setEnableSound(bool value)
Definition: utilities.cpp:370
int getPoliceCoverage(int x, int y)
bool mustUpdateOptions
Options displayed at user need updating.
Definition: micropolis.h:2639
void setEnableDisasters(bool value)
Definition: utilities.cpp:317
int getFireCoverage(int x, int y)
Quad cityPop
Definition: micropolis.h:1574
MapShort8 fireStationMap
Definition: micropolis.h:1301
short cityCenterX
X coordinate of city center.
Definition: micropolis.h:2044
bool doNotices
Definition: micropolis.h:1891
short totalPop
Definition: micropolis.h:1004
short cityYes
Definition: micropolis.h:1551
int getLandValue(int x, int y)
Quad cityAssessedValue
Definition: micropolis.h:1591
short landValueAverage
Definition: micropolis.h:1080
unsigned short * map[WORLD_W]
Definition: micropolis.h:1120
bool doMessages
Definition: micropolis.h:1889
void setFireCoverage(int x, int y, int coverage)
void initMapArrays()
Definition: allocate.cpp:88
void simHeat()
Definition: micropolis.cpp:806
short coalPowerPop
Definition: micropolis.h:1040
void doStartGame()
short hospitalPop
Number of hospitals.
Definition: micropolis.h:1022
Quad cityMonth
Definition: micropolis.h:1098
bool censusChanged
Definition: micropolis.h:1157
int terrainLakeLevel
Definition: micropolis.h:1723
bool simPaused
Definition: micropolis.h:1877
short * indHist
Definition: micropolis.h:1351
short trafficAverage
Definition: micropolis.h:1618
int mapSerial
The invalidateMaps method increases the map serial number every time the maps changes.
Definition: micropolis.h:2122
short comHist10Max
Definition: micropolis.h:1135
void destroyMapArrays()
Definition: allocate.cpp:113
short * comHist
Definition: micropolis.h:1346
short startingYear
Definition: micropolis.h:1109
bool enableSound
Enable sound.
Definition: micropolis.h:2344
Scenario disasterEvent
The disaster for which a count-down is running.
Definition: micropolis.h:2101
unsigned short * mapBase
Definition: micropolis.h:1396
MapShort8 policeStationMap
Definition: micropolis.h:1317
void makeSound(const std::string &channel, const std::string &sound, int x=-1, int y=-1)
Quad cityYear
Definition: micropolis.h:1104
MapByte2 pollutionDensityMap
Pollution density map.
Definition: micropolis.h:1246
MapByte2 trafficDensityMap
Traffic density map.
Definition: micropolis.h:1245
bool autoBudget
Definition: micropolis.h:2330
int getTile(int x, int y)
short cityScore
Definition: micropolis.h:1604
short categoryLast
City class of last city class check.
Definition: micropolis.h:1952
bool comCap
Block commercial growth.
Definition: micropolis.h:2094
int getPollutionDensity(int x, int y)
Quad policeSpend
Definition: micropolis.h:1170
void * getFireCoverageMapBuffer()
CityClass cityClass
City class, affected by city population.
Definition: micropolis.h:1593
short nuclearPowerPop
Definition: micropolis.h:1045
void spend(int dollars)
static bool testBounds(int wx, int wy)
Definition: micropolis.h:2378
void invalidateMaps()
short floodCount
Definition: micropolis.h:1512
void clearMap()
Definition: generate.cpp:175
void setPopulationDensity(int x, int y, int density)
short fireStationPop
Definition: micropolis.h:1035
void doStartScenario(int scenario)
void freePtr(void *data)
Ptr newPtr(int size)
void * getPollutionDensityMapBuffer()
short curMapStackPointer
Definition: micropolis.h:2602
short comPop
Definition: micropolis.h:989
int getPowerGrid(int x, int y)
short needHospital
Definition: micropolis.h:1383
int getPopulationDensity(const Position &pos, MapTile tile)
Definition: scan.cpp:198
MapByte2 populationDensityMap
Population density map.
Definition: micropolis.h:1244
void initWillStuff()
Definition: initialize.cpp:85
bool autoGoto
Definition: micropolis.h:1960
MapByte2 landValueMap
Land value map.
Definition: micropolis.h:1247
Quad policeFund
Definition: micropolis.h:1189
short needChurch
Definition: micropolis.h:1390
MapShort8 rateOfGrowthMap
Definition: micropolis.h:1290
void setRateOfGrowth(int x, int y, int rate)
void setCrimeRate(int x, int y, int rate)
short cityTax
Definition: micropolis.h:1224
void setPowerGrid(int x, int y, int power)
short railTotal
Definition: micropolis.h:970
short * miscHist
Definition: micropolis.h:1371
short crimeMaxY
Y coordinate of most criminal area. Not used.
Definition: micropolis.h:2051
short comZonePop
Number of commercial zones.
Definition: micropolis.h:1014
short seaportPop
Definition: micropolis.h:1050
void init()
Definition: micropolis.cpp:130
short roadTotal
Definition: micropolis.h:963
float policePercent
Definition: micropolis.h:1435
Quad totalFunds
Funds of the player.
Definition: micropolis.h:2315
short comHist120Max
Definition: micropolis.h:1140
bool autoBulldoze
Definition: micropolis.h:2323
void doEarthquake(int strength)
short resHist10Max
Definition: micropolis.h:1125
short indHist120Max
Definition: micropolis.h:1150
void setAutoBudget(bool value)
Definition: utilities.cpp:328
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)
Definition: micropolis.cpp:724
Header file for Micropolis game engine.
@ SC_NONE
No scenario (free playing)
Definition: micropolis.h:698
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:847
@ CC_VILLAGE
Village.
Definition: micropolis.h:751
@ LEVEL_EASY
Simple game level.
Definition: micropolis.h:763
@ CVP_PROBLEM_COMPLAINTS
Number of problems to complain about.
Definition: micropolis.h:744
@ SPRITE_COUNT
Number of sprite objects.
Definition: micropolis.h:340
static const int MAX_TRAFFIC_DISTANCE
Definition: micropolis.h:248