Skip to content

Commit

Permalink
Merge pull request #10127 from andrewzwicky/9615
Browse files Browse the repository at this point in the history
[18EU][18MT] Change default Pass optional to conditional in programmed auction bid, was causing infinite loops
  • Loading branch information
michaeljb authored Jan 25, 2024
2 parents 2565010 + 3f67508 commit 05da677
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/engine/step/programmer_auction_bid.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def activate_program_auction_bid(entity, program)
reason: "Price for #{target.name} exceeded maximum bid")]
end

[Action::Pass.new(entity)]
actions(entity).include?('pass') ? [Action::Pass.new(entity)] : []
end

def auto_buy?(_entity, program)
Expand Down
60 changes: 60 additions & 0 deletions spec/lib/engine/games/g_18eu_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# frozen_string_literal: true

require './spec/spec_helper'

require 'json'
require 'timeout'

module Engine
describe Game::G18EU do
let(:players) { %w[a b c] }

let(:actions) do
[
{ 'type' => 'bid', 'entity' => 'a', 'entity_type' => 'player', 'minor' => '1', 'price' => 100, 'id' => 1 },
{ 'type' => 'pass', 'entity' => 'b', 'entity_type' => 'player', 'id' => 2 },
{ 'type' => 'bid', 'entity' => 'c', 'entity_type' => 'player', 'minor' => '1', 'price' => 410, 'id' => 3 },
{ 'type' => 'pass', 'entity' => 'a', 'entity_type' => 'player', 'id' => 4 },
{
'type' => 'program_auction_bid',
'entity' => 'c',
'entity_type' => 'player',
'id' => 5,
'bid_target' => '15',
'enable_maximum_bid' => false,
'maximum_bid' => '100',
'enable_buy_price' => true,
'buy_price' => '60',
'auto_pass_after' => false,
},
{ 'type' => 'bid', 'entity' => 'b', 'entity_type' => 'player', 'minor' => '2', 'price' => 100, 'id' => 6 },
]
end

# issue 9615
# with the right combination of auto actions and player order, the auto actions could enter an infinite loop
# of continuous Pass actions. This test creates those conditions, attempting to trigger the loop,
# but protected by a timeout.

context '18EU programmed actions loop setup' do
let(:players) { %w[a b c] }
subject(:subject_with_actions) { Game::G18EU::Game.new(players, actions: actions) }

it 'should not enter infinite loop' do
expect(subject_with_actions.raw_actions.size).to be 6
expect(subject_with_actions.current_entity.name).to be players[0]
expect(subject.players.map(&:cash)).to eq([450, 450, 40])

Timeout.timeout(10) do
# Do not allow longer than 10 seconds to process pass action
action = Engine::Action::Pass.new(subject_with_actions.current_entity)
subject_with_actions.process_action(action, add_auto_actions: true)

expect(subject_with_actions.raw_actions.size).to be 7
expect(subject_with_actions.current_entity.name).to be players[2]
expect(subject.players.map(&:cash)).to eq([450, 350, 40])
end
end
end
end
end
45 changes: 45 additions & 0 deletions spec/lib/engine/games/g_18mt_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# frozen_string_literal: true

require './spec/spec_helper'

require 'json'

module Engine
describe Game::G18MT do
let(:players) { %w[a b c] }

let(:actions) do
[
{
'type' => 'program_auction_bid',
'entity' => 'c',
'entity_type' => 'player',
'id' => 1,
'bid_target' => 'GP',
'enable_maximum_bid' => false,
'maximum_bid' => '20',
'enable_buy_price' => true,
'buy_price' => '15',
'auto_pass_after' => false,
},
{ 'type' => 'bid', 'entity' => 'a', 'entity_type' => 'player', 'company' => 'GV', 'price' => 35, 'id' => 2 },

]
end

context '18MT programmed actions step' do
let(:players) { %w[a b c] }
subject(:subject_with_actions) { Game::G18MT::Game.new(players, actions: actions) }

it 'should pass if pass is an option' do
expect(subject_with_actions.raw_actions.size).to be 2
action = Engine::Action::Bid.new(subject_with_actions.current_entity, company: subject_with_actions.company_by_id('MW'),
price: 45)
subject_with_actions.process_action(action, add_auto_actions: true)

expect(subject_with_actions.raw_actions.size).to be 3
expect(subject_with_actions.current_entity.name).to be players[0]
end
end
end
end

0 comments on commit 05da677

Please sign in to comment.