Skip to content

banished-game ​

The rules of Banished 1.0.7, ported to Rust: citizens and their lives, jobs and professions, construction, production, farming, trade, wildlife, the weather, and disasters. Each ported function names the original function it came from, keeps the original's order of arithmetic and its float precision, and draws random numbers in the same order. Tests compare the results with output from the original functions in the emulator, and with real save files.

The crate has no graphics, windows or sound, and it is deterministic: the same inputs and the same seed always give the same results. The game program (apps/game) owns the town's state and calls these rules every simulation step.

Modules ​

The modules are grouped by domain. Each folder's mod.rs says what it holds.

FolderWhat it contains
peopleCitizens: ages and lives, households, names, needs, health, happiness, services, status counters, immigration, burial
behaviourHow characters act: the citizen AI and its activities, the agents that run citizens and animals, action stacks, animation, commuting
workThe work economy: the job manager, professions, construction and demolition, production recipes, storage, building controls, roads
productionWorkplaces that gather or grow resources: quarries and mines, foresters, herbalists, hunters, fishing docks, crop fields, orchards, pastures
commerceMarkets, the trading post and the trader boats
natureResource seeding and spawning, growth, wildlife, and the environment (temperature and weather)
worldThe gameplay map and its cells, bridges, building placement, terraforming
disastersFire, crop blight, tornadoes
town.rs, town/The simulation context that jobs and construction run in (Sim), with its methods split by topic: geometry, orders, construction sites, buildings, clearing, piles, storage, the state callbacks and the job manager's work slots
events.rsThe event log and stock warnings

It also re-exports the crates it builds on, so that one dependency is enough:

PathIs the same as
banished_game::{calendar, crt, math, noise, picking, random, scheduler}the modules of banished-core
banished_game::terrainthe banished-terrain crate
banished_game::{pathfind, sectors}the modules of banished-path

Use it ​

toml
[dependencies]
banished-game = { path = "crates/game" }
banished-formats = { path = "crates/formats" }

Name a citizen ​

Names come from the game's name databases (Game/Names/Male, Female and Cities). The same seed gives the same names as the original.

rust
use banished_formats::names::NameDatabase;
use banished_formats::pkg::Archive;
use banished_game::people::names::generate;
use banished_game::random::Random;

fn three_names(archive: &Archive) -> banished_formats::Result<Vec<String>> {
    let db = NameDatabase::read(&archive.read_ref("Game/Names/Male.rsc:resource")?)?;
    let mut rng = Random::new(7);
    // A first name has 3 to 10 letters; a town name has 5 to 20.
    Ok((0..3).map(|_| generate(&db, &mut rng, 3, 10)).collect())
}

Find the start of a new town ​

world::map::Map classifies every cell of a generated terrain. find_start finds the town's start cell as the original does: in rings outward from the centre of the map, the first place where every cell within radius is buildable ground. The start condition profile gives the radius (map_generator(...).start_radius).

rust
use banished_game::terrain::{Generator, HeightGrid};
use banished_game::world::map::Map;

fn start_cell(generator: &Generator, radius: i32) -> (i32, i32) {
    let heights = generator.heights();
    let terrain = HeightGrid { width: generator.width(), heights: &heights };
    // The gameplay map is the central n × n cells of the 2n-cell terrain.
    let map = Map::new(generator.record.half_size() as usize, &terrain);
    map.find_start(radius)
}

banished-terrain shows how to make the Generator.

More ​

The rest of the crate is the simulation itself. The best way to learn it is to read the topic documents, then the module that ports the part you are interested in:

Tests ​

bash
cargo test --release -p banished-game

The unit tests run without game data. The tests in tests/ compare with emulator output or with real saves. Each one names the generator in tools/emu/ that makes its data, and skips when the data is missing. For example:

TestWhat it checks
terrain_emuEach terrain generation stage, the cell types, the mesh and the start point
savesThe terrain of real saves, regenerated from their seed and settings
names_emuCitizen and town names
astar_emu, regions_emu, sectors_emuPath finding
game_loop_emu, time_emuThe simulation step and game time
growth_emu, storage_emu, equipment_emuGrowth, storage and equipment
crt_math, transform, picking_emuThe exact maths of banished-core

Example programs ​

examples/ has helpers for animation work: clips (the clips of an animation group), pose_bones, pose_scan and skin_bounds. rng_trace_names records the random draws of name generation, for comparison with the original (see Emulate for exact numbers).

The API ​

The full API documentation is at https://tanepiper.github.io/unbanished/api/banished_game/index.html.

Un-Banished 0.4.0-99617f9 is free software under the MIT or Apache-2.0 licence. It is not affiliated with or endorsed by Shining Rock Software.