summaryrefslogtreecommitdiffstats
path: root/lib/colonial_twilight/forces.rb
blob: 4991c891d0f50406c5199a5d738a22cd8ae0b4da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#! /usr/bin/env ruby
# frozen_string_literal: true

# rubocop:disable Style/AccessorGrouping
# rubocop:disable Style/ParallelAssignment

module ColonialTwilight
  class Forces
    attr_reader :name
    attr_reader :algerian_troops, :algerian_police
    attr_reader :french_troops, :french_police
    attr_reader :fln_underground, :fln_active
    attr_reader :fln_bases, :gov_bases
    attr_reader :max_bases, :control

    def initialize(sym)
      @name = sym
      @algerian_troops, @algerian_police = 0, 0
      @french_troops, @french_police, @gov_bases = 0, 0, 0
      @fln_underground, @fln_active, @fln_bases = 0, 0, 0
      @max_bases = nil
      @control = :uncontrolled
      @max_bases = 2 if %i[Country Sector].include? sym
      _variables_to_remove(sym)&.each do |s|
        instance_variable_set(s, nil)
      end
    end

    def init(data)
      data.each { |k, v| add(k, v) }
    end

    private

    def _variables_to_remove(sym)
      case sym
      when :available then %i[@control @fln_active]
      when :casualties then %i[@control @fln_active @fln_bases]
      when :out_of_play then %i[@control @algerian_troops @algerian_police @fln_active @fln_bases]
      when :Country then %i[@control @algerian_troops @algerian_police @french_troops @french_police]
      when :City then nil
      when :Sector then nil
      end
    end

    public

    def inspect
      "GOV bases: #{gov_bases}
        french troops: #{french_troops}
        french police: #{french_police}
        algerian troops: #{algerian_troops}
        algerian police: #{algerian_police}
      FLN bases: #{fln_bases}
        underground Guerrillas: #{fln_underground}
        active Guerrillas: #{fln_active}"
    end
    alias to_s inspect

    def data
      h = {}
      %i[algerian_troops algerian_police french_troops french_police gov_bases
         fln_underground fln_active fln_bases control].each do |sym|
        h[sym] = send(sym) unless send(sym).nil?
      end
      h
    end

    def bases
      (@gov_bases || 0) + (@fln_bases || 0)
    end

    def fln
      fln_cubes + (@fln_bases || 0)
    end

    def fln_cubes
      (@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(type, num = 1)
      case type
      when :french_troops then @french_troops += num
      when :french_police then @french_police += num
      when :algerian_troops then @algerian_troops += num
      when :algerian_police then @algerian_police += num
      when :fln_underground then @fln_underground += num
      when :fln_active then @fln_active.nil? ? @fln_underground += num : @fln_active += num
      when :gov_base then add_base(:gov_base, num)
      when :fln_base then add_base(:fln_base, num)
      else
        raise "unknown force type : #{type}"
      end
      update_control
    end

    private

    def add_base(type, num = 1)
      if !@max_bases.nil? && (bases + num) > @max_bases
        raise "too much bases in #{@name} (#{bases} + #{num}) > #{@max_bases}"
      end

      @gov_bases += num if type == :gov_base
      @fln_bases += num if type == :fln_base
    end

    def update_control
      return nil if @control.nil?

      ctr = @control
      @control = (
          case gov <=> fln
          when  0 then :uncontrolled
          when  1 then :GOV
          when -1 then :FLN
          end
        )
      @control != ctr
    end
  end
end