From 3011fbf0561570c0962e169a2d62d327edf19771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Zurcher?= Date: Tue, 24 Oct 2023 13:18:51 +0200 Subject: FLNBotRules : add #place_guerrillas_in, fix rally_7 --- lib/colonial_twilight/fln_bot_rules.rb | 40 +++++++++++++++---------- spec/fln_bot_rules_spec.rb | 55 +++++++++++++++++++++++----------- spec/mock_board.rb | 18 +++++++++-- 3 files changed, 79 insertions(+), 34 deletions(-) diff --git a/lib/colonial_twilight/fln_bot_rules.rb b/lib/colonial_twilight/fln_bot_rules.rb index 1049b82..78f06ba 100644 --- a/lib/colonial_twilight/fln_bot_rules.rb +++ b/lib/colonial_twilight/fln_bot_rules.rb @@ -6,10 +6,11 @@ module ColonialTwilight def dbg(msg, ret) return if @debug.zero? - case @debug - when 1 then puts " #{msg} : YES" if ret - else puts " #{msg} : #{ret ? 'YES' : 'NO'}" - end + s = case @debug + when 1 then " #{msg} : YES" if ret + else " #{msg} : #{ret ? 'YES' : 'NO'}" + end + puts s unless @debug == 666 end def pass?(board = @board) @@ -119,13 +120,11 @@ module ColonialTwilight end def rally_7_priority(spaces) - # highest population - _max(spaces, :pop).shuffle - end - - def rally_7_priority_after(spaces) - # in city, least terror - f = _filter(spaces, &:city?) + # highest population -> gain FLN control -> remove Gov control -> city -> least terror + f = _max(spaces, :pop) + f = _filter(f) { |s| s.gov < s.fln + place_guerrillas_in(s).values.sum } + f = _filter(f) { |s| s.gov == s.fln + place_guerrillas_in(s).values.sum } + f = _filter(f, &:city?) _min(f, :terror).shuffle end @@ -170,6 +169,17 @@ module ColonialTwilight max_placable_guerrillas(space).clamp(0, space.fln_bases.positive? ? (space.pop + 1 - space.guerrillas) : 666) end + def place_guerrillas_in(space, board = @board) + n = max_placable_guerrillas_in?(space) + h = { space: 0 } # do not select space + n -= h[:available] = (a = board.available_fln_underground) >= n ? n : a + while n.positive? && !(spaces = remove_guerrillas_priority(board.spaces, h)).empty? + s = spaces.sample + n -= h[s] = (g = removable_guerrillas(s)) >= n ? n : g + end + h + end + # 1) place: outofplay -> available | bases -> guerrillas if choice # 2) place: underground first unless from map then place active first flipped as underground # 3) march: underground -> active, unless march would activate then move active first @@ -189,14 +199,14 @@ module ColonialTwilight n.positive? ? n : 0 end - def not_selected(spaces, steps) - spaces.reject { |s| steps.key?(s) } + def not_selected(spaces, selected) + spaces.reject { |s| selected.key?(s) } end # FLNBot#_place_fln_in - def remove_guerrillas_priority(spaces, steps) + def remove_guerrillas_priority(spaces, selected) # 5) #removable_guerrillas then most guerrillas first - return [] if (l = not_selected(spaces, steps).select { |s| removable_guerrillas(s).positive? }).empty? + return [] if (l = not_selected(spaces, selected).select { |s| removable_guerrillas(s).positive? }).empty? _max(l, :guerrillas).shuffle end diff --git a/spec/fln_bot_rules_spec.rb b/spec/fln_bot_rules_spec.rb index a841b67..8667a11 100644 --- a/spec/fln_bot_rules_spec.rb +++ b/spec/fln_bot_rules_spec.rb @@ -9,7 +9,7 @@ class FLNRulesImpl attr_writer :limited_op_only, :first_eligible, :will_be_next_first_eligible def initialize - @debug = 0 + @debug = 666 @board = Board.new @limited_op_only = true @first_eligible = true @@ -305,31 +305,42 @@ describe ColonialTwilight::FLNBotRules do expect(@rules.may_rally_7_in?(a)).to be false end - it 'rally_7_priority_after city?' do - a = Sector.new({ name: 'city' }) - b = Sector.new - expect(@rules.rally_7_priority_after([a, b])[0]).to be a + it 'rally_7_priority population' do + a = Sector.new({ pop: 2 }) + b = Sector.new({ pop: 1 }) + c = Sector.new({ pop: 1 }) + expect(@rules.rally_7_priority([a, b, c])[0]).to be a end - it 'rally_7_priority_after least terror' do - a = Sector.new - b = Sector.new({ name: 'city', terror: 1 }) - c = Sector.new({ name: 'city', terror: 2 }) - expect(@rules.rally_7_priority_after([a, b, c])[0]).to be b + it 'rally_7_priority gain FLN control' do + a = Sector.new({ gov_cubes: 2 }) + b = Sector.new({ gov_cubes: 1, fln_active: 1 }) + c = Sector.new({ gov_cubes: 1 }) + @board.available_fln_underground = 1 + expect(@rules.rally_7_priority([a, b, c])[0]).to be b end - it 'rally_7_priority population' do - a = Sector.new({ pop: 2 }) - b = Sector.new({ pop: 1 }) - expect(@rules.rally_7_priority([a, b])[0]).to be a + it 'rally_7_priority remove GOV control' do + a = Sector.new({ gov_cubes: 3 }) + b = Sector.new({ gov_cubes: 1 }) + c = Sector.new({ gov_cubes: 2 }) + @board.available_fln_underground = 1 + expect(@rules.rally_7_priority([a, b, c])[0]).to be b end - it 'rally_7_priority population' do - a = Sector.new({ pop: 2 }) - b = Sector.new({ pop: 1 }) + it 'rally_7_priority city?' do + a = Sector.new({ name: 'city' }) + b = Sector.new expect(@rules.rally_7_priority([a, b])[0]).to be a end + it 'rally_7_priority least terror' do + a = Sector.new + b = Sector.new({ name: 'city', terror: 1 }) + c = Sector.new({ name: 'city', terror: 2 }) + expect(@rules.rally_7_priority([a, b, c])[0]).to be b + end + it 'may_rally_8_in? no fln guerrillas' do a = Sector.new expect(@rules.may_rally_8_in?(a)).to be false @@ -417,6 +428,16 @@ describe ColonialTwilight::FLNBotRules do expect(@rules.max_placable_guerrillas_in?(a)).to eq(1) end + it 'place_guerrillas_in' do + a = Sector.new({ pop: 2, fln_bases: 1 }) + @board.available_fln_underground = 1 + @board.spaces << Sector.new({ name: 'a', fln_bases: 1, fln_active: 2, fln_underground: 1 }) + h = @rules.place_guerrillas_in(a) + expect(@rules.max_placable_guerrillas_in?(a)).to eq(3) + expect(h[:available]).to eq(1) + expect(h[@board.spaces[0]]).to eq(1) + end + it 'removable_guerrillas active' do a = Sector.new({ fln_active: 2, fln_underground: 3 }) expect(@rules.removable_guerrillas(a)).to eq(2) diff --git a/spec/mock_board.rb b/spec/mock_board.rb index e75ba73..34c5272 100644 --- a/spec/mock_board.rb +++ b/spec/mock_board.rb @@ -57,19 +57,33 @@ class Sector @data[:fln_underground] || 0 end + def fln + fln_active + fln_underground + fln_bases + end + def gov_cubes @data[:gov_cubes] || 0 end + + def gov_bases + @data[:gov_bases] || 0 + end + + def gov + gov_cubes + gov_bases + end end class Board - attr_reader :sector - attr_accessor :fln_resources, :available_fln_bases + attr_reader :sector, :spaces + attr_accessor :fln_resources, :available_fln_underground, :available_fln_bases def initialize @fln_resources = 0 @available_fln_bases = 1 + @available_fln_underground = 0 @sector = Sector.new + @spaces = [] end def has(&block) -- cgit v1.1-2-g2b99