Ability Types Reference

Company and corporation abilities are defined as hashes in entities.rb files. The engine processes them via lib/engine/ability/ and evaluates their legality through Game::Base#ability_right_time?. This page is an exhaustive reference for ability types, their fields, and the when: vocabulary.


Ability Type Frequency

Frequencies extracted from analysis of 112 entities.rb files (1,111 COMPANIES, 1,241 CORPORATIONS) across the engine.

TypeOccurrencesGamesKey fields
exchange26031corporations:, from:, when:
tile_lay23259count:, when:, free:, tiles:, hexes:, consume_tile_lay:, closed_when_used_up:
blocks_hexes18040hexes:
no_buy17535(no extra fields)
shares12443shares:
close10838when:, corporation:, on_phase:
revenue_change9214revenue:, on_phase:
assign_hexes8234hexes:
reservation7811hexes:
hex_bonus5410hexes:, amount:
token5327price:, count:, corporation:
base508description:
tile_discount4428terrain:, discount:
assign_corporation3421corporations:
blocks_hexes_consent324(blocking released on owner consent)
description218description:
choose_ability196(no standard fields)
manual_close_company191(no standard fields)
sell_company192(no standard fields)
train_discount1612discount:, trains:
teleport1612hexes:, tiles:
tile_income109(no standard fields)
train_limit96(no standard fields)
generic81desc:
additional_token77(no standard fields)
train_buy66(no standard fields)
acquire_company62(no standard fields)
borrow_train22(no standard fields)
blocks_partition22(no standard fields)
train_scrapper11(no standard fields)
purchase_train11(no standard fields)

Ability Structure

Standard ability hash in entities.rb:

{
  type: 'tile_lay',           # required
  owner_type: 'player',       # 'player' | 'corporation'
  when: 'track',              # string or array; see When: Field section
  count: 2,                   # number of uses; omit = unlimited
  hexes: %w[A1 B2],           # hex restriction
  tiles: %w[57 58],           # tile number restriction
  free: true,                 # waives tile cost
  closed_when_used_up: true,  # close company when count reaches 0
  reachable: true,            # must be reachable from home token
  consume_tile_lay: true,     # consumes one of the corporation's normal lay slots
  terrain: 'mountain',        # (on tile_discount) terrain type
  discount: 20,               # (on tile_discount / train_discount) amount
  trains: %w[2+2 3+3],        # (on train_discount) train types
  corporations: %w[GWR LNWR], # (on exchange / token / assign_corporation)
  from: 'par',                # (on exchange) source
  description: 'text',        # (on base / description / generic)
  price: 0,                   # (on token) placement cost
  corporation: 'GWR',         # (on token / close) specific corporation
  on_phase: 'Phase 4',        # (on close / revenue_change) phase trigger
  revenue: 20,                # (on revenue_change) new value
  amount: 30,                 # (on hex_bonus) bonus amount
}

count: enforcement

ability.use! decrements @count [lib/engine/ability/base.rb:1]. When count reaches zero and @remove_when_used_up is true (the default), the ability is removed from the entity. TileLay#use! tracks lay_count and upgrade_count separately.

consume_tile_lay: on tile_lay abilities

  • consume_tile_lay: true — routes through lay_tile_action; increments @round.num_laid_track. The ability consumes one of the corporation's normal lay slots.
  • Without consume_tile_lay — routes through lay_tile directly. The ability is extra on top of the normal budget.
  • blocks_hexes — unconditional; blocked until the company is purchased or closed.
  • blocks_hexes_consent — blocking released when the owning player consents. Used for concession cards (released when the concession is transferred or the major is parred). Reference: 1822 family.

when: Field Complete Vocabulary

649 occurrences across 75 games; 27 distinct values. Source: Game::Base#ability_right_time? [lib/engine/game/base.rb].

OR Step-Scoped

Active only during the named Step class:

ValueActive whenTypical ability types
'track'Step::Tracktile_lay, tile_discount
'special_track'Step::SpecialTracktile_lay, teleport
'token'Step::Tokentoken
'special_token'Step::SpecialTokentoken, teleport
'route'Step::Routegeneric
'track_and_token'Step::TrackAndTokentile_lay, token
'buy_train'Step::BuyTraintrain_discount
'buying_train'During train purchase (alias)train_discount
'single_depot_train_buy'Variant buy-train steptrain_discount
'dividend'Step::Dividendgeneric, revenue_change
'exchange'SR Step::Exchangeexchange

OR Turn-Scoped

Active at any point during the owning entity's OR turn:

ValueCondition
'owning_corp_or_turn'OR active AND current operator owns the ability (155 occurrences)
'owning_player_or_turn'OR active AND the president is the ability's player
'owning_player_track'OR active AND president == ability's player AND in Track step
'owning_player_token'OR active AND president == ability's player AND in Token step
'or_between_turns'OR active AND !current_operator_acted
'or_start'OR active AND @round.at_start

SR Turn-Scoped

ValueCondition
'owning_player_sr_turn'SR active AND current entity is ability's player (155 occurrences)
'stock_round'SR active, any player, any turn

Event-Triggered (on close abilities only)

ValueTriggered by
'bought_train'base.rb#buy_trainclose_companies_on_event!
'ran_train'step/dividend.rbclose_companies_on_event!
'operated'step/dividend.rb#pass!close_companies_on_event!
'par'base.rb#after_parclose_companies_on_event!
'sold'step/buy_company.rb fires 'sold' abilities
'auction_end'Game-specific auction step
'has_train'Revenue-change at OR start when the corporation has trains

