summaryrefslogtreecommitdiffstats
path: root/lib/colonial_twilight
diff options
context:
space:
mode:
Diffstat (limited to 'lib/colonial_twilight')
-rw-r--r--lib/colonial_twilight/board.rb302
1 files changed, 209 insertions, 93 deletions
diff --git a/lib/colonial_twilight/board.rb b/lib/colonial_twilight/board.rb
index 3a1679a..473d0c1 100644
--- a/lib/colonial_twilight/board.rb
+++ b/lib/colonial_twilight/board.rb
@@ -23,7 +23,7 @@ module ColonialTwilight
attr_accessor :french_troops, :french_police
attr_accessor :fln_underground, :fln_active
attr_accessor :fln_bases, :gov_bases
- attr_reader :control
+ attr_reader :max_bases, :control
def initialize k
@algerian_troops = 0
@@ -34,8 +34,8 @@ module ColonialTwilight
@fln_underground = 0
@fln_active = 0
@fln_bases = 0
- @max_bases = 2
- @control = :none
+ @max_bases = nil
+ @control = :uncontrolled
rm = nil
case k
when :available
@@ -45,12 +45,13 @@ module ColonialTwilight
when :out_of_play
rm = [:@control, :@algerian_troops, :@algerian_police, :@fln_active, :@fln_bases]
when :Country
- @max_bases = 3
+ @max_bases = 2
rm = [:@control, :@algerian_troops, :@algerian_police, :@french_troops, :@french_police, :@gov_bases]
+ when :Sector
+ @max_bases = 2
end
rm.each do |sym|
- # maybe remove :sym= instead or set @sym to nil
- remove_instance_variable sym
+ instance_variable_set(sym, nil)
end unless rm.nil?
end
@@ -76,7 +77,39 @@ module ColonialTwilight
end
def bases
- @gov_bases||0 + @fln_bases||0
+ (@gov_bases||0) + (@fln_bases||0)
+ end
+
+ def fln
+ guerrillas + (@fln_bases||0)
+ end
+
+ def guerrillas
+ (@fln_underground||0) + (@fln_active||0)
+ end
+
+ def gov
+ gov_cubes + (@gov_bases||0)
+ end
+
+ def gov_cubes
+ french_cubes + algerian_cubes
+ end
+
+ def french_cubes
+ (@french_troops||0) + (@french_police||0)
+ end
+
+ def algerian_cubes
+ (@algerian_troops||0) + (@algerian_police||0)
+ end
+
+ def troops
+ (@french_troops||0) + (@algerian_troops||0)
+ end
+
+ def police
+ (@french_police||0) + (@algerian_police||0)
end
def add t, n=1
@@ -87,29 +120,31 @@ module ColonialTwilight
when :algerian_police; @algerian_police += n
when :fln_underground; @fln_underground += n
when :fln_active; @fln_active += n
+ when :gov_base; add_base :gov_base, n
+ when :fln_base; add_base :fln_base, n
else
raise "unknown force type : #{t}"
end
update_control
end
+ private
+
def add_base t, n=1
- raise "too much bases in #@name (#{bases} + #{n}) > #@max_bases" if (bases + n) > @max_bases
- @gov_bases += n if t == :gov
- @fln_bases += n if t == :fln
- update_control
+ raise "too much bases in #@name (#{bases} + #{n}) > #@max_bases" if not @max_bases.nil? and (bases + n) > @max_bases
+ @gov_bases += n if t == :gov_base
+ @fln_bases += n if t == :fln_base
end
- private
-
def update_control
return if @control.nil?
- gov = @algerian_troops + @algerian_police + @french_troops + @french_police + @gov_bases
- fln = @fln_underground + @fln_active + @fln_bases
- if gov == fln; @control = :none
- elsif gov > fln; @control = :GOV
- else @control = :FLN
- end
+ @control = (
+ case gov <=> fln
+ when 0; :uncontrolled
+ when 1; :GOV
+ when -1; :FLN
+ end
+ )
end
end
@@ -121,7 +156,7 @@ module ColonialTwilight
BORDER=4
attr_reader :wilaya, :sector, :name, :resettled
- attr_accessor :pop, :adjacents
+ attr_accessor :pop, :terror, :adjacents
attr_accessor :alignment
def initialize n, w, s, p, attrs=0
@@ -129,6 +164,7 @@ module ColonialTwilight
@wilaya = w
@sector = s
@pop = p
+ @terror = 0
@attributes = attrs
@descr = "#{self.class.name} #@name #{@wilaya == 0 ? '' : @wilaya}" + (@sector == 0 ? '' : "-#{@sector}")
@terrain = [mountain? ? 'mountain' : nil ,coastal? ? 'coastal' : nil, border? ? 'border' : nil].reject(&:nil?).join '/'
@@ -141,13 +177,20 @@ module ColonialTwilight
"#@descr #@terrain
control : #{@forces.control}
alignment : #@alignment
+ terror : #@terror
population : #{@pop}#{@resettled ? ' resettled' : ''}
forces : #{@forces}
adjs : #{@adjacents}"
end
def data
- { :name=>@name, :alignment=>@alignment, :pop=>@pop, :resettled=>@resettled }.merge(@forces.data)
+ { :name=>@name, :alignment=>@alignment, :terror=>@terror, :pop=>@pop, :resettled=>@resettled }.merge(@forces.data)
+ end
+
+ [:gov, :gov_cubes, :french_cubes, :algerian_cubes, :troops, :police, :gov_bases, :french_troops, :french_police, :algerian_troops, :algerian_police,
+ :fln, :guerrillas, :fln_bases, :fln_underground, :fln_active,
+ :max_bases].each do |sym|
+ define_method sym do @forces.send(sym) end
end
def city?; false; end
@@ -155,23 +198,28 @@ module ColonialTwilight
def border?; (@attributes & BORDER) == BORDER end
def coastal?; (@attributes & COASTAL) == COASTAL end
def mountain?; (@attributes & MOUNTAIN) == MOUNTAIN end
- def control; @forces.control; end
- def add_gov_base n=1; @forces.add_base :gov, n; end
- def add_fln_base n=1; @forces.add_base :fln, n; end
- def add_french_troops n=1; @forces.add :french_troops, n; end
- def add_french_police n=1; @forces.add :french_police, n; end
- def add_algerian_troops n=1; @forces.add :algerian_troops, n; end
- def add_algerian_police n=1; @forces.add :algerian_police, n; end
- def add_fln_underground n=1; @forces.add :fln_underground, n; end
- def add_fln_active n=1; @forces.add :fln_active, n; end
- def french_troops; @forces.french_troops end
- def french_police; @forces.french_police end
- def algerian_troops; @forces.algerian_troops end
- def algerian_police; @forces.algerian_police end
- def fln_underground; @forces.fln_underground end
- def fln_active; @forces.fln_active end
- def gov_bases; @forces.gov_bases end
- def fln_bases; @forces.fln_bases end
+ def support?; @alignment == :support end
+ def oppose?; @alignment == :oppose end
+ def neutral?; @alignment == :neutral end
+ def control; @forces.control end
+ def uncontrolled?; @forces.control == :uncontrolled end
+ def fln_control?; @forces.control == :FLN end
+ def gov_control?; @forces.control == :GOV end
+ def has_terror?; terror > 0 end
+ def has_gov?; not gov_bases_0? or not gov_cubes_0? end
+ def has_fln?; not fln_bases_0? or fln > 0 end
+ def gov_bases_0?; gov_bases == 0 end
+ def fln_bases_0?; fln_bases == 0 end
+ def gov_bases_1m?; gov_bases > 0 end
+ def fln_bases_1m?; fln_bases > 0 end
+ def pop0?; pop == 0 end
+ def gov_cubes_0?; gov_cubes == 0 end
+ def add t, n=1; @forces.add t, n end
+ def fln_u_1l?; fln_underground < 2 end
+ def fln_u_0?; fln_underground == 0 end
+ def fln_u_1m?; fln_underground > 0 end
+ def fln_u_2m?; fln_underground > 1 end
+ def fln_u_3m?; fln_underground > 2 end
def resettle!
raise "can't resettle a country " if country?
raise "can't resettle a sector with a population > 1" if @pop != 1
@@ -179,6 +227,17 @@ module ColonialTwilight
@resettled = true
end
+ def shift towards
+ if towards == :oppose
+ raise "can't shift towards oppose" if oppose?
+ @alignment = (support? ? :neutral : :oppose)
+ end
+ if towards == :support
+ raise "can't shift towards support" if support?
+ @alignment = (oppose? ? :neutral : :support)
+ end
+ end
+
end
class City < Sector
@@ -192,8 +251,8 @@ module ColonialTwilight
attr_reader :independant
- def initialize n
- super n, 0, 0, 1, MOUNTAIN|BORDER|COASTAL
+ def initialize n, w
+ super n, w, 0, 1, MOUNTAIN|BORDER|COASTAL
@descr += " #{@independant ? 'Independant' : 'French'}"
end
def add_gov_base n=1; raise "no gov bases allowed in #@name" end
@@ -203,37 +262,90 @@ module ColonialTwilight
class Board
- FRANCE_TRACK=['A','B','C','D','E'].freeze
+ FRANCE_TRACK=['A','B','C','D','E','F'].freeze
attr_accessor :commitment
attr_accessor :gov_resources, :fln_resources
- attr_accessor :support_commitment, :opposition_bases
+ attr_accessor :support_commitment,:opposition_bases
attr_accessor :resettled_sectors
attr_accessor :france_track, :border_zone_track
- attr_reader :spaces, :names
+ attr_reader :spaces, :sectors, :cities, :countries
+ attr_reader :spaces_h
def initialize
@names = []
- @spaces = {}
+ @spaces_h = {}
@capabilities = []
@available = Forces.new :available
@casualties = Forces.new :casualties
@out_of_play = Forces.new :out_of_play
feed
+ @spaces = @spaces_h.values
+ @sectors = @spaces.select { |s| not s.country? }
+ @cities = @spaces.select { |s| s.city? }
+ @countries = @spaces.select { |s| s.country? }
end
- def load scenario
- case scenario
- when :short; short
- when :medium; medium
- when :full; full
- else raise "unknown scenario : #{scenario}"
+ [:gov_bases, :french_troops, :french_police, :algerian_troops, :algerian_police,
+ :fln_bases, :fln_underground].each do |sym|
+ define_method "available_#{sym}" do @available.send(sym) end
+ # define_method "casualties_#{sym}" do @casualties.send(sym) end
+ # define_method "out_of_play_#{sym}" do @out_of_play.send(sym) end
+ end
+
+ def transfer n, what, from, to, towhat=nil
+ from = (from.is_a?(Sector) ? from : get_local(from) )
+ to = (to.is_a?(Sector) ? to : get_local(to) )
+ from.add what, -n
+ to.add towhat, n
+ end
+
+ def terror where, n
+ where.terror += n
+ end
+
+ def shift where, towards, n=1
+ n.times do
+ where.shift towards
end
end
- def sectors
- @spaces.select{ |k,s| not s.country? }
+ def shift_france_track dt
+ ft = @france_track + dt
+ return false if (ft < 0 or ft > 5)
+ @france_track = ft
+ true
+ end
+
+ def has where=:spaces, &block
+ r = search &block
+ r.length > 0
+ end
+
+ def search where=:spaces, &block
+ send(where).select &block
+ end
+
+ def count where=:spaces, &block
+ send(where).inject(0) {|i,s| i + block.call(s) }
+ end
+
+ def resettle sector
+ @spaces_h[sector].resettle!
+ @resettled_sectors += 1
+ end
+
+ def compute_victory_points
+ values = [@support_commitment, @opposition_bases]
+ @opposition_bases = 0
+ @support_commitment = @commitment
+ @spaces_h.each do |n,s|
+ @opposition_bases += s.fln_bases
+ @opposition_bases += s.pop if s.alignment == :oppose
+ @support_commitment += s.pop if s.alignment == :support
+ end
+ values << @support_commitment << @opposition_bases
end
def data
@@ -245,7 +357,7 @@ module ColonialTwilight
h[:available] = @available.data
h[:casualties] = @casualties.data
h[:out_of_play] = @out_of_play.data
- h[:spaces] = @spaces.inject([])do |a,(k,s)| a << s.data end
+ h[:spaces] = @spaces_h.inject([])do |a,(k,s)| a << s.data end
h
end
@@ -260,34 +372,38 @@ module ColonialTwilight
end
end
- def resettle sector
- @spaces[sector].resettle!
- @resettled_sectors += 1
- end
-
- def compute_victory
- @opposition_bases = 0
- @support_commitment = @commitment
- @spaces.each do |n,s|
- @opposition_bases += s.fln_bases
- @opposition_bases += s.pop if s.alignment == :oppose
- @support_commitment += s.pop if s.alignment == :support
+ def load scenario
+ case scenario
+ when :short; short
+ when :medium; medium
+ when :full; full
+ else raise "unknown scenario : #{scenario}"
end
end
private
+ def get_local sym
+ case sym
+ when :available; return @available
+ when :casualties; return @casualties
+ when :out_of_play; return @out_of_play
+ else
+ raise "unknown Board variable named #{sym}"
+ end
+ end
+
def add k, *args
s = k.new *args
# puts s
@names << s.name
- @spaces[s.name] = s
+ @spaces_h[s.name] = s
end
def adjacents i, *args
- @spaces[@names[i]].adjacents = args
- # @spaces[@names[i]].adjacents = args.map { |i| @names[i] }
- # puts @spaces[@names[i]]
+ @spaces_h[@names[i]].adjacents = args
+ # @spaces_h[@names[i]].adjacents = args.map { |i| @names[i] }
+ # puts @spaces_h[@names[i]]
end
def feed
@@ -322,8 +438,8 @@ module ColonialTwilight
add Sector, 'Laghouat', 'V', 9, 0 # 25
add Sector, 'Sidi Aissa', 'VI', 1, 0, mountain # 26
add Sector, 'Ain Oussera', 'VI', 2, 1, mountain # 27
- add Country, 'Moroco' # 28
- add Country, 'Tunisia' # 29
+ add Country, 'Moroco', 0 # 28
+ add Country, 'Tunisia', 1 # 29
adjacents 0, 1, 2, 3, 7, 8, 11, 19
adjacents 1, 0, 2, 3, 5
adjacents 2, 0, 1, 5, 25, 26, 29
@@ -357,15 +473,15 @@ module ColonialTwilight
end
def set_sector i, h, align=nil
- s = @spaces[@names[i]]
+ s = @spaces_h[@names[i]]
s.alignment = align unless align.nil?
- s.add_gov_base h[:govb] if h.has_key? :govb
- s.add_fln_base h[:flnb] if h.has_key? :flnb
- s.add_french_troops h[:ft] if h.has_key? :ft
- s.add_french_police h[:fp] if h.has_key? :fp
- s.add_algerian_troops h[:at] if h.has_key? :at
- s.add_algerian_police h[:ap] if h.has_key? :ap
- s.add_fln_underground h[:fln] if h.has_key? :fln
+ s.add :gov_base, h[:govb] if h.has_key? :govb
+ s.add :fln_base, h[:flnb] if h.has_key? :flnb
+ s.add :french_troops, h[:ft] if h.has_key? :ft
+ s.add :french_police, h[:fp] if h.has_key? :fp
+ s.add :algerian_troops, h[:at] if h.has_key? :at
+ s.add :algerian_police, h[:ap] if h.has_key? :ap
+ s.add :fln_underground, h[:fln] if h.has_key? :fln
# puts s
end
@@ -410,9 +526,9 @@ module ColonialTwilight
set_sector 27, {}, :oppose
set_sector 28, {:fln=>4, :flnb=>2}
set_sector 29, {:fln=>5, :flnb=>2}
- compute_victory
- raise "wrong opposition bases" if @opposition_bases != 19
- raise "wrong support_commitment" if @support_commitment != 22
+ compute_victory_points
+ raise "wrong opposition + bases" if @opposition_bases != 19
+ raise "wrong support + commitment" if @support_commitment != 22
end
def medium
@@ -434,21 +550,21 @@ end
if $PROGRAM_NAME == __FILE__
def check b
# puts '--- Coastal'
- # b.spaces.select{ |k,s| s.coastal? }.each { |k,s| puts s.name }
- raise "coastal sectors error" if b.spaces.select{ |k,s| s.coastal? }.size != 14
+ # b.spaces.select{ |s| s.coastal? }.each { |s| puts s.name }
+ raise "coastal sectors error" if b.spaces.select{ |s| s.coastal? }.size != 14
# puts '--- not Mountain'
- # b.spaces.select{ |k,s| not s.mountain? }.each { |k,s| puts s.name }
- raise "not moauntain sectors error" if b.spaces.select{ |k,s| not s.mountain? }.size != 9
+ # b.spaces.select{ |s| not s.mountain? }.each { |s| puts s.name }
+ raise "not moauntain sectors error" if b.spaces.select{ |s| not s.mountain? }.size != 9
# puts '--- Border'
- # b.spaces.select{ |k,s| s.border? }.each { |k,s| puts s.name }
- raise "border sectors error" if b.spaces.select{ |k,s| s.border? }.size != 9
+ # b.spaces.select{ |s| s.border? }.each { |s| puts s.name }
+ raise "border sectors error" if b.spaces.select{ |s| s.border? }.size != 9
# puts '--- City'
- # b.spaces.select{ |k,s| s.city? }.each { |k,s| puts s.name }
- raise "city sectors error" if b.spaces.select{ |k,s| s.city? }.size != 3
+ # b.spaces.select{ |s| s.city? }.each { |s| puts s.name }
+ raise "city sectors error" if b.spaces.select{ |s| s.city? }.size != 3
[[0,11],[1,9],[2,9],[3,1]].each do |p,n|
# puts "--- Population #{p}"
- # b.spaces.select{ |k,s| s.pop==p }.each { |k,s| puts s.name }
- raise "population #{p} error" if b.spaces.select{ |k,s| s.pop==p}.size != n
+ # b.spaces.select{ |s| s.pop==p }.each { |s| puts s.name }
+ raise "population #{p} error" if b.spaces.select{ |s| s.pop==p}.size != n
end
raise "sectors count wrong" if b.sectors.size != 28
end
@@ -457,7 +573,7 @@ if $PROGRAM_NAME == __FILE__
sup, opp, gov, fln = 0, 0, 0, 0
ft, fp, at, ap, g = 0, 0, 0, 0, 0
gb, fb = 0, 0
- b.spaces.each do |n,s|
+ b.spaces.each do |s|
sup += 1 if s.alignment == :support
opp += 1 if s.alignment == :oppose
gov += 1 if s.control == :GOV