diff --git a/src/clj/game/cards-events.clj b/src/clj/game/cards-events.clj index 59c3643910..f4fc7620d1 100644 --- a/src/clj/game/cards-events.clj +++ b/src/clj/game/cards-events.clj @@ -640,13 +640,13 @@ stypes (:subtype ice)] (resolve-ability state :runner - {:msg (msg "give sentry, code gate, and barrier to " (if (:rezzed ice) (:title ice) "the ICE at position ") - (ice-index state ice) " of " serv " until the end of the turn") + {:msg (msg "make " (card-str state ice) " gain sentry, code gate, and barrier until the end of the turn") :effect (effect (update! (assoc ice :subtype (->> (vec (.split (:subtype ice) " - ")) (concat ["Sentry" "Code Gate" "Barrier"]) distinct (join " - ")))) + (update-ice-strength (get-card state ice)) (register-events {:runner-turn-ends {:effect (effect (update! (assoc (get-card state ice) :subtype stypes)))}} (assoc card :zone '(:discard))))} diff --git a/src/clj/game/cards-ice.clj b/src/clj/game/cards-ice.clj index 773eb96bc2..b555f2146f 100644 --- a/src/clj/game/cards-ice.clj +++ b/src/clj/game/cards-ice.clj @@ -108,7 +108,16 @@ :effect (req (swap! state assoc-in [:run :position] 0) (derez state side card))}]} "Changeling" - {:advanceable :always :abilities [end-the-run]} + (let [ab {:req (req (= (:cid card) (:cid target))) + :effect (req (if (odd? (:advance-counter (get-card state card))) + (morph state side card "Sentry" "Barrier") + (morph state side card "Barrier" "Sentry")))}] + {:advanceable :always + :effect (req (if (odd? (get card :advance-counter 0)) + (morph state side card "Sentry" "Barrier") + (morph state side card "Barrier" "Sentry"))) + :abilities [end-the-run] + :events {:advance ab :advancement-placed ab}}) "Checkpoint" {:effect (effect (gain :bad-publicity 1) (system-msg "takes 1 bad publicity")) @@ -426,8 +435,16 @@ :flags {:cannot-lower-strength true}} "Lycan" - {:advanceable :always - :abilities [trash-program]} + (let [ab {:req (req (= (:cid card) (:cid target))) + :effect (req (if (odd? (:advance-counter (get-card state card))) + (morph state side card "Code Gate" "Sentry") + (morph state side card "Sentry" "Code Gate")))}] + {:advanceable :always + :effect (req (if (odd? (get card :advance-counter 0)) + (morph state side card "Code Gate" "Sentry") + (morph state side card "Sentry" "Code Gate"))) + :abilities [trash-program] + :events {:advance ab :advancement-placed ab}}) "Mamba" {:abilities [{:msg "do 1 net damage" :effect (effect (damage :net 1 {:card card}))} @@ -759,8 +776,16 @@ {:abilities [end-the-run {:msg "do 2 net damage" :effect (effect (damage :net 2 {:card card}))}]} "Wendigo" - {:advanceable :always - :abilities [{:msg "prevent the Runner from using a chosen program for the remainder of this run"}]} + (let [ab {:req (req (= (:cid card) (:cid target))) + :effect (req (if (odd? (:advance-counter (get-card state card))) + (morph state side card "Barrier" "Code Gate") + (morph state side card "Code Gate" "Barrier")))}] + {:advanceable :always + :effect (req (if (odd? (get card :advance-counter 0)) + (morph state side card "Barrier" "Code Gate") + (morph state side card "Code Gate" "Barrier"))) + :abilities [{:msg "prevent the Runner from using a chosen program for the remainder of this run"}] + :events {:advance ab :advancement-placed ab}}) "Whirlpool" {:abilities [{:msg "prevent the Runner from jacking out" diff --git a/src/clj/game/cards-programs.clj b/src/clj/game/cards-programs.clj index 0076bb9a73..ab9bed5125 100644 --- a/src/clj/game/cards-programs.clj +++ b/src/clj/game/cards-programs.clj @@ -401,16 +401,18 @@ state :runner {:prompt (msg "Choose a subtype") :choices ["Sentry" "Code Gate" "Barrier"] - :msg (msg "give " (:title ice) " " (.toLowerCase target) " until the end of the next run this turn") + :msg (msg "make " (card-str state ice) " gain " (.toLowerCase target) " until the end of the next run this turn") :effect (effect (update! (assoc ice :subtype (->> (vec (.split (:subtype ice) " - ")) (cons target) distinct (join " - ")))) + (update-ice-strength (get-card state ice)) (register-events {:run-ends {:effect (effect (update! (assoc ice :subtype stypes)) - (unregister-events card))}} card))} - card nil)))}] + (unregister-events card) + (update-ice-strength (get-card state ice)))}} card))} + card nil)))}] :events {:run-ends nil}} "Parasite" diff --git a/src/clj/game/cards.clj b/src/clj/game/cards.clj index df3f09d2d6..ce819af0e0 100644 --- a/src/clj/game/cards.clj +++ b/src/clj/game/cards.clj @@ -1,5 +1,11 @@ (in-ns 'game.core) +(defn morph [state side card new old] + (update! state side (assoc card :subtype (->> (remove #(= old %) (.split (:subtype card) " - ")) + vec (concat [new]) distinct (join " - ")))) + (update-ice-strength state side card) + (update-run-ice state side)) + (def trash-program {:prompt "Choose a program to trash" :label "Trash a program" :msg (msg "trash " (:title target)) :choices {:req #(and (:installed %) (= (:type %) "Program"))} diff --git a/src/clj/game/core.clj b/src/clj/game/core.clj index f1bf2cb4b7..713fe39a00 100644 --- a/src/clj/game/core.clj +++ b/src/clj/game/core.clj @@ -570,22 +570,18 @@ (update-all-ice state side) (clear-run-register! state)))) - (defn add-prop ([state side card key n] (add-prop state side card key n nil)) ([state side card key n {:keys [placed] :as args}] - (let [updated-card (if - (has? card :subtype "Virus") - (assoc card :added-virus-counter true) - card - )] + (let [updated-card (if (has? card :subtype "Virus") + (assoc card :added-virus-counter true) card)] (update! state side (update-in updated-card [key] #(+ (or % 0) n))) (if (= key :advance-counter) (do (when (and (ice? updated-card) (rezzed? updated-card)) (update-ice-strength state side updated-card)) - (when (not placed) - (trigger-event state side :advance (get-card state updated-card)))) - (trigger-event state side :counter-added (get-card state updated-card))) - ))) + (if (not placed) + (trigger-event state side :advance (get-card state updated-card)) + (trigger-event state side :advancement-placed (get-card state updated-card)))) + (trigger-event state side :counter-added (get-card state updated-card)))))) (defn set-prop [state side card & args] (update! state side (apply assoc (cons card args)))) diff --git a/src/clj/test/cards-ice.clj b/src/clj/test/cards-ice.clj index 5751ef18fb..63d9eed9de 100644 --- a/src/clj/test/cards-ice.clj +++ b/src/clj/test/cards-ice.clj @@ -58,6 +58,30 @@ (take-credits state :corp 2) (is (= 5 (:current-strength (refresh lotus))) "Lotus Field strength increased")))) +(deftest morph-ice-subtype-changing + "Morph ice gain and lose subtypes from normal advancements and placed advancements" + (do-game + (new-game (default-corp [(qty "Wendigo" 1) (qty "Shipment from SanSan" 1) (qty "Superior Cyberwalls" 1)]) + (default-runner)) + (core/gain state :corp :click 2) + (play-from-hand state :corp "Superior Cyberwalls" "New remote") + (let [sc (get-in @state [:corp :servers :remote1 :content 0])] + (score-agenda state :corp sc) + (play-from-hand state :corp "Wendigo" "HQ") + (let [wend (get-in @state [:corp :servers :hq :ices 0])] + (core/rez state :corp wend) + (is (= 4 (:current-strength (refresh wend))) "Wendigo at normal 4 strength") + (core/advance state :corp {:card (refresh wend)}) + (is (= true (has? (refresh wend) :subtype "Barrier")) "Wendigo gained Barrier") + (is (= false (has? (refresh wend) :subtype "Code Gate")) "Wendigo lost Code Gate") + (is (= 5 (:current-strength (refresh wend))) "Wendigo boosted to 5 strength by scored Superior Cyberwalls") + (play-from-hand state :corp "Shipment from SanSan") + (prompt-choice :corp "1") + (prompt-select :corp wend) + (is (= false (has? (refresh wend) :subtype "Barrier")) "Wendigo lost Barrier") + (is (= true (has? (refresh wend) :subtype "Code Gate")) "Wendigo gained Code Gate") + (is (= 4 (:current-strength (refresh wend))) "Wendigo returned to normal 4 strength"))))) + (deftest special-offer-trash-ice-during-run "Special Offer trashes itself and updates the run position" (do-game