Skip to content

Commit

Permalink
Merge pull request #10207 from patrikolesen/18_uruguay_pre_alpha_deli…
Browse files Browse the repository at this point in the history
…ver_goods

[18Uruguay] Adding support for delivering goods
  • Loading branch information
michaeljb authored Feb 10, 2024
2 parents 7010ac7 + 09a4471 commit e17d4b9
Show file tree
Hide file tree
Showing 4 changed files with 333 additions and 26 deletions.
46 changes: 20 additions & 26 deletions lib/engine/game/g_18_uruguay/game.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
require_relative 'loans'
require_relative '../../loan'
require_relative 'ability_ship'
require_relative 'goods'
require_relative 'step/route_rptla'

module Engine
module Game
Expand All @@ -26,9 +28,9 @@ class Game < Game::Base
include Phases
include InterestOnLoans
include Loans
include Goods

EBUY_SELL_MORE_THAN_NEEDED = true
GOODS_TRAIN = 'Goods'

register_colors(darkred: '#ff131a',
red: '#d1232a',
Expand All @@ -44,7 +46,6 @@ class Game < Game::Base
SELL_BUY_ORDER = :sell_buy
TILE_RESERVATION_BLOCKS_OTHERS = true
CURRENCY_FORMAT_STR = '$U%d'
GOODS_DESCRIPTION_STR = 'Number of goods: '

MUST_BUY_TRAIN = :always

Expand Down Expand Up @@ -173,6 +174,7 @@ def cattle_farm

def setup
super
goods_setup
@rptla = @corporations.find { |c| c.id == 'RPTLA' }
@fce = @corporations.find { |c| c.id == 'FCE' }

Expand Down Expand Up @@ -274,7 +276,8 @@ def operating_round(round_num)
Engine::Step::HomeToken,
Engine::Step::Track,
G18Uruguay::Step::Token,
Engine::Step::Route,
G18Uruguay::Step::Route,
G18Uruguay::Step::RouteRptla,
G18Uruguay::Step::Dividend,
G18Uruguay::Step::DiscardTrain,
G18Uruguay::Step::BuyTrain,
Expand Down Expand Up @@ -338,26 +341,6 @@ def perform_ebuy_loans(entity, remaining)
end
end

# Goods
def number_of_goods_at_harbor
ability = @rptla.abilities.find { |a| a.type == 'Goods' }
ability.description[/\d+/].to_i
end

def add_good_to_rptla
ability = @rptla.abilities.find { |a| a.type == 'Goods' }
count = number_of_goods_at_harbor + 1
ability.description = GOODS_DESCRIPTION_STR + count.to_s
end

def remove_goods_from_rptla(goods_count)
return if number_of_goods_at_harbor < goods_count

ability = @rptla.abilities.find { |a| a.type == 'Goods' }
count = number_of_goods_at_harbor - goods_count
ability.description = GOODS_DESCRIPTION_STR + count.to_s
end

def check_distance(route, visits, train = nil)
@round.current_routes[route.train] = route
if route.corporation != @rptla && !nationalized?
Expand All @@ -372,10 +355,21 @@ def check_distance(route, visits, train = nil)
end

# Revenue
def revenue_str_rptla(route)
count = goods_on_ship(route.train)
str = 'No goods'
str = count.to_s + ' good' if count.positive?
str += 's' if count > 1
str
end

def revenue_str(route)
return super unless route&.corporation == @rptla
return revenue_str_rptla(route) if route&.corporation == @rptla

'Ship'
good_hex = good_pickup_hex(route.train)
str = super
str += '+Good(' + good_hex.id + ')' unless good_hex.nil?
str
end

def rptla_revenue(corporation)
Expand All @@ -397,7 +391,7 @@ def revenue_for(route, stops)
return revenue unless route&.corporation == @rptla

train = route.train
revenue * goods_on_train(train)
revenue * goods_on_ship(train)
end

def or_round_finished
Expand Down
94 changes: 94 additions & 0 deletions lib/engine/game/g_18_uruguay/goods.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# frozen_string_literal: true

module Engine
module Game
module G18Uruguay
module Goods
GOODS_DESCRIPTION_STR = 'Number of goods: '

def goods_setup
@pickup_hex_for_train = {}
@goods_on_ship = {}
@number_of_goods_at_harbor = 0
end

# Train delivery
def train_with_goods?(train)
return unless train

@pickup_hex_for_train.key?(train.id)
end

def attach_good_to_train(train, hex)
@pickup_hex_for_train[train.id] = hex
end

def good_pickup_hex(train)
@pickup_hex_for_train[train.id]
end

def unload_good(train)
@pickup_hex_for_train.delete(train.id) if train_with_goods?(train)
end

# Harbor
def visits_include_port?(visits)
visits.any? { |visit| self.class::PORTS.include?(visit.hex.id) }
end

def route_include_port?(route)
route.hexes.any? { |hex| self.class::PORTS.include?(hex.id) }
end

def check_for_goods_if_run_to_port(route, visits)
true if route.corporation == @rptla
visits_include_port?(visits) || !train_with_goods?(route.train)
end

def check_for_port_if_goods_attached(route, visits)
true if route.corporation == @rptla
!visits_include_port?(visits) || train_with_goods?(route.train)
end

def number_of_goods_at_harbor
@number_of_goods_at_harbor
end

def add_good_to_rptla
ability = @rptla.abilities.find { |a| a.type == :Goods }
return if ability.nil?

@number_of_goods_at_harbor += 1
ability.description = GOODS_DESCRIPTION_STR + @number_of_goods_at_harbor.to_s
end

def remove_goods_from_rptla(goods_count)
return if @number_of_goods_at_harbor < goods_count

ability = @rptla.abilities.find { |a| a.type == :Goods }
return if ability.nil?

@number_of_goods_at_harbor -= goods_count
ability.description = GOODS_DESCRIPTION_STR + count.to_s
end

# Ship gooods
def add_goods_to_ship(ship, count)
@goods_on_ship[ship.id] = count
end

def remove_goods_from_ship(ship)
return unless @goods_on_ship.key?(ship.id)

@goods_on_ship[ship.id] = 0
end

def goods_on_ship(ship)
return 0 unless @goods_on_ship.key?(ship.id)

@goods_on_ship[ship.id]
end
end
end
end
end
130 changes: 130 additions & 0 deletions lib/engine/game/g_18_uruguay/step/route.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# frozen_string_literal: true

require_relative '../../../step/route'

module Engine
module Game
module G18Uruguay
module Step
class Route < Engine::Step::Route
def setup
@round.current_routes = {}
end

def actions(entity)
return %w[].freeze if entity.corporation == @game.rptla
return [] if !entity.operator? || @game.route_trains(entity).empty? || !@game.can_run_route?(entity)
return [] if entity.corporation? && entity.type == :minor

actions = ACTIONS.dup
actions << 'choose' if choosing?(entity)
actions
end

def choosing?(_entity)
true
end

def choice_name
return 'Attach goods to ships' if current_entity == @game.rptla

'Attach good to a train'
end

def goods_hexes
@game.hexes.select do |hex|
hex.assignments.keys.find { |a| a.include? 'GOODS' }
end
end

def choices
choices = {}
goods_train_choices(current_entity).each_with_index do |train, _index|
hex = train['hex']
index_str = "train\##{train['train_index']}"
index_str += "_#{train['hex'].id}" unless hex.nil?
choices[index_str] = "#{train['train'].name} train\##{train['train_index']} (#{train['hex'].id})" unless hex.nil?
choices[index_str] = "#{train['train'].name} train\##{train['train_index']} unload" if hex.nil?
end
choices
end

def route_for_train(train)
@round.current_routes[train] unless train.nil?
end

def get_train_goods_combo(name)
str_split = name.split('_')
train_index = str_split[0].split('#')[1]
train = @game.route_trains(current_entity)[train_index.to_i - 1]
hex = @game.hex_by_id(str_split[1]) if str_split.size > 1
[train, hex]
end

def goods_train_choices(entity)
choices_array = []
@game.route_trains(entity).each_with_index do |train, index|
route = route_for_train(train)
if @game.train_with_goods?(train)
choices_array.push({ train: train, train_index: index + 1, hex: nil, loaded: true })
else
goods_hexes.each do |hex|
if route
val = { train: train, train_index: index + 1, hex: hex, loaded: false }
choices_array.push(val) if route.hexes.include?(hex)
end
end
end
end
choices_array
end

def process_choose(action)
entity = action.entity

train, hex = get_train_goods_combo(action.choice)

if hex
@log << "#{entity.id} attaches good from #{hex.id} to a #{train.name} train"

@game.attach_good_to_train(train, hex)
else
@log << "#{entity.id} remove good from #{train.name} train"
@game.unload_good(train)
end
end

def detach_goods(routes)
routes.each do |route|
train = route.train
next unless @game.train_with_goods?(train)

hex = @game.good_pickup_hex(train)
good = hex.assignments.keys.find { |a| a.include? 'GOODS' }
@game.unload_good(train)
raise NoToken, "No good token found at Hex #{hex&.id}" if good.nil?
raise NoToken, "Hex #{hex&.id} is not included in route for train #{train.name}" unless route.hexes.include?(hex)

hex.remove_assignment!(good)
@log << "#{current_entity.id} moves a good to the harbor"
@game.add_good_to_rptla unless good.nil?
end
end

def process_run_routes(action)
super
entity = action.entity
detach_goods(action.routes) unless action.entity == @game.rptla
@game.route_trains(entity)&.each do |train|
@game.unload_good(train)
end
end

def round_state
super.merge({ current_routes: {} })
end
end
end
end
end
end
Loading

0 comments on commit e17d4b9

Please sign in to comment.