diff options
| author | Jérémy Zurcher <jeremy@asynk.ch> | 2026-03-15 21:42:14 +0100 |
|---|---|---|
| committer | Jérémy Zurcher <jeremy@asynk.ch> | 2026-03-15 21:42:14 +0100 |
| commit | f0c2066e3ffffe3212658313cd6e30d85028412c (patch) | |
| tree | 7fffcf8fcde438d1a565e154a52909fa6c054832 /lib/colonial_twilight/actions | |
| parent | e4e09f936d38a89082f40354fdf451ad875baffa (diff) | |
| download | colonial-twilight-f0c2066e3ffffe3212658313cd6e30d85028412c.zip colonial-twilight-f0c2066e3ffffe3212658313cd6e30d85028412c.tar.gz | |
implement FLN action & operations
Diffstat (limited to 'lib/colonial_twilight/actions')
| -rw-r--r-- | lib/colonial_twilight/actions/action.rb | 2 | ||||
| -rw-r--r-- | lib/colonial_twilight/actions/fln/agitate.rb | 2 | ||||
| -rw-r--r-- | lib/colonial_twilight/actions/fln/ambush.rb | 35 | ||||
| -rw-r--r-- | lib/colonial_twilight/actions/fln/attack.rb | 57 | ||||
| -rw-r--r-- | lib/colonial_twilight/actions/fln/extort.rb | 35 | ||||
| -rw-r--r-- | lib/colonial_twilight/actions/fln/march.rb | 62 | ||||
| -rw-r--r-- | lib/colonial_twilight/actions/fln/oas.rb | 33 | ||||
| -rw-r--r-- | lib/colonial_twilight/actions/fln/rally.rb | 2 | ||||
| -rw-r--r-- | lib/colonial_twilight/actions/fln/subvert.rb | 62 | ||||
| -rw-r--r-- | lib/colonial_twilight/actions/fln/terror.rb | 33 |
10 files changed, 320 insertions, 3 deletions
diff --git a/lib/colonial_twilight/actions/action.rb b/lib/colonial_twilight/actions/action.rb index 3be8483..4b7ea6c 100644 --- a/lib/colonial_twilight/actions/action.rb +++ b/lib/colonial_twilight/actions/action.rb @@ -67,7 +67,7 @@ module ColonialTwilight end def available_modes(_space) - nil + {} end def possible_spaces(board) diff --git a/lib/colonial_twilight/actions/fln/agitate.rb b/lib/colonial_twilight/actions/fln/agitate.rb index fd0e287..8434662 100644 --- a/lib/colonial_twilight/actions/fln/agitate.rb +++ b/lib/colonial_twilight/actions/fln/agitate.rb @@ -34,7 +34,7 @@ module ColonialTwilight # with Base and or Control && terror or shift to oppose possible def applicable?(space) - Rally.applicable?(space) && + Rally.applicable?(space) && !space.country? && (space.fln_bases.positive? || space.fln_control?) && (space.terror.positive? || !space.oppose?) end diff --git a/lib/colonial_twilight/actions/fln/ambush.rb b/lib/colonial_twilight/actions/fln/ambush.rb new file mode 100644 index 0000000..9756c55 --- /dev/null +++ b/lib/colonial_twilight/actions/fln/ambush.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require_relative 'fln_action' + +module ColonialTwilight + module Actions + module FLN + # Ambush 4.3.3 : max 2 + class Ambush < FlnAction + def initialize(space) + super(space, {}, cost: 0) + end + + # Activate only 1 Underground Guerrilla + # Remove 1 Government piece (Police first, then Troops, then Base) into casualties + # No Attrition + # -1 Commitment per French Base removed + def apply!(board) + raise NotImplementedError + end + + class << self + def special? + true + end + + # any space where an Attack is occurring with Underground Guerrillas. + def applicable?(space) + Attack.applicable?(space) && space.fln_underground.positive? + end + end + end + end + end +end diff --git a/lib/colonial_twilight/actions/fln/attack.rb b/lib/colonial_twilight/actions/fln/attack.rb new file mode 100644 index 0000000..298f28e --- /dev/null +++ b/lib/colonial_twilight/actions/fln/attack.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +require_relative 'fln_action' +require_relative 'ambush' + +module ColonialTwilight + module Actions + module FLN + # Attack 3.3.3 + class Attack < FlnAction + def initialize(space) + super(space, {}, cost: 1) + @ambush = nil + end + + # can be combined with Ambush (replaces Attack procedure) + def ambush! + raise 'ambush! called twice' unless @ambush.nil? + + @ambush = Ambush.new(space) + self + end + + + # def validate! + # super + # raise 'select conduct mode' unless mode.key?(:conduct) + # end + + # Activate all Guerrillas in the space + # Roll 1d6: if result is less than or equal to number of Guerrillas + # remove up to 2 Gov pieces (Police first, then Troops, then Base) into casualties + # If result is a 1, add 1 underground Guerrillas + # Attrition (not Ambush) : for each French piece removed : remove 1 FLN Guerrillas (alternate available / casualties) + # -1 Commitment per French Base removed + def apply!(board) + raise NotImplementedError + end + + class << self + def op? + true + end + + # any space with FLN cubes and Gov pieces + def applicable?(space) + space.guerrillas.positive? && space.gov.positive? + end + + # def available_modes(_space) + # { conduct: 1 } + # end + end + end + end + end +end diff --git a/lib/colonial_twilight/actions/fln/extort.rb b/lib/colonial_twilight/actions/fln/extort.rb new file mode 100644 index 0000000..58b4e18 --- /dev/null +++ b/lib/colonial_twilight/actions/fln/extort.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require_relative 'fln_action' + +module ColonialTwilight + module Actions + module FLN + # Extort 4.3.1 + class Extort < FlnAction + def initialize(space, mode) + super(space, mode, cost: 0) + end + + # flip 1 Underground Guerrilla to Active + # add 1 Resources to FLN track per space. + def apply!(board) + raise NotImplementedError + end + + class << self + def special? + true + end + + # any space with Population, Underground Guerrillas, and FLN Control + # also Morocco/Tunisia if Independent and have Underground Guerrillas + def applicable?(space) + space.fln_underground.positive? && + (space.country? ? space.independent? : space.pop.positive? && space.fln_control?) + end + end + end + end + end +end diff --git a/lib/colonial_twilight/actions/fln/march.rb b/lib/colonial_twilight/actions/fln/march.rb new file mode 100644 index 0000000..e738733 --- /dev/null +++ b/lib/colonial_twilight/actions/fln/march.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +require_relative 'fln_action' + +module ColonialTwilight + module Actions + module FLN + # March 3.3.2 + class March < FlnAction + def initialize(space, mode) + super(space, mode, cost: 1) + end + + def cost + # Cost is 1 Resource per destination space moved into + mode.keys.size + end + + def validate! + super + raise 'select at least 1 destination' if mode.empty? + + total_moved = mode.values.sum + raise "total moved #{total_moved} exceeds available #{space.guerrillas}" if total_moved > space.guerrillas + end + + # move any number of Guerrillas to adjacent spaces as a group + def apply!(board) + raise NotImplementedError + end + + class << self + def op? + true + end + + # any space with FLN cubes + def applicable?(space) + space.guerrillas.positive? + end + + def available_modes(space) + space.adjacents.to_h { |idx| [idx, space.guerrillas] } + end + + # the group must stop if moving across a Wilaya border or an International border + def must_stop?(space_from, space_to) + space_from.wilaya != space_to.wilaya || space_from.country? || space_to.country? + end + + # if destination is at Support: activate group if moved FLN + Gov cubes > 3 + # when crossing International border: activate group if moved FLN + Gov cubes + Border level > 3 + def must_activate?(board, space_from, space_to, num = 1) + international = space_from.country? || space_to.country? + (international || space_to.support?) && + (num + space_to.gov_cubes + (international ? board.border_zone_track : 0)) > 3 + end + end + end + end + end +end diff --git a/lib/colonial_twilight/actions/fln/oas.rb b/lib/colonial_twilight/actions/fln/oas.rb new file mode 100644 index 0000000..6d38e0f --- /dev/null +++ b/lib/colonial_twilight/actions/fln/oas.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require_relative 'fln_action' + +module ColonialTwilight + module Actions + module FLN + # OAS 5.3.1 + class Oas < FlnAction + def initialize(space, mode) + super(space, mode, cost: 0) + end + + # add 1 Terror, set to Neutral + # GOV lose Commitment equal to Population, FLN lose Resources equal to twice Population. + def apply!(board) + raise NotImplementedError + end + + class << self + def special? + true + end + + # 1 populated space with no Terror not Country. + def applicable?(space) + !space.country? && space.pop.positive? && space.terror.zero? + end + end + end + end + end +end diff --git a/lib/colonial_twilight/actions/fln/rally.rb b/lib/colonial_twilight/actions/fln/rally.rb index c9ed489..bfa7ab2 100644 --- a/lib/colonial_twilight/actions/fln/rally.rb +++ b/lib/colonial_twilight/actions/fln/rally.rb @@ -9,7 +9,7 @@ module ColonialTwilight # Rally 3.3.1 class Rally < FlnAction def initialize(space, mode) - super(space, mode) + super(space, mode, cost: 1) @agitate = nil end diff --git a/lib/colonial_twilight/actions/fln/subvert.rb b/lib/colonial_twilight/actions/fln/subvert.rb new file mode 100644 index 0000000..a6ec252 --- /dev/null +++ b/lib/colonial_twilight/actions/fln/subvert.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +require_relative 'fln_action' + +module ColonialTwilight + module Actions + module FLN + # Subvert 4.3.2 + class Subvert < FlnAction + def initialize(space, mode) + super(space, mode, cost: 0) + @second = nil + end + + def validate! + super + return if @second.nil? + + p = (mode[:remove_police] || 0) + (@second.mode[:remove_police] || 0) + t = (mode[:remove_troops] || 0) + (@second.mode[:remove_troops] || 0) + raise "remove #{p} police + #{t} troops > 2" if p + t > 2 + end + + def subvert!(space2, mode2) + raise 'subvert! called twice' unless @second.nil? + raise 'cannot subvert! after replace algerian police' if mode.key?(:replace_police) + raise 'cannot subvert! with replace algerian police' if mode2.key?(:replace_police) + + @second = Subvert.new(space2, mode2) + validate! + end + + # remove 2 Algerian cubes into Available, among selected spaces + # or remove 1 Algerian Police and replace it with 1 Underground Guerrilla from Available. + def apply!(board) + raise NotImplementedError + end + + class << self + def special? + true + end + + # spaces with Underground Guerrillas and Algerian cubes. + def applicable?(space) + space.fln_underground.positive? && space.algerian_cubes.positive? + end + + def available_modes(space) + modes = {} + if space.algerian_police.positive? + modes[:replace_police] = 1 + modes[:remove_police] = space.algerian_police > 1 ? 2 : 1 + end + modes[:remove_troops] = space.algerian_troops > 1 ? 2 : 1 if space.algerian_troops.positive? + modes + end + end + end + end + end +end diff --git a/lib/colonial_twilight/actions/fln/terror.rb b/lib/colonial_twilight/actions/fln/terror.rb new file mode 100644 index 0000000..b812bb4 --- /dev/null +++ b/lib/colonial_twilight/actions/fln/terror.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require_relative 'fln_action' + +module ColonialTwilight + module Actions + module FLN + # Terror 3.3.4 + class Terror < FlnAction + def initialize(space, mode) + super(space, mode, cost: 1) + end + + # flip 1 Underground Guerrilla to Active. + # place 1 Terror marker if none (max 12 on the map), set to Neutral + def apply!(board) + raise NotImplementedError + end + + class << self + def op? + true + end + + # Populated not Resettled space with Underground Guerrillas. + def applicable?(space) + !space.country? && space.pop.positive? && space.fln_underground.positive? # && !space.resettled? + end + end + end + end + end +end |
