Skip to content

Commit

Permalink
Merge branch 'upstream' into 18bf
Browse files Browse the repository at this point in the history
  • Loading branch information
ollybh committed May 29, 2023
2 parents 1516087 + 20fe877 commit 5b0b38c
Show file tree
Hide file tree
Showing 324 changed files with 2,460 additions and 4,463 deletions.
6 changes: 6 additions & 0 deletions TILES.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ game config/code:
- **upgrade**
- **cost** - *required* - integer
- **terrain** - `mountain`/`water` - multiple terrain types separated by `|`
- **loc** - (currently only supported for `:pointy` layouts) corner to
render the upgrade in, `5.5` to be where edges `5` and `0` meet, `0.5` for
edges `0` and `1`, and so on
- **border**
- **edge** - *required* - integer - which edge to modify
- **type** - `mountain`/`water`/`impassable` - Border type. If not'
Expand All @@ -91,6 +94,9 @@ game config/code:
upgrade is placed on this hex
- **blocks_lay** - indicates this tile cannot be laid normally
but can only be laid by special ability, such as a private company's ability.
- **loc** - (currently only supported for `:pointy` layouts) corner to
render the upgrade in, `5.5` to be where edges `5` and `0` meet, `0.5` for
edges `0` and `1`, and so on
- **frame**
- **color** - *required* - the color of the frame
- **color2** - A second color to display on the frame
Expand Down
12 changes: 11 additions & 1 deletion api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
require_relative 'models'
require_rel './lib'
require_rel './models'
require_relative 'lib/engine/test_tiles'

class Api < Roda
opts[:check_dynamic_arity] = false
Expand Down Expand Up @@ -132,7 +133,16 @@ class Api < Roda

r.on 'tiles' do
parts = request.path.split('/')
titles = parts.size == 4 ? parts[2].split(/[+ ]/) : []

titles =
if parts.size == 4
parts[2].split(/[+ ]/)
elsif parts[2] == 'test'
Engine::TestTiles::TEST_TILES.keys.compact
else
[]
end

render(titles: titles)
end

Expand Down
2 changes: 1 addition & 1 deletion assets/app/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def render_content
when /about/
h(View::About)
when /tiles/
h(View::TilesPage, route: @app_route)
h(View::TilesPage, route: @app_route, connection: @connection)
when /map/
h(View::MapPage, route: @app_route)
when /market/
Expand Down
72 changes: 45 additions & 27 deletions assets/app/view/create_game.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,19 @@ class CreateGame < Form
needs :min_players, default: nil, store: true
needs :max_players, default: nil, store: true

def render_create_button(check_options: true)
error = check_options &&
selected_game_or_variant.check_options(@optional_rules, @min_players, @max_players)&.[](:error)
(render_button('Create', { style: { margin: '0.5rem 1rem 1rem 0' }, attrs: { disabled: !!error } }) { submit })
end

def render_content
@label_style = { display: 'block' }

inputs = [mode_selector]

if @mode == :json
inputs << (render_button('Create', { style: { margin: '0.5rem 1rem 1rem 0' } }) { submit })
inputs << render_create_button(check_options: false)
inputs << render_upload_button
inputs << render_input(
'',
Expand All @@ -58,7 +64,7 @@ def render_content
else
if selected_game_or_variant
update_player_range(selected_game_or_variant)
inputs << (render_button('Create', { style: { margin: '0.5rem 1rem 1rem 0' } }) { submit })
inputs << render_create_button
inputs << h(:h2, selected_game_or_variant.meta.full_title)
inputs << render_inputs

Expand Down Expand Up @@ -274,23 +280,34 @@ def render_optional
},
}

info = selected_game_or_variant.respond_to?(:check_options) &&
selected_game_or_variant.check_options(@optional_rules, @min_players, @max_players)
children = [
h(:h4, 'Game Variants / Optional Rules'),
h(:ul, ul_props, [*game_variants, *optional_rules]),
]

if info
h(:div, [
h(:h4, 'Game Variants / Optional Rules'),
h(:ul, ul_props, [*game_variants, *optional_rules]),
h(:h4, 'Option Info/Errors'),
h(:div, info),
h(:br),
])
else
h(:div, [
h(:h4, 'Game Variants / Optional Rules'),
h(:ul, ul_props, [*game_variants, *optional_rules]),
])
checked_options = selected_game_or_variant.check_options(@optional_rules, @min_players, @max_players)
if checked_options
if (info = checked_options[:info])
children.concat(
[
h(:h4, 'Option Info'),
h(:div, info),
h(:br),
]
)
end
if (error = checked_options[:error])
children.concat(
[
h(:h4, 'Option Errors'),
h(:div, error),
h(:br),
]
)
end
end

