summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/colonial_twilight/fln_bot_rules.rb40
-rw-r--r--spec/fln_bot_rules_spec.rb55
-rw-r--r--spec/mock_board.rb18
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)