citylimits/core/emscripten.cpp

1160 lines
51 KiB
C++
Raw Permalink Normal View History

2024-05-03 22:50:34 -04:00
/* emscripten.cpp
*
* 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 emscripten.cpp
* @brief Emscripten bindings for Micropolis game engine.
*
* This file contains Emscripten bindings that allow the Micropolis
* (open-source version of SimCity) game engine to be used in a web
* environment. It utilizes Emscripten's Embind feature to expose C++
* classes, functions, enums, and data structures to JavaScript,
* enabling the Micropolis game engine to be controlled and interacted
* with through a web interface. This includes key functionalities
* such as simulation control, game state management, map
* manipulation, and event handling. The binding includes only
* essential elements for gameplay, omitting low-level rendering and
* platform-specific code.
*/
////////////////////////////////////////////////////////////////////////
#include <emscripten/bind.h>
#include "micropolis.h"
////////////////////////////////////////////////////////////////////////
using namespace emscripten;
////////////////////////////////////////////////////////////////////////
// This file uses emscripten's embind to bind C++ classes,
// C structures, functions, enums, and contents into JavaScript,
// so you can even subclass C++ classes in JavaScript,
// for implementing plugins and user interfaces.
//
// Wrapping the entire Micropolis class from the Micropolis (open-source
// version of SimCity) code into Emscripten for JavaScript access is a
// large and complex task, mainly due to the size and complexity of the
// class. The class encompasses almost every aspect of the simulation,
// including map generation, simulation logic, user interface
// interactions, and more.
//
// Strategy for Wrapping
//
// 1. Core Simulation Logic: Focus on the core simulation aspects, such
// as the methods to run the simulation, update game states, and handle
// user inputs (like building tools and disaster simulations). This is
// crucial for any gameplay functionality.
//
// 2. Memory and Performance Considerations: JavaScript and WebAssembly
// run in a browser context, which can have memory limitations and
// performance constraints. Carefully manage memory allocation,
// especially when dealing with the game's map and various buffers.
//
// 3. Direct Memory Access: Provide JavaScript access to critical game
// data structures like the map buffer for efficient reading and
// writing. This can be done using Emscripten's heap access functions
// (HEAP8, HEAP16, HEAP32, etc.).
//
// 4. User Interface and Rendering: This part might not be necessary to
// wrap, as modern web technologies (HTML, CSS, WebGL) can be used for
// UI. However, providing some hooks for game state (like score, budget,
// etc.) to JavaScript might be helpful.
//
// 5. Callbacks and Interactivity: Ensure that key game events and
// callbacks are exposed to JavaScript, allowing for interactive and
// responsive gameplay.
//
// 6. Optimizations: Where possible, optimize C++ code for WebAssembly,
// focusing on critical paths in the simulation loop.
//
// Decisions and Explanations
//
// - Excluded Elements:
//
// - Low-level rendering or platform-specific code, as this can be
// handled more efficiently with web technologies.
//
// - Parts of the code that handle file I/O directly, as file access
// in a web context is typically handled differently (e.g., using
// browser APIs or server-side support).
//
// - Any networking or multiplayer code, as web-based
// implementations would differ significantly from desktop-based
// network code.
//
// - Included Elements:
//
// - Core game mechanics, such as map generation, zone simulation
// (residential, commercial, industrial), disaster simulation, and
// basic utilities.
//
// - Game state management, including budgeting, scoring, and city
// evaluation.
//
// - Direct memory access to critical structures like the map
// buffer, allowing efficient manipulation from JavaScript.
//
// - Essential callbacks and event handling mechanisms to ensure
// interactivity.
//
// Conclusion
//
// Given the complexity and size of the Micropolis class, wrapping the
// entire class directly is impractical. However, focusing on key areas
// essential for gameplay and providing efficient interfaces for
// critical data structures can create a functional and interactive city
// simulation in a web context. Further optimizations and adjustments
// would likely be needed based on testing and specific requirements of
// the web implementation.
//
// Implementation Notes
//
// The enum_, class_, constructor, function, and property functions
// from the emscripten namespace are used to specify how C++
// constructs should be exposed to JavaScript. You can use these to
// control which parts of your code are accessible and how they should
// be used from JavaScript.
//
// I've made some assumptions here:
//
// The types MapValue and MapTile are simple types (like integers or
// floats). If they are complex types, they would need their own
// bindings.
//
// I'm assuming that the copy constructor and copy assignment
// operator for the Position class are correctly implemented. If
// they aren't, then the Position object may not behave as expected
// in JavaScript.
//
// Micropolis Binding Design
//
// The Micropolis interface organizes the Micropolis class header into
// categories of functions that are relevant for interaction with the
// JavaScript user interface, scripts, or plugins. The aim is to expose
// functions that could help in monitoring and controlling game state
// effectively.
//
// - Exposed to JavaScript (Public Interface)
// - Simulation Control and Settings
// - void simTick()
// - void setSpeed(short speed)
// - void setGameLevel(GameLevel level)
// - void setCityName(const std::string &name)
// - void setYear(int year)
// - void pause()
// - void resume()
// - 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 doNewGame()
// - void doBudget()
// - void doScoreCard()
// - void updateFunds()
// - Gameplay Mechanics
// - void doTool(EditingTool tool, short tileX, short tileY)
// - void generateMap(int seed)
// - void clearMap()
// - void makeDisaster(DisasterType type)
// - void getDemands(float *resDemandResult, float *comDemandResult, float *indDemandResult)
// - Random Number Generation
// - int simRandom()
// - int getRandom(short range)
// - int getRandom16()
// - int getRandom16Signed()
// - short getERandom(short limit)
// - void randomlySeedRandom()
// - void seedRandom(int seed)
// - Game State and Data Access
// - int getTile(int x, int y)
// - void setTile(int x, int y, int tile)
// - void setFunds(Quad dollars)
// - Quad getCityPopulation()
// - void updateMaps()
// - void updateGraphs()
// - void updateEvaluation()
// - void updateBudget()
// - Events and Callbacks
// - void sendMessage(short messageNumber, short x = NOWHERE, short y = NOWHERE)
// - void makeSound(std::string channel, std::string sound, int x = -1, int y = -1)
// - Hidden from JavaScript (Private Interface)
// - Internal Simulation Mechanics
// - void simFrame()
// - void simulate()
// - void doSimInit()
// - void setValves()
// - void clearCensus()
// - void collectTax()
// - void mapScan(int x1, int x2)
// - Utility Functions
// - void initMapArrays()
// - void destroyMapArrays()
// - void initSimMemory()
// - void initGraphs()
// - Zone Handling
// - void doZone(const Position &pos)
// - void doResidential(const Position &pos, bool zonePower)
// - void doCommercial(const Position &pos, bool zonePower)
// - void doIndustrial(const Position &pos, bool zonePower)
// - Disaster Simulation
// - void doDisasters()
// - void scenarioDisaster()
// - void fireAnalysis()
// - void makeFire()
// - void makeFlood()
//
// Conclusion
//
// These exposed functions provide a comprehensive interface for
// scripting, plugins, and user interactions through JavaScript. The
// exposed set of functions includes random number generation,
// simulation control mechanisms, UI-triggered actions like budget
// updates, along with essential gameplay mechanics. The private section
// continues to encapsulate internal simulation details and complex data
// management routines integral to the game's core mechanics.
EMSCRIPTEN_BINDINGS(MicropolisEngine) {
// position.h
enum_<Direction2>("Direction2")
.value("INVALID", Direction2::DIR2_INVALID)
.value("NORTH", Direction2::DIR2_NORTH)
.value("NORTH_EAST", Direction2::DIR2_NORTH_EAST)
.value("EAST", Direction2::DIR2_EAST)
.value("SOUTH_EAST", Direction2::DIR2_SOUTH_EAST)
.value("SOUTH", Direction2::DIR2_SOUTH)
.value("SOUTH_WEST", Direction2::DIR2_SOUTH_WEST)
.value("WEST", Direction2::DIR2_WEST)
.value("NORTH_WEST", Direction2::DIR2_NORTH_WEST)
;
class_<Position>("Position")
.constructor<>()
.constructor<int, int>()
.function("move", &Position::move)
.function("testBounds", &Position::testBounds)
.property("posX", &Position::posX)
.property("posY", &Position::posY)
;
function("increment45", &increment45);
function("increment90", &increment90);
function("rotate45", &rotate45);
function("rotate90", &rotate90);
function("rotate180", &rotate180);
// tool.h
class_<ToolEffects>("ToolEffects")
//.constructor<Micropolis*>() // TODO: wrap
.function("clear", &ToolEffects::clear)
.function("modifyWorld", &ToolEffects::modifyWorld)
.function("modifyIfEnoughFunding", &ToolEffects::modifyIfEnoughFunding)
.function("getMapValue", select_overload<MapValue(const Position&) const>(&ToolEffects::getMapValue))
.function("getMapTile", select_overload<MapTile(const Position&) const>(&ToolEffects::getMapTile))
.function("getCost", &ToolEffects::getCost)
.function("addCost", &ToolEffects::addCost)
.function("setMapValue", select_overload<void(const Position&, MapValue)>(&ToolEffects::setMapValue))
//.function("addFrontendMessage", &ToolEffects::addFrontendMessage) // TODO: wrap
;
enum_<MapTileBits>("MapTileBits")
.value("PWRBIT", PWRBIT)
.value("CONDBIT", CONDBIT)
.value("BURNBIT", BURNBIT)
.value("BULLBIT", BULLBIT)
.value("ANIMBIT", ANIMBIT)
.value("ZONEBIT", ZONEBIT)
.value("ALLBITS", ALLBITS)
.value("LOMASK", LOMASK)
.value("BLBNBIT", BLBNBIT)
.value("BLBNCNBIT", BLBNCNBIT)
.value("BNCNBIT", BNCNBIT)
;
enum_<EditingTool>("EditingTool")
.value("TOOL_RESIDENTIAL", TOOL_RESIDENTIAL)
.value("TOOL_COMMERCIAL", TOOL_COMMERCIAL)
.value("TOOL_INDUSTRIAL", TOOL_INDUSTRIAL)
.value("TOOL_FIRESTATION", TOOL_FIRESTATION)
.value("TOOL_POLICESTATION", TOOL_POLICESTATION)
.value("TOOL_QUERY", TOOL_QUERY)
.value("TOOL_WIRE", TOOL_WIRE)
.value("TOOL_BULLDOZER", TOOL_BULLDOZER)
.value("TOOL_RAILROAD", TOOL_RAILROAD)
.value("TOOL_ROAD", TOOL_ROAD)
.value("TOOL_STADIUM", TOOL_STADIUM)
.value("TOOL_PARK", TOOL_PARK)
.value("TOOL_SEAPORT", TOOL_SEAPORT)
.value("TOOL_COALPOWER", TOOL_COALPOWER)
.value("TOOL_NUCLEARPOWER", TOOL_NUCLEARPOWER)
.value("TOOL_AIRPORT", TOOL_AIRPORT)
.value("TOOL_NETWORK", TOOL_NETWORK)
.value("TOOL_WATER", TOOL_WATER)
.value("TOOL_LAND", TOOL_LAND)
.value("TOOL_FOREST", TOOL_FOREST)
.value("TOOL_COUNT", TOOL_COUNT)
.value("TOOL_FIRST", TOOL_FIRST)
.value("TOOL_LAST", TOOL_LAST);
;
// map_type.h
class_<Map<Byte, 1>>("MapByte1")
.constructor<Byte>()
.property("MAP_BLOCKSIZE", &Map<Byte, 1>::MAP_BLOCKSIZE)
.property("MAP_W", &Map<Byte, 1>::MAP_W)
.property("MAP_H", &Map<Byte, 1>::MAP_H)
.function("fill", &Map<Byte, 1>::fill)
.function("clear", &Map<Byte, 1>::clear)
.function("set", &Map<Byte, 1>::set)
.function("get", &Map<Byte, 1>::get)
.function("onMap", &Map<Byte, 1>::onMap)
.function("worldSet", &Map<Byte, 1>::worldSet)
.function("worldGet", &Map<Byte, 1>::worldGet)
.function("worldOnMap", &Map<Byte, 1>::worldOnMap)
//.function("getBase", &Map<Byte, 1>::getBase, allow_raw_pointers()) // TODO: wrap
.function("getTotalByteSize", &Map<Byte, 1>::getTotalByteSize)
;
class_<Map<Byte, 2>>("MapByte2")
.constructor<Byte>()
.property("MAP_BLOCKSIZE", &Map<Byte, 2>::MAP_BLOCKSIZE)
.property("MAP_W", &Map<Byte, 2>::MAP_W)
.property("MAP_H", &Map<Byte, 2>::MAP_H)
.function("fill", &Map<Byte, 2>::fill)
.function("clear", &Map<Byte, 2>::clear)
.function("set", &Map<Byte, 2>::set)
.function("get", &Map<Byte, 2>::get)
.function("onMap", &Map<Byte, 2>::onMap)
.function("worldSet", &Map<Byte, 2>::worldSet)
.function("worldGet", &Map<Byte, 2>::worldGet)
.function("worldOnMap", &Map<Byte, 2>::worldOnMap)
//.function("getBase", &Map<Byte, 2>::getBase, allow_raw_pointers()) // TODO: wrap
.function("getTotalByteSize", &Map<Byte, 2>::getTotalByteSize)
;
class_<Map<Byte, 4>>("MapByte4")
.constructor<Byte>()
.property("MAP_BLOCKSIZE", &Map<Byte, 4>::MAP_BLOCKSIZE)
.property("MAP_W", &Map<Byte, 4>::MAP_W)
.property("MAP_H", &Map<Byte, 4>::MAP_H)
.function("fill", &Map<Byte, 4>::fill)
.function("clear", &Map<Byte, 4>::clear)
.function("set", &Map<Byte, 4>::set)
.function("get", &Map<Byte, 4>::get)
.function("onMap", &Map<Byte, 4>::onMap)
.function("worldSet", &Map<Byte, 4>::worldSet)
.function("worldGet", &Map<Byte, 4>::worldGet)
.function("worldOnMap", &Map<Byte, 4>::worldOnMap)
//.function("getBase", &Map<Byte, 4>::getBase, allow_raw_pointers()) // TODO: wrap
.function("getTotalByteSize", &Map<Byte, 4>::getTotalByteSize)
;
class_<Map<short, 8>>("MapShort8")
.constructor<short>()
.property("MAP_BLOCKSIZE", &Map<short, 8>::MAP_BLOCKSIZE)
.property("MAP_W", &Map<short, 8>::MAP_W)
.property("MAP_H", &Map<short, 8>::MAP_H)
.function("fill", &Map<short, 8>::fill)
.function("clear", &Map<short, 8>::clear)
.function("set", &Map<short, 8>::set)
.function("get", &Map<short, 8>::get)
.function("onMap", &Map<short, 8>::onMap)
.function("worldSet", &Map<short, 8>::worldSet)
.function("worldGet", &Map<short, 8>::worldGet)
.function("worldOnMap", &Map<short, 8>::worldOnMap)
//.function("getBase", &Map<short, 8>::getBase, allow_raw_pointers()) // TODO: wrap
.function("getTotalByteSize", &Map<short, 8>::getTotalByteSize)
;
/*
function createTypedArrayFromMap(mapInstance) {
var pointer = mapInstance.getBase();
var byteSize = mapInstance.getTotalByteSize();
var mapSize = mapInstance.MAP_W * mapInstance.MAP_H;
var arrayType;
// Determine the correct Typed Array type based on DATA type
if (byteSize === mapSize) {
arrayType = Uint8Array;
} else if (byteSize === mapSize * 2) {
arrayType = Uint16Array;
} else {
console.error("Unsupported data type for Typed Array.");
return null;
}
var typedArray = new arrayType(Module.HEAPU8.buffer, pointer, byteSize / arrayType.BYTES_PER_ELEMENT);
return typedArray;
}
*/
// text.h
enum_<Stri202>("Stri202")
.value("STR202_POPULATIONDENSITY_LOW", STR202_POPULATIONDENSITY_LOW) // 0: Low
.value("STR202_POPULATIONDENSITY_MEDIUM", STR202_POPULATIONDENSITY_MEDIUM) // 1: Medium
.value("STR202_POPULATIONDENSITY_HIGH", STR202_POPULATIONDENSITY_HIGH) // 2: High
.value("STR202_POPULATIONDENSITY_VERYHIGH", STR202_POPULATIONDENSITY_VERYHIGH) // 3: Very High
.value("STR202_LANDVALUE_SLUM", STR202_LANDVALUE_SLUM) // 4: Slum
.value("STR202_LANDVALUE_LOWER_CLASS", STR202_LANDVALUE_LOWER_CLASS) // 5: Lower Class
.value("STR202_LANDVALUE_MIDDLE_CLASS", STR202_LANDVALUE_MIDDLE_CLASS) // 6: Middle Class
.value("STR202_LANDVALUE_HIGH_CLASS", STR202_LANDVALUE_HIGH_CLASS) // 7: High
.value("STR202_CRIME_NONE", STR202_CRIME_NONE) // 8: Safe
.value("STR202_CRIME_LIGHT", STR202_CRIME_LIGHT) // 9: Light
.value("STR202_CRIME_MODERATE", STR202_CRIME_MODERATE) // 10: Moderate
.value("STR202_CRIME_DANGEROUS", STR202_CRIME_DANGEROUS) // 11: Dangerous
.value("STR202_POLLUTION_NONE", STR202_POLLUTION_NONE) // 12: None
.value("STR202_POLLUTION_MODERATE", STR202_POLLUTION_MODERATE) // 13: Moderate
.value("STR202_POLLUTION_HEAVY", STR202_POLLUTION_HEAVY) // 14: Heavy
.value("STR202_POLLUTION_VERY_HEAVY", STR202_POLLUTION_VERY_HEAVY) // 15: Very Heavy
.value("STR202_GROWRATE_DECLINING", STR202_GROWRATE_DECLINING) // 16: Declining
.value("STR202_GROWRATE_STABLE", STR202_GROWRATE_STABLE) // 17: Stable
.value("STR202_GROWRATE_SLOWGROWTH", STR202_GROWRATE_SLOWGROWTH) // 18: Slow Growth
.value("STR202_GROWRATE_FASTGROWTH", STR202_GROWRATE_FASTGROWTH) // 19: Fast Growth
;
enum_<MessageNumber>("MessageNumber")
.value("MESSAGE_NEED_MORE_RESIDENTIAL", MESSAGE_NEED_MORE_RESIDENTIAL) // 1: More residential zones needed.
.value("MESSAGE_NEED_MORE_COMMERCIAL", MESSAGE_NEED_MORE_COMMERCIAL) // 2: More commercial zones needed.
.value("MESSAGE_NEED_MORE_INDUSTRIAL", MESSAGE_NEED_MORE_INDUSTRIAL) // 3: More industrial zones needed.
.value("MESSAGE_NEED_MORE_ROADS", MESSAGE_NEED_MORE_ROADS) // 4: More roads required.
.value("MESSAGE_NEED_MORE_RAILS", MESSAGE_NEED_MORE_RAILS) // 5: Inadequate rail system.
.value("MESSAGE_NEED_ELECTRICITY", MESSAGE_NEED_ELECTRICITY) // 6: Build a Power Plant.
.value("MESSAGE_NEED_STADIUM", MESSAGE_NEED_STADIUM) // 7: Residents demand a Stadium.
.value("MESSAGE_NEED_SEAPORT", MESSAGE_NEED_SEAPORT) // 8: Industry requires a Sea Port.
.value("MESSAGE_NEED_AIRPORT", MESSAGE_NEED_AIRPORT) // 9: Commerce requires an Airport.
.value("MESSAGE_HIGH_POLLUTION", MESSAGE_HIGH_POLLUTION) // 10: Pollution very high.
.value("MESSAGE_HIGH_CRIME", MESSAGE_HIGH_CRIME) // 11: Crime very high.
.value("MESSAGE_TRAFFIC_JAMS", MESSAGE_TRAFFIC_JAMS) // 12: Frequent traffic jams reported.
.value("MESSAGE_NEED_FIRE_STATION", MESSAGE_NEED_FIRE_STATION) // 13: Citizens demand a Fire Department.
.value("MESSAGE_NEED_POLICE_STATION", MESSAGE_NEED_POLICE_STATION) // 14: Citizens demand a Police Department.
.value("MESSAGE_BLACKOUTS_REPORTED", MESSAGE_BLACKOUTS_REPORTED) // 15: Blackouts reported. Check power map.
.value("MESSAGE_TAX_TOO_HIGH", MESSAGE_TAX_TOO_HIGH) // 16: Citizens upset. The tax rate is too high.
.value("MESSAGE_ROAD_NEEDS_FUNDING", MESSAGE_ROAD_NEEDS_FUNDING) // 17: Roads deteriorating, due to lack of funds.
.value("MESSAGE_FIRE_STATION_NEEDS_FUNDING", MESSAGE_FIRE_STATION_NEEDS_FUNDING) // 18: Fire departments need funding.
.value("MESSAGE_POLICE_NEEDS_FUNDING", MESSAGE_POLICE_NEEDS_FUNDING) // 19: Police departments need funding.
.value("MESSAGE_FIRE_REPORTED", MESSAGE_FIRE_REPORTED) // 20: Fire reported!
.value("MESSAGE_MONSTER_SIGHTED", MESSAGE_MONSTER_SIGHTED) // 21: A Monster has been sighted!!
.value("MESSAGE_TORNADO_SIGHTED", MESSAGE_TORNADO_SIGHTED) // 22: Tornado reported!!
.value("MESSAGE_EARTHQUAKE", MESSAGE_EARTHQUAKE) // 23: Major earthquake reported!!!
.value("MESSAGE_PLANE_CRASHED", MESSAGE_PLANE_CRASHED) // 24: A plane has crashed!
.value("MESSAGE_SHIP_CRASHED", MESSAGE_SHIP_CRASHED) // 25: Shipwreck reported!
.value("MESSAGE_TRAIN_CRASHED", MESSAGE_TRAIN_CRASHED) // 26: A train crashed!
.value("MESSAGE_HELICOPTER_CRASHED", MESSAGE_HELICOPTER_CRASHED) // 27: A helicopter crashed!
.value("MESSAGE_HIGH_UNEMPLOYMENT", MESSAGE_HIGH_UNEMPLOYMENT) // 28: Unemployment rate is high.
.value("MESSAGE_NO_MONEY", MESSAGE_NO_MONEY) // 29: YOUR CITY HAS GONE BROKE!
.value("MESSAGE_FIREBOMBING", MESSAGE_FIREBOMBING) // 30: Firebombing reported!
.value("MESSAGE_NEED_MORE_PARKS", MESSAGE_NEED_MORE_PARKS) // 31: Need more parks.
.value("MESSAGE_EXPLOSION_REPORTED", MESSAGE_EXPLOSION_REPORTED) // 32: Explosion detected!
.value("MESSAGE_NOT_ENOUGH_FUNDS", MESSAGE_NOT_ENOUGH_FUNDS) // 33: Insufficient funds to build that.
.value("MESSAGE_BULLDOZE_AREA_FIRST", MESSAGE_BULLDOZE_AREA_FIRST) // 34: Area must be bulldozed first.
.value("MESSAGE_REACHED_TOWN", MESSAGE_REACHED_TOWN) // 35: Population has reached 2,000.
.value("MESSAGE_REACHED_CITY", MESSAGE_REACHED_CITY) // 36: Population has reached 10,000.
.value("MESSAGE_REACHED_CAPITAL", MESSAGE_REACHED_CAPITAL) // 37: Population has reached 50,000.
.value("MESSAGE_REACHED_METROPOLIS", MESSAGE_REACHED_METROPOLIS) // 38: Population has reached 100,000.
.value("MESSAGE_REACHED_MEGALOPOLIS", MESSAGE_REACHED_MEGALOPOLIS) // 39: Population has reached 500,000.
.value("MESSAGE_NOT_ENOUGH_POWER", MESSAGE_NOT_ENOUGH_POWER) // 40: Brownouts, build another Power Plant.
.value("MESSAGE_HEAVY_TRAFFIC", MESSAGE_HEAVY_TRAFFIC) // 41: Heavy Traffic reported.
.value("MESSAGE_FLOODING_REPORTED", MESSAGE_FLOODING_REPORTED) // 42: Flooding reported!!
.value("MESSAGE_NUCLEAR_MELTDOWN", MESSAGE_NUCLEAR_MELTDOWN) // 43: A Nuclear Meltdown has occurred!!!
.value("MESSAGE_RIOTS_REPORTED", MESSAGE_RIOTS_REPORTED) // 44: They're rioting in the streets!!
.value("MESSAGE_STARTED_NEW_CITY", MESSAGE_STARTED_NEW_CITY) // 45: Started a New City.
.value("MESSAGE_LOADED_SAVED_CITY", MESSAGE_LOADED_SAVED_CITY) // 46: Restored a Saved City.
.value("MESSAGE_SCENARIO_WON", MESSAGE_SCENARIO_WON) // 47: You won the scenario.
.value("MESSAGE_SCENARIO_LOST", MESSAGE_SCENARIO_LOST) // 48: You lose the scenario.
.value("MESSAGE_ABOUT_MICROPOLIS", MESSAGE_ABOUT_MICROPOLIS) // 49: About Micropolis.
.value("MESSAGE_SCENARIO_DULLSVILLE", MESSAGE_SCENARIO_DULLSVILLE) // 50: Dullsville scenario.
.value("MESSAGE_SCENARIO_SAN_FRANCISCO", MESSAGE_SCENARIO_SAN_FRANCISCO) // 51: San Francisco scenario.
.value("MESSAGE_SCENARIO_HAMBURG", MESSAGE_SCENARIO_HAMBURG) // 52: Hamburg scenario.
.value("MESSAGE_SCENARIO_BERN", MESSAGE_SCENARIO_BERN) // 53: Bern scenario.
.value("MESSAGE_SCENARIO_TOKYO", MESSAGE_SCENARIO_TOKYO) // 54: Tokyo scenario.
.value("MESSAGE_SCENARIO_DETROIT", MESSAGE_SCENARIO_DETROIT) // 55: Detroit scenario.
.value("MESSAGE_SCENARIO_BOSTON", MESSAGE_SCENARIO_BOSTON) // 56: Boston scenario.
.value("MESSAGE_SCENARIO_RIO_DE_JANEIRO", MESSAGE_SCENARIO_RIO_DE_JANEIRO) // 57: Rio de Janeiro scenario.
.value("MESSAGE_LAST", MESSAGE_LAST) // 57: Last valid message
;
// frontendmessage.h TODO
// The FrontendMessage class is defined as an abstract base class with pure_virtual()
// for the sendMessage method.
// FrontendMessageDidTool and FrontendMessageMakeSound are bound as subclasses of FrontendMessage.
// The allow_subclass method is used to register them as valid subclasses.
// Constructors and properties are exposed for FrontendMessageDidTool and
// FrontendMessageMakeSound to create instances and access their members in JavaScript.
/*
class_<FrontendMessage>("FrontendMessage")
.smart_ptr<std::shared_ptr<FrontendMessage>>("shared_ptr<FrontendMessage>")
.allow_subclass<FrontendMessageDidTool>("FrontendMessageDidTool")
.allow_subclass<FrontendMessageMakeSound>("FrontendMessageMakeSound")
.function("sendMessage", &FrontendMessage::sendMessage, pure_virtual())
;
class_<FrontendMessageDidTool, base<FrontendMessage>>("FrontendMessageDidTool")
.constructor<const char*, int, int>()
.property("tool", &FrontendMessageDidTool::tool)
.property("x", &FrontendMessageDidTool::x)
.property("y", &FrontendMessageDidTool::y)
;
class_<FrontendMessageMakeSound, base<FrontendMessage>>("FrontendMessageMakeSound")
.constructor<const char*, const char*, int, int>()
.property("channel", &FrontendMessageMakeSound::channel)
.property("sound", &FrontendMessageMakeSound::sound)
.property("x", &FrontendMessageMakeSound::x)
.property("y", &FrontendMessageMakeSound::y)
;
*/
// micropolis.h
constant("WORLD_W", WORLD_W);
constant("WORLD_H", WORLD_H);
constant("BITS_PER_TILE", BITS_PER_TILE);
constant("BYTES_PER_TILE", BYTES_PER_TILE);
constant("WORLD_W_2", WORLD_W_2);
constant("WORLD_H_2", WORLD_H_2);
constant("WORLD_W_4", WORLD_W_4);
constant("WORLD_H_4", WORLD_H_4);
constant("WORLD_W_8", WORLD_W_8);
constant("WORLD_H_8", WORLD_H_8);
constant("EDITOR_TILE_SIZE", EDITOR_TILE_SIZE);
constant("PASSES_PER_CITYTIME", PASSES_PER_CITYTIME);
constant("CITYTIMES_PER_MONTH", CITYTIMES_PER_MONTH);
constant("CITYTIMES_PER_YEAR", CITYTIMES_PER_YEAR);
constant("HISTORY_LENGTH", HISTORY_LENGTH);
constant("MISC_HISTORY_LENGTH", MISC_HISTORY_LENGTH);
constant("HISTORY_COUNT", HISTORY_COUNT);
constant("POWER_STACK_SIZE", POWER_STACK_SIZE);
constant("NOWHERE", NOWHERE);
constant("ISLAND_RADIUS", ISLAND_RADIUS);
constant("MAX_TRAFFIC_DISTANCE", MAX_TRAFFIC_DISTANCE);
constant("MAX_ROAD_EFFECT", MAX_ROAD_EFFECT);
constant("MAX_POLICE_STATION_EFFECT", MAX_POLICE_STATION_EFFECT);
constant("MAX_FIRE_STATION_EFFECT", MAX_FIRE_STATION_EFFECT);
constant("RES_VALVE_RANGE", RES_VALVE_RANGE);
constant("COM_VALVE_RANGE", COM_VALVE_RANGE);
constant("IND_VALVE_RANGE", IND_VALVE_RANGE);
emscripten::enum_<HistoryType>("HistoryType")
.value("HISTORY_TYPE_RES", HISTORY_TYPE_RES)
.value("HISTORY_TYPE_COM", HISTORY_TYPE_COM)
.value("HISTORY_TYPE_IND", HISTORY_TYPE_IND)
.value("HISTORY_TYPE_MONEY", HISTORY_TYPE_MONEY)
.value("HISTORY_TYPE_CRIME", HISTORY_TYPE_CRIME)
.value("HISTORY_TYPE_POLLUTION", HISTORY_TYPE_POLLUTION)
.value("HISTORY_TYPE_COUNT", HISTORY_TYPE_COUNT)
;
// HistoryScale
emscripten::enum_<HistoryScale>("HistoryScale")
.value("HISTORY_SCALE_SHORT", HISTORY_SCALE_SHORT)
.value("HISTORY_SCALE_LONG", HISTORY_SCALE_LONG)
.value("HISTORY_SCALE_COUNT", HISTORY_SCALE_COUNT)
;
// MapType
emscripten::enum_<MapType>("MapType")
.value("MAP_TYPE_ALL", MAP_TYPE_ALL)
.value("MAP_TYPE_RES", MAP_TYPE_RES)
.value("MAP_TYPE_COM", MAP_TYPE_COM)
.value("MAP_TYPE_IND", MAP_TYPE_IND)
.value("MAP_TYPE_POWER", MAP_TYPE_POWER)
.value("MAP_TYPE_ROAD", MAP_TYPE_ROAD)
.value("MAP_TYPE_POPULATION_DENSITY", MAP_TYPE_POPULATION_DENSITY)
.value("MAP_TYPE_RATE_OF_GROWTH", MAP_TYPE_RATE_OF_GROWTH)
.value("MAP_TYPE_TRAFFIC_DENSITY", MAP_TYPE_TRAFFIC_DENSITY)
.value("MAP_TYPE_POLLUTION", MAP_TYPE_POLLUTION)
.value("MAP_TYPE_CRIME", MAP_TYPE_CRIME)
.value("MAP_TYPE_LAND_VALUE", MAP_TYPE_LAND_VALUE)
.value("MAP_TYPE_FIRE_RADIUS", MAP_TYPE_FIRE_RADIUS)
.value("MAP_TYPE_POLICE_RADIUS", MAP_TYPE_POLICE_RADIUS)
.value("MAP_TYPE_DYNAMIC", MAP_TYPE_DYNAMIC)
.value("MAP_TYPE_COUNT", MAP_TYPE_COUNT)
;
// SpriteType
emscripten::enum_<SpriteType>("SpriteType")
.value("SPRITE_NOTUSED", SPRITE_NOTUSED)
.value("SPRITE_TRAIN", SPRITE_TRAIN)
.value("SPRITE_HELICOPTER", SPRITE_HELICOPTER)
.value("SPRITE_AIRPLANE", SPRITE_AIRPLANE)
.value("SPRITE_SHIP", SPRITE_SHIP)
.value("SPRITE_MONSTER", SPRITE_MONSTER)
.value("SPRITE_TORNADO", SPRITE_TORNADO)
.value("SPRITE_EXPLOSION", SPRITE_EXPLOSION)
.value("SPRITE_BUS", SPRITE_BUS)
.value("SPRITE_COUNT", SPRITE_COUNT)
;
// ConnectTileCommand
emscripten::enum_<ConnectTileCommand>("ConnectTileCommand")
.value("CONNECT_TILE_FIX", CONNECT_TILE_FIX)
.value("CONNECT_TILE_BULLDOZE", CONNECT_TILE_BULLDOZE)
.value("CONNECT_TILE_ROAD", CONNECT_TILE_ROAD)
.value("CONNECT_TILE_RAILROAD", CONNECT_TILE_RAILROAD)
.value("CONNECT_TILE_WIRE", CONNECT_TILE_WIRE)
;
// ToolResult
emscripten::enum_<ToolResult>("ToolResult")
.value("TOOLRESULT_NO_MONEY", TOOLRESULT_NO_MONEY)
.value("TOOLRESULT_NEED_BULLDOZE", TOOLRESULT_NEED_BULLDOZE)
.value("TOOLRESULT_FAILED", TOOLRESULT_FAILED)
.value("TOOLRESULT_OK", TOOLRESULT_OK)
;
// Scenario
emscripten::enum_<Scenario>("Scenario")
.value("SC_NONE", SC_NONE)
.value("SC_DULLSVILLE", SC_DULLSVILLE)
.value("SC_SAN_FRANCISCO", SC_SAN_FRANCISCO)
.value("SC_HAMBURG", SC_HAMBURG)
.value("SC_BERN", SC_BERN)
.value("SC_TOKYO", SC_TOKYO)
.value("SC_DETROIT", SC_DETROIT)
.value("SC_BOSTON", SC_BOSTON)
.value("SC_RIO", SC_RIO)
.value("SC_COUNT", SC_COUNT)
;
// ZoneType
emscripten::enum_<ZoneType>("ZoneType")
.value("ZT_COMMERCIAL", ZT_COMMERCIAL)
.value("ZT_INDUSTRIAL", ZT_INDUSTRIAL)
.value("ZT_RESIDENTIAL", ZT_RESIDENTIAL)
.value("ZT_NUM_DESTINATIONS", ZT_NUM_DESTINATIONS)
;
// CityVotingProblems
emscripten::enum_<CityVotingProblems>("CityVotingProblems")
.value("CVP_CRIME", CVP_CRIME)
.value("CVP_POLLUTION", CVP_POLLUTION)
.value("CVP_HOUSING", CVP_HOUSING)
.value("CVP_TAXES", CVP_TAXES)
.value("CVP_TRAFFIC", CVP_TRAFFIC)
.value("CVP_UNEMPLOYMENT", CVP_UNEMPLOYMENT)
.value("CVP_FIRE", CVP_FIRE)
.value("CVP_NUMPROBLEMS", CVP_NUMPROBLEMS)
.value("CVP_PROBLEM_COMPLAINTS", CVP_PROBLEM_COMPLAINTS)
.value("PROBNUM", PROBNUM)
;
// CityClass
emscripten::enum_<CityClass>("CityClass")
.value("CC_VILLAGE", CC_VILLAGE)
.value("CC_TOWN", CC_TOWN)
.value("CC_CITY", CC_CITY)
.value("CC_CAPITAL", CC_CAPITAL)
.value("CC_METROPOLIS", CC_METROPOLIS)
.value("CC_MEGALOPOLIS", CC_MEGALOPOLIS)
.value("CC_NUM_CITIES", CC_NUM_CITIES)
;
// GameLevel
emscripten::enum_<GameLevel>("GameLevel")
.value("LEVEL_EASY", LEVEL_EASY)
.value("LEVEL_MEDIUM", LEVEL_MEDIUM)
.value("LEVEL_HARD", LEVEL_HARD)
.value("LEVEL_COUNT", LEVEL_COUNT)
.value("LEVEL_FIRST", LEVEL_FIRST)
.value("LEVEL_LAST", LEVEL_LAST)
;
emscripten::enum_<Tiles>("Tiles")
.value("DIRT", DIRT) // 0: Clear tile
// tile 1 ?
// Water:
.value("RIVER", RIVER) // 2
.value("REDGE", REDGE) // 3
.value("CHANNEL", CHANNEL) // 4
.value("FIRSTRIVEDGE", FIRSTRIVEDGE) // 5
// tile 6 -- 19 ?
.value("LASTRIVEDGE", LASTRIVEDGE) // 20
.value("WATER_LOW", WATER_LOW) // 2 (RIVER): First water tile
.value("WATER_HIGH", WATER_HIGH) // 20 (LASTRIVEDGE): Last water tile (inclusive)
.value("TREEBASE", TREEBASE) // 21
.value("WOODS_LOW", WOODS_LOW) // 21 (TREEBASE)
.value("LASTTREE", LASTTREE) // 36
.value("WOODS", WOODS) // 37
.value("UNUSED_TRASH1", UNUSED_TRASH1) // 38
.value("UNUSED_TRASH2", UNUSED_TRASH2) // 39
.value("WOODS_HIGH", WOODS_HIGH) // 39 (UNUSED_TRASH2): Why is an 'UNUSED' tile used?
.value("WOODS2", WOODS2) // 40
.value("WOODS3", WOODS3) // 41
.value("WOODS4", WOODS4) // 42
.value("WOODS5", WOODS5) // 43
// Rubble (4 tiles)
.value("RUBBLE", RUBBLE) // 44
.value("LASTRUBBLE", LASTRUBBLE) // 47
.value("FLOOD", FLOOD) // 48
// tile 49, 50 ?
.value("LASTFLOOD", LASTFLOOD) // 51
.value("RADTILE", RADTILE) // 52: Radio-active contaminated tile
.value("UNUSED_TRASH3", UNUSED_TRASH3) // 53
.value("UNUSED_TRASH4", UNUSED_TRASH4) // 54
.value("UNUSED_TRASH5", UNUSED_TRASH5) // 55
// Fire animation (8 tiles)
.value("FIRE", FIRE) // 56
.value("FIREBASE", FIREBASE) // 56 (FIRE)
.value("LASTFIRE", LASTFIRE) // 63
.value("HBRIDGE", HBRIDGE) // 64: Horizontal bridge
.value("ROADBASE", ROADBASE) // 64 (HBRIDGE)
.value("VBRIDGE", VBRIDGE) // 65: Vertical bridge
.value("ROADS", ROADS) // 66
.value("ROADS2", ROADS2) // 67
.value("ROADS3", ROADS3) // 68
.value("ROADS4", ROADS4) // 69
.value("ROADS5", ROADS5) // 70
.value("ROADS6", ROADS6) // 71
.value("ROADS7", ROADS7) // 72
.value("ROADS8", ROADS8) // 73
.value("ROADS9", ROADS9) // 74
.value("ROADS10", ROADS10) // 75
.value("INTERSECTION", INTERSECTION) // 76
.value("HROADPOWER", HROADPOWER) // 77
.value("VROADPOWER", VROADPOWER) // 78
.value("BRWH", BRWH) // 79
.value("LTRFBASE", LTRFBASE) // 80: First tile with low traffic
// tile 81 -- 94 ?
.value("BRWV", BRWV) // 95
// tile 96 -- 110 ?
.value("BRWXXX1", BRWXXX1) // 111
// tile 96 -- 110 ?
.value("BRWXXX2", BRWXXX2) // 127
// tile 96 -- 110 ?
.value("BRWXXX3", BRWXXX3) // 143
.value("HTRFBASE", HTRFBASE) // 144: First tile with high traffic
// tile 145 -- 158 ?
.value("BRWXXX4", BRWXXX4) // 159
// tile 160 -- 174 ?
.value("BRWXXX5", BRWXXX5) // 175
// tile 176 -- 190 ?
.value("BRWXXX6", BRWXXX6) // 191
// tile 192 -- 205 ?
.value("LASTROAD", LASTROAD) // 206
.value("BRWXXX7", BRWXXX7) // 207
// Power lines
.value("HPOWER", HPOWER) // 208
.value("VPOWER", VPOWER) // 209
.value("LHPOWER", LHPOWER) // 210
.value("LVPOWER", LVPOWER) // 211
.value("LVPOWER2", LVPOWER2) // 212
.value("LVPOWER3", LVPOWER3) // 213
.value("LVPOWER4", LVPOWER4) // 214
.value("LVPOWER5", LVPOWER5) // 215
.value("LVPOWER6", LVPOWER6) // 216
.value("LVPOWER7", LVPOWER7) // 217
.value("LVPOWER8", LVPOWER8) // 218
.value("LVPOWER9", LVPOWER9) // 219
.value("LVPOWER10", LVPOWER10) // 220
.value("RAILHPOWERV", RAILHPOWERV) // 221: Horizontal rail, vertical power
.value("RAILVPOWERH", RAILVPOWERH) // 222: Vertical rail, horizontal power
.value("POWERBASE", POWERBASE) // 208 (HPOWER)
.value("LASTPOWER", LASTPOWER) // 222 (RAILVPOWERH)
.value("UNUSED_TRASH6", UNUSED_TRASH6) // 223
// Rail
.value("HRAIL", HRAIL) // 224
.value("VRAIL", VRAIL) // 225
.value("LHRAIL", LHRAIL) // 226
.value("LVRAIL", LVRAIL) // 227
.value("LVRAIL2", LVRAIL2) // 228
.value("LVRAIL3", LVRAIL3) // 229
.value("LVRAIL4", LVRAIL4) // 230
.value("LVRAIL5", LVRAIL5) // 231
.value("LVRAIL6", LVRAIL6) // 232
.value("LVRAIL7", LVRAIL7) // 233
.value("LVRAIL8", LVRAIL8) // 234
.value("LVRAIL9", LVRAIL9) // 235
.value("LVRAIL10", LVRAIL10) // 236
.value("HRAILROAD", HRAILROAD) // 237
.value("VRAILROAD", VRAILROAD) // 238
.value("RAILBASE", RAILBASE) // 224 (HRAIL)
.value("LASTRAIL", LASTRAIL) // 238 (VRAILROAD)
.value("ROADVPOWERH", ROADVPOWERH) // 239: bogus?
// Residential zone tiles
.value("RESBASE", RESBASE) // 240: Empty residential, tiles 240--248
.value("FREEZ", FREEZ) // 244: center-tile of 3x3 empty residential
.value("HOUSE", HOUSE) // 249: Single tile houses until 260
.value("LHTHR", LHTHR) // 249 (HOUSE)
.value("HHTHR", HHTHR) // 260
.value("RZB", RZB) // 265: center tile first 3x3 tile residential
.value("HOSPITALBASE", HOSPITALBASE) // 405: Center of hospital (tiles 405--413)
.value("HOSPITAL", HOSPITAL) // 409: Center of hospital (tiles 405--413)
.value("CHURCHBASE", CHURCHBASE) // 414: Center of church (tiles 414--422)
.value("CHURCH0BASE", CHURCH0BASE) // 414 (CHURCHBASE): numbered alias
.value("CHURCH", CHURCH) // 418: Center of church (tiles 414--422)
.value("CHURCH0", CHURCH0) // 418 (CHURCH): numbered alias
// Commercial zone tiles
.value("COMBASE", COMBASE) // 423: Empty commercial, tiles 423--431
// tile 424 -- 426 ?
.value("COMCLR", COMCLR) // 427
// tile 428 -- 435 ?
.value("CZB", CZB) // 436
// tile 437 -- 608 ?
.value("COMLAST", COMLAST) // 609
// tile 610, 611 ?
// Industrial zone tiles.
.value("INDBASE", INDBASE) // 612: Top-left tile of empty industrial zone.
.value("INDCLR", INDCLR) // 616: Center tile of empty industrial zone.
.value("LASTIND", LASTIND) // 620: Last tile of empty industrial zone.
// Industrial zone population 0, value 0: 621 -- 629
.value("IND1", IND1) // 621: Top-left tile of first non-empty industry zone.
.value("IZB", 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
.value("IND2", IND2) // 641
.value("IND3", IND3) // 644
// Industrial zone population 3, value 0: 648 -- 656
.value("IND4", IND4) // 649
.value("IND5", 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
.value("IND6", IND6) // 676
.value("IND7", IND7) // 677
// Industrial zone population 3, value 1: 684 -- 692
.value("IND8", IND8) // 686
.value("IND9", IND9) // 689
// Seaport
.value("PORTBASE", PORTBASE) // 693: Top-left tile of the seaport.
.value("PORT", PORT) // 698: Center tile of the seaport.
.value("LASTPORT", LASTPORT) // 708: Last tile of the seaport.
.value("AIRPORTBASE", AIRPORTBASE) // 709
// tile 710 ?
.value("RADAR", RADAR) // 711
// tile 712 -- 715 ?
.value("AIRPORT", AIRPORT) // 716
// tile 717 -- 744 ?
// Coal power plant (4x4).
.value("COALBASE", COALBASE) // 745: First tile of coal power plant.
.value("POWERPLANT", POWERPLANT) // 750: 'Center' tile of coal power plant.
.value("LASTPOWERPLANT", LASTPOWERPLANT) // 760: Last tile of coal power plant.
// Fire station (3x3).
.value("FIRESTBASE", FIRESTBASE) // 761: First tile of fire station.
.value("FIRESTATION", FIRESTATION) // 765: 'Center tile' of fire station.
// 769 last tile fire station.
.value("POLICESTBASE", POLICESTBASE) // 770
// tile 771 -- 773 ?
.value("POLICESTATION", POLICESTATION) // 774
// tile 775 -- 778 ?
// Stadium (4x4).
.value("STADIUMBASE", STADIUMBASE) // 779: First tile stadium.
.value("STADIUM", STADIUM) // 784: 'Center tile' stadium.
// Last tile stadium 794.
// tile 785 -- 799 ?
.value("FULLSTADIUM", FULLSTADIUM) // 800
// tile 801 -- 810 ?
// Nuclear power plant (4x4).
.value("NUCLEARBASE", NUCLEARBASE) // 811: First tile nuclear power plant.
.value("NUCLEAR", NUCLEAR) // 816: 'Center' tile nuclear power plant.
.value("LASTZONE", LASTZONE) // 826: Also last tile nuclear power plant.
.value("LIGHTNINGBOLT", LIGHTNINGBOLT) // 827
.value("HBRDG0", HBRDG0) // 828
.value("HBRDG1", HBRDG1) // 829
.value("HBRDG2", HBRDG2) // 830
.value("HBRDG3", HBRDG3) // 831
.value("HBRDG_END", HBRDG_END) // 832
.value("RADAR0", RADAR0) // 832
.value("RADAR1", RADAR1) // 833
.value("RADAR2", RADAR2) // 834
.value("RADAR3", RADAR3) // 835
.value("RADAR4", RADAR4) // 836
.value("RADAR5", RADAR5) // 837
.value("RADAR6", RADAR6) // 838
.value("RADAR7", RADAR7) // 839
.value("FOUNTAIN", FOUNTAIN) // 840
// tile 841 -- 843: fountain animation.
.value("INDBASE2", INDBASE2) // 844
.value("TELEBASE", TELEBASE) // 844 (INDBASE2)
// tile 845 -- 850 ?
.value("TELELAST", TELELAST) // 851
.value("SMOKEBASE", SMOKEBASE) // 852
// tile 853 -- 859 ?
.value("TINYEXP", TINYEXP) // 860
// tile 861 -- 863 ?
.value("SOMETINYEXP", SOMETINYEXP) // 864
// tile 865 -- 866 ?
.value("LASTTINYEXP", LASTTINYEXP) // 867
// tile 868 -- 882 ?
.value("TINYEXPLAST", TINYEXPLAST) // 883
// tile 884 -- 915 ?
.value("COALSMOKE1", COALSMOKE1) // 916: Chimney animation at coal power plant (2, 0).
// 919 last animation tile for chimney at coal power plant (2, 0).
.value("COALSMOKE2", COALSMOKE2) // 920: Chimney animation at coal power plant (3, 0).
// 923 last animation tile for chimney at coal power plant (3, 0).
.value("COALSMOKE3", COALSMOKE3) // 924: Chimney animation at coal power plant (2, 1).
// 927 last animation tile for chimney at coal power plant (2, 1).
.value("COALSMOKE4", COALSMOKE4) // 928: Chimney animation at coal power plant (3, 1).
// 931 last animation tile for chimney at coal power plant (3, 1).
.value("FOOTBALLGAME1", FOOTBALLGAME1) // 932
// tile 933 -- 939 ?
.value("FOOTBALLGAME2", FOOTBALLGAME2) // 940
// tile 941 -- 947 ?
.value("VBRDG0", VBRDG0) // 948
.value("VBRDG1", VBRDG1) // 949
.value("VBRDG2", VBRDG2) // 950
.value("VBRDG3", VBRDG3) // 951
.value("NUKESWIRL1", NUKESWIRL1) // 952
.value("NUKESWIRL2", NUKESWIRL2) // 953
.value("NUKESWIRL3", NUKESWIRL3) // 954
.value("NUKESWIRL4", NUKESWIRL4) // 955
// Tiles 956-959 unused (originally)
// TILE_COUNT = 960,
// Extended zones: 956-1019
.value("CHURCH1BASE", CHURCH1BASE) // 956
.value("CHURCH1", CHURCH1) // 960
.value("CHURCH1BASE", CHURCH1BASE) // 956
.value("CHURCH1", CHURCH1) // 960
.value("CHURCH2BASE", CHURCH2BASE) // 965
.value("CHURCH2", CHURCH2) // 969
.value("CHURCH3BASE", CHURCH3BASE) // 974
.value("CHURCH3", CHURCH3) // 978
.value("CHURCH4BASE", CHURCH4BASE) // 983
.value("CHURCH4", CHURCH4) // 987
.value("CHURCH5BASE", CHURCH5BASE) // 992
.value("CHURCH5", CHURCH5) // 996
.value("CHURCH6BASE", CHURCH6BASE) // 1001
.value("CHURCH6", CHURCH6) // 1005
.value("CHURCH7BASE", CHURCH7BASE) // 1010
.value("CHURCH7", CHURCH7) // 1014
.value("CHURCH7LAST", CHURCH7LAST) // 1018
// Tiles 1020-1023 unused
.value("TILE_COUNT", TILE_COUNT) // 1024
.value("TILE_INVALID", TILE_INVALID) // -1, Invalid tile (not used in the world map).
;
class_<SimSprite>("SimSprite")
.property("name", &SimSprite::name)
.property("type", &SimSprite::type)
.property("frame", &SimSprite::frame)
.property("x", &SimSprite::x)
.property("y", &SimSprite::y)
.property("width", &SimSprite::width)
.property("height", &SimSprite::height)
.property("xOffset", &SimSprite::xOffset)
.property("yOffset", &SimSprite::yOffset)
.property("xHot", &SimSprite::xHot)
.property("yHot", &SimSprite::yHot)
.property("origX", &SimSprite::origX)
.property("origY", &SimSprite::origY)
.property("destX", &SimSprite::destX)
.property("destY", &SimSprite::destY)
.property("count", &SimSprite::count)
.property("soundCount", &SimSprite::soundCount)
.property("dir", &SimSprite::dir)
.property("newDir", &SimSprite::newDir)
.property("step", &SimSprite::step)
.property("flag", &SimSprite::flag)
.property("control", &SimSprite::control)
.property("turn", &SimSprite::turn)
.property("accel", &SimSprite::accel)
.property("speed", &SimSprite::speed)
;
class_<Micropolis>("Micropolis")
.constructor<>()
// Simulation Control and Settings
.function("simTick", &Micropolis::simTick)
.function("setSpeed", &Micropolis::setSpeed)
.function("setGameLevel", &Micropolis::setGameLevel)
.function("setCityName", &Micropolis::setCityName)
.function("setYear", &Micropolis::setYear)
.function("pause", &Micropolis::pause)
.function("resume", &Micropolis::resume)
.function("setEnableDisasters", &Micropolis::setEnableDisasters)
.function("setAutoBudget", &Micropolis::setAutoBudget)
.function("setAutoBulldoze", &Micropolis::setAutoBulldoze)
.function("setAutoGoto", &Micropolis::setAutoGoto)
.function("setEnableSound", &Micropolis::setEnableSound)
.function("setDoAnimation", &Micropolis::setDoAnimation)
.function("doNewGame", &Micropolis::doNewGame)
.function("doBudget", &Micropolis::doBudget)
.function("doScoreCard", &Micropolis::doScoreCard)
.function("updateFunds", &Micropolis::updateFunds)
// Game State and Statistics
.property("simSpeed", &Micropolis::simSpeed)
.property("simSpeedMeta", &Micropolis::simSpeedMeta)
.property("simPaused", &Micropolis::simPaused)
.property("disasterEvent", &Micropolis::disasterEvent)
.property("disasterWait", &Micropolis::disasterWait)
.property("scenario", &Micropolis::scenario)
.property("heatSteps", &Micropolis::heatSteps)
.property("heatFlow", &Micropolis::heatFlow)
.property("heatRule", &Micropolis::heatRule)
.property("heatWrap", &Micropolis::heatWrap)
.property("totalFunds", &Micropolis::totalFunds)
.property("cityPop", &Micropolis::cityPop)
.property("cityTime", &Micropolis::cityTime)
.property("cityYear", &Micropolis::cityYear)
.property("cityMonth", &Micropolis::cityMonth)
.property("cityYes", &Micropolis::cityYes)
.property("cityScore", &Micropolis::cityScore)
.property("cityClass", &Micropolis::cityClass)
.property("gameLevel", &Micropolis::gameLevel)
.property("mapSerial", &Micropolis::mapSerial)
.property("trafficAverage", &Micropolis::trafficAverage)
.property("pollutionAverage", &Micropolis::pollutionAverage)
.property("crimeAverage", &Micropolis::crimeAverage)
.property("landValueAverage", &Micropolis::landValueAverage)
.property("startingYear", &Micropolis::startingYear)
.property("generatedCitySeed", &Micropolis::generatedCitySeed)
.property("cityPopDelta", &Micropolis::cityPopDelta)
.property("cityAssessedValue", &Micropolis::cityAssessedValue)
.property("cityScoreDelta", &Micropolis::cityScoreDelta)
.property("trafficAverage", &Micropolis::trafficAverage)
.property("pollutionAverage", &Micropolis::pollutionAverage)
.property("crimeAverage", &Micropolis::crimeAverage)
.property("totalPop", &Micropolis::totalPop)
.property("totalZonePop", &Micropolis::totalZonePop)
.property("hospitalPop", &Micropolis::hospitalPop)
.property("churchPop", &Micropolis::churchPop)
.property("stadiumPop", &Micropolis::stadiumPop)
.property("coalPowerPop", &Micropolis::coalPowerPop)
.property("nuclearPowerPop", &Micropolis::nuclearPowerPop)
// Resource Management
.property("roadTotal", &Micropolis::roadTotal)
.property("railTotal", &Micropolis::railTotal)
.property("resPop", &Micropolis::resPop)
.property("comPop", &Micropolis::comPop)
.property("indPop", &Micropolis::indPop)
.property("policeStationPop", &Micropolis::policeStationPop)
.property("fireStationPop", &Micropolis::fireStationPop)
.property("seaportPop", &Micropolis::seaportPop)
.property("airportPop", &Micropolis::airportPop)
.property("cashFlow", &Micropolis::cashFlow)
.property("cityTax", &Micropolis::cityTax)
.property("roadEffect", &Micropolis::roadEffect)
.property("policeEffect", &Micropolis::policeEffect)
.property("fireEffect", &Micropolis::fireEffect)
// User Interface and Preferences
.property("autoGoto", &Micropolis::autoGoto)
.property("autoBudget", &Micropolis::autoBudget)
.property("autoBulldoze", &Micropolis::autoBulldoze)
.property("enableSound", &Micropolis::enableSound)
.property("enableDisasters", &Micropolis::enableDisasters)
.property("doAnimation", &Micropolis::doAnimation)
.property("doMessages", &Micropolis::doMessages)
.property("doNotices", &Micropolis::doNotices)
// Gameplay Mechanics
.property("cityFileName", &Micropolis::cityFileName)
.property("cityName", &Micropolis::cityName)
.function("doTool", &Micropolis::doTool)
.function("generateMap", &Micropolis::generateMap)
.function("clearMap", &Micropolis::clearMap)
//.function("getDemands", &Micropolis::getDemands, allow_raw_pointers()) // TODO: wrap
// Random Number Generation
.function("simRandom", &Micropolis::simRandom)
.function("getRandom", &Micropolis::getRandom)
.function("getRandom16", &Micropolis::getRandom16)
.function("getRandom16Signed", &Micropolis::getRandom16Signed)
.function("getERandom", &Micropolis::getERandom)
.function("randomlySeedRandom", &Micropolis::randomlySeedRandom)
.function("seedRandom", &Micropolis::seedRandom)
// Game State and Data Access
.function("getTile", &Micropolis::getTile)
.function("setTile", &Micropolis::setTile)
.function("setFunds", &Micropolis::setFunds)
.function("updateMaps", &Micropolis::updateMaps)
.function("updateGraphs", &Micropolis::updateGraphs)
.function("updateEvaluation", &Micropolis::updateEvaluation)
.function("updateBudget", &Micropolis::updateBudget)
// City History Arrays
//.function("getResidentialHistory", &Micropolis::getResidentialHistory, allow_raw_pointers()) // TODO: wrap
//.function("getCommercialHistory", &Micropolis::getCommercialHistory, allow_raw_pointers()) // TODO: wrap
//.function("getIndustrialHistory", &Micropolis::getIndustrialHistory, allow_raw_pointers()) // TODO: wrap
// Events and Callbacks
.function("sendMessage", &Micropolis::sendMessage)
.function("makeSound", &Micropolis::makeSound)
;
}
////////////////////////////////////////////////////////////////////////