h(:div, children)
end

def render_upload_button
Expand Down Expand Up @@ -378,18 +395,12 @@ def submit
game_params[:seed] = game_params[:seed].to_i
game_params[:seed] = nil if (game_params[:seed]).zero?

if @mode == :multi
begin
return create_game(game_params)
rescue Engine::OptionError => e
return store(:flash_opts, e.message)
end
end
return create_game(game_params) if @mode == :multi

players = game_params
.select { |k, _| k.start_with?('player_') }
.values
.map { |name| name.gsub(/\s+/, ' ').strip }
.select { |k, _| k.start_with?('player_') }
.values
.map { |name| name.gsub(/\s+/, ' ').strip }

return store(:flash_opts, 'Cannot have duplicate player names') if players.uniq.size != players.size

Expand All @@ -408,6 +419,13 @@ def submit
game_data[:settings][:seed] = game_params[:seed] if game_params[:seed]
end

checked_options = Engine.meta_by_title(game_data[:title])
.check_options(game_data[:settings][:optional_rules],
game_data[:min_players], game_data[:max_players])
if (options_error_msg = checked_options&.[](:error))
return store(:flash_opts, "game_data Optional Rules Error: #{options_error_msg}")
end

create_hotseat(
id: Time.now.to_i,
players: players.map.with_index { |name, i| { name: name, id: i } },
Expand Down
3 changes: 2 additions & 1 deletion assets/app/view/form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,10 @@ def render_input(label, id:, placeholder: '', el: 'input', type: 'text', attrs:
)
end

def render_button(text, style: {}, &block)
def render_button(text, style: {}, attrs: {}, &block)
props = {
attrs: {
**attrs,
type: :button,
},
style: {
Expand Down
7 changes: 4 additions & 3 deletions assets/app/view/game/acquire_companies.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,20 @@ def render_companies
end

def render_acquire_input
selected_company = @selected_company
acquire_click = lambda do
acquire = lambda do
process_action(Engine::Action::AcquireCompany.new(
@corporation,
company: @selected_company,
company: selected_company,
))
store(:selected_company, nil, skip: true)
end

if @selected_company.owner == @corporation.owner || !@selected_company.owner
if selected_company.owner == @corporation.owner || !selected_company.owner
acquire.call
else
check_consent(@selected_company.owner, acquire)
check_consent(@corporation, selected_company.owner, acquire)
end
end

Expand Down
15 changes: 12 additions & 3 deletions assets/app/view/game/actionable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,20 @@ def participant?
@participant = (@game.players.map(&:id) + [@game_data['user']['id']]).include?(@user&.dig('id'))
end

def check_consent(player, click)
def check_consent(entity, consenters, click)
consenters = Array(consenters).uniq
names = consenters.map(&:name).sort.join(', ')
consenters_str = consenters.size > 1 ? "one of #{names}" : names

log_and_click = lambda do
process_action(Engine::Action::Log.new(entity.player, message: "• confirmed receiving consent from #{consenters_str}"))
click.call
end

opts = {
color: :yellow,
click: click,
message: "Click confirm if #{player.name} has already consented to this action.",
click: log_and_click,
message: "Click confirm if #{consenters_str} has already consented to this action.",
}
store(:confirm_opts, opts, skip: false)
end
Expand Down
61 changes: 61 additions & 0 deletions assets/app/view/game/alternate_corporations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,67 @@ def render_rs_income
h(:div, { style: { gridColumnStart: 2 } }, [movement_table]),
])
end

# This is used by 1858 which has private railway companies that act a bit
# like minor railways, laying track in operating rounds. This rendering
# code is a simplified version of Engine::View::Game::Company.render.
def render_private_railway
minor = @corporation

select_minor = lambda do
if @selectable
selected_corporation = selected? ? nil : minor
store(:selected_corporation, selected_corporation)
end
end

header_style = {
background: minor.color,
color: minor.text_color,
border: '1px solid',
borderRadius: '5px',
marginBottom: '0.5rem',
fontSize: '90%',
}
description_style = {
margin: '0.5rem 0',
fontSize: '80%',
textAlign: 'left',
fontWeight: 'normal',
}
value_style = {
float: 'left',
}
revenue_style = {
float: 'right',
}
props = {
style: {
cursor: 'pointer',
boxSizing: 'border-box',
padding: '0.5rem',
margin: '0.5rem 5px 0 0',
textAlign: 'center',
fontWeight: 'bold',
},
on: { click: select_minor },
}
if selected?
props[:style][:backgroundColor] = 'lightblue'
props[:style][:color] = 'black'
props[:style][:border] = '1px solid'
end

children = [
h(:div, { style: header_style }, @game.company_header(minor)),
h(:div, minor.full_name),
h(:div, { style: description_style }, @game.private_description(minor)),
h(:div, { style: value_style }, "Value: #{@game.private_value(minor)}"),
h(:div, { style: revenue_style }, "Revenue: #{@game.private_revenue(minor)}"),
]

h('div.company.card', props, children)
end
end
end
end
22 changes: 14 additions & 8 deletions assets/app/view/game/button/buy_share.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,20 @@ def render
text += " (#{@game.format_currency(modified_price)})" if modified_price
text += " for #{@purchase_for.name}" if @purchase_for

h(:button, {
on: {
click: lambda {
buy_shares(@entity, bundle, share_price: modified_price, swap: @swap_share,
purchase_for: @purchase_for, borrow_from: @borrow_from)
},
},
}, text)
process_buy = lambda do
do_buy = lambda do
buy_shares(@entity, bundle, share_price: modified_price, swap: @swap_share,
purchase_for: @purchase_for, borrow_from: @borrow_from)
end

if (consenter = @game.consenter_for_buy_shares(@entity, bundle))
check_consent(@entity, consenter, do_buy)
else
do_buy.call
end
end

h(:button, { on: { click: process_buy } }, text)
end

def buy_shares(entity, bundle, share_price: nil, swap: nil, purchase_for: nil, borrow_from: nil)
Expand Down
2 changes: 1 addition & 1 deletion assets/app/view/game/buy_company_from_other_player.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def render_company_buy(input, company)
))
end

