Road

Road tile variants
Road variants
Plaza tile variants
Plaza variants

The Road is the foundation of city logistics. Every building that spawns walkers — service providers, traders, priests, tax collectors — requires road access, and all walkers travel exclusively on roads.

Roads are draggable: click and drag to lay a chain of tiles at once. The game auto-routes the cheapest path between the start and end tile. Roads placed in high-desirability areas or near fountains automatically display a paved stone appearance. Placing a Plaza tile on an existing road gives a permanent decorative upgrade and a small desirability bonus.

A companion building, the Roadblock, is placed on any road tile to control which categories of roaming walkers are allowed to pass, letting you shape service coverage without demolishing roads.

Road

1×1Size
0Workers
0Desirability

Cost (Normal)
5 Db
Cost by difficulty
VE 1 · Easy 2 · Normal 5 · Hard 10 · VH 15
Draggable
Yes — auto-routes between start and end
Fire / Damage risk
None

Plaza

1×1Size
0Workers
+4Desirability

Cost (Normal)
10 Db
Cost by difficulty
VE 3 · Easy 5 · Normal 10 · Hard 15 · VH 20
Placement
On existing road tiles only
Fire / Damage risk
None (fire-proof, damage-proof)

Overview

Ancient Egyptian settlements were crisscrossed by paths of packed earth, worn smooth by the feet of workers, merchants, and priests. Major temples and administrative centres were linked by processional avenues paved with stone, flanked by sphinxes and obelisks. The Nile itself served as the primary highway, but inland roads carried the daily flow of goods, food, and people between fields, workshops, and homes.

In the game, the road network is the circulatory system of your city. Walkers from service buildings — architects, fire marshals, physicians, bazaar traders, tax collectors, priests, and entertainers — all roam the streets. If housing has no road access, no walker can reach it; the house will devolve. If a production building has no road access, its cartpushers cannot leave with goods. Roads are not optional infrastructure: a city without a connected road network cannot function.

Mechanics

Road network connectivity

Every game tick the engine scans the map and assigns a network ID to each connected cluster of road tiles using a BFS flood-fill. All buildings and figures track which network they belong to. A Granary on network 3 is invisible to a Bazaar buyer on network 7 — even if they are two tiles apart — because there is no road linking them.

Simplified connectivity example
Building A — road — road — road — Building B  →  same network, walkers can travel
Building C —  (gap)  — road — Building D  →  different networks, walkers cannot travel

The engine specifically tracks the largest road networks for efficient routing. When you place a building that needs to reach distant storage buildings or housing, always verify it is on the same connected network.

Walker types and roads

There are two walker types relevant to road layout:

Because roaming walkers choose randomly at intersections, a long straight road with no side branches gives very predictable linear coverage. A dense grid gives unpredictable coverage — walkers may double back and miss streets entirely. Plan road layouts deliberately: use loop roads so walkers always find a forward path, and use Roadblocks to prevent them from wandering into zones you do not want served.

Building road access

A building is considered to have road access if at least one of the tiles adjacent to its footprint is a road tile. Larger buildings (2×2, 3×3, 4×4) only need one adjacent road tile — walkers spawn from the tile closest to that road. Buildings with no adjacent road tile are shown with a warning in their right-click panel and cannot spawn any walkers.

Paving & Plaza

Automatic paving

A dirt road tile automatically displays a paved stone appearance (without extra cost) when either condition is met:

Paving is purely visual — it does not affect walker speed or routing. It does give a clear indication that the surrounding neighbourhood has high desirability, which correlates with housing evolution potential.

Plaza

Placing a Plaza tile on any existing road tile permanently upgrades its appearance to the decorative plaza look and grants +4 desirability at that tile (fading over 2 tiles). Plaza tiles are fire-proof and damage-proof. They are most useful for:

Plaza cannot be placed on empty ground — place a Road tile first, then the Plaza on top of it. Demolishing a Plaza tile returns the underlying road.

Floodplain & Canals

Floodplain roads

Roads can be placed on floodplain tiles, but with restrictions:

Road under canal