Meta / Any-Round

ValueMeaning
'any'Usable at any time. Short-circuits all other checks.

Always-valid values (no step prerequisite): any, owning_corp_or_turn, owning_player_or_turn, owning_player_track, owning_player_token, owning_player_sr_turn, stock_round, or_between_turns, or_start.


exchange Ability — from: Values

ValueMeaning
'par'Concession pattern — company exchanged to float a corporation at par
'ipo'Exchange for a share from the IPO pool
'market'Exchange for a share from the secondary market
%w[ipo market]Either source
%i[reserved]Reserved share

Concessions use from: 'par' per the 1822/1866 concession pattern.


description Ability

Used to associate a minor with a major and to hold the human-readable rulebook ability text:

# In CORPORATIONS for a minor:
abilities: [{ type: 'description', description: 'Associated minor for GWR' }]

The par_via_exchange field handles the mechanical association; the description ability is UI display only.


18OE Ability Mapping

Minor special abilities

MinorRule descriptionAbility types needed
A — Silver BannerBank pays major treasury = share value on mergebase + custom hook in merge_minor
B — Orange ScrollTrack upgrades cost 1 tile point (not cities/grand/metro)tile_discount + tile_lay extra slot
C — Golden BellPresident chooses operating position each ORchoose_ability + custom operating_order
D — Green JunctionToken in non-metro city; £20/£40 bonus by phase; removed at Phase 5token (free) + hex_bonus (phase-conditional)
E — Blue Coast33% discount on blue terrain; +1 tile pt in blue hexestile_discount (terrain: water) + tile_lay
F — White Peak33% discount on green terrain; +1 tile pt in green hexestile_discount (terrain: mountain) + tile_lay
G — Indigo Foundry+2 tile points per ORCustom tile_lays returning extra slots
H — Great Western SteamshipReduces sea zones counted by 1 (Phase 1–6) or 2 (Phase 7–8)Custom game hook; no standard type
J — Grey Locomotive Works10% discount on all train purchasestrain_discount
K — Vermilion SealMail contract pays revenue to treasury at OR startextra_revenue hook or hex_bonus
L — Krasnaya Strela+1+1 marker adds 1 city limit and 1 town count to assigned trainCustom game hook; no standard type
M — CIWL10 Pullman carsCustom Pullman asset; no standard type

Private special abilities

PrivateRule descriptionAbility types needed
Wien SüdbahnhofFree station token placementtoken (price: 0, when: 'token')
Barclay, Bevan, Barclay & TrittonOption 3 (alpha): prevent one corp's price from moving DOWN for rest of SR; options 1+2 deferred to betaSR choose action; @bbbt_protected_corp; sell_shares_and_change_price override (movement: :none); finish_bbbt_sr! clears + closes at SR end
Star Harbor Trading Co.Port token in port city (doesn't consume slot)token + assign_hexes
Central Circle Transport Corp.Token in non-port city as town (£10–£60 by phase)token + hex_bonus
White Cliffs FerryLille (N31) token at Phase 5; enables ferrytile_lay + phase-trigger logic
Hochberg Mining & LumberToken in rough terrain hex; track restricted to ownerassign_hexes + custom hook in check_route_token
Brandt & Brandau, Engineers4 tokens, up to 2/OR, free yellow tile on terrain hex; non-owner RRs blockedtile_lay (free, count: 4, count_per_or: 2, owner_type: corporation) + @bbe_hexes tracking + check_bbe_exclusion!
Swift Metropolitan LineFrom Phase 4: preserved 2+2 outside train limit; cannot be soldSR choose action; claim_sml_train! assigns rusted 2+2 (buyable=false); num_corp_trains + must_buy_train? exclude SML train

Implementation notes — BBBT, BBE, and SML

Barclay, Bevan, Barclay & Tritton (BBBT)

Option 3 only implemented for alpha. During the player's own SR turn, can_use_bbbt_option3? gates a choose action in BuySellParShares. Choice keys are prefixed bbbt_<corp_id> to avoid collisions with the SML choose keys. bbbt_protect!(corp, player) stores @bbbt_protected_corp and logs the protection. sell_shares_and_change_price is overridden in game.rb to pass movement: :none when the protected corp is being sold, suppressing all DOWN movement for that sale. next_round! calls finish_bbbt_sr! when leaving an SR — this clears @bbbt_protected_corp and closes BBBT. Options 1 (re-set par) and 2 (custodianship) are deferred to beta.

Brandt & Brandau, Engineers (BBE)

owner_type: 'corporation' on the tile_lay ability means the ability only activates after a corporation has purchased BBE from the player. Once corp-owned, during the Track step on a terrain hex, upgrade_cost returns 0 (terrain free). After the lay, the Track step calls ability.use! and mark_bbe_hex!(hex, corp), storing the hex in @bbe_hexes. check_bbe_exclusion! (called from check_route_token) raises GameError if a non-owning corp routes through a marked hex. The removal mechanic (opponent pays terrain + tile point to remove token) is not yet implemented.

Swift Metropolitan Line (SML)

Implemented entirely in game.rb via can_claim_sml? / claim_sml_train! and an SR choose action on BuySellParShares. The rusted 2+2 is assigned with buyable = false and tracked in @sml_trains. num_corp_trains and must_buy_train? both exclude SML trains from their counts.


What's next


Version: 2026-05-19 — derived from lib/engine/ability/base.rb, lib/engine/ability/tile_lay.rb, lib/engine/game/base.rb.