buy = -> { check_consent(company.owner, buy_company) }
buy = -> { check_consent(@game.current_entity, company.owner, buy_company) }

owner_name = company.owner.nil? ? 'the market' : company.owner.name
h(:button, { on: { click: buy } }, "Buy #{company.id} from #{owner_name}")
Expand Down
2 changes: 1 addition & 1 deletion assets/app/view/game/buy_trains.rb
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ def other_trains(other_corp_trains, corporation)
buy_train.call
end
else
check_consent(other_owner(other), buy_train)
check_consent(@corporation, other_owner(other), buy_train)
end
end

Expand Down
2 changes: 1 addition & 1 deletion assets/app/view/game/buy_value_input.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def render
if @selected_entity.owner == @corporation.owner || !@selected_entity.owner
buy.call
else
check_consent(@selected_entity.owner, buy)
check_consent(@corporation, @selected_entity.owner, buy)
end
end

Expand Down
25 changes: 17 additions & 8 deletions assets/app/view/game/dividend.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,33 @@ def render

corp_income = option[:corporation] + option[:divs_to_corporation]

new_share = entity.share_price

direction =
if new_share && option[:share_direction]
if (new_share_price = entity.share_price) && option[:share_direction]
moves = Array(option[:share_times]).zip(Array(option[:share_direction]))

moves.map do |times, dir|
times.times { new_share = @game.stock_market.find_relative_share_price(new_share, dir) }
movement_str =
moves.map do |times, dir|
real_moves = 0
times.times do
prev_price = new_share_price
new_share_price = @game.stock_market.find_relative_share_price(new_share_price, dir)
break if prev_price == new_share_price

real_moves += 1
end
next if real_moves.zero?

"#{real_moves} #{dir}"
end.compact.join(', ')

@step.respond_to?(:movement_str) ? @step.movement_str(times, dir) : "#{times} #{dir}"
end.join(', ')
movement_str.empty? ? 'None' : movement_str
else
'None'
end

if entity.loans.any? && !@game.can_pay_interest?(entity, corp_income) && @game.cannot_pay_interest_str
text += " #{@game.cannot_pay_interest_str}"
elsif new_share&.acquisition?
elsif new_share_price&.acquisition?
text += ' (Acquisition)'
end

Expand Down
Loading

0 comments on commit 5b0b38c

Please sign in to comment.