108void Micropolis::simFrame()
115 if (++speedCycle > 1023) {
119 if (simSpeed == 1 && (speedCycle % 5) != 0) {
123 if (simSpeed == 2 && (speedCycle % 3) != 0) {
132void 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);
159 switch (phaseCycle) {
163 if (++simCycle > 1023) {
175 if (!(simCycle & 1)) {
193 mapScan((phaseCycle - 1) *
WORLD_W / 8, phaseCycle *
WORLD_W / 8);
215 if (!(simCycle % 5)) {
235 if ((simCycle % speedPowerScan[speedIndex]) == 0) {
245 if ((simCycle % SpeedPollutionTerrainLandValueScan[speedIndex]) == 0) {
246 pollutionTerrainLandValueScan();
253 if ((simCycle % speedCrimeScan[speedIndex]) == 0) {
261 if ((simCycle % speedPopulationDensityScan[speedIndex]) == 0) {
269 if ((simCycle % speedFireAnalysis[speedIndex]) == 0) {
280 phaseCycle = (phaseCycle + 1) & 15;
293 if (initSimLoad == 2) {
298 if (initSimLoad == 1) {
308 pollutionTerrainLandValueScan();
327 for (x = 0; x <
WORLD_W; x++) {
328 for (y = 0; y <
WORLD_H; y++) {
385 z =
clamp(z, (
short)-200, (
short)200);
392 z =
clamp(z, (
short)-200, (
short)200);
401void Micropolis::initSimMemory()
407 for (
short x = 0; x < 240; x++) {
426 externalMarket = 6.0;
443 static const short disasterWaitTable[
SC_COUNT] = {
456 static const short scoreWaitTable[
SC_COUNT] = {
468 externalMarket = (float)
miscHist[1];
486 if (!externalMarket) {
487 externalMarket = 4.0;
513 cityTaxAverage = (
cityTime % 48) * 7;
552void Micropolis::setCommonInits()
567 static const short taxTable[21] = {
568 200, 150, 120, 100, 80, 50, 30, 0, -10, -40, -100,
569 -150, -200, -250, -300, -350, -400, -450, -500, -550, -600,
571 static const float extMarketParamTable[3] = {
577 short resPopDenom = 8;
578 float birthRate = 0.02;
579 float laborBaseMax = 1.3;
580 float internalMarketDenom = 3.7;
581 float projectedIndPopMin = 5.0;
582 float resRatioDefault = 1.3;
583 float resRatioMax = 2;
584 float comRatioMax = 2;
585 float indRatioMax = 2;
587 float taxTableScale = 600;
591 float employment, migration, births, laborBase, internalMarket;
592 float resRatio, comRatio, indRatio;
593 float normalizedResPop, projectedResPop, projectedComPop, projectedIndPop;
595 miscHist[1] = (short)externalMarket;
611 normalizedResPop = (float)
resPop / (
float)resPopDenom;
621 migration = normalizedResPop * (employment - 1);
622 births = normalizedResPop * birthRate;
623 projectedResPop = normalizedResPop + migration + births;
628 laborBase = (
resHist[1] / temp);
632 laborBase =
clamp(laborBase, 0.0f, laborBaseMax);
634 internalMarket = (float)(normalizedResPop +
comPop +
indPop) / internalMarketDenom;
636 projectedComPop = internalMarket * laborBase;
640 projectedIndPop =
max(projectedIndPop, projectedIndPopMin);
642 if (normalizedResPop > 0) {
643 resRatio = (float)projectedResPop / (
float)normalizedResPop;
645 resRatio = resRatioDefault;
649 comRatio = (float)projectedComPop / (
float)
comPop;
651 comRatio = (float)projectedComPop;
655 indRatio = (float)projectedIndPop / (
float)
indPop;
657 indRatio = (float)projectedIndPop;
660 resRatio =
min(resRatio, resRatioMax);
661 comRatio =
min(comRatio, comRatioMax);
662 resRatio =
min(indRatio, indRatioMax);
666 resRatio = (resRatio - 1) * taxTableScale + taxTable[z];
667 comRatio = (comRatio - 1) * taxTableScale + taxTable[z];
668 indRatio = (indRatio - 1) * taxTableScale + taxTable[z];
671 resValve =
clamp(resValve + (
short)resRatio, -RES_VALVE_RANGE, RES_VALVE_RANGE);
672 comValve =
clamp(comValve + (
short)comRatio, -COM_VALVE_RANGE, COM_VALVE_RANGE);
673 indValve =
clamp(indValve + (
short)indRatio, -IND_VALVE_RANGE, IND_VALVE_RANGE);
675 if (
resCap && resValve > 0) {
679 if (
comCap && comValve > 0) {
683 if (
indCap && indValve > 0) {
692void Micropolis::clearCensus()
742 for (x = 118; x >= 0; x--) {
771 x = (cashFlow / 20) + 128;
776 short resPopScaled =
resPop >> 8;
790 int faithfulPop = resPopScaled +
faith;
807void Micropolis::take120Census()
819 for (x = 238; x >= 120; x--) {
863 static const float RLevels[3] = { 0.7, 0.9, 1.2 };
864 static const float FLevels[3] = { 1.4, 1.2, 0.8 };
880 z = cityTaxAverage / 48;
936 printf(
"========== updateFundEffects road %d %d %d fire %d %d %d police %d %d %d\n",
947void Micropolis::mapScan(
int x1,
int x2)
953 for (x = x1; x < x2; x++) {
954 for (y = 0; y <
WORLD_H; y++) {
972 if (tile < ROADBASE) {
974 if (tile >= FIREBASE) {
991 if (newPower && (mapVal &
CONDBIT)) {
996 if (tile >= ROADBASE && tile < POWERBASE) {
1006 if (tile >= RAILBASE && tile < RESBASE) {
1011 if (tile >= SOMETINYEXP && tile <= LASTTINYEXP) {
1043 if (tile < RAILBASE + 2) {
1090 if ((tile & 15) < 2 || (tile & 15) == 15) {
1101 if ((mapValue &
BURNBIT) == 0) {
1119 if (trafficDensity > 1) {
1123 if (tden != trafficDensity) {
1124 z = ((tile - ROADBASE) & 15) + densityTable[trafficDensity];
1127 if (trafficDensity > 0) {
1147 static short HDx[7] = { -2, 2, -2, -1, 0, 1, 2 };
1148 static short HDy[7] = { -1, -1, 0, 0, 0, 0, 0 };
1149 static short HBRTAB[7] = {
1153 static short HBRTAB2[7] = {
1157 static short VDx[7] = { 0, 1, 0, 0, 0, 0, 1 };
1158 static short VDy[7] = { -2, -2, -1, 0, 1, 2, 2 };
1159 static short VBRTAB[7] = {
1163 static short VBRTAB2[7] = {
1173 for (z = 0; z < 7; z++) {
1175 x = pos.
posX + VDx[z];
1176 y = pos.
posY + VDy[z];
1181 map[x][y] = VBRTAB2[z];
1194 for (z = 0; z < 7; z++) {
1196 x = pos.
posX + HDx[z];
1197 y = pos.
posY + HDy[z];
1203 map[x][y] = HBRTAB2[z];
1217 for (z = 0; z < 7; z++) {
1219 x = pos.
posX + VDx[z];
1220 y = pos.
posY + VDy[z];
1225 if (MPtem == CHANNEL || ((MPtem & 15) == (VBRTAB2[z] & 15))) {
1226 map[x][y] = VBRTAB[z];
1241 for (z = 0; z < 7; z++) {
1243 x = pos.
posX + HDx[z];
1244 y = pos.
posY + HDy[z];
1249 if (((MPtem & 15) == (HBRTAB2[z] & 15)) || MPtem == CHANNEL) {
1250 map[x][y] = HBRTAB[z];
1276 int mx = pos.
posX * 16 + 8;
1277 int my = pos.
posY * 16 + 8;
1279 for (sprite =
spriteList; sprite != NULL; sprite = sprite->
next) {
1285 dist =
min(dist, sprDist);
1302 static const short DX[4] = { -1, 0, 1, 0 };
1303 static const short DY[4] = { 0, -1, 0, 1 };
1306 for (
short z = 0; z < 4; z++) {
1310 short xTem = pos.
posX + DX[z];
1311 short yTem = pos.
posY + DY[z];
1368 value =
clamp(value - 20, -200, 200);
1376 if (ch == AIRPORT) {
1384 for (
short x = -1; x < XYmax; x++) {
1385 for (
short y = -1; y < XYmax; y++) {
1387 short xTem = pos.
posX + x;
1388 short yTem = pos.
posY + y;
1412 MapTile tile = zCent - 2 - zSize;
1415 for (
short y = -1; y < zSize - 1; y++) {
1416 for (
short x = -1; x < zSize - 1; x++) {
1418 int xx = pos.
posX + x;
1419 int yy = pos.
posY + y;
1437 if (mapTile < RUBBLE || mapTile >= ROADBASE) {
1454 static const short meltdownTable[3] = { 30000, 20000, 10000 };
1522 case POLICESTATION: {
1636 for (y = center.
posY - 1; y < center.
posY + 3; y++) {
1637 for (x = center.
posX - 1; x < center.
posX + 3; x++) {
1638 map[x][y] = z | BNCNBIT;
1670 static const short SmTb[4] = {
1674 static const short dx[4] = { 1, 2, 1, 2 };
1675 static const short dy[4] = { -1, -1, 0, 0 };
1677 for (
short x = 0; x < 4; x++) {
1696 for (
int x = pos.
posX - 1; x < pos.
posX + 3; x++) {
1697 for (
int y = pos.
posY - 1; y < pos.
posY + 3; y++) {
1703 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 !!!