diff --git a/lib/engine/game/g_18_mo/entities.rb b/lib/engine/game/g_18_mo/entities.rb index 4903e79f42..0acdb98f15 100644 --- a/lib/engine/game/g_18_mo/entities.rb +++ b/lib/engine/game/g_18_mo/entities.rb @@ -158,7 +158,7 @@ module Entities type: 'train_discount', discount: 60, owner_type: 'corporation', - trains: %w[2Y 3Y 3G 4G 3E 5 6], + trains: %w[Y2 Y2 G3 G4 3E 5 6], count: 1, closed_when_used_up: true, when: 'buying_train', diff --git a/lib/engine/game/g_18_mo/game.rb b/lib/engine/game/g_18_mo/game.rb index fa8d3ce9f5..d2815c8eb4 100644 --- a/lib/engine/game/g_18_mo/game.rb +++ b/lib/engine/game/g_18_mo/game.rb @@ -15,7 +15,7 @@ class Game < G1846::Game include G18MO::Entities include G18MO::Map - STARTING_CASH = { 2 => 600, 3 => 425, 4 => 400, 5 => 385 }.freeze + STARTING_CASH = { 2 => 600, 3 => 400, 4 => 400, 5 => 385 }.freeze TILE_COST = 0 PHASES = [ @@ -29,7 +29,7 @@ class Game < G1846::Game { name: '3', train_limit: 4, - on: '3G', + on: 'G3', tiles: %i[yellow green], operating_rounds: 2, status: ['can_buy_companies'], @@ -67,28 +67,32 @@ class Game < G1846::Game TRAINS = [ { - name: '2Y', - distance: 2, + name: 'Y2', + distance: [{ 'nodes' => %w[city offboard], 'pay' => 2, 'visit' => 2 }, + { 'nodes' => ['town'], 'pay' => 0, 'visit' => 99 }], price: 100, obsolete_on: '3E', rusts_on: '7', variants: [ { - name: '3Y', - distance: 3, + name: 'Y3', + distance: [{ 'nodes' => %w[city offboard], 'pay' => 3, 'visit' => 3 }, + { 'nodes' => ['town'], 'pay' => 0, 'visit' => 99 }], price: 150, }, ], }, { - name: '3G', - distance: 3, + name: 'G3', + distance: [{ 'nodes' => %w[city offboard], 'pay' => 3, 'visit' => 3 }, + { 'nodes' => ['town'], 'pay' => 0, 'visit' => 99 }], price: 180, obsolete_on: '5E', variants: [ { - name: '4G', - distance: 4, + name: 'G4', + distance: [{ 'nodes' => %w[city offboard], 'pay' => 4, 'visit' => 4 }, + { 'nodes' => ['town'], 'pay' => 0, 'visit' => 99 }], price: 240, }, ], @@ -101,12 +105,14 @@ class Game < G1846::Game }, { name: '5', - distance: 5, + distance: [{ 'nodes' => %w[city offboard], 'pay' => 5, 'visit' => 5 }, + { 'nodes' => ['town'], 'pay' => 0, 'visit' => 99 }], price: 450, variants: [ { name: '6', - distance: 6, + distance: [{ 'nodes' => %w[city offboard], 'pay' => 6, 'visit' => 6 }, + { 'nodes' => ['town'], 'pay' => 0, 'visit' => 99 }], price: 540, }, ], @@ -119,12 +125,14 @@ class Game < G1846::Game }, { name: '7', - distance: 7, + distance: [{ 'nodes' => %w[city offboard], 'pay' => 7, 'visit' => 7 }, + { 'nodes' => ['town'], 'pay' => 0, 'visit' => 99 }], price: 700, variants: [ { name: '8', - distance: 8, + distance: [{ 'nodes' => %w[city offboard], 'pay' => 8, 'visit' => 8 }, + { 'nodes' => ['town'], 'pay' => 0, 'visit' => 99 }], price: 800, }, ], @@ -256,9 +264,9 @@ def num_trains(train) num_players = @players.size case train[:name] - when '2Y' + when 'Y2' two_player? ? 7 : num_players + 4 - when '3G' + when 'G3' two_player? ? 4 : num_players when '3E', '5E' 1 @@ -270,14 +278,25 @@ def num_trains(train) end def num_removals(group) - return 0 if @players.size == 5 - return 1 if @players.size == 4 - case group when ORANGE_GROUP, BLUE_GROUP - @players.size == 2 ? 1 : 2 + case @players.size + when 2, 4 + 2 + when 3 + 3 + else + 1 + end when GREEN_GROUP - 2 + case @players.size + when 2, 3 + 2 + when 4 + 1 + else + 0 + end end end @@ -340,6 +359,31 @@ def place_second_token(corporation, two_player_only: true, deferred: true) super(corporation, two_player_only: two_player_only, deferred: false) end + # override compute_stops to allow visiting dit in East St. Louis and replacing city/offboard + # with its value + # + def compute_stops(route) + visits = route.visited_stops + distance = route.train.distance + return [] if visits.empty? + + paying_distance = distance.find { |d| d['pay'].positive? } + + # Separate between city/offboard and dits (exception: E-trains) + # There should only be one dit_stop at most + normal_stops, dit_stops = visits.partition { |node| paying_distance['nodes'].include?(node.type) } + + # if no dit stops + return visits if dit_stops.empty? + + # return if not enough normal stops + return visits if normal_stops.size < paying_distance['pay'] + + # remove smallest normal stop that has less revenue than dit + worst_stop = normal_stops.min_by { |stop| stop.route_revenue(route.phase, route.train) } + visits.reject { |stop| stop == worst_stop } + end + def setup_turn 1 end diff --git a/lib/engine/game/g_18_mo/map.rb b/lib/engine/game/g_18_mo/map.rb index be32a054c8..3b12e34c73 100644 --- a/lib/engine/game/g_18_mo/map.rb +++ b/lib/engine/game/g_18_mo/map.rb @@ -126,8 +126,8 @@ module Map HEXES = { white: { - %w[A9 A11 B8 B10 B12 C3 C9 C11 C15 D2 D14 E3 F12 L6 L8 L10 I11 J12 K15] => '', - %w[D4 E15 F4 H12 K5] => 'city=revenue:0', + %w[A9 A11 B6 B8 B10 B12 C3 C9 C11 C15 D2 D14 E3 F12 L6 L8 L10 I11 J12 K15] => '', + %w[C5 D4 E15 F4 H12] => 'city=revenue:0', %w[D16 F14 F16 G13 H14 G15 I13 I15] => 'upgrade=cost:20,terrain:mountain', ['C13'] => 'city=revenue:10;path=a:1,b:_0', ['H10'] => 'city=revenue:0;border=edge:2,type:water,cost:20', @@ -144,7 +144,6 @@ module Map ['L12'] => 'border=edge:1,type:water,cost:40', ['E11'] => 'border=edge:1,type:water,cost:20;border=edge:2,type:water,cost:20;'\ 'border=edge:3,type:water,cost:40', - ['B6'] => 'border=edge:4,type:water,cost:20', ['E5'] => 'border=edge:0,type:water,cost:20', ['D12'] => 'border=edge:4,type:water,cost:20', ['H2'] => 'border=edge:1,type:water,cost:40', @@ -164,18 +163,18 @@ module Map 'border=edge:4,type:water,cost:20', ['F6'] => 'border=edge:0,type:water,cost:20;border=edge:1,type:water,cost:20', ['F8'] => 'border=edge:3,type:water,cost:20;border=edge:4,type:water,cost:20', - ['J4'] => 'city=revenue:0;border=edge:1,type:water,cost:20;border=edge:2,type:water,cost:20', - ['C5'] => 'city=revenue:0;border=edge:1,type:water,cost:20', + ['J4'] => 'city=revenue:10;path=a:_0,b:3;border=edge:1,type:water,cost:20;border=edge:2,type:water,cost:20', + ['K5'] => 'city=revenue:10;path=a:_0,b:3', ['J14'] => 'city=revenue:10;path=a:0,b:_0;', }, red: { - ['A7'] => 'city=revenue:yellow_30|brown_40,groups:W;icon=image:1846/30;path=a:0,b:_0;path=a:5,b:_0;label=W', + ['A7'] => 'city=revenue:yellow_30|brown_40,groups:W;icon=image:1846/50;path=a:0,b:_0;path=a:5,b:_0;label=W', ['A15'] => 'offboard=revenue:yellow_30|brown_60,groups:W;icon=image:1846/30;path=a:4,b:_0;label=W;', ['E1'] => 'offboard=revenue:yellow_20|brown_50;path=a:0,b:_0', ['E17'] => 'offboard=revenue:yellow_20|brown_50;path=a:2,b:_0;path=a:3,b:_0;path=a:4,b:_0', - ['J2'] => 'offboard=revenue:yellow_30|brown_40,groups:E;icon=image:1846/20;path=a:0,b:_0;label=E', - ['K3'] => 'offboard=revenue:yellow_30|brown_40,groups:E;icon=image:1846/20;path=a:0,b:_0;path=a:1,b:_0;label=E', + ['J2'] => 'offboard=revenue:yellow_30|brown_40,groups:E;icon=image:1846/50;path=a:0,b:_0;label=E', + ['K3'] => 'offboard=revenue:yellow_30|brown_40,groups:E;icon=image:1846/50;path=a:0,b:_0;path=a:1,b:_0;label=E', ['K17'] => 'offboard=revenue:yellow_30|brown_60,groups:E;icon=image:1846/30;path=a:2,b:_0;label=E', },