An Irrigation Ditch (canal) can cross over a road tile. The game checks whether a road can pass under a given canal tile (map_can_place_road_under_canal) and renders a combined road+canal image when both are present on the same tile. This lets you run canals across major roads without severing the road network.

Tips

Developer reference

All paths relative to the repository root.

Building config — src/scripts/buildings.js

src/scripts/buildings.js defines building_road and building_plaza. The Roadblock config is documented on the Roadblock page.

building_road {
  animations {
    preview { pack:PACK_TERRAIN, id:33 }
    base    { pack:PACK_TERRAIN, id:33 }
  }
  building_size : 1
  cost [ 1, 2, 5, 10, 15 ]    // VE · Easy · Normal · Hard · VH
  planner_update_rule {
    is_draggable : true
  }
}

building_plaza {
  animations {
    preview : { pack:PACK_GENERAL, id:168 }
    base    : { pack:PACK_GENERAL, id:168 }
  },
  planner_update_rule { is_draggable : true }
  fire_proof      : true
  damage_proof    : true
  meta            : { help_id: 80, text_id: 137 }
  building_size   : 1
  cost            : [ 3, 5, 10, 15, 20 ]
  desirability    : { value[4], step[1], step_size[-2], range[2] }
}
C++ implementation — src/building/building_road.h / .cpp

src/building/building_road.h declares building_road (inherits building_impl). Key static methods:

  • set_road(tile2i) — adds TERRAIN_ROAD flag to the tile and refreshes surrounding tile images; returns true if the tile was newly set.
  • is_paved(tile2i) — returns true if desirability > 4, or (desirability > 0 && within fountain range). This drives the visual switch between dirt and stone road images.
  • set_image(tile2i) — selects the correct image variant for a road tile based on adjacent terrain (auto-connects to neighbours, handles canal-over-road, floodplain, plaza).

The nested preview struct implements the drag-to-place planner:

  • can_construction_start() — calls map_routing_calculate_distances_for_building(ROUTED_BUILDING_ROAD, start) to verify a route exists.
  • construction_update() / construction_place() — use place_routed_building() to lay tiles along the auto-routed path.
  • ghost_preview() — draws red ghost on blocked tiles (water, non-clearable terrain, inundated floodplain, out-of-money), green/neutral ghost otherwise.

Placement is blocked (red ghost) when the player is out of money, the tile is water, or the tile is an inundated floodplain. Roads can be placed on non-inundated floodplain and over canals.

Road network — src/grid/road_network.cpp

src/grid/road_network.cpp implements the connectivity flood-fill. city_map_t::update_road_network() scans every tile once per update cycle:

// Assigns network_id to every connected road cluster via BFS
for each unvisited road tile:
    size = mark_road_network(tile, network_id++)
    add_to_largest_road_networks(network_id, size)

// BFS kernel — 4-directional, max 1000 tiles in queue
mark_road_network(grid_offset, network_id):
    flood-fill using map_routing_citizen_is_passable()
    marks tile as network_id in road_network grid

The queue limit is 1 000 tiles (MAX_ROAD_QUEUE). Very large connected road grids are handled correctly; the limit only affects queue depth per iteration, not total reachability. The engine tracks the largest networks so that buildings preferentially connect to the biggest network when multiple are reachable.

Road access API — src/grid/road_access.h

src/grid/road_access.h exposes the building-to-road connectivity checks used throughout the codebase:

  • map_has_road_access(tile, size) — returns true if any tile adjacent to the N×N footprint is a valid road tile.
  • map_get_road_access_tile(tile, size) — returns the specific adjacent road tile (used to spawn walkers at the right edge).
  • map_closest_road_within_radius(tile, size, radius) — finds the nearest road tile within a given search radius; used by buildings that spawn destination walkers.
  • map_get_adjacent_road_tiles_for_roaming(grid_offset, road_tiles, permission) — fills an array with the adjacent road tiles a roaming walker may step onto, respecting Roadblock permissions. This is the function that enforces Roadblock filtering during figure movement.

road_tile_valid_access(int grid_offset) validates a tile as a usable road: must have TERRAIN_ROAD, must not be water or deep water. Buildings placed over roads are also allowed through (Booths, Bandstands, Pavilions, Festival Squares, and Mud Gatehouses are explicit exceptions).