From d31c111a377fe26450b392c599d1397480db7b6e Mon Sep 17 00:00:00 2001 From: Oguz Han Asnaz Date: Fri, 5 Jul 2019 22:15:05 +0200 Subject: [PATCH 1/6] Fix heartbeat logging trashed card --- src/clj/game/cards/hardware.clj | 4 +++- test/clj/game_test/cards/hardware.clj | 4 +++- test/clj/game_test/utils.clj | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/clj/game/cards/hardware.clj b/src/clj/game/cards/hardware.clj index 4f32e92f81..ed28eaf5ab 100644 --- a/src/clj/game/cards/hardware.clj +++ b/src/clj/game/cards/hardware.clj @@ -611,7 +611,9 @@ {:in-play [:memory 1] :interactions {:prevent [{:type #{:net :brain :meat} :req (req true)}]} - :abilities [{:msg (msg "prevent 1 damage, trashing a facedown " (:title target)) + :abilities [{:msg (msg "prevent 1 damage, trashing " + (when (facedown? target) "a facedown ") + (:title target)) :choices {:req #(and (runner? %) (installed? %))} :priority 50 :effect (effect (trash target {:unpreventable true}) diff --git a/test/clj/game_test/cards/hardware.clj b/test/clj/game_test/cards/hardware.clj index 8ec1a1012b..5262180b82 100644 --- a/test/clj/game_test/cards/hardware.clj +++ b/test/clj/game_test/cards/hardware.clj @@ -683,11 +683,13 @@ (click-prompt state :runner "Done") (is (= 1 (count (:discard (get-runner)))) "Prevented 1 net damage") (is (= 2 (count (:hand (get-runner))))) + (is (second-last-log-contains? state "Runner uses Heartbeat to prevent 1 damage, trashing Cache\\.") "Prompt correct") (card-subroutine state :corp (refresh nk) 0) (card-ability state :runner hb 0) (click-card state :runner hbdown) (click-prompt state :runner "Done") - (is (= 4 (count (:discard (get-runner)))) "Prevented 1 of 3 net damage; used facedown card")))) + (is (= 4 (count (:discard (get-runner)))) "Prevented 1 of 3 net damage; used facedown card") + (is (last-n-log-contains? state 2 "Runner uses Heartbeat to prevent 1 damage, trashing a facedown Heartbeat\\.") "Prompt correct")))) (deftest hijacked-router ;; Hijacked Router diff --git a/test/clj/game_test/utils.clj b/test/clj/game_test/utils.clj index 9708f99fa0..a21e8e8d83 100644 --- a/test/clj/game_test/utils.clj +++ b/test/clj/game_test/utils.clj @@ -105,6 +105,11 @@ (some? (re-find (re-pattern content) (-> @state :log butlast last :text)))) +(defn last-n-log-contains? + [state n content] + (some? (re-find (re-pattern content) + (:text (nth (-> @state :log reverse) n))))) + (defmethod assert-expr 'last-log-contains? [msg form] `(let [state# ~(nth form 1) @@ -131,6 +136,20 @@ :message ~msg}) found#)) +(defmethod assert-expr 'last-n-log-contains? + [msg form] + `(let [state# ~(nth form 1) + n# ~(nth form 2) + content# ~(nth form 3) + log# (:text (nth (-> @state# :log reverse) n#)) + found# ~form] + (do-report + {:type (if found# :pass :fail) + :actual log# + :expected content# + :message ~msg}) + found#)) + (defmethod assert-expr 'prompt-is-type? [msg form] `(let [state# ~(nth form 1) From cc44cef4dbaa0b8164e30e9111ba1da8bc48c8f7 Mon Sep 17 00:00:00 2001 From: Oguz Han Asnaz Date: Fri, 5 Jul 2019 23:13:12 +0200 Subject: [PATCH 2/6] Damage prevention is now shown more verbosely --- src/clj/game/core/rules.clj | 14 +++++++++++++- test/clj/game_test/cards/hardware.clj | 6 ++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/clj/game/core/rules.clj b/src/clj/game/core/rules.clj index 7c11e3eb07..dae55a3dc3 100644 --- a/src/clj/game/core/rules.clj +++ b/src/clj/game/core/rules.clj @@ -160,7 +160,19 @@ (defn damage-prevent "Registers a prevention of n damage to the next damage application of the given type." [state side dtype n] - (swap! state update-in [:damage :damage-prevent dtype] (fnil #(+ % n) 0))) + (swap! state update-in [:damage :damage-prevent dtype] (fnil #(+ % n) 0)) + (let [oldprompt (first (get-in @state [side :prompt])) + newprompt (assoc oldprompt :msg (if-let [match (re-matches #"^Prevent any of the (\d+) (\w+) damage\?.*" (:msg oldprompt))] + (let [dnumber (second match) + promptdtype (case (nth match 2) + "net" :net + "brain" :brain + "meat" :meat) + prevented (get-in @state [:damage :damage-prevent promptdtype])] + (str "Prevent any of the " dnumber " " (name promptdtype) " damage? (" prevented "/" dnumber " prevented)")) + (:msg oldprompt))) + update-fn #(cons newprompt (rest %))] + (swap! state update-in [side :prompt] update-fn))) (defn damage-defer "Registers n damage of the given type to be deferred until later. (Chronos Protocol.)" diff --git a/test/clj/game_test/cards/hardware.clj b/test/clj/game_test/cards/hardware.clj index 5262180b82..9096416046 100644 --- a/test/clj/game_test/cards/hardware.clj +++ b/test/clj/game_test/cards/hardware.clj @@ -678,8 +678,14 @@ (core/rez state :corp pup) (core/rez state :corp nk) (card-subroutine state :corp (refresh pup) 0) + (is (= (-> (get-runner) :prompt first :msg) + "Prevent any of the 1 net damage?") + "Damage prevention message correct.") (card-ability state :runner hb 0) (click-card state :runner cache) + (is (= (-> (get-runner) :prompt first :msg) + "Prevent any of the 1 net damage? (1/1 prevented)") + "Damage prevention message correct.") (click-prompt state :runner "Done") (is (= 1 (count (:discard (get-runner)))) "Prevented 1 net damage") (is (= 2 (count (:hand (get-runner))))) From ed5281108c9ddfd709187cf9fafcface5959cc53 Mon Sep 17 00:00:00 2001 From: Oguz Han Asnaz Date: Fri, 5 Jul 2019 23:24:55 +0200 Subject: [PATCH 3/6] Fixed behaviour when called without open prompt --- src/clj/game/core/rules.clj | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/clj/game/core/rules.clj b/src/clj/game/core/rules.clj index dae55a3dc3..d36a4784e7 100644 --- a/src/clj/game/core/rules.clj +++ b/src/clj/game/core/rules.clj @@ -161,18 +161,18 @@ "Registers a prevention of n damage to the next damage application of the given type." [state side dtype n] (swap! state update-in [:damage :damage-prevent dtype] (fnil #(+ % n) 0)) - (let [oldprompt (first (get-in @state [side :prompt])) - newprompt (assoc oldprompt :msg (if-let [match (re-matches #"^Prevent any of the (\d+) (\w+) damage\?.*" (:msg oldprompt))] - (let [dnumber (second match) - promptdtype (case (nth match 2) - "net" :net - "brain" :brain - "meat" :meat) - prevented (get-in @state [:damage :damage-prevent promptdtype])] - (str "Prevent any of the " dnumber " " (name promptdtype) " damage? (" prevented "/" dnumber " prevented)")) - (:msg oldprompt))) - update-fn #(cons newprompt (rest %))] - (swap! state update-in [side :prompt] update-fn))) + (if-let [oldprompt (first (get-in @state [side :prompt]))] + (let [newprompt (assoc oldprompt :msg (if-let [match (re-matches #"^Prevent any of the (\d+) (\w+) damage\?.*" (:msg oldprompt))] + (let [dnumber (second match) + promptdtype (case (nth match 2) + "net" :net + "brain" :brain + "meat" :meat) + prevented (get-in @state [:damage :damage-prevent promptdtype] 0)] + (str "Prevent any of the " dnumber " " (name promptdtype) " damage? (" prevented "/" dnumber " prevented)")) + (:msg oldprompt))) + update-fn #(cons newprompt (rest %))] + (swap! state update-in [side :prompt] update-fn)))) (defn damage-defer "Registers n damage of the given type to be deferred until later. (Chronos Protocol.)" From 55796ae96db5efe930edffd773b533ae1a630990 Mon Sep 17 00:00:00 2001 From: Oguz Han Asnaz Date: Sat, 6 Jul 2019 00:11:08 +0200 Subject: [PATCH 4/6] Since over-preventing damage is not allowed, we can "press [Done]" when all damage is prevented --- src/clj/game/core/rules.clj | 25 ++++++++++++++----------- test/clj/game_test/cards/hardware.clj | 10 ++++++---- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/clj/game/core/rules.clj b/src/clj/game/core/rules.clj index d36a4784e7..d25b46330b 100644 --- a/src/clj/game/core/rules.clj +++ b/src/clj/game/core/rules.clj @@ -162,17 +162,20 @@ [state side dtype n] (swap! state update-in [:damage :damage-prevent dtype] (fnil #(+ % n) 0)) (if-let [oldprompt (first (get-in @state [side :prompt]))] - (let [newprompt (assoc oldprompt :msg (if-let [match (re-matches #"^Prevent any of the (\d+) (\w+) damage\?.*" (:msg oldprompt))] - (let [dnumber (second match) - promptdtype (case (nth match 2) - "net" :net - "brain" :brain - "meat" :meat) - prevented (get-in @state [:damage :damage-prevent promptdtype] 0)] - (str "Prevent any of the " dnumber " " (name promptdtype) " damage? (" prevented "/" dnumber " prevented)")) - (:msg oldprompt))) - update-fn #(cons newprompt (rest %))] - (swap! state update-in [side :prompt] update-fn)))) + (if-let [match (re-matches #"^Prevent any of the (\d+) (\w+) damage\?.*" (:msg oldprompt))] + (let [dnumber (str->int (second match)) + promptdtype (case (nth match 2) + "net" :net + "brain" :brain + "meat" :meat) + prevented (get-in @state [:damage :damage-prevent promptdtype] 0) + newprompt (assoc oldprompt :msg (str "Prevent any of the " dnumber " " (name promptdtype) " damage? (" prevented "/" dnumber " prevented)")) + update-fn #(cons newprompt (rest %)) + done-update-fn #(rest %)] + (if (>= prevented dnumber) + (do ((:effect oldprompt) nil) + (swap! state update-in [side :prompt] done-update-fn)) + (swap! state update-in [side :prompt] update-fn)))))) (defn damage-defer "Registers n damage of the given type to be deferred until later. (Chronos Protocol.)" diff --git a/test/clj/game_test/cards/hardware.clj b/test/clj/game_test/cards/hardware.clj index 9096416046..94f897e491 100644 --- a/test/clj/game_test/cards/hardware.clj +++ b/test/clj/game_test/cards/hardware.clj @@ -683,16 +683,18 @@ "Damage prevention message correct.") (card-ability state :runner hb 0) (click-card state :runner cache) - (is (= (-> (get-runner) :prompt first :msg) - "Prevent any of the 1 net damage? (1/1 prevented)") - "Damage prevention message correct.") - (click-prompt state :runner "Done") (is (= 1 (count (:discard (get-runner)))) "Prevented 1 net damage") (is (= 2 (count (:hand (get-runner))))) (is (second-last-log-contains? state "Runner uses Heartbeat to prevent 1 damage, trashing Cache\\.") "Prompt correct") (card-subroutine state :corp (refresh nk) 0) + (is (= (-> (get-runner) :prompt first :msg) + "Prevent any of the 3 net damage?") + "Damage prevention message correct.") (card-ability state :runner hb 0) (click-card state :runner hbdown) + (is (= (-> (get-runner) :prompt first :msg) + "Prevent any of the 3 net damage? (1/3 prevented)") + "Damage prevention message correct.") (click-prompt state :runner "Done") (is (= 4 (count (:discard (get-runner)))) "Prevented 1 of 3 net damage; used facedown card") (is (last-n-log-contains? state 2 "Runner uses Heartbeat to prevent 1 damage, trashing a facedown Heartbeat\\.") "Prompt correct")))) From 0bcc76ad05052cf32666a27b47e130d7e9f1d0db Mon Sep 17 00:00:00 2001 From: Oguz Han Asnaz Date: Sat, 6 Jul 2019 00:13:19 +0200 Subject: [PATCH 5/6] Created private function for damage prevention prompt feature --- src/clj/game/core/rules.clj | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/clj/game/core/rules.clj b/src/clj/game/core/rules.clj index d25b46330b..4d8e872ef8 100644 --- a/src/clj/game/core/rules.clj +++ b/src/clj/game/core/rules.clj @@ -157,10 +157,9 @@ [state side dtype n] (swap! state update-in [:damage :damage-bonus dtype] (fnil #(+ % n) 0))) -(defn damage-prevent - "Registers a prevention of n damage to the next damage application of the given type." +(defn- damage-prevent-update-prompt + "Look at the current runner prompt and (if a damage prevention prompt), update message." [state side dtype n] - (swap! state update-in [:damage :damage-prevent dtype] (fnil #(+ % n) 0)) (if-let [oldprompt (first (get-in @state [side :prompt]))] (if-let [match (re-matches #"^Prevent any of the (\d+) (\w+) damage\?.*" (:msg oldprompt))] (let [dnumber (str->int (second match)) @@ -177,6 +176,12 @@ (swap! state update-in [side :prompt] done-update-fn)) (swap! state update-in [side :prompt] update-fn)))))) +(defn damage-prevent + "Registers a prevention of n damage to the next damage application of the given type. Afterwards update current prevention prompt, if found." + [state side dtype n] + (swap! state update-in [:damage :damage-prevent dtype] (fnil #(+ % n) 0)) + (damage-prevent-update-prompt state side dtype n)) + (defn damage-defer "Registers n damage of the given type to be deferred until later. (Chronos Protocol.)" ([state side dtype n] (damage-defer state side dtype n nil)) From 7116423bc3f7d3cb4f23f573b659757a82d2dd52 Mon Sep 17 00:00:00 2001 From: Oguz Han Asnaz Date: Sat, 6 Jul 2019 10:05:54 +0200 Subject: [PATCH 6/6] Fixed damage prevention tests --- test/clj/game_test/cards/agendas.clj | 1 - test/clj/game_test/cards/assets.clj | 1 - test/clj/game_test/cards/events.clj | 5 +---- test/clj/game_test/cards/hardware.clj | 2 -- test/clj/game_test/cards/identities.clj | 1 - test/clj/game_test/cards/programs.clj | 2 -- test/clj/game_test/cards/upgrades.clj | 1 - test/clj/game_test/engine/scenarios.clj | 1 - 8 files changed, 1 insertion(+), 13 deletions(-) diff --git a/test/clj/game_test/cards/agendas.clj b/test/clj/game_test/cards/agendas.clj index a58e02aaf6..45b8e956d6 100644 --- a/test/clj/game_test/cards/agendas.clj +++ b/test/clj/game_test/cards/agendas.clj @@ -2463,7 +2463,6 @@ (is (= 2 (count (:discard (get-runner))))) (card-subroutine state :corp viktor 0) (card-ability state :runner ff 1) ;; Prevent the brain damage this time - (click-prompt state :runner "Done") (is (= 3 (count (:discard (get-runner)))) "Feedback filter trashed, didn't take another net damage") (is (= 1 (:brain-damage (get-runner))))))) diff --git a/test/clj/game_test/cards/assets.clj b/test/clj/game_test/cards/assets.clj index 9150cd0070..12c23cc841 100644 --- a/test/clj/game_test/cards/assets.clj +++ b/test/clj/game_test/cards/assets.clj @@ -230,7 +230,6 @@ (let [filter (get-hardware state 0)] (is (= 2 (count (:prompt (get-runner)))) "Runner has a single damage prevention prompt") (card-ability state :runner filter 0) - (click-prompt state :runner "Done") (is (zero? (count (:discard (get-runner)))) "Runner prevented damage") (is (= 2 (count (:prompt (get-runner)))) "Runner has a next damage prevention prompt") (click-prompt state :runner "Done") diff --git a/test/clj/game_test/cards/events.clj b/test/clj/game_test/cards/events.clj index f4b7978c6c..ac0705d7be 100644 --- a/test/clj/game_test/cards/events.clj +++ b/test/clj/game_test/cards/events.clj @@ -1867,7 +1867,6 @@ (letfn [(prevent-snare [existing-dmg] (click-prompt state :corp "Yes") (card-ability state :runner (get-program state 0) 1) - (click-prompt state :runner "Done") (is (= (inc existing-dmg) (count (:discard (get-runner)))) "Damage from Snare! prevented") (click-prompt state :runner (-> (prompt-map :runner) :choices first)) (when (-> (prompt-map :runner) :choices first) @@ -1879,8 +1878,7 @@ (allow-pad [existing-dmg] (click-prompt state :runner (-> (prompt-map :runner) :choices first)) (card-ability state :runner (get-program state 0) 1) - (is (= (inc existing-dmg) (count (:discard (get-runner)))) "Runner prevented damage from Hostile Inf") - (click-prompt state :runner "Done"))] + (is (= (inc existing-dmg) (count (:discard (get-runner)))) "Runner prevented damage from Hostile Inf"))] (if (= :waiting (-> (get-runner) :prompt first :prompt-type)) ; hit the snare ;; prevent the damage (do (prevent-snare (count (:discard (get-runner)))) @@ -2501,7 +2499,6 @@ (take-credits state :runner) (play-and-score state "Show of Force") (card-ability state :runner (-> (get-resource state 0) :hosted first) 1) - (click-prompt state :runner "Done") (is (zero? (count-tags state)) "Runner should avoid all meat damage") (is (= 1 (-> (get-runner) :discard count)) "Runner should have 1 card in Heap")))) diff --git a/test/clj/game_test/cards/hardware.clj b/test/clj/game_test/cards/hardware.clj index 94f897e491..da51501654 100644 --- a/test/clj/game_test/cards/hardware.clj +++ b/test/clj/game_test/cards/hardware.clj @@ -486,7 +486,6 @@ (core/rez state :corp dm) (card-subroutine state :corp dm 0) (card-ability state :runner ff 0) - (click-prompt state :runner "Done") (is (= 3 (count (:hand (get-runner)))) "1 net damage prevented") (is (= 4 (:credit (get-runner)))) (run-successful state) @@ -1463,7 +1462,6 @@ (card-ability state :runner plas 0) (card-ability state :runner plas 0) (card-ability state :runner plas 0) - (click-prompt state :runner "Done") (is (= 1 (count (:hand (get-runner)))) "All meat damage prevented") (is (empty? (get-hardware state)) "Plascrete depleted and trashed")))) diff --git a/test/clj/game_test/cards/identities.clj b/test/clj/game_test/cards/identities.clj index dead55d162..85e7c35a90 100644 --- a/test/clj/game_test/cards/identities.clj +++ b/test/clj/game_test/cards/identities.clj @@ -2116,7 +2116,6 @@ (click-prompt state :corp "2 [Credits]") (click-prompt state :runner "0 [Credits]") (card-ability state :runner ff 0) - (click-prompt state :runner "Done") (is (zero? (:credit (get-runner))) "Runner has no more credits left") (is (= 1 (count (:hand (get-runner)))) "Prevented 1 net damage") (is (empty? (:discard (get-runner))) "No cards discarded") diff --git a/test/clj/game_test/cards/programs.clj b/test/clj/game_test/cards/programs.clj index 78915ba875..fc4c33d7bd 100644 --- a/test/clj/game_test/cards/programs.clj +++ b/test/clj/game_test/cards/programs.clj @@ -620,7 +620,6 @@ (click-prompt state :runner "Pay 5 [Credits] to trash") (let [dx (get-program state 0)] (card-ability state :runner dx 1) - (click-prompt state :runner "Done") (is (= 2 (count (:hand (get-runner)))) "Deus X prevented one Hostile net damage")))) (testing "vs Multiple sources of net damage" (do-game @@ -634,7 +633,6 @@ (run-empty-server state "Server 1") (let [dx (get-program state 0)] (card-ability state :runner dx 1) - (click-prompt state :runner "Done") (click-prompt state :runner "Pay to steal") (is (= 3 (count (:hand (get-runner)))) "Deus X prevented net damage from accessing Fetal AI, but not from Personal Evolution") (is (= 1 (count (:scored (get-runner)))) "Fetal AI stolen"))))) diff --git a/test/clj/game_test/cards/upgrades.clj b/test/clj/game_test/cards/upgrades.clj index 6c1efbb897..ad20a41169 100644 --- a/test/clj/game_test/cards/upgrades.clj +++ b/test/clj/game_test/cards/upgrades.clj @@ -2164,7 +2164,6 @@ (core/rez state :corp tori) (card-subroutine state :corp pup 0) (card-ability state :runner nshld 0) - (click-prompt state :runner "Done") (is (empty? (:discard (get-runner))) "1 net damage prevented") (card-subroutine state :corp pup 0) (click-prompt state :runner "Done") ; decline to prevent diff --git a/test/clj/game_test/engine/scenarios.clj b/test/clj/game_test/engine/scenarios.clj index 3c65b3d3a1..012f73a5db 100644 --- a/test/clj/game_test/engine/scenarios.clj +++ b/test/clj/game_test/engine/scenarios.clj @@ -31,7 +31,6 @@ fg (first (:hosted (refresh apt)))] (card-ability state :runner ns 0) (is (= 5 (:credit (get-runner))) "Runner paid 1c to survive Neural EMP") - (click-prompt state :runner "Done") (play-from-hand state :corp "SEA Source") (click-prompt state :corp "3") ; boost trace to 6 (click-prompt state :runner "0")