18xx introduction

18xx refers to a family of board games that focus on investing in, and operating, train companies. Players aim to end the game with the most wealth, and this can be achieved in a number of different ways. Players can buy stock in companies, and the player who owns the most shares in a company is responsible for operating the company. Companies lay track by placing hexagonal tiles, and run trains along the track network to earn revenue. Dividends may then be paid to all players who own shares in the company. Some games emphasise manipulating the stock market, while other games place a greater emphasis on running profitable companies.

Rusty Train

Rusty Train is a graphical user interface that uses the navig18xx crate to allow users to track the state of 18xx game maps, and to calculate the optimal revenue that each company can earn.

See the user guide for details.

The navig18xx crate (”navigating ex ex”) allows players to identify the train routes that will earn the most revenue for a company. It also provides lower-level building blocks for defining tiles and creating game maps.

See the developer guide for details.

An example tile

An example tile

This image was produced by the following code:

use navig18xx::prelude::*;
use std::path::Path;

mod output;

fn main() {
    // Specify where to save the output images.
    let output_dir: &Path = output::Dir::BookRoot.into();

    let hex_max_diameter = 125.0;
    let hex = Hex::new(hex_max_diameter);

    let tile_x5 = Tile::new(
        HexColour::Brown,
        "X5",
        vec![
            Track::straight(HexFace::Top).with_span(0.0, 0.1),
            Track::straight(HexFace::Top)
                .with_span(0.1, 1.0)
                .with_clip(0.3625, 0.75),
            Track::mid(HexFace::UpperLeft),
            Track::mid(HexFace::LowerLeft),
            Track::mid(HexFace::LowerRight),
            Track::mid(HexFace::UpperRight),
        ],
        vec![
            City::single_at_face(70, &HexFace::Top),
            City::double(70).in_dir(Direction::S, 0.1),
        ],
        &hex,
    )
    .label(Label::City("M".to_string()), HexCorner::BottomLeft)
    .label(Label::Revenue(0), HexCorner::Left.to_centre(0.1));

    tile_x5
        .save_svg(&hex, output_dir.join("tile_x5.svg"))
        .expect("Could not save tile X5 as an SVG");
}

An example route

An example route