diff --git a/lib/magic/cards/battle_for_bretagard.rb b/lib/magic/cards/battle_for_bretagard.rb new file mode 100644 index 0000000..bd3f248 --- /dev/null +++ b/lib/magic/cards/battle_for_bretagard.rb @@ -0,0 +1,59 @@ +module Magic + module Cards + class BattleForBretagard < Saga + card_name "Battle for Bretagard" + cost generic: 1, green: 1, white: 1 + + HumanWarriorToken = Token.create "Human Warrior" do + creature_type "Human Warrior" + power 1 + toughness 1 + colors :white + end + + ElfWarriorToken = Token.create "Elf Warrior" do + creature_type "Elf Warrior" + power 1 + toughness 1 + colors :green + end + + class Chapter1 < Chapter + def start + actor.trigger_effect(:create_token, token_class: HumanWarriorToken) + end + end + + class Chapter2 < Chapter + def start + actor.trigger_effect(:create_token, token_class: ElfWarriorToken) + end + end + + class Chapter3 < Chapter + def start + actor.game.add_choice(BattleForBretagard::Choice.new(actor: actor)) + end + end + + class Choice < Magic::Choice + def choices + you_control = battlefield.controlled_by(controller) + + Magic::Targets::Choices.new( + choices: you_control.artifact.tokens + you_control.creature.tokens, + amount: 0.. + ) + end + + def resolve!(targets:) + targets.each(&:copy!) + end + end + + def chapters + [Chapter1, Chapter2, Chapter3] + end + end + end +end diff --git a/lib/magic/cards/saga.rb b/lib/magic/cards/saga.rb new file mode 100644 index 0000000..cf62366 --- /dev/null +++ b/lib/magic/cards/saga.rb @@ -0,0 +1,58 @@ +module Magic + module Cards + class Saga < Card + class Chapter + attr_reader :actor + + def initialize(actor:) + @actor = actor + end + end + + type T::Enchantment, "Saga" + + enters_the_battlefield do + actor.trigger_effect(:add_counter, counter_type: Counters::Lore, target: actor) + end + + class CounterAddedTrigger < TriggeredAbility + def should_perform? + this? && event.counter_type == Counters::Lore + end + + def call + lore_counters = actor.counters.of_type(Counters::Lore) + chapter_class = card.chapter(lore_counters) + chapter_class.new(actor: actor).start + + actor.sacrifice! if card.chapters.count == lore_counters.count + end + end + + class FirstMainPhaseTrigger < TriggeredAbility + def should_perform? + you? + end + + def call + actor.trigger_effect(:add_counter, counter_type: Counters::Lore, target: actor) + end + end + + def chapter(counters) + chapters[counters.count - 1] + end + + def chapters + raise NotImplementedError + end + + def event_handlers + { + Events::CounterAddedToPermanent => CounterAddedTrigger, + Events::FirstMainPhaseStarted => FirstMainPhaseTrigger, + } + end + end + end +end diff --git a/lib/magic/cards/sanctum_of_calm_waters.rb b/lib/magic/cards/sanctum_of_calm_waters.rb index 01ece56..9fe9812 100644 --- a/lib/magic/cards/sanctum_of_calm_waters.rb +++ b/lib/magic/cards/sanctum_of_calm_waters.rb @@ -6,8 +6,8 @@ module Cards def event_handlers { - Events::FirstMainPhase => -> (receiver, event) do - return unless event.active_player == receiver.controller + Events::FirstMainPhaseStarted => -> (receiver, event) do + return unless event.player == receiver.controller game.choices.add(SanctumOfCalmWaters::Choice.new(actor: receiver)) end diff --git a/lib/magic/counters/lore.rb b/lib/magic/counters/lore.rb new file mode 100644 index 0000000..33a434a --- /dev/null +++ b/lib/magic/counters/lore.rb @@ -0,0 +1,6 @@ +module Magic + module Counters + class Lore + end + end +end diff --git a/lib/magic/events/first_main_phase.rb b/lib/magic/events/first_main_phase.rb deleted file mode 100644 index cf1448e..0000000 --- a/lib/magic/events/first_main_phase.rb +++ /dev/null @@ -1,15 +0,0 @@ -module Magic - module Events - class FirstMainPhase - attr_reader :active_player - - def initialize(active_player:) - @active_player = active_player - end - - def inspect - "#" - end - end - end -end diff --git a/lib/magic/events/first_main_phase_started.rb b/lib/magic/events/first_main_phase_started.rb new file mode 100644 index 0000000..0e7caa7 --- /dev/null +++ b/lib/magic/events/first_main_phase_started.rb @@ -0,0 +1,15 @@ +module Magic + module Events + class FirstMainPhaseStarted + attr_reader :player + + def initialize(player:) + @player = player + end + + def inspect + "#" + end + end + end +end diff --git a/lib/magic/game/turn.rb b/lib/magic/game/turn.rb index 71b7e48..94dd05a 100644 --- a/lib/magic/game/turn.rb +++ b/lib/magic/game/turn.rb @@ -37,7 +37,7 @@ class Turn after_transition to: :first_main do |turn| turn.notify!( - Events::FirstMainPhase.new(active_player: turn.active_player) + Events::FirstMainPhaseStarted.new(player: turn.active_player) ) end diff --git a/lib/magic/permanent.rb b/lib/magic/permanent.rb index f6d2d34..2456688 100644 --- a/lib/magic/permanent.rb +++ b/lib/magic/permanent.rb @@ -142,6 +142,17 @@ def copy? @copy end + def copy! + self.class.resolve( + game: game, + owner: owner, + card: card, + token: token?, + cast: false, + copy: true, + ) + end + def cast? @cast end diff --git a/lib/magic/triggered_ability.rb b/lib/magic/triggered_ability.rb index 9a06be9..b2508f9 100644 --- a/lib/magic/triggered_ability.rb +++ b/lib/magic/triggered_ability.rb @@ -24,6 +24,10 @@ def type?(type) event.permanent.types.include?(type) end + def card + actor.card + end + def perform! return unless should_perform? call diff --git a/spec/game/integration/saga_lore_counters_spec.rb b/spec/game/integration/saga_lore_counters_spec.rb new file mode 100644 index 0000000..5b6381b --- /dev/null +++ b/spec/game/integration/saga_lore_counters_spec.rb @@ -0,0 +1,67 @@ +require "spec_helper" + +RSpec.describe "Saga Lore Counters" do + include_context "two player game" + + let(:p1_library) do + 10.times.map { Card("Island", owner: p1) } + end + + let(:p2_library) do + 10.times.map { Card("Mountain", owner: p2) } + end + + context "as a card" do + let(:card) { Card("Battle For Bretagard") } + + it "adds a lore counter when it enters" do + p1.add_mana(white: 2, green: 1) + p1.cast(card: card) do + _1.auto_pay_mana + end + + game.stack.resolve! + + permanent = game.battlefield.by_name("Battle for Bretagard").first + + expect(permanent.counters.of_type(Magic::Counters::Lore).count).to eq(1) + human_warrior = game.battlefield.by_name("Human Warrior") + expect(human_warrior.count).to eq(1) + + game.next_turn + game.next_turn + + turn_3 = game.current_turn + + turn_3.untap! + turn_3.upkeep! + turn_3.draw! + turn_3.first_main! + + expect(permanent.counters.of_type(Magic::Counters::Lore).count).to eq(2) + + elf_warrior = game.battlefield.by_name("Elf Warrior") + expect(elf_warrior.count).to eq(1) + + game.next_turn + game.next_turn + + turn_5 = game.current_turn + turn_5.untap! + turn_5.upkeep! + turn_5.draw! + turn_5.first_main! + + expect(game.battlefield.by_name("Battle for Bretagard")).to be_empty + expect(card.zone).to be_graveyard + + human_warrior = game.battlefield.by_name("Human Warrior").first + elf_warrior = game.battlefield.by_name("Elf Warrior").first + + game.resolve_choice!(targets: [human_warrior, elf_warrior]) + + expect(game.battlefield.by_name("Human Warrior").count).to eq(2) + expect(game.battlefield.by_name("Elf Warrior").count).to eq(2) + end + end +end