summaryrefslogtreecommitdiffstats
path: root/lib/colonial_twilight/spaces.rb
diff options
context:
space:
mode:
authorJérémy Zurcher <jeremy@asynk.ch>2023-10-03 22:40:39 +0200
committerJérémy Zurcher <jeremy@asynk.ch>2023-10-03 22:40:39 +0200
commit1e45085b7730bdb9b0b0ed76e6613a9fac5136cd (patch)
tree96a8108a128b4b738f52af98b93cdb672e577d73 /lib/colonial_twilight/spaces.rb
parent85f520041046be2a184af31bff8a1d7ca0027f2a (diff)
downloadcolonial-twilight-1e45085b7730bdb9b0b0ed76e6613a9fac5136cd.zip
colonial-twilight-1e45085b7730bdb9b0b0ed76e6613a9fac5136cd.tar.gz
Board : split out spaces & forces
Diffstat (limited to 'lib/colonial_twilight/spaces.rb')
-rw-r--r--lib/colonial_twilight/spaces.rb212
1 files changed, 212 insertions, 0 deletions
diff --git a/lib/colonial_twilight/spaces.rb b/lib/colonial_twilight/spaces.rb
new file mode 100644
index 0000000..bc0bfbd
--- /dev/null
+++ b/lib/colonial_twilight/spaces.rb
@@ -0,0 +1,212 @@
+#! /usr/bin/env ruby
+# frozen_string_literal: true
+
+require 'colonial_twilight/forces'
+
+module ColonialTwilight
+ class Track
+ attr_accessor :v
+
+ def initialize(max)
+ @v = 0
+ @max = max
+ end
+
+ # FIXME: is that needed ?
+ # def shift(val)
+ # w = @v + val
+ # return false if w.negative? || w > @max
+ #
+ # @v = w
+ # true
+ # end
+
+ def clamp(val)
+ @v = (@v + val).clamp(0, @max)
+ end
+
+ def data
+ @v
+ end
+ end
+
+ class Box < Forces
+ end
+
+ class Sector
+ MOUNTAIN = 1
+ COASTAL = 2
+ BORDER = 4
+
+ attr_reader :wilaya, :sector, :name, :resettled
+ attr_accessor :pop, :terror, :adjacents, :alignment
+
+ def initialize(name, wilaya, sector, pop, attrs = 0)
+ @name = name
+ @wilaya = wilaya
+ @sector = sector
+ @pop = pop
+ @attrs = attrs
+ @alignment = :neutral
+ @resettled = false
+ @terror = 0
+ @forces = Forces.new self.class.name.split('::')[-1].to_sym
+ _compute_strings
+ end
+
+ private
+
+ def _compute_strings
+ @terrain = %i[mountain coastal border].map { |s| send("#{s}?") ? s : nil }.reject(&:nil?).join('/')
+ @descr = "#{@name} #{self.class.name.split('::')[-1]}#{number}"
+ end
+
+ def number
+ return '' if @wilaya.nil? && @sector.nil?
+
+ @descr = "(#{@wilaya}-#{@sector})"
+ end
+
+ public
+
+ def to_s
+ @name
+ end
+
+ def inspect
+ "\n#{@descr} : #{@terrain}
+ population : #{@pop}#{@resettled ? ' resettled' : ''}
+ control : #{control}
+ alignment : #{@alignment}
+ terror : #{@terror}
+ #{@forces}
+ adjs : #{@adjacents}"
+ end
+
+ def data
+ { name: @name, alignment: @alignment, terror: @terror, pop: @pop, resettled: @resettled }.merge(@forces.data)
+ end
+
+ %i[gov gov_bases gov_cubes french_cubes algerian_cubes troops police
+ french_troops french_police algerian_troops algerian_police
+ fln fln_bases fln_cubes fln_underground fln_active max_bases control].each do |sym|
+ define_method(sym) { @forces.send(sym) }
+ end
+
+ def sector?
+ true
+ end
+
+ def city?
+ false
+ end
+
+ def country?
+ false
+ end
+
+ def border?
+ (@attrs & BORDER) == BORDER
+ end
+
+ def coastal?
+ (@attrs & COASTAL) == COASTAL
+ end
+
+ def mountain?
+ (@attrs & MOUNTAIN) == MOUNTAIN
+ end
+
+ def support?
+ @alignment == :support
+ end
+
+ def oppose?
+ @alignment == :oppose
+ end
+
+ def neutral?
+ @alignment == :neutral
+ end
+
+ def uncontrolled?
+ control == :uncontrolled
+ end
+
+ def fln_control?
+ control == :FLN
+ end
+
+ def gov_control?
+ control == :GOV
+ end
+
+ def add(type, num = 1)
+ @forces.add(type, num)
+ end
+
+ def resettle!
+ raise "can't resettle a country " if country?
+ raise "can't resettle a sector with a population > 1" if @pop != 1
+
+ @pop = 0
+ @resettled = true
+ end
+
+ def shift(towards)
+ if towards == :oppose
+ raise "can't shift towards oppose" if oppose?
+
+ @alignment = (support? ? :neutral : :oppose)
+ elsif towards == :support
+ raise "can't shift towards support" if support?
+
+ @alignment = (oppose? ? :neutral : :support)
+ else
+ raise "unknown shift direction : #{towards}"
+ end
+ end
+ end
+
+ class City < Sector
+ def initialize(name, wilaya, pop, attrs = 0)
+ super name, wilaya, 0, pop, attrs
+ end
+
+ def sector?
+ false
+ end
+
+ def city?
+ true
+ end
+ end
+
+ # if independent, FLN may Rally, March and Extort in these Countries,
+ # but their Population is never counted in the total Opposition
+ class Country < Sector
+ attr_reader :independent
+
+ def initialize(name)
+ super(name, nil, nil, 1, MOUNTAIN | BORDER | COASTAL)
+ @descr += ' : French'
+ end
+
+ def sector?
+ false
+ end
+
+ def country?
+ true
+ end
+
+ def independent?
+ @independent
+ end
+
+ def independent!
+ @independent = true
+ @descr.gsub!(/French/, 'Independent')
+ end
+ end
+end