From 39ee3c84363172ed644ea42c299dfbd412faeee7 Mon Sep 17 00:00:00 2001 From: Noah Date: Tue, 15 Oct 2019 21:14:54 -0400 Subject: [PATCH 1/9] Fix Steve Cambridge --- src/clj/game/cards/identities.clj | 69 +++++++++++-------------- test/clj/game_test/cards/identities.clj | 16 ++++++ 2 files changed, 46 insertions(+), 39 deletions(-) diff --git a/src/clj/game/cards/identities.clj b/src/clj/game/cards/identities.clj index 43b90d659d..029dcfaa32 100644 --- a/src/clj/game/cards/identities.clj +++ b/src/clj/game/cards/identities.clj @@ -1261,45 +1261,33 @@ {:events [{:event :successful-run :req (req (and (= target :hq) (first-successful-run-on-server? state :hq) - (if (pos? (count (->> @state :run :run-effects #(map :card)))) - (> (count (:discard runner)) 2) - (> (count (:discard runner)) 1)))) + (<= 2 (count (:discard runner))))) :interactive (req true) :async true - :effect (effect (continue-ability - {:async true - :prompt "Select 2 cards in your Heap" - :show-discard true - :choices {:max 2 - :req #(and (in-discard? %) - (runner? %) - (not (some (fn [c] (same-card? % (:card c))) (:run-effects run))))} - :cancel-effect (req (effect-completed state side eid)) - :effect (req (let [c1 (first targets) - c2 (second targets)] - (show-wait-prompt state :runner "Corp to choose which card to remove from the game") - (continue-ability - state :corp - {:prompt "Choose which card to remove from the game" - :player :corp - :choices [c1 c2] - :effect (req (if (= target c1) - (do (move state :runner c1 :rfg) - (move state :runner c2 :hand) - (system-msg state :runner - (str "uses Steve Cambridge: Master Grifter" - " to add " (:title c2) " to their Grip." - " Corp removes " (:title c1) " from the game"))) - (do (move state :runner c2 :rfg) - (move state :runner c1 :hand) - (system-msg state :runner - (str "uses Steve Cambridge: Master Grifter" - " to add " (:title c1) " to their Grip." - " Corp removes " (:title c2) " from the game")))) - (clear-wait-prompt state :runner) - (effect-completed state side eid))} - card nil)))} - card nil))}]} + :prompt "Select 2 cards in your Heap" + :show-discard true + :choices {:max 2 + :req #(and (in-discard? %) + (runner? %))} + :effect (req (let [c1 (first targets) + c2 (second targets)] + (show-wait-prompt state :runner "Corp to choose which card to remove from the game") + (continue-ability + state :corp + {:prompt "Choose which card to remove from the game" + :player :corp + :choices [c1 c2] + :effect (req (let [[chosen other] (if (= target c1) + [c1 c2] + [c2 c1])] + (move state :runner chosen :rfg) + (move state :runner other :hand) + (system-msg state :runner + (str "uses Steve Cambridge: Master Grifter" + " to add " (:title other) " to their grip." + " Corp removes " (:title chosen) " from the game"))) + (clear-wait-prompt state :runner))} + card nil)))}]} "Strategic Innovations: Future Forward" {:events [{:event :pre-start-game @@ -1309,8 +1297,11 @@ (has-most-faction? state :corp "Haas-Bioroid") (pos? (count (:discard corp))))) :prompt "Select a card in Archives to shuffle into R&D" - :choices {:req #(and (corp? %) (in-discard? %))} - :player :corp :show-discard true :priority true + :choices {:req #(and (corp? %) + (in-discard? %))} + :player :corp + :show-discard true + :priority true :msg (msg "shuffle " (if (:seen target) (:title target) "a card") " into R&D") :effect (effect (move :corp target :deck) diff --git a/test/clj/game_test/cards/identities.clj b/test/clj/game_test/cards/identities.clj index c9b4191ed3..1577ea519c 100644 --- a/test/clj/game_test/cards/identities.clj +++ b/test/clj/game_test/cards/identities.clj @@ -2400,6 +2400,22 @@ (take-credits state :corp) (is (empty? (:prompt (get-corp))) "Not prompted when all ice advanced")))) +(deftest steve-cambridge-master-grifter + ;; Steve + (do-game + (new-game {:corp {:deck [(qty "Hedge Fund" 5)] + :hand ["Hedge Fund"]} + :runner {:id "Steve Cambridge: Master Grifter" + :discard ["Sure Gamble" "Easy Mark"]}}) + (take-credits state :corp) + (run-empty-server state :hq) + (click-card state :runner "Sure Gamble") + (click-card state :runner "Easy Mark") + (click-prompt state :corp "Sure Gamble") + (click-prompt state :runner "No action") + (is (= "Easy Mark" (-> (get-runner) :hand first :title)) "Easy Mark should be in the hand") + (is (= "Sure Gamble" (-> (get-runner) :rfg first :title)) "Sure Gamble should be removed from game"))) + (deftest strategic-innovations-future-forward ;; Strategic Innovations: Future Forward (do-game From e446572d287eee6d501f051bf80b46c32ba591c1 Mon Sep 17 00:00:00 2001 From: Noah Date: Tue, 15 Oct 2019 21:26:26 -0400 Subject: [PATCH 2/9] Fix Patchwork --- src/clj/game/cards/hardware.clj | 2 ++ src/clj/game/core/costs.clj | 3 ++- test/clj/game_test/cards/hardware.clj | 15 ++++++++++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/clj/game/cards/hardware.clj b/src/clj/game/cards/hardware.clj index 949295da5d..fa5ecf4c4d 100644 --- a/src/clj/game/cards/hardware.clj +++ b/src/clj/game/cards/hardware.clj @@ -527,6 +527,7 @@ :interactions {:pay-credits {:req (req (and (= :ability (:source-type eid)) (same-card? card (:host target)) (pos? (get-counters card :credit)))) + :custom-amount 1 :custom (req (add-counter state side card :credit -1) (register-events state side (get-card state card) @@ -1071,6 +1072,7 @@ (not (get-in card [:special :patchwork])) ;; Check if Patchwork can trigger (can-trigger? state side patchwork-ability card targets))) + :custom-amount 2 :custom (req (let [cost-type (str (when (= :play (:source-type eid)) "play") (when (= :runner-install (:source-type eid)) "install")) patchwork card diff --git a/src/clj/game/core/costs.clj b/src/clj/game/core/costs.clj index 0f7d310197..2f633de314 100644 --- a/src/clj/game/core/costs.clj +++ b/src/clj/game/core/costs.clj @@ -147,7 +147,8 @@ (+ (get-in @state [side :credit]) (->> (eligible-pay-credit-cards state side eid card) (map #(+ (get-counters % :recurring) - (get-counters % :credit))) + (get-counters % :credit) + (-> (card-def %) :interactions :pay-credits ((fn [x] (:custom-amount x 0)))))) (reduce +)))) (defn- can-pay-impl diff --git a/test/clj/game_test/cards/hardware.clj b/test/clj/game_test/cards/hardware.clj index ebe1fd7b3e..6c7e3f925d 100644 --- a/test/clj/game_test/cards/hardware.clj +++ b/test/clj/game_test/cards/hardware.clj @@ -1529,7 +1529,20 @@ (click-card state :runner (get-hardware state 0)) (click-card state :runner (find-card "Cyberfeeder" (:hand (get-runner)))) (is (= 2 (count (:hand (get-runner)))) "Cyberfeeder is still in hand") - (is (not-empty (:prompt (get-runner))) "Prompt still open")))) + (is (not-empty (:prompt (get-runner))) "Prompt still open"))) + (testing "Used when runner credit pool is under printed cost. Issue #4563" + (do-game + (new-game {:runner {:deck ["Patchwork" "Sure Gamble" "Easy Mark"] + :credits 7}}) + (take-credits state :corp) + (play-from-hand state :runner "Patchwork") + (is (= 3 (:credit (get-runner))) "Runner has 3 credits") + (play-from-hand state :runner "Sure Gamble") + (click-card state :runner (get-hardware state 0)) + (is (empty? (:discard (get-runner))) "Easy Mark is not in heap yet") + (click-card state :runner "Easy Mark") + (is (not-empty (:discard (get-runner))) "Easy Mark is in heap") + (is (= 9 (:credit (get-runner))) "Runner has only paid 3 for Sure Gamble")))) (deftest plascrete-carapace ;; Plascrete Carapace - Prevent meat damage From 2d4be43e3959cd45b25391a5a99cf79bbcbeacca Mon Sep 17 00:00:00 2001 From: Noah Date: Tue, 15 Oct 2019 21:32:31 -0400 Subject: [PATCH 3/9] Add Trick of Light test --- src/clj/game/cards/operations.clj | 5 +- test/clj/game_test/cards/operations.clj | 61 +++++++++++++++++-------- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/clj/game/cards/operations.clj b/src/clj/game/cards/operations.clj index 63cb177e5b..2427812a33 100644 --- a/src/clj/game/cards/operations.clj +++ b/src/clj/game/cards/operations.clj @@ -2081,8 +2081,7 @@ :choices {:req #(pos? (get-counters % :advancement))} :effect (effect (continue-ability - (let [fr target - tol card] + (let [fr target] {:async true :prompt "Move how many advancement tokens?" :choices (take (inc (get-counters fr :advancement)) ["0" "1" "2"]) @@ -2096,7 +2095,7 @@ (card-str state fr) " to " (card-str state target)) :effect (effect (add-prop :corp target :advance-counter c {:placed true}) (add-prop :corp fr :advance-counter (- c) {:placed true}))}) - tol nil))}) + card nil))}) card nil))} "Trojan Horse" diff --git a/test/clj/game_test/cards/operations.clj b/test/clj/game_test/cards/operations.clj index b7fb96cdaa..16e6136809 100644 --- a/test/clj/game_test/cards/operations.clj +++ b/test/clj/game_test/cards/operations.clj @@ -3793,24 +3793,49 @@ (is (= 5 (:credit (get-corp))) "Transparency initiative didn't fire")))) (deftest trick-of-light - ;; NGO Front - (do-game - (new-game {:corp {:deck [(qty "Hedge Fund" 5)] - :hand ["Trick of Light" "Ice Wall" "NGO Front"] - :credits 10}}) - (core/gain state :corp :click 5) - (play-from-hand state :corp "Ice Wall" "HQ") - (play-from-hand state :corp "NGO Front" "New remote") - (let [ngo (get-content state :remote1 0) - iw (get-ice state :hq 0)] - (advance state (refresh ngo) 2) - (is (= 2 (get-counters (refresh ngo) :advancement)) "NGO Front should have 2 counters") - (play-from-hand state :corp "Trick of Light") - (click-card state :corp ngo) - (click-prompt state :corp "2") - (click-card state :corp "Ice Wall") - (is (= 2 (get-counters (refresh iw) :advancement)) "Ice Wall is now advanced") - (is (zero? (get-counters (refresh ngo) :advancement)) "NGO Front should have 0 counters")))) + ;; Trick of Light + (testing "Basic test" + (do-game + (new-game {:corp {:deck [(qty "Hedge Fund" 5)] + :hand ["Trick of Light" "Ice Wall" "NGO Front"] + :credits 10}}) + (core/gain state :corp :click 5) + (play-from-hand state :corp "Ice Wall" "HQ") + (play-from-hand state :corp "NGO Front" "New remote") + (let [ngo (get-content state :remote1 0) + iw (get-ice state :hq 0)] + (advance state (refresh ngo) 2) + (is (= 2 (get-counters (refresh ngo) :advancement)) "NGO Front should have 2 counters") + (play-from-hand state :corp "Trick of Light") + (click-card state :corp ngo) + (click-prompt state :corp "2") + (click-card state :corp "Ice Wall") + (is (= 2 (get-counters (refresh iw) :advancement)) "Ice Wall is now advanced") + (is (zero? (get-counters (refresh ngo) :advancement)) "NGO Front should have 0 counters")))) + (testing "Playing 2 Trick of Lights. Issue #4565" + (do-game + (new-game {:corp {:deck [(qty "Hedge Fund" 5)] + :hand [(qty "Trick of Light" 2) "Ice Wall" "NGO Front"] + :credits 10}}) + (core/gain state :corp :click 5) + (play-from-hand state :corp "Ice Wall" "HQ") + (play-from-hand state :corp "NGO Front" "New remote") + (let [ngo (get-content state :remote1 0) + iw (get-ice state :hq 0)] + (advance state (refresh ngo) 2) + (is (= 2 (get-counters (refresh ngo) :advancement)) "NGO Front should have 2 counters") + (play-from-hand state :corp "Trick of Light") + (click-card state :corp (refresh ngo)) + (click-prompt state :corp "2") + (click-card state :corp (refresh iw)) + (is (= 2 (get-counters (refresh iw) :advancement)) "Ice Wall is now advanced") + (is (zero? (get-counters (refresh ngo) :advancement)) "NGO Front should have 0 counters") + (play-from-hand state :corp "Trick of Light") + (click-card state :corp (refresh iw)) + (click-prompt state :corp "2") + (click-card state :corp (refresh ngo)) + (is (zero? (get-counters (refresh iw) :advancement)) "Ice Wall should have 0 counters") + (is (= 2 (get-counters (refresh ngo) :advancement)) "NGO Front should have 2 counters"))))) (deftest trojan-horse ;; Trojan Horse From cbc1552c240525fde9bfdf35f99cf07e35f458e6 Mon Sep 17 00:00:00 2001 From: Noah Date: Tue, 15 Oct 2019 21:36:17 -0400 Subject: [PATCH 4/9] Fix Credit Kiting and Priority Construction --- src/clj/game/cards/events.clj | 2 +- src/clj/game/cards/operations.clj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clj/game/cards/events.clj b/src/clj/game/cards/events.clj index 3916bdfeaf..226390e420 100644 --- a/src/clj/game/cards/events.clj +++ b/src/clj/game/cards/events.clj @@ -459,7 +459,7 @@ :async true :effect (req (wait-for (runner-install state :runner (make-eid state {:source card :source-type :runner-install}) target {:cost-bonus -8}) - (gain-tags state eid :runner 1)))} + (gain-tags state :runner eid 1)))} "Cyber Threat" {:prompt "Choose a server" diff --git a/src/clj/game/cards/operations.clj b/src/clj/game/cards/operations.clj index 2427812a33..91bc3ed7f6 100644 --- a/src/clj/game/cards/operations.clj +++ b/src/clj/game/cards/operations.clj @@ -1373,7 +1373,7 @@ {:prompt "Select a remote server" :choices (req (conj (vec (get-remote-names state)) "New remote")) :async true - :effect (effect (corp-install (assoc chosen :advance-counter 3) target {:ignore-all-cost true}))})] + :effect (effect (corp-install eid (assoc chosen :advance-counter 3) target {:ignore-all-cost true}))})] {:async true :prompt "Choose a piece of ICE in HQ to install" :choices {:req #(and (in-hand? %) (corp? %) (ice? %))} From ed9615aef4d5ab2c2300049fc5d30326fbf60b2b Mon Sep 17 00:00:00 2001 From: Noah Date: Tue, 15 Oct 2019 21:45:52 -0400 Subject: [PATCH 5/9] Fix Slot Machine --- src/clj/game/cards/ice.clj | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/clj/game/cards/ice.clj b/src/clj/game/cards/ice.clj index dd9e4d8e14..84063063c3 100644 --- a/src/clj/game/cards/ice.clj +++ b/src/clj/game/cards/ice.clj @@ -2557,28 +2557,34 @@ :effect (req (do-access state :runner eid [:rd] {:no-root true}))}]} "Slot Machine" - (letfn [(name-builder [card] (str (:title card) " (" (:type card) ")")) - (top-3 [state] (take 3 (get-in @state [:runner :deck]))) - (top-3-names [state] (map name-builder (top-3 state))) - (top-3-types [state] (->> (top-3 state) (map :type) (into #{}) count))] + (letfn [(top-3 [state] (take 3 (get-in @state [:runner :deck]))) + (name-builder [card] (str (:title card) " (" (:type card) ")")) + (top-3-names [card] (map name-builder (get-in card [:special :top-3]))) + (top-3-types [card] (->> (get-in card [:special :top-3]) (map :type) (into #{}) count))] {:implementation "Encounter effect is manual" :abilities [{:label "Roll them bones" :req (req (same-card? current-ice card)) :effect (effect (move :runner (first (:deck runner)) :deck) - (reveal (take 3 (:deck runner))) + (reveal (top-3 state)) + (update! (assoc-in card [:special :top-3] (top-3 state))) (system-msg (str "uses Slot Machine to put the top card of the stack to the bottom," " then reveal the top 3 cards in the stack: " - (join ", " (top-3-names state)))))}] + (join ", " (top-3-names (get-card state card))))))}] + :events (into [] + (for [event [:run :approach-ice :pass-ice :run-ends]] + {:event event + :req (req (get-in card [:special :top-3])) + :effect (effect (update! (dissoc-in card [:special :top-3])))})) :subroutines [{:label "Runner loses 3 [Credits]" :msg "force the Runner to lose 3 [Credits]" :effect (effect (lose-credits :runner 3))} {:label "Gain 3 [Credits]" - :effect (req (let [unique-types (top-3-types state)] + :effect (req (let [unique-types (top-3-types (get-card state card))] (when (>= 2 unique-types) (system-msg state :corp (str "uses Slot Machine to gain 3 [Credits]")) (gain-credits state :corp 3))))} {:label "Place 3 advancement tokens" - :effect (req (let [unique-types (top-3-types state)] + :effect (req (let [unique-types (top-3-types (get-card state card))] (when (= 1 unique-types) (continue-ability state side From 5a68df78d3a9ce2ba0df916741275596fcbfed0c Mon Sep 17 00:00:00 2001 From: Noah Date: Tue, 15 Oct 2019 21:53:11 -0400 Subject: [PATCH 6/9] Fix Hayley end of turn triggers --- src/clj/game/core/turns.clj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/clj/game/core/turns.clj b/src/clj/game/core/turns.clj index 3f8047681c..1a9e447ccc 100644 --- a/src/clj/game/core/turns.clj +++ b/src/clj/game/core/turns.clj @@ -170,6 +170,9 @@ (defn start-turn "Start turn." [state side args] + ; Don't clear :turn-events until the player clicks "Start Turn" + ; Fix for Hayley triggers + (swap! state assoc :turn-events nil) ; Functions to set up state for undo-turn functionality (doseq [s [:runner :corp]] (swap! state dissoc-in [s :undo-turn])) @@ -269,7 +272,6 @@ (swap! state update-in [side :register] dissoc :cannot-draw) (swap! state update-in [side :register] dissoc :drawn-this-turn) (clear-turn-register! state) - (swap! state assoc :turn-events nil) (when-let [extra-turns (get-in @state [side :extra-turns])] (when (pos? extra-turns) (start-turn state side nil) From 930585bec2256e58feea9abbac850756d606ec0d Mon Sep 17 00:00:00 2001 From: Noah Date: Tue, 15 Oct 2019 21:55:50 -0400 Subject: [PATCH 7/9] Fix clicking opponents cards --- src/cljs/nr/gameboard.cljs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cljs/nr/gameboard.cljs b/src/cljs/nr/gameboard.cljs index d199f3d94d..dcefda060e 100644 --- a/src/cljs/nr/gameboard.cljs +++ b/src/cljs/nr/gameboard.cljs @@ -195,7 +195,8 @@ (swap! c-state assoc :runner-abilities true)))) ;; Trigger first (and only) ability / action - (= c 1) + (and (= c 1) + (= side card-side)) (if (= (count abilities) 1) (send-command "ability" {:card card :ability 0}) (send-command (first actions) {:card card})))))) From 8882af274db11b258e5c0507f889a1a5c47ed589 Mon Sep 17 00:00:00 2001 From: Noah Date: Tue, 15 Oct 2019 22:06:08 -0400 Subject: [PATCH 8/9] Test for Leela + Gang Sign interaction --- test/clj/game_test/cards/identities.clj | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/test/clj/game_test/cards/identities.clj b/test/clj/game_test/cards/identities.clj index 1577ea519c..c18cf08c34 100644 --- a/test/clj/game_test/cards/identities.clj +++ b/test/clj/game_test/cards/identities.clj @@ -1607,7 +1607,30 @@ (click-prompt state :runner "Steal") (click-card state :runner (get-content state :archives 0)) (is (not (get-content state :archives 0)) "Upgrade returned to hand") - (is (not (:run @state)) "Run ended, no more accesses")))) + (is (not (:run @state)) "Run ended, no more accesses"))) + (testing "" + (do-game + (new-game {:corp {:id "Titan Transnational: Investing In Your Future" + :deck ["Project Atlas" + "Hostile Takeover" + "Geothermal Fracking" + "Merger"]} + :runner {:id "Leela Patel: Trained Pragmatist" + :deck ["Gang Sign"]}}) + (play-from-hand state :corp "Project Atlas" "New remote") + (play-from-hand state :corp "Hostile Takeover" "New remote") + (play-from-hand state :corp "Geothermal Fracking" "New remote") + (take-credits state :corp) + (play-from-hand state :runner "Gang Sign") + (take-credits state :runner) + (score-agenda state :corp (get-content state :remote1 0)) + ;; Simultaneous prompt: Leela or Gang Sign + (click-prompt state :runner "Gang Sign") + (click-prompt state :runner "Card from hand") + (click-prompt state :runner "Steal") + (click-card state :runner (get-content state :remote2 0)) ; Bounce from Gang Sign steal + (click-card state :runner (get-content state :remote3 0)) ; Bounce from Hostile score + (is (= 2 (count (:hand (get-corp)))) "Corp should have 2 cards in hand now")))) (deftest liza-talking-thunder-prominent-legislator ;; Liza Talking Thunder: Prominent Legislator From 003febe1bdb7e4794fb0153719ea6324712e2c0c Mon Sep 17 00:00:00 2001 From: Noah Date: Tue, 15 Oct 2019 22:09:29 -0400 Subject: [PATCH 9/9] Fix CST --- src/clj/game/cards/agendas.clj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/clj/game/cards/agendas.clj b/src/clj/game/cards/agendas.clj index d341569832..c268466d67 100644 --- a/src/clj/game/cards/agendas.clj +++ b/src/clj/game/cards/agendas.clj @@ -391,10 +391,10 @@ :effect (effect (gain-bad-publicity :corp 1))}} "Corporate Sales Team" - (let [e {:effect (req (when (pos? (get-counters card :credit)) - (gain-credits state :corp 1) - (system-msg state :corp (str "uses Corporate Sales Team to gain 1 [Credits]")) - (add-counter state side card :credit -1)))}] + (let [e {:req (req (pos? (get-counters card :credit))) + :msg "gain 1 [Credits]" + :effect (req (gain-credits state :corp 1) + (add-counter state side card :credit -1))}] {:effect (effect (add-counter card :credit 10)) :silent (req true) :events [(assoc e :event :runner-turn-begins)