citylimits/core/micropolis.h
2024-05-03 22:50:34 -04:00

2702 lines
63 KiB
C++

/* micropolis.h
*
* Micropolis, Unix Version. This game was released for the Unix platform
* in or about 1990 and has been modified for inclusion in the One Laptop
* Per Child program. Copyright (C) 1989 - 2007 Electronic Arts Inc. If
* you need assistance with this program, you may contact:
* http://wiki.laptop.org/go/Micropolis or email micropolis@laptop.org.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. You should have received a
* copy of the GNU General Public License along with this program. If
* not, see <http://www.gnu.org/licenses/>.
*
* ADDITIONAL TERMS per GNU GPL Section 7
*
* No trademark or publicity rights are granted. This license does NOT
* give you any right, title or interest in the trademark SimCity or any
* other Electronic Arts trademark. You may not distribute any
* modification of this program using the trademark SimCity or claim any
* affliation or association with Electronic Arts Inc. or its employees.
*
* Any propagation or conveyance of this program must include this
* copyright notice and these terms.
*
* If you convey this program (or any modifications of it) and assume
* contractual liability for the program to recipients of it, you agree
* to indemnify Electronic Arts for any liability that those contractual
* assumptions impose on Electronic Arts.
*
* You may not misrepresent the origins of this program; modified
* versions of the program must be marked as such and not identified as
* the original program.
*
* This disclaimer supplements the one included in the General Public
* License. TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS
* PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY
* OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF
* SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS
* DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES,
* INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY,
* FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY
* RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING,
* USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT AGAINST
* INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL
* MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE
* UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE
* WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE
* CORRECTED. NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR
* ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY. SOME
* JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED
* WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A
* CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY
* NOT APPLY TO YOU.
*/
/**
* @file micropolis.h
* @brief Header file for Micropolis game engine.
*
* This file contains class and method declarations, constant
* definitions, enumerations, and other essential elements for the
* Micropolis game engine. It serves as the central include file that
* brings together various components of the simulation, such as map
* handling, disaster events, budgeting, and zone management. It also
* defines key data structures, such as the SimSprite class for
* handling sprites within the game. This header file is crucial for
* providing the necessary declarations for different parts of the
* game engine to interact and function cohesively.
*/
#ifndef H_MICROPOLIS
#define H_MICROPOLIS
////////////////////////////////////////////////////////////////////////
// Includes
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <math.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/types.h>
#include <string.h>
#include <vector>
#include <map>
#include <emscripten.h>
#include <emscripten/bind.h>
#include "data_types.h"
#include "map_type.h"
#include "position.h"
#include "text.h"
#include "frontendmessage.h"
#include "tool.h"
#include "callback.h"
////////////////////////////////////////////////////////////////////////
// Definitions
/**
* Used to determine byte order.
*
* @todo Determine byte order a better way.
*/
#define IS_INTEL 1
////////////////////////////////////////////////////////////////////////
// Constants
/**
* The number of bits per tile.
* @todo Only used in python/micropolisdrawingarea.py
*/
static const int BITS_PER_TILE = 16;
/**
* The number of bytes per tile.
* @todo Only used in python/micropolisdrawingarea.py
*/
static const int BYTES_PER_TILE = 2;
/**
* Horizontal size of the world for a map that stores a value for every 2x2
* square.
* @todo Make a Map class that keeps its 2x2 square storage details internally,
* so the code doesn't need to bother with it.
*/
static const int WORLD_W_2 = WORLD_W / 2;
/**
* Vertical size of the world for a map that stores a value for every 2x2
* square.
*/
static const int WORLD_H_2 = WORLD_H / 2;
/**
* Horizontal size of the world for a map that stores a value for every 4x4
* square.
* @todo Make a Map class that keeps its 4x4 square storage details internally,
* so the code doesn't need to bother with it.
*/
static const int WORLD_W_4 = WORLD_W / 4;
/**
* Vertical size of the world for a map that stores a value for every 4x4
* square.
*/
static const int WORLD_H_4 = WORLD_H / 4;
/**
* Horizontal size of the world for a map that stores a value for every 8x8
* square.
* @todo Make a Map class that keeps its 8x8 square storage details internally,
* so the code doesn't need to bother with it.
*/
static const int WORLD_W_8 = WORLD_W / 8;
/**
* Vertical size of the world for a map that stores a value for every 8x8
* square.
*/
static const int WORLD_H_8 = (WORLD_H + 7) / 8;
/**
* The size of the editor view tiles, in pixels.
*/
static const int EDITOR_TILE_SIZE = 16;
/**
* The number of simulator passes per #cityTime unit.
*/
static const int PASSES_PER_CITYTIME = 16;
/**
* The number of #cityTime units per month.
*/
static const int CITYTIMES_PER_MONTH = 4;
/**
* The number of #cityTime units per year.
*/
static const int CITYTIMES_PER_YEAR = CITYTIMES_PER_MONTH * 12;
/**
* The number of history entries.
*/
static const int HISTORY_LENGTH = 480;
/**
* The number of miscellaneous history entries.
*/
static const int MISC_HISTORY_LENGTH = 240;
/**
* Length of the history tables.
* @todo It is not really a count of histories, rename to something else?
*/
static const int HISTORY_COUNT = 120;
/**
* The size of the power stack.
*/
static const int POWER_STACK_SIZE = (WORLD_W * WORLD_H) / 4;
/**
* A constant used in place of an x or y position to indicate
* "nowhere".
*/
static const int NOWHERE = -1;
/**
* The default radius of an island, used by the terrain generator.
*/
static const int ISLAND_RADIUS = 18;
///////////////////////////////////////////////////
// Traffic
/**
* Maximal number of map tiles to drive, looking for a destination
*/
static const int MAX_TRAFFIC_DISTANCE = 30;
/**
* Maximal value of Micropolis::roadEffect
*/
static const int MAX_ROAD_EFFECT = 32;
/**
* Maximal value of Micropolis::policeEffect
*/
static const int MAX_POLICE_STATION_EFFECT = 1000;
/**
* Maximal value of Micropolis::fireEffect
*/
static const int MAX_FIRE_STATION_EFFECT = 1000;
////////////////////////////////////////////////////////////////////////
// Valves
static const int RES_VALVE_RANGE = 2000;
static const int COM_VALVE_RANGE = 1500;
static const int IND_VALVE_RANGE = 1500;
////////////////////////////////////////////////////////////////////////
// Enumerated types.
/**
* Available types of historic data.
*/
enum HistoryType
{
HISTORY_TYPE_RES, ///< Residiential history type
HISTORY_TYPE_COM, ///< Commercial history type
HISTORY_TYPE_IND, ///< Industry history type
HISTORY_TYPE_MONEY, ///< Money history type
HISTORY_TYPE_CRIME, ///< Crime history type
HISTORY_TYPE_POLLUTION, ///< Pollution history type
HISTORY_TYPE_COUNT, ///< Number of history types
};
/**
* Available historic scales.
*/
enum HistoryScale
{
HISTORY_SCALE_SHORT, ///< Short scale data (10 years)
HISTORY_SCALE_LONG, ///< Long scale data (120 years)
HISTORY_SCALE_COUNT, ///< Number of history scales available
};
/**
* Available map types.
*/
enum MapType
{
MAP_TYPE_ALL, ///< All zones
MAP_TYPE_RES, ///< Residential zones
MAP_TYPE_COM, ///< Commercial zones
MAP_TYPE_IND, ///< Industrial zones
MAP_TYPE_POWER, ///< Power connectivity
MAP_TYPE_ROAD, ///< Roads
MAP_TYPE_POPULATION_DENSITY, ///< Population density
MAP_TYPE_RATE_OF_GROWTH, ///< Rate of growth
MAP_TYPE_TRAFFIC_DENSITY, ///< Traffic
MAP_TYPE_POLLUTION, ///< Pollution
MAP_TYPE_CRIME, ///< Crime rate
MAP_TYPE_LAND_VALUE, ///< Land value
MAP_TYPE_FIRE_RADIUS, ///< Fire station coverage radius
MAP_TYPE_POLICE_RADIUS, ///< Police station coverage radius
MAP_TYPE_DYNAMIC, ///< Dynamic filter
MAP_TYPE_COUNT, ///< Number of map types
};
/* Object & Sound Numbers */
enum SpriteType
{
SPRITE_NOTUSED = 0,
SPRITE_TRAIN, ///< Train sprite
SPRITE_HELICOPTER, ///< Helicopter sprite
SPRITE_AIRPLANE, ///< Airplane sprite
SPRITE_SHIP, ///< Ship
SPRITE_MONSTER, ///< Scary monster
SPRITE_TORNADO, ///< Tornado sprite
SPRITE_EXPLOSION, ///< Explosion sprite
SPRITE_BUS, ///< Bus sprite
SPRITE_COUNT, ///< Number of sprite objects
};
///////////////////////////////////////////////////
// Tiles
/**
* Connect tile commands.
*/
enum ConnectTileCommand
{
CONNECT_TILE_FIX, ///< Fix zone (connect wire, road, and rail).
CONNECT_TILE_BULLDOZE, ///< Bulldoze and fix zone.
CONNECT_TILE_ROAD, ///< Lay road and fix zone.
CONNECT_TILE_RAILROAD, ///< Lay rail and fix zone.
CONNECT_TILE_WIRE, ///< Lay wire and fix zone.
};
/**
* Tool result.
* @todo Make the rest of the code use this instead of magic numbers.
*/
enum ToolResult
{
TOOLRESULT_NO_MONEY = -2, ///< User has not enough money for tool.
TOOLRESULT_NEED_BULLDOZE = -1, ///< Clear the area first.
TOOLRESULT_FAILED = 0, ///< Cannot build here.
TOOLRESULT_OK = 1, ///< Build succeeded.
};
/**
* Characters of the map tiles, the lower 10 bits (0--9).
* @see LOMASK MapTileBitmasks
* @todo Add TILE_ prefix
* @todo Make LOW/BASE and LAST/HIGH consistent everywhere?
* @todo Figure out what sprite groups really exist (maybe we can learn more by
* examining the actual sprites, and/or by using hexadecimal or bite-wise
* notation?)
* @todo Add comments for each sprite (0--1023)
*/
enum Tiles
{
DIRT = 0, ///< Clear tile
// tile 1 ?
/* Water */
RIVER = 2,
REDGE = 3,
CHANNEL = 4,
FIRSTRIVEDGE = 5,
// tile 6 -- 19 ?
LASTRIVEDGE = 20,
WATER_LOW = RIVER, ///< First water tile
WATER_HIGH = LASTRIVEDGE, ///< Last water tile (inclusive)
TREEBASE = 21,
WOODS_LOW = TREEBASE,
LASTTREE = 36,
WOODS = 37,
UNUSED_TRASH1 = 38,
UNUSED_TRASH2 = 39,
WOODS_HIGH = UNUSED_TRASH2, // Why is an 'UNUSED' tile used?
WOODS2 = 40,
WOODS3 = 41,
WOODS4 = 42,
WOODS5 = 43,
/* Rubble (4 tiles) */
RUBBLE = 44,
LASTRUBBLE = 47,
FLOOD = 48,
// tile 49, 50 ?
LASTFLOOD = 51,
RADTILE = 52, ///< Radio-active contaminated tile
UNUSED_TRASH3 = 53,
UNUSED_TRASH4 = 54,
UNUSED_TRASH5 = 55,
/* Fire animation (8 tiles) */
FIRE = 56,
FIREBASE = FIRE,
LASTFIRE = 63,
HBRIDGE = 64, ///< Horizontal bridge
ROADBASE = HBRIDGE,
VBRIDGE = 65, ///< Vertical bridge
ROADS = 66,
ROADS2 = 67,
ROADS3 = 68,
ROADS4 = 69,
ROADS5 = 70,
ROADS6 = 71,
ROADS7 = 72,
ROADS8 = 73,
ROADS9 = 74,
ROADS10 = 75,
INTERSECTION = 76,
HROADPOWER = 77,
VROADPOWER = 78,
BRWH = 79,
LTRFBASE = 80, ///< First tile with low traffic
// tile 81 -- 94 ?
BRWV = 95,
// tile 96 -- 110 ?
BRWXXX1 = 111,
// tile 96 -- 110 ?
BRWXXX2 = 127,
// tile 96 -- 110 ?
BRWXXX3 = 143,
HTRFBASE = 144, ///< First tile with high traffic
// tile 145 -- 158 ?
BRWXXX4 = 159,
// tile 160 -- 174 ?
BRWXXX5 = 175,
// tile 176 -- 190 ?
BRWXXX6 = 191,
// tile 192 -- 205 ?
LASTROAD = 206,
BRWXXX7 = 207,
/* Power lines */
HPOWER = 208,
VPOWER = 209,
LHPOWER = 210,
LVPOWER = 211,
LVPOWER2 = 212,
LVPOWER3 = 213,
LVPOWER4 = 214,
LVPOWER5 = 215,
LVPOWER6 = 216,
LVPOWER7 = 217,
LVPOWER8 = 218,
LVPOWER9 = 219,
LVPOWER10 = 220,
RAILHPOWERV = 221, ///< Horizontal rail, vertical power
RAILVPOWERH = 222, ///< Vertical rail, horizontal power
POWERBASE = HPOWER,
LASTPOWER = RAILVPOWERH,
UNUSED_TRASH6 = 223,
/* Rail */
HRAIL = 224,
VRAIL = 225,
LHRAIL = 226,
LVRAIL = 227,
LVRAIL2 = 228,
LVRAIL3 = 229,
LVRAIL4 = 230,
LVRAIL5 = 231,
LVRAIL6 = 232,
LVRAIL7 = 233,
LVRAIL8 = 234,
LVRAIL9 = 235,
LVRAIL10 = 236,
HRAILROAD = 237,
VRAILROAD = 238,
RAILBASE = HRAIL,
LASTRAIL = 238,
ROADVPOWERH = 239, /* bogus? */
// Residential zone tiles
RESBASE = 240, // Empty residential, tiles 240--248
FREEZ = 244, // center-tile of 3x3 empty residential
HOUSE = 249, // Single tile houses until 260
LHTHR = HOUSE,
HHTHR = 260,
RZB = 265, // center tile first 3x3 tile residential
HOSPITALBASE = 405, // Center of hospital (tiles 405--413)
HOSPITAL = 409, // Center of hospital (tiles 405--413)
CHURCHBASE = 414, // Center of church (tiles 414--422)
CHURCH0BASE = 414, // numbered alias
CHURCH = 418, // Center of church (tiles 414--422)
CHURCH0 = 418, // numbered alias
// Commercial zone tiles
COMBASE = 423, // Empty commercial, tiles 423--431
// tile 424 -- 426 ?
COMCLR = 427,
// tile 428 -- 435 ?
CZB = 436,
// tile 437 -- 608 ?
COMLAST = 609,
// tile 610, 611 ?
// Industrial zone tiles.
INDBASE = 612, ///< Top-left tile of empty industrial zone.
INDCLR = 616, ///< Center tile of empty industrial zone.
LASTIND = 620, ///< Last tile of empty industrial zone.
// Industrial zone population 0, value 0: 621 -- 629
IND1 = 621, ///< Top-left tile of first non-empty industry zone.
IZB = 625, ///< Center tile of first non-empty industry zone.
// Industrial zone population 1, value 0: 630 -- 638
// Industrial zone population 2, value 0: 639 -- 647
IND2 = 641,
IND3 = 644,
// Industrial zone population 3, value 0: 648 -- 656
IND4 = 649,
IND5 = 650,
// Industrial zone population 0, value 1: 657 -- 665
// Industrial zone population 1, value 1: 666 -- 674
// Industrial zone population 2, value 1: 675 -- 683
IND6 = 676,
IND7 = 677,
// Industrial zone population 3, value 1: 684 -- 692
IND8 = 686,
IND9 = 689,
// Seaport
PORTBASE = 693, ///< Top-left tile of the seaport.
PORT = 698, ///< Center tile of the seaport.
LASTPORT = 708, ///< Last tile of the seaport.
AIRPORTBASE = 709,
// tile 710 ?
RADAR = 711,
// tile 712 -- 715 ?
AIRPORT = 716,
// tile 717 -- 744 ?
// Coal power plant (4x4).
COALBASE = 745, ///< First tile of coal power plant.
POWERPLANT = 750, ///< 'Center' tile of coal power plant.
LASTPOWERPLANT = 760, ///< Last tile of coal power plant.
// Fire station (3x3).
FIRESTBASE = 761, ///< First tile of fire station.
FIRESTATION = 765, ///< 'Center tile' of fire station.
// 769 last tile fire station.
POLICESTBASE = 770,
// tile 771 -- 773 ?
POLICESTATION = 774,
// tile 775 -- 778 ?
// Stadium (4x4).
STADIUMBASE = 779, ///< First tile stadium.
STADIUM = 784, ///< 'Center tile' stadium.
// Last tile stadium 794.
// tile 785 -- 799 ?
FULLSTADIUM = 800,
// tile 801 -- 810 ?
// Nuclear power plant (4x4).
NUCLEARBASE = 811, ///< First tile nuclear power plant.
NUCLEAR = 816, ///< 'Center' tile nuclear power plant.
LASTZONE = 826, ///< Also last tile nuclear power plant.
LIGHTNINGBOLT = 827,
HBRDG0 = 828,
HBRDG1 = 829,
HBRDG2 = 830,
HBRDG3 = 831,
HBRDG_END = 832,
RADAR0 = 832,
RADAR1 = 833,
RADAR2 = 834,
RADAR3 = 835,
RADAR4 = 836,
RADAR5 = 837,
RADAR6 = 838,
RADAR7 = 839,
FOUNTAIN = 840,
// tile 841 -- 843: fountain animation.
INDBASE2 = 844,
TELEBASE = 844,
// tile 845 -- 850 ?
TELELAST = 851,
SMOKEBASE = 852,
// tile 853 -- 859 ?
TINYEXP = 860,
// tile 861 -- 863 ?
SOMETINYEXP = 864,
// tile 865 -- 866 ?
LASTTINYEXP = 867,
// tile 868 -- 882 ?
TINYEXPLAST = 883,
// tile 884 -- 915 ?
COALSMOKE1 = 916, ///< Chimney animation at coal power plant (2, 0).
///< 919 last animation tile for chimney at coal power plant (2, 0).
COALSMOKE2 = 920, ///< Chimney animation at coal power plant (3, 0).
///< 923 last animation tile for chimney at coal power plant (3, 0).
COALSMOKE3 = 924, ///< Chimney animation at coal power plant (2, 1).
///< 927 last animation tile for chimney at coal power plant (2, 1).
COALSMOKE4 = 928, ///< Chimney animation at coal power plant (3, 1).
///< 931 last animation tile for chimney at coal power plant (3, 1).
FOOTBALLGAME1 = 932,
// tile 933 -- 939 ?
FOOTBALLGAME2 = 940,
// tile 941 -- 947 ?
VBRDG0 = 948,
VBRDG1 = 949,
VBRDG2 = 950,
VBRDG3 = 951,
NUKESWIRL1 = 952,
NUKESWIRL2 = 953,
NUKESWIRL3 = 954,
NUKESWIRL4 = 955,
// Tiles 956-959 unused (originally)
// TILE_COUNT = 960,
// Extended zones: 956-1019
CHURCH1BASE = 956,
CHURCH1 = 960,
CHURCH2BASE = 965,
CHURCH2 = 969,
CHURCH3BASE = 974,
CHURCH3 = 978,
CHURCH4BASE = 983,
CHURCH4 = 987,
CHURCH5BASE = 992,
CHURCH5 = 996,
CHURCH6BASE = 1001,
CHURCH6 = 1005,
CHURCH7BASE = 1010,
CHURCH7 = 1014,
CHURCH7LAST = 1018,
// Tiles 1020-1023 unused
TILE_COUNT = 1024,
TILE_INVALID = -1, ///< Invalid tile (not used in the world map).
};
///////////////////////////////////////////////////
// Scenarios
/** Available scenarios */
enum Scenario
{
SC_NONE, ///< No scenario (free playing)
SC_DULLSVILLE, ///< Dullsville (boredom)
SC_SAN_FRANCISCO, ///< San francisco (earthquake)
SC_HAMBURG, ///< Hamburg (fire bombs)
SC_BERN, ///< Bern (traffic)
SC_TOKYO, ///< Tokyo (scary monster)
SC_DETROIT, ///< Detroit (crime)
SC_BOSTON, ///< Boston (nuclear meltdown)
SC_RIO, ///< Rio (flooding)
SC_COUNT, ///< Number of scenarios
};
///////////////////////////////////////////////////
// Zones
/** Available zone types */
enum ZoneType
{
ZT_COMMERCIAL, ///< Commercial zone
ZT_INDUSTRIAL, ///< Industrial zone
ZT_RESIDENTIAL, ///< Residential zone
ZT_NUM_DESTINATIONS, ///< Number of available zones
};
///////////////////////////////////////////////////
// City problems
/**
* Problems in the city where citizens vote on
* @todo Eliminate PROBNUM
*/
enum CityVotingProblems
{
CVP_CRIME, ///< Crime
CVP_POLLUTION, ///< Pollution
CVP_HOUSING, ///< Housing
CVP_TAXES, ///< Taxes
CVP_TRAFFIC, ///< Traffic
CVP_UNEMPLOYMENT, ///< Unemployment
CVP_FIRE, ///< Fire
CVP_NUMPROBLEMS, ///< Number of problems
CVP_PROBLEM_COMPLAINTS = 4, ///< Number of problems to complain about.
PROBNUM = 10,
};
/** Available classes of cities */
enum CityClass
{
CC_VILLAGE, ///< Village
CC_TOWN, ///< Town, > 2000 citizens
CC_CITY, ///< City, > 10000 citizens
CC_CAPITAL, ///< Capital, > 50000 citizens
CC_METROPOLIS, ///< Metropolis, > 100000 citizens
CC_MEGALOPOLIS, ///< Megalopolis, > 500000 citizens
CC_NUM_CITIES, ///< Number of city classes
};
/** Game levels */
enum GameLevel
{
LEVEL_EASY, ///< Simple game level
LEVEL_MEDIUM, ///< Intermediate game level
LEVEL_HARD, ///< Difficult game level
LEVEL_COUNT, ///< Number of game levels
LEVEL_FIRST = LEVEL_EASY, ///< First game level value
LEVEL_LAST = LEVEL_HARD, ///< Last game level value
};
////////////////////////////////////////////////////////////////////////
// Inline functions
/**
* Compute minimal value.
* @param a First value.
* @param b Second value.
* @return Minimum of \a a and \a b.
*/
template <typename T>
static inline T min(const T a, const T b)
{
return (a < b) ? a : b;
}
/**
* Compute maximal value.
* @param a First value.
* @param b Second value.
* @return Maximum of \a a and \a b.
*/
template <typename T>
static inline T max(const T a, const T b)
{
return (a > b) ? a : b;
}
/**
* Clamp value between lower and upper bound.
* @param val Value.
* @param lower Lower bound (inclusive).
* @param upper Upper bound (inclusive).
* @return \a val, limited to the range given by the lower and upper bound.
*/
template <typename T>
static inline T clamp(const T val, const T lower, const T upper)
{
if (val < lower)
{
return lower;
}
if (val > upper)
{
return upper;
}
return val;
}
/**
* Compute absolute value.
* @param val Input value.
* @return Absolute value of \a val.
*/
template <typename T>
static inline T absoluteValue(const T val)
{
if (val < 0)
{
return -val;
}
return val;
}
////////////////////////////////////////////////////////////////////////
// Macros
/**
* Compute length of array
* @param array Array to get length from
* @note Macro only works for statically allocated arrays
*/
#define LENGTH_OF(array) (sizeof(array) / sizeof((array)[0]))
/**
* Give a fatal error and exit.
*/
#define NOT_REACHED() not_reached(__LINE__, __FILE__)
/**
* Give a fatal error and exit the program.
* @param line Source line number of the fatal error.
* @param fname Filename of the source file.
* @return Does not return to the caller.
* @todo Generalize error handling/exiting of the simulator.
*/
static inline void not_reached(int line, const char *fname)
{
fprintf(stderr, "Code unexpectedly executed at line %d, at file %s\n", line, fname);
exit(1);
}
////////////////////////////////////////////////////////////////////////
// Forward class definitions
class Micropolis;
class Callback;
class ConsoleCallback;
class ToolEffects;
class BuildingProperties;
////////////////////////////////////////////////////////////////////////
// Classes
/** Sprite in the simulator.
* @todo SimSprite::name is never set to anything else than \c "", and only
* used to detect a non-removed non-active sprite (in a non-robust way).
*/
class SimSprite
{
public:
SimSprite *next; ///< Pointer to next #SimSprite object in the list.
std::string name; ///< Name of the sprite.
int type; ///< Type of the sprite (TRA -- BUS).
int frame; ///< Frame (\c 0 means non-active sprite)
int x; ///< X coordinate of the sprite in pixels?
int y; ///< Y coordinate of the sprite in pixels?
int width;
int height;
int xOffset;
int yOffset;
int xHot; ///< Offset of the hot-spot relative to SimSprite::x?
int yHot; ///< Offset of the hot-spot relative to SimSprite::y?
int origX;
int origY;
int destX; ///< Destination X coordinate of the sprite.
int destY; ///< Destination Y coordinate of the sprite.
int count;
int soundCount;
int dir;
int newDir;
int step;
int flag;
int control;
int turn;
int accel;
int speed;
};
/**
* Main simulator class
* @todo Modify Micropolis::roadPercent, Micropolis::policePercent, and
* Micropolis::firePercent to hold real percentage from \c 0 to \c 100
* instead of a floating point fraction
* @todo Micropolis::crimeMaxX and Micropolis::crimeMaxY seem unused.
*/
class Micropolis
{
public:
////////////////////////////////////////////////////////////////////////
Micropolis();
~Micropolis();
void setCallback(Callback *callback, emscripten::val callbackVal);
private:
void destroy();
void init();
////////////////////////////////////////////////////////////////////////
// allocate.cpp
public:
/**
* Callback interface.
*/
Callback *callback;
/**
* Number of road tiles in the game.
*
* Bridges count as 4 tiles, and high density traffic counts as
* 2 tiles.
*/
short roadTotal;
/**
* Total number of rails.
*
* No penalty for bridges or high traffic density.
*/
short railTotal;
/**
* Number of fires.
*/
short firePop;
/**
* Number of people in the residential zones.
*
* Depends on level of zone development.
*/
short resPop;
/**
* Commercial zone population.
*
* Depends on level of zone development.
*/
short comPop;
/**
* Industrial zone population.
*
* Depends on level of zone development.
*/
short indPop;
/**
* Total population.
*
* Includes residential pop / 8 plus industrial pop plus commercial
* pop.
*/
short totalPop;
/**
* Last total population.
*
* Not used?
*/
short totalPopLast;
short resZonePop; ///< Number of residential zones.
short comZonePop; ///< Number of commercial zones.
short indZonePop; ///< Number of industrial zones.
/**
* Total zone population.
*/
short totalZonePop;
short hospitalPop; ///< Number of hospitals.
short churchPop; ///< Number of churches.
short faith; ///< Faith bias.
short stadiumPop; ///< Number of stadiums.
/**
* Police station population.
*/
short policeStationPop;
/**
* Fire station population.
*/
short fireStationPop;
/**
* Coal power plant population.
*/
short coalPowerPop;
/**
* Nuclear power plant population.
*/
short nuclearPowerPop;
/**
* Seaport population.
*/
short seaportPop;
/**
* Airport population.
*/
short airportPop;
/**
* Average crime.
*
* Affected by land value, population density, police station
* distance.
*/
short crimeAverage;
/**
* Average pollution.
*
* Affected by PollutionMem, which is effected by traffic, fire,
* radioactivity, industrial zones, seaports, airports, power
* plants.
*/
short pollutionAverage;
/**
* Land value average.
*
* Affected by distance from city center, development density
* (terrainMem), pollution, and crime.
*/
short landValueAverage;
/** @name Dates */
//@{
/**
* City time unit counter, increnented once every 16 runs through
* the simulator (at fast speed). A time unit is 7.6 days. 4 units
* per month, 48 units per year, relative to #startingYear
*
* Four units per month, so one unit is about a week (7.6 days).
*/
Quad cityTime;
/**
* City month, 4 time units per month.
* @todo Remove, can be computed from Micropolis::cityTime.
*/
Quad cityMonth;
/**
* City year, (Micropolis::cityTime / 48) + Micropolis::startingYear.
* @todo Remove, can be computed from Micropolis::cityTime.
*/
Quad cityYear;
/**
* City starting year.
*/
short startingYear;
//@}
/* Maps */
/**
* Two-dimensional array of map tiles.
*
* Map[0 <= x < 120][0 <= y < 100]
*/
unsigned short *map[WORLD_W];
/**
* 10 year residential history maximum value.
*/
short resHist10Max;
/**
* 120 year residential history maximum value.
*/
short resHist120Max;
/**
* 10 year commercial history maximum value.
*/
short comHist10Max;
/**
* 120 year commercial history maximum value.
*/
short comHist120Max;
/**
* 10 year industrial history maximum value.
*/
short indHist10Max;
/**
* 120 year industrial history maximum value.
*/
short indHist120Max;
/**
* Census changed flag.
*
* Need to redraw census dependent stuff.
*/
bool censusChanged;
/** @name Budget */
//@{
/**
* Spending on roads.
*/
Quad roadSpend;
/**
* Spending on police stations.
*/
Quad policeSpend;
/**
* Spending on fire stations.
*/
Quad fireSpend;
/**
* Requested funds for roads.
*
* Depends on number of roads, rails, and game level.
*/
Quad roadFund;
/**
* Requested funds for police stations.
*
* Depends on police station population.
*/
Quad policeFund;
/**
* Requested funds for fire stations.
*
* Depends on fire station population.
*/
Quad fireFund;
/**
* Ratio of road spending over road funding, times #MAX_ROAD_EFFECT.
*/
Quad roadEffect;
/**
* Ratio of police spending over police funding, times #MAX_POLICE_EFFECT.
*/
Quad policeEffect;
/**
* Ratio of fire spending over fire funding, times #MAX_FIRE_EFFECT.
*/
Quad fireEffect;
/**
* Funds from taxes.
*
* Depends on total population, average land value, city tax, and
* game level.
*/
Quad taxFund;
/**
* City tax rate.
*/
short cityTax;
/**
* Tax port flag.
*
* Apparently never used. CollectTax checks it.
*
* @todo Apparently taxFlag is never set to true in MicropolisEngine
* or the TCL code.
* @todo Don should check old Mac code to see if it's ever set.
* @todo Variable is always \c 0. Decide whether to keep it, and if yes,
* create means to modify its value
*/
bool taxFlag;
//@}
/** @name Maps */
//@{
MapByte2 populationDensityMap; ///< Population density map.
MapByte2 trafficDensityMap; ///< Traffic density map.
MapByte2 pollutionDensityMap; ///< Pollution density map.
MapByte2 landValueMap; ///< Land value map.
MapByte2 crimeRateMap; ///< Crime rate map.
/**
* Terrain development density map.
*
* Used to calculate land value.
*/
MapByte4 terrainDensityMap;
/**
* Temporary map 1.
*
* Used to smooth population density, pollution.
*/
MapByte2 tempMap1;
/**
* Temporary map 2.
*
* Used to smooth population density, pollution.
*/
MapByte2 tempMap2;
/**
* Temporary map 3.
*
* Used to smooth development density, for terrainDensityMap.
*/
MapByte4 tempMap3;
/**
* Power grid map.
*/
MapByte1 powerGridMap;
/**
* Rate of growth map.
*
* Affected by DecROGMem, incROG called by zones. Decreased by fire
* explosions from sprites, fire spreading. Doesn't seem to
* actually feed back into the simulation. Output only.
*/
MapShort8 rateOfGrowthMap;
/**
* Fire station map.
*
* Effectivity of fire control in this area.
*
* Affected by fire stations, powered, fire funding ratio, road
* access. Affects how long fires burn.
* @see #fireEffect
*/
MapShort8 fireStationMap;
/**
* Copy of fire station map to display.
*/
MapShort8 fireStationEffectMap;
/**
* Police station map.
*
* Effectivity of police in fighting crime.
*
* Affected by police stations, powered, police funding ratio, road
* access. Affects crime rate.
* @see #policeEffect
*/
MapShort8 policeStationMap;
/**
* Copy of police station map to display.
*/
MapShort8 policeStationEffectMap;
/**
* Commercial rate map.
*
* Depends on distance to city center. Affects commercial zone
* evaluation.
*/
MapShort8 comRateMap;
//@}
/** @name Historic graphs. */
//@{
/**
* Residential population history.
*/
short *resHist;
/**
* Commercial population history.
*/
short *comHist;
/**
* Industrial population history.
*/
short *indHist;
/**
* Money history.
*/
short *moneyHist;
/**
* Pollution history.
*/
short *pollutionHist;
/**
* Crime history.
*/
short *crimeHist;
/**
* Memory used to save miscelaneous game values in save file.
*/
short *miscHist;
//@}
private:
/**
* Need hospital?
*
* 0 if no, 1 if yes, -1 if too many.
*/
short needHospital;
/**
* Need church?
*
* 0 if no, 1 if yes, -1 if too many.
*/
short needChurch;
/**
* Memory for map array.
*/
unsigned short *mapBase;
void initMapArrays();
void destroyMapArrays();
////////////////////////////////////////////////////////////////////////
// animate.cpp
public:
void animateTiles();
static int getNextAnimatedTile(int index);
////////////////////////////////////////////////////////////////////////
// budget.cpp
public:
/**
* Percentage of requested road and rail costs to funding level.
*
* Value between \c 0 and ::MAX_ROAD_EFFECT.
* Affected by road funds slider and budgetary constraints.
*/
float roadPercent;
/**
* Percentage of requested police station costs to funding level.
*
* Value between \c 0 and ::MAX_POLICESTATION_EFFECT.
* Affected by road funds slider and budgetary constraints.
*/
float policePercent;
/**
* Percentage of requested fire station costs to funding level.
*
* Value between \c 0 and ::MAX_FIRESTATION_EFFECT.
* Affected by road funds slider and budgetary constraints.
*/
float firePercent;
/**
* Amount of road funding granted.
*/
Quad roadValue;
/**
* Amount of police funding granted.
*/
Quad policeValue;
/**
* Amount of fire station funding granted.
*/
Quad fireValue;
/**
* Flag set when budget window needs to be updated.
*/
int mustDrawBudget;
void initFundingLevel();
void doBudget();
void doBudgetFromMenu();
void doBudgetNow(bool fromMenu);
void updateBudget();
void showBudgetWindowAndStartWaiting();
void setCityTax(short tax);
////////////////////////////////////////////////////////////////////////
// connect.cpp
private:
ToolResult connectTile(short x, short y,
ConnectTileCommand cmd, ToolEffects *effects);
ToolResult layDoze(int x, int y, ToolEffects *effects);
ToolResult layRoad(int x, int y, ToolEffects *effects);
ToolResult layRail(int x, int y, ToolEffects *effects);
ToolResult layWire(int x, int y, ToolEffects *effects);
void fixZone(int x, int y, ToolEffects *effects);
void fixSingle(int x, int y, ToolEffects *effects);
////////////////////////////////////////////////////////////////////////
// disasters.cpp
public:
/**
* Size of flooding disaster.
*/
short floodCount;
void makeMeltdown();
void makeFireBombs();
void makeEarthquake();
void makeFire();
void makeFlood();
void setFire();
void fireBomb();
private:
void doDisasters();
void scenarioDisaster();
bool vulnerable(int tem);
void doFlood(const Position &pos);
////////////////////////////////////////////////////////////////////////
// evaluate.cpp
public:
/**
* Yes votes.
*
* Percentage of people who think the mayor is doing a good job.
*/
short cityYes;
/**
* Problem votes.
*
* The number of votes for each problem.
* @see CityVotingProblems
*/
short problemVotes[PROBNUM];
/**
* Order of taken problems.
*
* Contains index of MicropolisEngine::problemVotes of taken problems, in decreasing order.
* @note Value CVP_NUMPROBLEMS means that the entry is not used
*/
short problemOrder[CVP_PROBLEM_COMPLAINTS];
/**
* City population.
*
* Depends of ResPop, ComPop and IndPop.
*/
Quad cityPop;
/**
* Change in the city population.
*
* Depends on last cityPop.
*/
Quad cityPopDelta;
/**
* City assessed value.
*
* Depends on roadTotal, railTotal, policeStationPop,
* fireStationPop, hospitalPop, stadiumPop, seaportPop,
* airportPop, coalPowerPop, and nuclearPowerPop, and their
* respective values.
*/
Quad cityAssessedValue;
CityClass cityClass; ///< City class, affected by city population.
/**
* City score.
*
* Affected by average of problems, residential cap, commercial cap,
* industrial cap, road effect, police effect, fire effect,
* residential valve, commercial valve, industrial valve, city
* population, delta city population, fires, tax rate, and unpowered
* zones.
*/
short cityScore;
/**
* Change in the city score.
*
* Depends on city score.
*/
short cityScoreDelta;
/**
* Average traffic.
*
* Depends on average traffic density of tiles with non-zero land value.
*/
short trafficAverage;
void cityEvaluation();
void evalInit();
void doScoreCard();
void changeEval();
void scoreDoer();
int countProblems();
int getProblemNumber(int i);
int getProblemVotes(int i);
private:
void getAssessedValue();
void doPopNum();
Quad getPopulation();
CityClass getCityClass(Quad cityPop);
void doProblems(short problemTable[PROBNUM]);
void voteProblems(const short problemTable[PROBNUM]);
short getTrafficAverage();
short getUnemployment();
short getFireSeverity();
void getScore(const short problemTable[PROBNUM]);
void doVotes();
////////////////////////////////////////////////////////////////////////
// fileio.cpp
public:
bool loadFileData(const std::string &filename);
bool loadFile(const std::string &filename);
bool saveFile(const std::string &filename);
void loadScenario(Scenario s);
void didLoadScenario(int s, const std::string name, const std::string fname);
bool loadCity(const std::string &filename);
void didLoadCity(const std::string &filename);
void didntLoadCity(const std::string &msg);
void saveCity();
void doSaveCityAs(const std::string &filename);
void didSaveCity(const std::string &filename);
void didntSaveCity(const std::string &msg);
void saveCityAs(const std::string &filename);
////////////////////////////////////////////////////////////////////////
// generate.cpp
public:
/** @name Terrain generator.
* features available incrementally as city building tools.
*
* The user should be able to place water and trees, and it should
* dynamically smooth the edges.
*
* The user interface could restrict the user to only drawing
* terrain before any zones were built, but it would be best if
* the terrain editing tools worked properly when there were zones
* built (by automatically bulldozing zones whose underlying
* terrain it's modifying).
*/
//@{
/**
* Controls the level of tree creation.
* -1 => create default number of trees, 0 => never create trees, >0 => create more trees
*/
int terrainTreeLevel;
/**
* Controls the level of lake creation.
* -1 => create default number of lakes, 0 => never create lakes, >0 => create more lakes
*/
int terrainLakeLevel;
/**
* Controls the level of river curviness.
* -1 => default curve level, 0 => never create rivers, >0 => create curvier rivers
*/
int terrainCurveLevel;
/**
* Controls how often to create an island.
* -1 => 10% chance of island, 0 => never create island, 1 => always create island
*/
int terrainCreateIsland;
/**
* The seed of the most recently generated city.
*/
int generatedCitySeed;
void generateSomeRandomCity();
void clearMap();
void clearUnnatural();
void makeIsland();
void treeSplash(short xloc, short yloc);
void makeSingleLake(const Position &pos);
void plopBRiver(const Position &pos);
void plopSRiver(const Position &pos);
void generateSomeCity(int seed);
void generateMap(int seed);
private:
void makeNakedIsland();
void doTrees();
bool isTree(MapValue cell);
void smoothTrees();
void smoothTreesAt(int x, int y, bool preserve);
void smoothTreesAt(int x, int y, bool preserve, ToolEffects *effects);
void makeLakes();
void doRivers(const Position &terrainPos);
Direction2 doBRiver(const Position &riverPos,
Direction2 riverDir, Direction2 terrainDir);
Direction2 doSRiver(const Position &riverPos,
Direction2 riverDir, Direction2 terrainDir);
void smoothRiver();
void smoothWater();
void putOnMap(MapValue mChar, short xLoc, short yLoc);
//@}
////////////////////////////////////////////////////////////////////////
// graph.cpp
public:
/**
* @todo Nobody uses this variable. Can it be removed?
*/
bool historyInitialized;
/**
* @todo Write-only variable. Can it be removed?
*/
short graph10Max;
/**
* @todo Write-only variable. Can it be removed?
*/
short graph120Max;
void drawMonth(short *hist, unsigned char *s, float scale);
void changeCensus();
void graphDoer();
void initGraphs();
void initGraphMax();
#ifdef SWIG
// This tells SWIG that minValResult, maxValResult are output parameters,
// which will be returned in a tuple of length two.
%apply short *OUTPUT { short *minValResult };
%apply short *OUTPUT { short *maxValResult };
#endif
void getHistoryRange(int historyType, int historyScale,
short *minValResult, short *maxValResult);
short getHistory(int historyType, int historyScale,
int historyIndex);
void setHistory(int historyType, int historyScale,
int historyIndex, short historyValue);
////////////////////////////////////////////////////////////////////////
// initialize.cpp
private:
void initWillStuff();
void resetMapState();
void resetEditorState();
////////////////////////////////////////////////////////////////////////
// main.cpp
public:
int simLoops;
/**
* The number of passes through the simulator loop to take each tick.
*/
int simPasses;
/**
* The count of the current pass through the simulator loop.
*/
int simPass;
/**
* Simulation is paused
* @todo Variable has reversed logic, maybe use sim_running instead?
*/
bool simPaused;
int simPausedSpeed;
bool tilesAnimated; ///< @todo Not currently used, should hook it up.
/**
* Enable animation.
* @todo Currently always \c true. Should connect it to a frontend option.
*/
bool doAnimation;
bool doMessages; ///< @todo Not currently used, should hook it up.
bool doNotices; ///< @todo Not currently used, should hook it up.
std::string getMicropolisVersion();
void simUpdate();
void simTick();
void simulateRobots();
public:
std::string cityFileName; ///< Filename of the last loaded city
/**
* Name of the city.
*/
std::string cityName; ///< Name of the city
/**
* Heat steps.
*/
int heatSteps;
/**
* Heat flow.
*/
int heatFlow;
/**
* Heat rule.
*/
int heatRule;
/**
* Heat wrap.
*/
int heatWrap;
private:
short *cellSrc;
short *cellDst;
void simInit();
void simHeat();
void simLoop(bool doSim);
////////////////////////////////////////////////////////////////////////
// message.cpp
public:
Quad cityPopLast; ///< Population of last city class check. @see CheckGrowth
short categoryLast; ///< City class of last city class check. @see CheckGrowth
/**
* Enable auto goto
*
* When enabled and an important event happens, the map display will jump to
* the location of the event
*/
bool autoGoto;
void sendMessages();
void checkGrowth();
void doScenarioScore(Scenario type);
void sendMessage(
short Mnum,
short x = NOWHERE, short y = NOWHERE,
bool picture = false, bool important = false);
void doMakeSound(int mesgNum, int x, int y);
void doAutoGoto(short x, short y, const std::string &message);
void doLoseGame();
void doWinGame(); ///< @todo This may not be called. Call it when appropriate.
////////////////////////////////////////////////////////////////////////
// power.cpp
private:
/** @name Power stack
* Stack used to find powered tiles by tracking conductive tiles.
*/
//@{
int powerStackPointer; ///< Stack counter, points to top-most item.
/** Stack of X/Y positions for traversing setting the power grid. */
Position powerStackXY[POWER_STACK_SIZE];
void doPowerScan();
bool testForConductive(const Position &pos, Direction2 testDir);
void pushPowerStack(const Position &pos);
Position pullPowerStack();
//@}
////////////////////////////////////////////////////////////////////////
// random.cpp
public:
UQuad nextRandom;
int simRandom();
short getRandom(short range);
int getRandom16();
int getRandom16Signed();
short getERandom(short limit);
void randomlySeedRandom();
void seedRandom(int seed);
////////////////////////////////////////////////////////////////////////
// scan.cpp
private:
/** @todo Write-only variable, can be removed? */
short newMap;
/** @todo Write-only variable, can be removed? */
short newMapFlags[MAP_TYPE_COUNT];
short cityCenterX; ///< X coordinate of city center
short cityCenterY; ///< Y coordinate of city center
short pollutionMaxX; ///< X coordinate of most polluted area
short pollutionMaxY; ///< Y coordinate of most polluted area
short crimeMaxX; ///< X coordinate of most criminal area. Not used.
short crimeMaxY; ///< Y coordinate of most criminal area. Not used.
/**
* Integer with bits 0..2 that control smoothing.
*/
Quad donDither;
void fireAnalysis();
void populationDensityScan();
int getPopulationDensity(const Position &pos, MapTile tile);
void pollutionTerrainLandValueScan();
int getPollutionValue(int loc);
int getCityCenterDistance(int x, int y);
void crimeScan();
void smoothTerrain();
void doSmooth1();
void doSmooth2();
void computeComRateMap();
////////////////////////////////////////////////////////////////////////
// simulate.cpp
public:
bool valveFlag;
short crimeRamp;
short pollutionRamp;
bool resCap; ///< Block residential growth
bool comCap; ///< Block commercial growth
bool indCap; ///< Block industrial growth
short cashFlow;
float externalMarket;
Scenario disasterEvent; ///< The disaster for which a count-down is running
short disasterWait; ///< Count-down timer for the disaster
Scenario scoreType; ///< The type of score table to use
short scoreWait; ///< Time to wait before computing the score
short poweredZoneCount; ///< Number of powered tiles in all zone
short unpoweredZoneCount; ///< Number of unpowered tiles in all zones
bool newPower; /* post */
short cityTaxAverage;
short simCycle;
short phaseCycle;
short speedCycle;
bool doInitialEval; ///< Need to perform initial city evaluation.
int mapSerial; ///< The invalidateMaps method increases the map serial number every time the maps changes.
private:
short resValve;
short comValve;
short indValve;
public:
void updateFundEffects();
private:
/** Generate a random animated Tiles::FIRE tile */
inline MapValue randomFire()
{
return (FIRE + (getRandom16() & 7)) | ANIMBIT;
};
/** Generate a random Tiles::RUBBLE tile */
inline MapValue randomRubble()
{
return (RUBBLE + (getRandom16() & 3)) | BULLBIT;
};
void simFrame();
void simulate();
void doSimInit();
void doNilPower();
void decTrafficMap();
void decRateOfGrowthMap();
void initSimMemory();
void simLoadInit();
void setCommonInits();
void setValves();
void clearCensus();
void take10Census();
void take120Census();
void collectTax();
void mapScan(int x1, int x2);
void doRail(const Position &pos);
void doRadTile(const Position &pos);
void doRoad(const Position &pos);
bool doBridge(const Position &pos, MapTile tile);
int getBoatDistance(const Position &pos);
void doFire(const Position &pos);
void fireZone(const Position &pos, MapValue ch);
void repairZone(const Position &pos, MapTile zCent, short zSize);
void doSpecialZone(const Position &pos, bool PwrOn);
void drawStadium(const Position &center, MapTile z);
void doAirport(const Position &pos);
void coalSmoke(const Position &pos);
void doMeltdown(const Position &pos);
////////////////////////////////////////////////////////////////////////
// sprite.cpp
public:
SimSprite *spriteList; ///< List of active sprites.
SimSprite *newSprite(const std::string &name, int type, int x, int y);
void initSprite(SimSprite *sprite, int x, int y);
void destroyAllSprites();
void destroySprite(SimSprite *sprite);
SimSprite *getSprite(int type);
SimSprite *makeSprite(int type, int x, int y);
private:
SimSprite *freeSprites; ///< Pool of free #SimSprite objects.
SimSprite *globalSprites[SPRITE_COUNT];
int absDist;
short spriteCycle;
public:
short getChar(int x, int y);
short turnTo(int p, int d);
bool tryOther(int Tpoo, int Told, int Tnew);
bool spriteNotInBounds(SimSprite *sprite);
short getDir(int orgX, int orgY, int desX, int desY);
int getDistance(int x1, int y1, int x2, int y2);
bool checkSpriteCollision(SimSprite *s1, SimSprite *s2);
void moveObjects();
void doTrainSprite(SimSprite *sprite);
void doCopterSprite(SimSprite *sprite);
void doAirplaneSprite(SimSprite *sprite);
void doShipSprite(SimSprite *sprite);
void doMonsterSprite(SimSprite *sprite);
void doTornadoSprite(SimSprite *sprite);
void doExplosionSprite(SimSprite *sprite);
void doBusSprite(SimSprite *sprite);
int canDriveOn(int x, int y);
void explodeSprite(SimSprite *sprite);
bool checkWet(int x);
void destroyMapTile(int ox, int oy);
void startFireInZone(int Xloc, int Yloc, int ch);
void startFire(int x, int y);
void generateTrain(int x, int y);
void generateBus(int x, int y);
void generateShip();
void makeShipHere(int x, int y);
void makeMonster();
void makeMonsterAt(int x, int y);
void generateCopter(const Position &pos);
void generatePlane(const Position &pos);
void makeTornado();
void makeExplosion(int x, int y);
void makeExplosionAt(int x, int y);
////////////////////////////////////////////////////////////////////////
// stubs.cpp
public:
Quad totalFunds; ///< Funds of the player
/**
* Enable auto-bulldoze
*
* When enabled, the game will silently clear tiles when the user
* builds something on non-clear and bulldozable tiles
*/
bool autoBulldoze;
/**
* Enable auto budget
*
* When enabled, the program will perform budgetting of the city
*/
bool autoBudget;
Quad messageTimeLast;
GameLevel gameLevel; ///< Difficulty level of the game (0..2)
short initSimLoad;
Scenario scenario; ///< Scenario being played
short simSpeed;
short simSpeedMeta;
bool enableSound; ///< Enable sound
bool enableDisasters; ///< Enable disasters
short messageNumber;
bool evalChanged; ///< The evaluation window should be shown to the user
/**
* @todo Variable is not used, can we remove it?
*/
short blinkFlag;
emscripten::val callbackVal;
/**
* Hook for scripting language to store scripted callback function.
* (i.e. a callable Python object.)
*/
void *callbackData;
/**
* Hook for scripting language to store context (i.e. peer object).
* (i.e. Python SWIG wrapper of this Micropolis object.)
*/
void *userData;
/**
* Check that the given coordinate is within world bounds
* @param wx World x coordinate
* @param wy World y coordinate
* @return Boolean indicating (wx, wy) is inside the world bounds
*/
static inline bool testBounds(int wx, int wy)
{
return (wx >= 0 && wx < WORLD_W && wy >= 0 && wy < WORLD_H);
};
void spend(int dollars);
void setFunds(int dollars);
Quad tickCount();
Ptr newPtr(int size);
void freePtr(void *data);
void doStartScenario(int scenario);
void doStartGame();
void initGame();
void doEarthquake(int strength);
void invalidateMaps();
void makeSound(
const std::string &channel,
const std::string &sound,
int x = -1,
int y = -1);
// Map
int getTile(int x, int y);
void setTile(int x, int y, int tile);
void *getMapBuffer();
// Residential.
// Commercial.
// Industrial.
// Power.
int getPowerGrid(int x, int y);
void setPowerGrid(int x, int y, int power);
void *getPowerGridMapBuffer();
// Roads.
// Population density.
int getPopulationDensity(int x, int y);
void setPopulationDensity(int x, int y, int density);
void *getPopulationDensityMapBuffer();
// Rate of growth.
int getRateOfGrowth(int x, int y);
void setRateOfGrowth(int x, int y, int rate);
void *getRateOfGrowthMapBuffer();
// Traffic density.
int getTrafficDensity(int x, int y);
void setTrafficDensity(int x, int y, int density);
void *getTrafficDensityMapBuffer();
// Pollution density.
int getPollutionDensity(int x, int y);
void setPollutionDensity(int x, int y, int density);
void *getPollutionDensityMapBuffer();
// Crime rate.
int getCrimeRate(int x, int y);
void setCrimeRate(int x, int y, int rate);
void *getCrimeRateMapBuffer();
// Land value.
int getLandValue(int x, int y);
void setLandValue(int x, int y, int value);
void *getLandValueMapBuffer();
// Fire coverage.
int getFireCoverage(int x, int y);
void setFireCoverage(int x, int y, int coverage);
void *getFireCoverageMapBuffer();
// Police coverage.
int getPoliceCoverage(int x, int y);
void setPoliceCoverage(int x, int y, int coverage);
void *getPoliceCoverageMapBuffer();
////////////////////////////////////////////////////////////////////////
// tool.cpp
public:
ToolResult doTool(EditingTool tool, short tileX, short tileY);
void toolDown(EditingTool tool, short tileX, short tileY);
void toolDrag(EditingTool tool, short fromX, short fromY,
short toX, short toY);
void didTool(std::string name, short x, short y);
private:
ToolResult queryTool(short x, short y);
ToolResult bulldozerTool(short x, short y);
ToolResult bulldozerTool(short x, short y, ToolEffects *effects);
ToolResult roadTool(short x, short y, ToolEffects *effects);
ToolResult railroadTool(short x, short y, ToolEffects *effects);
ToolResult wireTool(short x, short y, ToolEffects *effects);
ToolResult parkTool(short x, short y, ToolEffects *effects);
ToolResult buildBuildingTool(short x, short y,
const BuildingProperties *bprops,
ToolEffects *effects);
ToolResult networkTool(short x, short y, ToolEffects *effects);
ToolResult waterTool(short x, short y, ToolEffects *effects);
ToolResult landTool(short x, short y, ToolEffects *effects);
ToolResult forestTool(short x, short y, ToolEffects *effects);
ToolResult putDownPark(short mapH, short mapV, ToolEffects *effects);
ToolResult putDownNetwork(short mapH, short mapV, ToolEffects *effects);
ToolResult putDownWater(short mapH, short mapV, ToolEffects *effects);
ToolResult putDownLand(short mapH, short mapV, ToolEffects *effects);
ToolResult putDownForest(short mapH, short mapV, ToolEffects *effects);
void doZoneStatus(short mapH, short mapV);
void doShowZoneStatus(
int tileCategoryIndex,
int populationDensityIndex,
int landValueIndex,
int crimeRateIndex,
int pollutionIndex,
int growthRateIndex,
int x,
int y);
void putBuilding(int leftX, int topY, int sizeX, int sizeY,
MapTile baseTile, bool aniFlag,
ToolEffects *effects);
ToolResult prepareBuildingSite(int leftX, int topY, int sizeX, int sizeY,
ToolEffects *effects);
ToolResult buildBuilding(int mapH, int mapV,
const BuildingProperties *bprops,
ToolEffects *effects);
int getDensity(short catNo, short mapH, short mapV);
bool tally(short tileValue);
short checkSize(short tileValue);
void checkBorder(short xMap, short yMap, int sizeX, int sizeY,
ToolEffects *effects);
void putRubble(int x, int y, int size, ToolEffects *effects);
////////////////////////////////////////////////////////////////////////
// traffic.cpp
public:
short makeTrafficAt(int x, int y, ZoneType dest);
short makeTraffic(int x, int y, ZoneType dest);
private:
short makeTraffic(const Position &startPos, ZoneType dest);
/* Position stack */
/** Position stack top pointer, points to top position. */
short curMapStackPointer;
Position curMapStackXY[MAX_TRAFFIC_DISTANCE + 1]; ///< Position stack.
short trafMaxX; ///< X coordinate of a position with heavy traffic
short trafMaxY; ///< Y coordinate of a position with heavy traffic
void addToTrafficDensityMap();
void pushPos(const Position &pos);
Position pullPos();
bool findPerimeterRoad(Position *pos);
bool findPerimeterTelecom(const Position &pos);
bool tryDrive(const Position &startPos, ZoneType destZone);
Direction2 tryGo(const Position &pos, Direction2 dirLast);
MapTile getTileFromMap(const Position &pos,
Direction2 dir, MapTile defaultTile);
bool driveDone(const Position &pos, ZoneType destZone);
bool roadTest(MapValue tile);
////////////////////////////////////////////////////////////////////////
// update.cpp
public:
bool mustUpdateFunds;
bool mustUpdateOptions; ///< Options displayed at user need updating.
Quad cityTimeLast;
Quad cityYearLast;
Quad cityMonthLast;
Quad totalFundsLast;
Quad resLast;
Quad comLast;
Quad indLast;
void doUpdateHeads();
void updateMaps();
void updateGraphs();
void updateEvaluation();
void updateHeads();
void updateFunds();
void reallyUpdateFunds();
void doTimeStuff();
void updateDate();
void showValves();
void drawValve();
void setDemand(float r, float c, float i);
void updateOptions();
void updateUserInterface();
////////////////////////////////////////////////////////////////////////
// utilities.cpp
public:
void pause();
void resume();
void setSpeed(short speed);
void setPasses(int passes);
void setGameLevelFunds(GameLevel level);
void setGameLevel(GameLevel level);
void updateGameLevel();
void setCityName(const std::string &name);
void setCleanCityName(const std::string &name);
void setYear(int year);
int currentYear();
void doNewGame();
void setEnableDisasters(bool value);
void setAutoBudget(bool value);
void setAutoBulldoze(bool value);
void setAutoGoto(bool value);
void setEnableSound(bool value);
void setDoAnimation(bool value);
void setDoMessages(bool value);
void setDoNotices(bool value);
#ifdef SWIG
// This tells SWIG that resDemandResult, comDemandResult and indDemandResult
// are output parameters, which will be returned in a tuple of length three.
%apply float *OUTPUT { float *resDemandResult };
%apply float *OUTPUT { float *comDemandResult };
%apply float *OUTPUT { float *indDemandResult };
#endif
void getDemands(
float *resDemandResult,
float *comDemandResult,
float *indDemandResult);
private:
std::string makeDollarDecimalStr(const std::string &numStr);
////////////////////////////////////////////////////////////////////////
// zone.cpp
private:
void doZone(const Position &pos);
void doHospitalChurch(const Position &pos);
void setSmoke(const Position &pos, bool zonePower);
void makeHospital(const Position &pos);
short getLandPollutionValue(const Position &pos);
void incRateOfGrowth(const Position &pos, int amount);
bool zonePlop(const Position &pos, int base);
short doFreePop(const Position &pos);
bool setZonePower(const Position &pos);
void buildHouse(const Position &pos, int value);
short evalLot(int x, int y);
void doResidential(const Position &pos, bool zonePower);
void doResIn(const Position &pos, int pop, int value);
void doResOut(const Position &pos, int pop, int value);
short getResZonePop(MapTile mapTile);
void resPlop(const Position &pos, int Den, int Value);
short evalRes(const Position &pos, int traf);
// Commercial zone handling
void doCommercial(const Position &pos, bool zonePower);
void doComIn(const Position &pos, int pop, int value);
void doComOut(const Position &pos, int pop, int value);
short getComZonePop(MapTile tile);
void comPlop(const Position &pos, int Den, int Value);
short evalCom(const Position &pos, int traf);
// Industrial zone handling
void doIndustrial(const Position &pos, bool zonePower);
void doIndIn(const Position &pos, int pop, int value);
void doIndOut(const Position &pos, int pop, int value);
short getIndZonePop(MapTile tile);
void indPlop(const Position &pos, int den, int value);
short evalInd(int traf);
////////////////////////////////////////////////////////////////////////
};
////////////////////////////////////////////////////////////////////////
#endif