From ca128a74ae0f238b9ba81df68ed26e3b9a223e1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Zurcher?= Date: Thu, 21 Sep 2023 09:22:07 +0200 Subject: Cards : set attributes with specs --- lib/colonial_twilight/card_attributes.rb | 97 ++++++++++++++++++ lib/colonial_twilight/cards.rb | 164 ------------------------------- lib/colonial_twilight/deck.rb | 128 ++++++++++++++++++++++++ spec/cards_spec.rb | 69 +++++++++++++ 4 files changed, 294 insertions(+), 164 deletions(-) create mode 100644 lib/colonial_twilight/card_attributes.rb delete mode 100644 lib/colonial_twilight/cards.rb create mode 100644 lib/colonial_twilight/deck.rb create mode 100644 spec/cards_spec.rb diff --git a/lib/colonial_twilight/card_attributes.rb b/lib/colonial_twilight/card_attributes.rb new file mode 100644 index 0000000..bf339d8 --- /dev/null +++ b/lib/colonial_twilight/card_attributes.rb @@ -0,0 +1,97 @@ +#! /usr/bin/env ruby +# frozen_string_literal: true + +# rubocop:disable Style/Documentation + +module ColonialTwilight + module CardAttributes + MAX_CARD_NUM = 71 + SINGLE = 1 + FLN_MARKED = 2 + FLN_SPECIAL = 4 + FLN_CAPABILITY = 8 + FLN_MOMENTUM = 16 + GOV_CAPABILITY = 32 + GOV_MOMENTUM = 64 + DUAL_CAPABILITY = 128 + DUAL_MOMENTUM = 256 + + class << self + attr_reader :cards + end + + @cards = { + 1 => ['Quadrillage', 0], + 2 => ['Balky Conscripts', 0 | FLN_MOMENTUM], + 3 => ['Leadership Snatch', 0 | FLN_MARKED], + 4 => ['Oil & Gas Discoveries', 0 | SINGLE], + 5 => ['Peace of the Brave', 0 | GOV_MOMENTUM], + 6 => ['Factionalism', 0], + 7 => ['5th Bureau', 0 | FLN_MARKED], + 8 => ['Cross-border air strike', 0 | FLN_MOMENTUM], + 9 => ['Beni-Oui-Oui', 0 | SINGLE | FLN_MARKED], + 10 => ['Moudjahidine', 0 | FLN_MARKED | FLN_MOMENTUM], + 11 => ['Bananes', 0 | FLN_MARKED | GOV_MOMENTUM], + 12 => ['Ventilos', 0 | FLN_MARKED | FLN_SPECIAL | GOV_MOMENTUM], + 13 => ['SAS', 0 | GOV_CAPABILITY], + 14 => ['Protest in Paris', 0 | SINGLE | FLN_MARKED], + 15 => ['Jean-Paul Sarte', 0], + 16 => ['NATO', 0], + 17 => ['Commandos', 0 | FLN_CAPABILITY], + 18 => ['Torture', 0 | SINGLE | FLN_MARKED | DUAL_CAPABILITY], + 19 => ['General Strike', 0 | FLN_MARKED], + 20 => ['Sauve qui peut', 0 | SINGLE | FLN_MARKED | FLN_SPECIAL], + 21 => ['UN Resolution', 0], + 22 => ['The Government of USA is Convinced...', 0 | FLN_MARKED], + 23 => ['Diplomatic Leanings', 0 | FLN_MARKED], + 24 => ['Economic Development', 0 | FLN_MARKED], + 25 => ['Purge', 0 | SINGLE], + 26 => ['Casbah', 0 | FLN_MARKED], + 27 => ['Covert Movement', 0 | FLN_CAPABILITY], + 28 => ['Atrocities and Reprisals', 0 | SINGLE | FLN_MARKED], + 29 => ['The Call Up', 0 | FLN_MOMENTUM], + 30 => ['Change in Tactics', 0 | SINGLE], + 31 => ['Intimidation', 0 | FLN_MARKED | GOV_MOMENTUM], + 32 => ['Teleb the Bomb-maker', 0 | FLN_CAPABILITY], + 33 => ['Overkill', 0 | FLN_MARKED | FLN_CAPABILITY], + 34 => ['Elections', 0 | FLN_MARKED], + 35 => ['Napalm', 0 | FLN_MARKED | GOV_CAPABILITY], + 36 => ['Assassination', 0 | FLN_MARKED], + 37 => ['Integration', 0], + 38 => ['French Economic Crisis', 0], + 39 => ['Retreat into Djebel', 0], + 40 => ['Strategic Movement', 0 | FLN_MOMENTUM], + 41 => ['Egypt', 0 | FLN_MARKED], + 42 => ['Czech Arms Deal', 0 | FLN_MARKED], + 43 => ['Refugees', 0 | FLN_MARKED], + 44 => ['Paranoia', 0 | GOV_MOMENTUM], + 45 => ['Challe Plan', 0 | GOV_MOMENTUM | FLN_MOMENTUM], + 46 => ['Moghazni', 0 | GOV_MOMENTUM], + 47 => ['Third Force', 0 | FLN_MARKED], + 48 => ['Ultras', 0 | FLN_MARKED], + 49 => ['Factional Plot', 0 | FLN_MARKED | FLN_SPECIAL], + 50 => ['Bleuite', 0], + 51 => ['Stripey Hole', 0 | FLN_MARKED | FLN_SPECIAL], + 52 => ['Cabinet Shuffle', 0 | SINGLE], + 53 => ['Population Control', 0 | FLN_MARKED | GOV_MOMENTUM], + 54 => ['Operation 744', 0 | SINGLE | FLN_MARKED | FLN_SPECIAL], + 55 => ['Development', 0 | FLN_MARKED], + 56 => ['Hardened Attitudes', 0 | SINGLE | FLN_MARKED | FLN_SPECIAL | DUAL_MOMENTUM], + 57 => ['Peace Talks', 0 | SINGLE | FLN_MARKED | DUAL_MOMENTUM], + 58 => ['Army in Waiting', 0], + 59 => ['Bandung Conference', 0 | FLN_MARKED], + 60 => ['Soummam Conference', 0 | FLN_MARKED], + 61 => ['Morocco and Tunisia Independent', 0 | SINGLE], + 62 => ['Suez Crisis', 0 | SINGLE], + 63 => ['OAS', 0 | SINGLE], + 64 => ['Mobilization', 0 | SINGLE], + 65 => ['Recall De Gaulle', 0 | SINGLE], + 66 => ['Coup d\'etat', 0 | SINGLE], + 67 => ['Propaganda!', 0 | SINGLE], + 68 => ['Propaganda!', 0 | SINGLE], + 69 => ['Propaganda!', 0 | SINGLE], + 70 => ['Propaganda!', 0 | SINGLE], + 71 => ['Propaganda!', 0 | SINGLE] + } + end +end diff --git a/lib/colonial_twilight/cards.rb b/lib/colonial_twilight/cards.rb deleted file mode 100644 index de962c0..0000000 --- a/lib/colonial_twilight/cards.rb +++ /dev/null @@ -1,164 +0,0 @@ -#! /usr/bin/env ruby -# frozen_string_literal: true - -# rubocop:disable Style/Documentation - -module ColonialTwilight - CARD_SINGLE = 1 - CARD_FLN_MARKED = 2 - CARD_ALWAYS_PLAY = 4 - - class Card - attr_reader :num, :title - - def initialize(num, title, attr, act0 = nil, act1 = nil) - @num = num - @title = title - @attributes = attr - @act0 = act0 - @act1 = act1 - end - - def dual? - @attributes & CARD_SINGLE.zero? - end - - def single? - @attributes & CARD_SINGLE == CARD_SINGLE - end - - def fln_marked? - @attributes & CARD_FLN_MARKED == CARD_FLN_MARKED - end - - def always_play? - @attributes & CARD_ALWAYS_PLAY == CARD_ALWAYS_PLAY - end - - def capability? - false - end - - def fln_effective? - false - end - - def fln_effectiveness - 0 - end - - def fln_playable? - # reduce GOV support or resources or commitment - # shift France Track toward F - # place FLN base or increase FLN resources - false - end - - def check - # @attributes.each do |attr| raise "unknown attribute : #{attr}" if attr not in ATTRS end - # puts single? - # puts dual? - # puts flnmarked? - # puts alwaysplay? - end - end - - class CardAction - def initialize(txt, cond) - @txt = txt - @condition = cond - end - end - - class Deck - attr_reader :cards - - def initialize - @cards = {} - add_card 0, 'None', nil, nil - add_card 1, 'Quadrillage', 0, CardAction.new('Place up to all French Police in Available in up to 3 spaces', { what: :french_police, from: :available }) - end - - def pull(num) - @cards[num.positive? ? 1 : 0] # FIXME - end - - private - - def add_card(num, title, attrs, _action) - @cards[num] = Card.new num, title, attrs - @cards[num].check - end - end -end - - # 'Balky Conscripts' - # 'Leadership Snatch' - # 'Oil & Gas Discoveries' - # 'Peace of the Brave' - # 'Factionalism' - # '5th Bureau' - # 'Cross-border air strike' - # 'Beni-Oui-Oui' - # 'Moudjahidine' - # 'Bananes' - # 'Ventilos' - # 'SAS' - # 'Protest in Paris' - # 'Jean-Paul Sarte' - # 'NATO' - # 'Commandos' - # 'Torture' - # 'General Strike' - # 'Sauve qui peut' - # 'United Nations Resolution' - # 'The Government of USA is Convinced...' - # 'Diplomatic Leanings' - # 'Economic Development' - # 'Purge' - # 'Casbah' - # 'Covert Movement' - # 'Atrocities and Reprisals' - # 'The Call Up' - # 'Change in Tactics' - # 'Intimidation' - # 'Teleb the Bomb-maker' - # 'Overkill' - # 'Elections' - # 'Napalm' - # 'Assassination' - # 'Integration' - # 'Economic Crisis in France' - # 'Retreat into Djebel' - # 'Strategic Movement' - # 'Egypt' - # 'Czech Arms Deal' - # 'Refugees' - # 'Paranoia' - # 'Challe Plan' - # 'Moghazni' - # 'Third Force' - # 'Ultras' - # 'Factional Plot' - # 'Bleuite' - # 'Stripey Hole' - # 'Cabinet Shuffle' - # 'Population Control' - # 'Operation 744' - # 'Development' - # 'Hardened Attitudes' - # 'Peace Talks' - # 'Army in Waiting' - # 'Bandung Conference' - # 'Soummam Conference' - # 'Morocco and Tunisia Independent' - # 'Suez Crisis' - # 'OAS' - # 'Mobilization' - # 'Recall De Gaulle' - # "Coup d'etat" - # "Propaganda!" - # "Propaganda!" - # "Propaganda!" - # "Propaganda!" - # "Propaganda!" diff --git a/lib/colonial_twilight/deck.rb b/lib/colonial_twilight/deck.rb new file mode 100644 index 0000000..747cb2f --- /dev/null +++ b/lib/colonial_twilight/deck.rb @@ -0,0 +1,128 @@ +#! /usr/bin/env ruby +# frozen_string_literal: true + +# rubocop:disable Style/Documentation + +require 'colonial_twilight/card_attributes' +module ColonialTwilight + class Card + include ColonialTwilight::CardAttributes + + attr_reader :num, :title + + def set(num) + raise "card #{num} is out of range [1; #{MAX_CARD_NUM}]" if !num.positive? || num > MAX_CARD_NUM + + @num = num + card = ColonialTwilight::CardAttributes.cards[num] || [nil, nil] + @title = card[0] + @attributes = card[1] + self + end + + def propaganda? + @num >= 67 + end + + def dual? + (@attributes & SINGLE).zero? + end + + def single? + (@attributes & SINGLE) == SINGLE + end + + def fln_marked? + (@attributes & FLN_MARKED) == FLN_MARKED + end + + def special? + (@attributes & FLN_SPECIAL) == FLN_SPECIAL + end + + def fln_capability? + (@attributes & FLN_CAPABILITY) == FLN_CAPABILITY + end + + def gov_capability? + (@attributes & GOV_CAPABILITY) == GOV_CAPABILITY + end + + def dual_capability? + (@attributes & DUAL_CAPABILITY) == DUAL_CAPABILITY + end + + def fln_momentum? + (@attributes & FLN_MOMENTUM) == FLN_MOMENTUM + end + + def gov_momentum? + (@attributes & GOV_MOMENTUM) == GOV_MOMENTUM + end + + def dual_momentum? + (@attributes & DUAL_MOMENTUM) == DUAL_MOMENTUM + end + + def fln_effective? + # FIXME: todo + false + end + + def fln_effectiveness + # FIXME: todo + 0 + end + + def fln_playable? + # reduce GOV support or resources or commitment + # shift France Track toward F + # place FLN base or increase FLN resources + false + end + + def inspect + s = @num < 10 ? ' ' : '' + t = title + ' ' * (38 - title.size) + s += "#{@num} - #{single? ? 'Single' : 'Dual '} : #{t} : #{_capability} : #{_momentum}" + s + end + + def _capability + s = '' + s += ' FLN-capability' if fln_capability? + s += ' GOV-capability' if gov_capability? + s += 'DUAL-capability' if dual_capability? + s = ' ' * 15 if s.empty? + s + end + + def _momentum + s = '' + s += ' FLN-momentum ' if fln_momentum? + s += ' GOV-momentum ' if gov_momentum? + s += 'DUAL-momentum ' if dual_momentum? + s + end + end + + # class CardAction + # def initialize(txt, cond) + # @txt = txt + # @condition = cond + # end + # end + + class Deck + attr_reader :card + + def initialize + @card = Card.new + end + + def pull(num) + @card.set(num) + end + end + # 1.upto(71) { |n| puts Deck.new.pull(n).inspect } +end diff --git a/spec/cards_spec.rb b/spec/cards_spec.rb new file mode 100644 index 0000000..12ffb24 --- /dev/null +++ b/spec/cards_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require './lib/colonial_twilight/deck' + +describe ColonialTwilight::Card do + describe 'Propaganda' do + deck = ColonialTwilight::Deck.new + s = [67, 68, 69, 70, 71] + 1.upto(71) do |n| + it "is flags right #{n}" do expect(deck.pull(n).propaganda?).to be s.include?(n) end + end + end + + describe 'Single or Dual' do + deck = ColonialTwilight::Deck.new + s = [4, 9, 14, 18, 20, 25, 28, 30, 52, 54, 56, 57, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71] + 1.upto(71) do |n| + it "is flags right #{n}" do expect(deck.pull(n).single?).to be s.include?(n) end + end + end + + describe 'FLN capability' do + deck = ColonialTwilight::Deck.new + s = [17, 27, 32, 33] + 1.upto(71) do |n| + it "is flags right #{n}" do expect(deck.pull(n).fln_capability?).to be s.include?(n) end + end + end + + describe 'GOV capability' do + deck = ColonialTwilight::Deck.new + s = [13, 35] + 1.upto(71) do |n| + it "is flags right #{n}" do expect(deck.pull(n).gov_capability?).to be s.include?(n) end + end + end + + describe 'DUAL capability' do + deck = ColonialTwilight::Deck.new + s = [18] + 1.upto(71) do |n| + it "is flags right #{n}" do expect(deck.pull(n).dual_capability?).to be s.include?(n) end + end + end + + describe 'FLN momentum' do + deck = ColonialTwilight::Deck.new + s = [2, 8, 10, 29, 40, 45] + 1.upto(71) do |n| + it "is flags right #{n}" do expect(deck.pull(n).fln_momentum?).to be s.include?(n) end + end + end + + describe 'GOV momentum' do + deck = ColonialTwilight::Deck.new + s = [5, 11, 12, 31, 44, 45, 46, 53] + 1.upto(71) do |n| + it "is flags right #{n}" do expect(deck.pull(n).gov_momentum?).to be s.include?(n) end + end + end + + describe 'DUAL momentum' do + deck = ColonialTwilight::Deck.new + s = [56, 57] + 1.upto(71) do |n| + it "is flags right #{n}" do expect(deck.pull(n).dual_momentum?).to be s.include?(n) end + end + end +end -- cgit v1.1-2-g2b99