City Simulation Utility

malekithe

King
Joined
Feb 5, 2006
Messages
755
How many times have you been curious to try out a new build order or tile utilization strategy, or check the effects of chopping on early production? If you wanted to do this, the typical method was to fire up the world builder, set things up just right, and slowly click through the turns. Trying various methods was very time-consuming.

I was getting tired of this, so I decided to write my own city simulator. It's a java script utility that uses an xml datafile. There's a link to a zip file with the script and a sample datafile at the end of the post.

To jump right into it: Run "cscript /nologo CitySim.js" from a command line.

Seeing as I didn't bother with much documentation so far, I figured I'd give a quick run-through of how to use the tool and what it can do. (If you really want to know what's going on, look at the script source.)

For starters, let's look at the datafile:

There are up to 6 main nodes in a datafile. These are <Environment>, <City>, <Tiles>, <Population>, <Events>, and <Queue>.

<Environment> contains all of the commands that need to be executed before the simulator starts. This includes things like discovering appropriate technologies, or setting certain building in place. I'll talk more about the syntax of these commands later.

<City> contains the Yields for the center city square inside of a <Yields> tag. The sample sets up the city as a basic starting capital generating 2 food, 1 hammer, and 9 commerce (8 from palace).

<Tiles> contains a description of the tiles available for the city to work. Each <Tile> needs an <ID> tag that you will use to reference that tile in the rest of the file. You also need to specify a <Type> from this list: Grassland, Plains, Ocean, Coast, Tundra, FloodPlains, or Other (any tile with no yield). There are also Feature keys that are limited to <Hill>, <Forest>, <Jungle>, and <River>. You can also add pre-built improvements with an <Improvement> tag. To add a Bonus (Resource) to a tile, use the <Bonus> tag. To see all of this in use, see the sample.

<Population> contains a couple of tags. <StartingPop> and <EndingPop> set the population to start city growth at and what population to stop growing at (turn on avoid growth). EndingPop can be modified through events later. Then, there should be a <Pop#> tag for every point of population growth. These are commands (more about commands later) that are executed as soon as the appropriate population is reached. Mostly, these will be limited to <Start> and <Stop> commands which alter the tiles currently being worked.

<Events> contains a list of events that are to be triggered over the course of the simulation. Each <Event> can have an id specified as an attribute (<Event ID="myEvent">). This ID allows you to reference the event in other events. An event is essentially a command that is executed after a particular criteria is met. The criteria is specified in one of 4 tags <Turns>, <Pop>, <Hammers>, or <Commerce> (<Hammers>70</Hammers> will execute the command after 70 hammers have accrued). There can also be a <Link> tag containing another event ID. This will essentially say, I want this event to occur after the linked event. The simulator will wait until your criteria has lapsed, treating the linked event as the base (<Link>myEvent</Link> <Hammers>70</Hammers> will wait until 70 hammers have accrued SINCE the linked event. There also needs to be a command tag in each event.

<Queue> contains the build queue you want to work on over the course of the simulation. Basically, the name of the tag is whatever you want to build (<Granary ID="myGranary">90</Granary> builds a granary). You can specify an ID for the items so that they can be linked by events. You can also specify the cost of the item, in case you're building something the simulator doesn't know the cost of (fairly likely right now).

Commands

Commands are what really drive the simulator. The syntax of a command, in general, looks like this <Name Tile="tileID">Data</Name>. Some commands will have both a tileID and Data, others will only have one or the other (all have a Name). They give instructions to the simulator to do something to some tile using some data. I'll describe them all below.

<Start Tile="ID">: Start working on a Tile
<Stop Tile="ID">: Stops working on a Tile
<Improve Tile="ID">Data: Adds the improvement 'Data' to a tile
<Set>Data: Sets the global setting 'Data' to true
<Clear>Data: Sets the global setting 'Data' to false
<Chop Tile="ID">Data: Chops a forest or jungle in the tile; 'data' should be the distance to the tile, the tile id is optional
<Max>Data: Sets the maximum allowed population to 'Data'
<HammerBonus>Data: Sets the Production bonus multiplier (Forge would use 0.25)
<CommerceBonus>Data: Sets the Commerce bonus multiplier
<BenchMark>Data: A no-op that simply insert 'data' into the summary

There's quite a few more lists I could make, but I'll restrain myself and get into the running of the utility.

To run it, copy it (and the datafile) to your computer and open a command prompt to the location where you put it. Then, type "cscript /nologo CitySim.js". That will most likely output a lot of data that looks something like this:

Code:
Turn, Population, FoodBank, Hammers, Commerce
1 , 1, 0, 7, 10
2 , 1, 0, 14, 20
3 , 1, 0, 21, 30
4 , 1, 0, 28, 40
5 , 1, 0, 35, 50
6 , 1, 0, 42, 60
7 , 1, 0, 49, 70
8 , 1, 0, 56, 80
9 , 1, 0, 63, 90
10 , 1, 0, 70, 100
11 , 1, 0, 77, 110
12 , 1, 6, 78, 120
13 , 1, 12, 79, 130
14 , 1, 18, 80, 140
15 , 1, 24, 126, 150
16 , 1, 30, 127, 160
17 , 2, 3, 128, 170
18 , 2, 9, 129, 181
19 , 2, 15, 130, 192
20 , 2, 21, 131, 203
21 , 2, 27, 132, 214
.
.
.
197 , 5, 45, 1607, 3863
198 , 5, 45, 1616, 3887
199 , 5, 45, 1625, 3911
200 , 5, 45, 1634, 3935

Turn 0: Started working Tile 0
Turn 11: Worker completed
Turn 15: Chopped a Forest on Tile 5
Turn 17: Population grew to 2
Turn 17: Started working Tile 1
Turn 23: Population grew to 3
Turn 23: Started working Tile 3
Turn 23: Added Cottage to Tile 1
Turn 29: Population grew to 4
Turn 29: Started working Tile 2
Turn 36: Set Granary
Turn 36: Granary completed
Turn 38: Population grew to 5
Turn 38: Started working Tile 4
Turn 38: Added Cottage to Tile 0
Turn 118: Reached 2000 Commerce

That output (aside from the summary) is in CSV (comma seperated values) format and all ready to be loaded up in Excel. All those numbers are keeping track of your city's Population, food bank, accrued hammers, and accrued commerce each turn. The summary at the end is simply the turn that all the interesting stuff happened.

To run your own datafile for an arbitrary number of turns you'd use something like "cscript /nologo CitySim.js 100 MyConfig.xml". Note that if you specify your own datafile, you also need to specify the number of turns to simulate. (I didn't build in variable parameter order).

There's, likely, still bugs in the script. If you spot any, please do me the favor of pointing them out here so I can fix them. Also, be aware that all of the speed-sensitive elements of the script assume epic speed right now. I'll eventually implement some way to pick which speed to simulate.

Things I still need to implement:
  • Other game speeds
  • More Buildings
  • Specialists
  • Different types of commerce (beakers, gold)
  • Great person points
  • Railroads
  • Health/Happiness
  • Sanity checking for commands (worked tiles exceeding population, mine on flat land)
  • Stuff I haven't thought of yet
  • Stuff you suggest

Hope you enjoy!

EDIT: Updated to reflect forest chopping values in 1.61, and improvement from mathematics.
 

Attachments

  • CitySim.zip
    7.8 KB · Views: 42
Good job :goodjob: dude. It's cool if I can see the projection of my cities.
 
Top Bottom