108 void Micropolis::simFrame()
115 if (++speedCycle > 1023) {
119 if (simSpeed == 1 && (speedCycle % 5) != 0) {
123 if (simSpeed == 2 && (speedCycle % 3) != 0) {
132 void Micropolis::simulate()
134 static const short speedPowerScan[3] =
136 static const short SpeedPollutionTerrainLandValueScan[3] =
138 static const short speedCrimeScan[3] =
140 static const short speedPopulationDensityScan[3] =
142 static const short speedFireAnalysis[3] =
145 short speedIndex =
clamp((
short)(simSpeed - 1), (
short)0, (
short)2);
157 switch (phaseCycle) {
161 if (++simCycle > 1023) {
173 if (!(simCycle & 1)) {
191 mapScan((phaseCycle - 1) *
WORLD_W / 8, phaseCycle *
WORLD_W / 8);
213 if (!(simCycle % 5)) {
233 if ((simCycle % speedPowerScan[speedIndex]) == 0) {
243 if ((simCycle % SpeedPollutionTerrainLandValueScan[speedIndex]) == 0) {
244 pollutionTerrainLandValueScan();
251 if ((simCycle % speedCrimeScan[speedIndex]) == 0) {
259 if ((simCycle % speedPopulationDensityScan[speedIndex]) == 0) {
267 if ((simCycle % speedFireAnalysis[speedIndex]) == 0) {
278 phaseCycle = (phaseCycle + 1) & 15;
291 if (initSimLoad == 2) {
296 if (initSimLoad == 1) {
306 pollutionTerrainLandValueScan();
325 for (x = 0; x <
WORLD_W; x++) {
326 for (y = 0; y <
WORLD_H; y++) {
383 z =
clamp(z, (
short)-200, (
short)200);
390 z =
clamp(z, (
short)-200, (
short)200);
399 void Micropolis::initSimMemory()
403 for (
short x = 0; x < 240; x++) {
422 externalMarket = 6.0;
439 static const short disasterWaitTable[
SC_COUNT] = {
452 static const short scoreWaitTable[
SC_COUNT] = {
464 externalMarket = (float)
miscHist[1];
482 if (!externalMarket) {
483 externalMarket = 4.0;
509 cityTaxAverage = (
cityTime % 48) * 7;
548 void Micropolis::setCommonInits()
563 static const short taxTable[21] = {
564 200, 150, 120, 100, 80, 50, 30, 0, -10, -40, -100,
565 -150, -200, -250, -300, -350, -400, -450, -500, -550, -600,
567 static const float extMarketParamTable[3] = {
573 short resPopDenom = 8;
574 float birthRate = 0.02;
575 float laborBaseMax = 1.3;
576 float internalMarketDenom = 3.7;
577 float projectedIndPopMin = 5.0;
578 float resRatioDefault = 1.3;
579 float resRatioMax = 2;
580 float comRatioMax = 2;
581 float indRatioMax = 2;
583 float taxTableScale = 600;
587 float employment, migration, births, laborBase, internalMarket;
588 float resRatio, comRatio, indRatio;
589 float normalizedResPop, projectedResPop, projectedComPop, projectedIndPop;
591 miscHist[1] = (short)externalMarket;
607 normalizedResPop = (float)
resPop / (
float)resPopDenom;
617 migration = normalizedResPop * (employment - 1);
618 births = normalizedResPop * birthRate;
619 projectedResPop = normalizedResPop + migration + births;
624 laborBase = (
resHist[1] / temp);
628 laborBase =
clamp(laborBase, 0.0f, laborBaseMax);
630 internalMarket = (float)(normalizedResPop +
comPop +
indPop) / internalMarketDenom;
632 projectedComPop = internalMarket * laborBase;
636 projectedIndPop =
max(projectedIndPop, projectedIndPopMin);
638 if (normalizedResPop > 0) {
639 resRatio = (float)projectedResPop / (
float)normalizedResPop;
641 resRatio = resRatioDefault;
645 comRatio = (float)projectedComPop / (
float)
comPop;
647 comRatio = (float)projectedComPop;
651 indRatio = (float)projectedIndPop / (
float)
indPop;
653 indRatio = (float)projectedIndPop;
656 resRatio =
min(resRatio, resRatioMax);
657 comRatio =
min(comRatio, comRatioMax);
658 resRatio =
min(indRatio, indRatioMax);
662 resRatio = (resRatio - 1) * taxTableScale + taxTable[z];
663 comRatio = (comRatio - 1) * taxTableScale + taxTable[z];
664 indRatio = (indRatio - 1) * taxTableScale + taxTable[z];
667 resValve =
clamp(resValve + (
short)resRatio, -RES_VALVE_RANGE, RES_VALVE_RANGE);
668 comValve =
clamp(comValve + (
short)comRatio, -COM_VALVE_RANGE, COM_VALVE_RANGE);
669 indValve =
clamp(indValve + (
short)indRatio, -IND_VALVE_RANGE, IND_VALVE_RANGE);
671 if (
resCap && resValve > 0) {
675 if (
comCap && comValve > 0) {
679 if (
indCap && indValve > 0) {
688 void Micropolis::clearCensus()
738 for (x = 118; x >= 0; x--) {
767 x = (cashFlow / 20) + 128;
772 short resPopScaled =
resPop >> 8;
786 int faithfulPop = resPopScaled +
faith;
803 void Micropolis::take120Census()
815 for (x = 238; x >= 120; x--) {
859 static const float RLevels[3] = { 0.7, 0.9, 1.2 };
860 static const float FLevels[3] = { 1.4, 1.2, 0.8 };
876 z = cityTaxAverage / 48;
932 printf(
"========== updateFundEffects road %d %d %d fire %d %d %d police %d %d %d\n",
943 void Micropolis::mapScan(
int x1,
int x2)
947 for (x = x1; x < x2; x++) {
948 for (y = 0; y <
WORLD_H; y++) {
951 if (mapVal ==
DIRT) {
966 if (tile < ROADBASE) {
968 if (tile >= FIREBASE) {
985 if (newPower && (mapVal &
CONDBIT)) {
990 if (tile >= ROADBASE && tile < POWERBASE) {
1000 if (tile >= RAILBASE && tile < RESBASE) {
1005 if (tile >= SOMETINYEXP && tile <= LASTTINYEXP) {
1037 if (tile < RAILBASE + 2) {
1084 if ((tile & 15) < 2 || (tile & 15) == 15) {
1095 if ((mapValue &
BURNBIT) == 0) {
1113 if (trafficDensity > 1) {
1117 if (tden != trafficDensity) {
1118 z = ((tile - ROADBASE) & 15) + densityTable[trafficDensity];
1121 if (trafficDensity > 0) {
1141 static short HDx[7] = { -2, 2, -2, -1, 0, 1, 2 };
1142 static short HDy[7] = { -1, -1, 0, 0, 0, 0, 0 };
1143 static short HBRTAB[7] = {
1147 static short HBRTAB2[7] = {
1151 static short VDx[7] = { 0, 1, 0, 0, 0, 0, 1 };
1152 static short VDy[7] = { -2, -2, -1, 0, 1, 2, 2 };
1153 static short VBRTAB[7] = {
1157 static short VBRTAB2[7] = {
1167 for (z = 0; z < 7; z++) {
1169 x = pos.
posX + VDx[z];
1170 y = pos.
posY + VDy[z];
1175 map[x][y] = VBRTAB2[z];
1188 for (z = 0; z < 7; z++) {
1190 x = pos.
posX + HDx[z];
1191 y = pos.
posY + HDy[z];
1197 map[x][y] = HBRTAB2[z];
1211 for (z = 0; z < 7; z++) {
1213 x = pos.
posX + VDx[z];
1214 y = pos.
posY + VDy[z];
1219 if (MPtem == CHANNEL || ((MPtem & 15) == (VBRTAB2[z] & 15))) {
1220 map[x][y] = VBRTAB[z];
1235 for (z = 0; z < 7; z++) {
1237 x = pos.
posX + HDx[z];
1238 y = pos.
posY + HDy[z];
1243 if (((MPtem & 15) == (HBRTAB2[z] & 15)) || MPtem == CHANNEL) {
1244 map[x][y] = HBRTAB[z];
1270 int mx = pos.
posX * 16 + 8;
1271 int my = pos.
posY * 16 + 8;
1273 for (sprite =
spriteList; sprite != NULL; sprite = sprite->
next) {
1279 dist =
min(dist, sprDist);
1296 static const short DX[4] = { -1, 0, 1, 0 };
1297 static const short DY[4] = { 0, -1, 0, 1 };
1300 for (
short z = 0; z < 4; z++) {
1304 short xTem = pos.
posX + DX[z];
1305 short yTem = pos.
posY + DY[z];
1362 value =
clamp(value - 20, -200, 200);
1370 if (ch == AIRPORT) {
1378 for (
short x = -1; x < XYmax; x++) {
1379 for (
short y = -1; y < XYmax; y++) {
1381 short xTem = pos.
posX + x;
1382 short yTem = pos.
posY + y;
1406 MapTile tile = zCent - 2 - zSize;
1409 for (
short y = -1; y < zSize - 1; y++) {
1410 for (
short x = -1; x < zSize - 1; x++) {
1412 int xx = pos.
posX + x;
1413 int yy = pos.
posY + y;
1431 if (mapTile < RUBBLE || mapTile >= ROADBASE) {
1448 static const short meltdownTable[3] = { 30000, 20000, 10000 };
1516 case POLICESTATION: {
1630 for (y = center.
posY - 1; y < center.
posY + 3; y++) {
1631 for (x = center.
posX - 1; x < center.
posX + 3; x++) {
1632 map[x][y] = z | BNCNBIT;
1664 static const short SmTb[4] = {
1668 static const short dx[4] = { 1, 2, 1, 2 };
1669 static const short dy[4] = { -1, -1, 0, 0 };
1671 for (
short x = 0; x < 4; x++) {
1690 for (
int x = pos.
posX - 1; x < pos.
posX + 3; x++) {
1691 for (
int y = pos.
posY - 1; y < pos.
posY + 3; y++) {
1697 for (
int z = 0; z < 200; z++) {
DATA worldGet(int x, int y) const
void set(int x, int y, DATA val)
const int MAP_W
Number of clusters in horizontal direction.
const int MAP_H
Number of clusters in vertical direction.
DATA get(int x, int y) const
void worldSet(int x, int y, DATA val)
SimSprite * spriteList
List of active sprites.
void generateCopter(const Position &pos)
bool doInitialEval
Need to perform initial city evaluation.
void doMeltdown(const Position &pos)
short stadiumPop
Number of stadiums.
short indZonePop
Number of industrial zones.
Scenario scoreType
The type of score table to use.
void coalSmoke(const Position &pos)
void doRadTile(const Position &pos)
void doZone(const Position &pos)
GameLevel gameLevel
Difficulty level of the game (0..2)
Scenario scenario
Scenario being played.
short poweredZoneCount
Number of powered tiles in all zone.
void doSpecialZone(const Position &pos, bool PwrOn)
void makeExplosion(int x, int y)
int powerStackPointer
Stack counter, points to top-most item.
short unpoweredZoneCount
Number of unpowered tiles in all zones.
bool setZonePower(const Position &pos)
void doRoad(const Position &pos)
short newMapFlags[MAP_TYPE_COUNT]
short churchPop
Number of churches.
MapShort8 fireStationEffectMap
short getRandom(short range)
int getBoatDistance(const Position &pos)
void decRateOfGrowthMap()
bool enableDisasters
Enable disasters.
void generatePlane(const Position &pos)
short scoreWait
Time to wait before computing the score.
void fireZone(const Position &pos, MapValue ch)
short resZonePop
Number of residential zones.
void drawStadium(const Position ¢er, MapTile z)
void pushPowerStack(const Position &pos)
bool indCap
Block industrial growth.
bool resCap
Block residential growth.
void repairZone(const Position &pos, MapTile zCent, short zSize)
short disasterWait
Count-down timer for the disaster.
SimSprite * getSprite(int type)
unsigned short * map[WORLD_W]
short hospitalPop
Number of hospitals.
void generateTrain(int x, int y)
void sendMessage(short Mnum, short x=NOWHERE, short y=NOWHERE, bool picture=false, bool important=false)
void doAirport(const Position &pos)
Scenario disasterEvent
The disaster for which a count-down is running.
MapShort8 policeStationMap
void setGameLevel(GameLevel level)
MapByte2 trafficDensityMap
Traffic density map.
bool comCap
Block commercial growth.
void doFire(const Position &pos)
CityClass cityClass
City class, affected by city population.
static bool testBounds(int wx, int wy)
void makeExplosionAt(int x, int y)
void doStartScenario(int scenario)
MapShort8 rateOfGrowthMap
bool doBridge(const Position &pos, MapTile tile)
short comZonePop
Number of commercial zones.
void populationDensityScan()
void doFlood(const Position &pos)
void doRail(const Position &pos)
bool findPerimeterRoad(Position *pos)
int posY
Vertical coordnate of the position.
int posX
Horizontal coordinate of the position.
int x
X coordinate of the sprite in pixels?
int yHot
Offset of the hot-spot relative to SimSprite::y?
int type
Type of the sprite (TRA – BUS).
SimSprite * next
Pointer to next SimSprite object in the list.
int y
Y coordinate of the sprite in pixels?
int frame
Frame (0 means non-active sprite)
int xHot
Offset of the hot-spot relative to SimSprite::x?
Header file for Micropolis game engine.
@ SC_NONE
No scenario (free playing)
@ SC_COUNT
Number of scenarios.
@ MAP_TYPE_DYNAMIC
Dynamic filter.
@ MAP_TYPE_IND
Industrial zones.
@ MAP_TYPE_COM
Commercial zones.
@ MAP_TYPE_RES
Residential zones.
@ MAP_TYPE_POWER
Power connectivity.
@ MAP_TYPE_TRAFFIC_DENSITY
Traffic.
@ HTRFBASE
First tile with high traffic.
@ HBRIDGE
Horizontal bridge.
@ VBRIDGE
Vertical bridge.
@ STADIUM
'Center tile' stadium.
@ NUCLEAR
'Center' tile nuclear power plant.
@ PORTBASE
Top-left tile of the seaport.
@ IZB
Center tile of first non-empty industry zone.
@ PORT
Center tile of the seaport.
@ COALSMOKE3
927 last animation tile for chimney at coal power plant (2, 1).
@ POWERPLANT
'Center' tile of coal power plant.
@ COALSMOKE4
931 last animation tile for chimney at coal power plant (3, 1).
@ RADTILE
Radio-active contaminated tile.
@ FIRESTATION
'Center tile' of fire station.
@ LTRFBASE
First tile with low traffic.
@ COALSMOKE1
919 last animation tile for chimney at coal power plant (2, 0).
@ COALSMOKE2
923 last animation tile for chimney at coal power plant (3, 0).
@ CC_MEGALOPOLIS
Megalopolis, > 500000 citizens.
static const int MAX_FIRE_STATION_EFFECT
@ LEVEL_FIRST
First game level value.
@ LEVEL_LAST
Last game level value.
@ LEVEL_COUNT
Number of game levels.
static T min(const T a, const T b)
static const int MAX_ROAD_EFFECT
static const int MAX_POLICE_STATION_EFFECT
static T clamp(const T val, const T lower, const T upper)
static T absoluteValue(const T val)
static T max(const T a, const T b)
static const int CENSUS_FREQUENCY_10
static const int CENSUS_FREQUENCY_120
static const int TAX_FREQUENCY
Defines string identification numbers for texts used in the Micropolis game engine.
@ MESSAGE_NUCLEAR_MELTDOWN
A Nuclear Meltdown has occurred !!!