From dba96bec4654f1604a2d97f2f7e232b6a3c5bb24 Mon Sep 17 00:00:00 2001 From: NB Kelly Date: Fri, 14 Mar 2025 17:12:29 +1300 Subject: [PATCH 1/4] support for adding special data to operations on play, autoresolve for death and taxes --- src/clj/game/cards/operations.clj | 21 +++++++++++---------- src/clj/game/core/play_instants.clj | 14 ++++++++------ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/clj/game/cards/operations.clj b/src/clj/game/cards/operations.clj index e0b8d4ad9e..e830b0d544 100644 --- a/src/clj/game/cards/operations.clj +++ b/src/clj/game/cards/operations.clj @@ -36,6 +36,7 @@ [game.core.memory :refer [mu+ update-mu]] [game.core.moving :refer [as-agenda mill move swap-agendas swap-ice trash trash-cards]] + [game.core.optional :refer [get-autoresolve set-autoresolve]] [game.core.payment :refer [can-pay? cost-target ->c]] [game.core.play-instants :refer [play-instant]] [game.core.prevention :refer [damage-boost]] @@ -687,16 +688,16 @@ :effect (effect (purge eid))}}) (defcard "Death and Taxes" - {:implementation "Credit gain mandatory to save on wait-prompts, adjust credits manually if credit not wanted." - :events [{:event :runner-install - :msg "gain 1 [Credits]" - :async true - :effect (effect (gain-credits :corp eid 1))} - {:event :runner-trash - :req (req (installed? (:card target))) - :msg "gain 1 [Credits]" - :async true - :effect (effect (gain-credits :corp eid 1))}]}) + (let [maybe-gain-credit {:prompt "Gain 1 [Credits]?" + :waiting-prompt true + :autoresolve (get-autoresolve :auto-fire) + :yes-ability {:msg "gain 1 [Credits]" + :async true + :effect (effect (gain-credits :corp eid 1))}}] + {:special {:auto-fire :always} + :abilities [(set-autoresolve :auto-fire "Death and Taxes")] + :events [{:event :runner-install :optional maybe-gain-credit} + {:event :runner-trash :optional (assoc maybe-gain-credit :req (req (installed? (:card target))))}]})) (defcard "Dedication Ceremony" {:on-play diff --git a/src/clj/game/core/play_instants.clj b/src/clj/game/core/play_instants.clj index 8099117aa5..62e3338c91 100644 --- a/src/clj/game/core/play_instants.clj +++ b/src/clj/game/core/play_instants.clj @@ -145,7 +145,9 @@ cost-paid (merge-costs-paid (:cost-paid eid) (:cost-paid async-result)) eid (assoc eid :cost-paid cost-paid :source-type :ability)] (if payment-str - (complete-play-instant state side eid moved-card payment-str ignore-cost) + (do + (update! state side (assoc moved-card :special (:special (card-def moved-card)))) + (complete-play-instant state side eid moved-card payment-str ignore-cost)) ;; could not pay the card's price; put it back and mark the effect as being over. (let [returned-card (move state side moved-card original-zone)] (continue-ability @@ -153,11 +155,11 @@ {:msg (msg "reveal that they are unable to play " (:title card)) :cost (when (:base-cost args) [(:base-cost args)]) :async true - :effect (req (update! state :runner (-> returned-card - (dissoc :seen) - (assoc - :cid (:cid card) - :previous-zone (:previous-zone card)))) + :effect (req (update! state side (-> returned-card + (dissoc :seen) + (assoc + :cid (:cid card) + :previous-zone (:previous-zone card)))) (reveal state side eid card))} card nil))))))) From 52b9c5cca55a0b2105438366c85f433c698befba Mon Sep 17 00:00:00 2001 From: NB Kelly Date: Fri, 14 Mar 2025 17:12:47 +1300 Subject: [PATCH 2/4] autoresolve for technoco, personalized portal --- src/clj/game/cards/assets.clj | 42 +++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/clj/game/cards/assets.clj b/src/clj/game/cards/assets.clj index 74e6e9f6a8..bb65985994 100644 --- a/src/clj/game/cards/assets.clj +++ b/src/clj/game/cards/assets.clj @@ -2168,16 +2168,25 @@ :abilities [ability]})) (defcard "Personalized Portal" - {:events [{:event :corp-turn-begins + {:special {:auto-fire :always} + :abilities [(set-autoresolve :auto-fire "Personalized Portal (gain credits)")] + :events [{:event :corp-turn-begins :interactive (req true) :async true - :effect (req (wait-for (draw state :runner 1) - (let [cnt (count (get-in @state [:runner :hand])) - credits (quot cnt 2)] - (system-msg state :corp - (str "uses " (:title card) " to force the runner to draw " - "1 card and gain " credits " [Credits]")) - (gain-credits state :corp eid credits))))}]}) + :msg "force the runner to draw 1 card" + :effect (req (wait-for + (draw state :runner 1) + (let [creds-to-gain (quot (count (get-in @state [:runner :hand])) 2)] + (continue-ability + state side + {:optional {:prompt (str "Gain " creds-to-gain " [Credits]?") + :autoresolve (get-autoresolve :auto-fire) + :req (req (pos? creds-to-gain)) + :waiting-prompt true + :yes-ability {:msg (str "gain " creds-to-gain " [Credits]") + :async true + :effect (req (gain-credits state side eid creds-to-gain))}}} + card nil))))}]}) (defcard "Plan B" (advance-ambush @@ -2895,16 +2904,21 @@ (hardware? card) (and (resource? card) (has-subtype? card "Virtual"))))] - {:static-abilities [{:type :install-cost + {:special {:auto-fire :always} + :abilities [(set-autoresolve :auto-fire "TechnoCo")] + :static-abilities [{:type :install-cost :req (req (and (is-techno-target target) (not (:facedown (second targets))))) :value 1}] :events [{:event :runner-install - :req (req (and (is-techno-target (:card context)) - (not (:facedown context)))) - :msg "gain 1 [Credits]" - :async true - :effect (effect (gain-credits :corp eid 1))}]})) + :optional {:req (req (and (is-techno-target (:card context)) + (not (:facedown context)))) + :prompt "Gain 1 [Credit]?" + :waiting-prompt true + :autoresolve (get-autoresolve :auto-fire) + :yes-ability {:msg "gain 1 [Credits]" + :async true + :effect (effect (gain-credits :corp eid 1))}}}]})) (defcard "Tenma Line" {:abilities [{:action true From 083b766a1a9ae32743153314cbcee1afe3ed9346 Mon Sep 17 00:00:00 2001 From: NB Kelly Date: Fri, 14 Mar 2025 17:13:13 +1300 Subject: [PATCH 3/4] autoresolve for psych mike, pad tap --- src/clj/game/cards/resources.clj | 58 +++++++++++--------------- test/clj/game/cards/resources_test.clj | 7 +--- 2 files changed, 26 insertions(+), 39 deletions(-) diff --git a/src/clj/game/cards/resources.clj b/src/clj/game/cards/resources.clj index 0af2482ecc..31c144246c 100644 --- a/src/clj/game/cards/resources.clj +++ b/src/clj/game/cards/resources.clj @@ -860,6 +860,7 @@ :interactive (req true) :optional {:prompt "Place 1 virus counter?" :req (req (has-subtype? (:card context) "Virus")) + :waiting-prompt true :autoresolve (get-autoresolve :auto-fire) :yes-ability {:msg (msg "place 1 virus counter on " (card-str state (:card context))) :async true @@ -1536,23 +1537,12 @@ (effect-completed state side eid)))}]})) (defcard "Find the Truth" - {:implementation "Corporation can click Find the Truth for explicit card reveals" - :events [{:event :post-runner-draw + {:events [{:event :post-runner-draw :msg (msg "reveal that they drew " (enumerate-str (map :title runner-currently-drawing))) :async true :effect (req (let [current-draws runner-currently-drawing] - (reveal state side eid current-draws) - ;; If the corp wants explicit reveals from FTT, then show a prompt with - ;; the card names in it - (when (= (get-in (get-card state card) [:special :explicit-reveal]) - :yes) - (continue-ability - state :corp - {:prompt (msg "The runner reveals that they drew " - (enumerate-str (map :title current-draws))) - :choices ["OK"]} - card nil))))} + (reveal state side eid current-draws)))} {:event :successful-run :interactive (get-autoresolve :auto-peek (complement never?)) :silent (get-autoresolve :auto-peek never?) @@ -1563,15 +1553,7 @@ :yes-ability {:prompt (req (->> corp :deck first :title (str "The top card of R&D is "))) :msg "look at the top card of R&D" :choices ["OK"]}}}] - :abilities [(set-autoresolve :auto-peek "Find the Truth looking at the top card of R&D")] - :corp-abilities [{:label "Explicitly reveal drawn cards" - :prompt "Explicitly reveal cards the Runner draws?" - :choices ["Yes" "No"] - :effect (effect (update! (assoc-in card [:special :explicit-reveal](keyword (str/lower-case target)))) - (toast (str "From now on, " (:title card) " will " - (when (= target "No") "Not") - "explicitly reveal cards the Runner draws") - "info"))}]}) + :abilities [(set-autoresolve :auto-peek "Find the Truth looking at the top card of R&D")]}) (defcard "First Responders" {:abilities [{:cost [(->c :credit 2)] @@ -1961,7 +1943,8 @@ (effect-completed state side eid))))}]}) (defcard "Kasi String" - {:events [{:event :run-ends + {:special {:auto-place-counter :always} + :events [{:event :run-ends :optional {:req (req (and (first-event? state :runner :run-ends #(is-remote? (:server (first %)))) (not (:did-steal target)) @@ -2254,7 +2237,8 @@ {:prompt (req (->> runner :deck first :title (str "The top card of the stack is "))) :msg "look at the top card of the stack" :choices ["OK"]}}}] - {:flags {:runner-turn-draw true + {:special {:auto-fire :always} + :flags {:runner-turn-draw true :runner-phase-12 (req (some #(card-flag? % :runner-turn-draw true) (all-active-installed state :runner)))} :events [(assoc ability :event :runner-turn-begins)] :abilities [ability (set-autoresolve :auto-fire "Motivation")]})) @@ -2522,15 +2506,20 @@ (assoc ability :event :runner-spent-credits)]})) (defcard "PAD Tap" - {:events [{:event :corp-credit-gain - :req (req (and (not= (:action context) :corp-click-credit) - (= 1 (->> (turn-events state :corp :corp-credit-gain) - (remove (fn [[context]] - (= (:action context) :corp-click-credit))) - count)))) - :msg "gain 1 [Credits]" - :async true - :effect (effect (gain-credits :runner eid 1))}] + {:special {:auto-fire :always} + :events [{:event :corp-credit-gain + :optional {:prompt "Gain 1 [Credit]?" + :req (req (and (not= (:action context) :corp-click-credit) + (= 1 (->> (turn-events state :corp :corp-credit-gain) + (remove (fn [[context]] + (= (:action context) :corp-click-credit))) + count)))) + :waiting-prompt true + :autoresolve (get-autoresolve :auto-fire) + :yes-ability {:msg "gain 1 [Credits]" + :async true + :effect (effect (gain-credits :runner eid 1))}}}] + :abilities [(set-autoresolve :auto-fire "PAD Tap")] :corp-abilities [{:action true :label "Trash PAD Tap" :async true @@ -2785,7 +2774,8 @@ (draw state side eid 1)))}]}) (defcard "Psych Mike" - {:events [{:event :run-ends + {:special {:auto-fire :always} + :events [{:event :run-ends :optional {:req (req (and (= :rd (target-server context)) (first-successful-run-on-server? state :rd) (pos? (total-cards-accessed target :deck)))) diff --git a/test/clj/game/cards/resources_test.clj b/test/clj/game/cards/resources_test.clj index 6a81a90e9d..ce7e67ecee 100644 --- a/test/clj/game/cards/resources_test.clj +++ b/test/clj/game/cards/resources_test.clj @@ -3732,7 +3732,6 @@ (dotimes [_ 3] (run-empty-server state "Server 1") (click-prompt state :runner "No action") - (click-prompt state :runner "Yes") (take-credits state :runner) (take-credits state :corp)) (take-credits state :runner) @@ -3769,7 +3768,6 @@ (take-credits state :corp) (run-empty-server state "Server 1") (click-prompt state :runner "No action") - (click-prompt state :runner "Yes") (is (= 1 (get-counters (get-resource state 0) :power)) "Kasi String should have 1 power counter on itself"))) (deftest kati-jones @@ -5353,7 +5351,6 @@ (let [credits (:credit (get-runner))] (run-empty-server state "R&D") (click-prompt state :runner "No action") - (click-prompt state :runner "Yes") (is (= (inc credits) (:credit (get-runner))) "Psych Mike should give 1 credit for accessing 1 card")) (let [credits (:credit (get-runner))] (run-empty-server state "R&D") @@ -5366,13 +5363,14 @@ (run-continue state) (dotimes [_ 5] (click-prompt state :runner "No action")) - (click-prompt state :runner "Yes") (is (= (+ credits 5) (:credit (get-runner))) "Psych Mike should give 5 credits for DDM accesses")) (run-empty-server state "HQ") (click-prompt state :runner "No action") (is (not (last-log-contains? state "Psych Mike to gain 0")) "No log should be printed") (take-credits state :runner) (take-credits state :corp) + (card-ability state :runner (get-resource state 0) 0) + (click-prompt state :runner "Ask") (let [credits (:credit (get-runner))] (run-empty-server state "R&D") (click-prompt state :runner "No action") @@ -5406,7 +5404,6 @@ (click-prompt state :runner "Unrezzed upgrade") (click-prompt state :runner "No action") (click-prompt state :runner "No action") - (click-prompt state :runner "Yes") (is (= (inc credits) (:credit (get-runner))) "Psych Mike should give 1 credit for accessing 1 card")))) (deftest reclaim-basic-behavior From 475389a8c8421642a7823f325ee1e1647ee9430a Mon Sep 17 00:00:00 2001 From: NB Kelly Date: Fri, 14 Mar 2025 17:21:22 +1300 Subject: [PATCH 4/4] takobi is automatically set to autoresolve --- src/clj/game/cards/programs.clj | 3 ++- test/clj/game/cards/programs_test.clj | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clj/game/cards/programs.clj b/src/clj/game/cards/programs.clj index fecf174133..ff726e40ae 100644 --- a/src/clj/game/cards/programs.clj +++ b/src/clj/game/cards/programs.clj @@ -3236,7 +3236,8 @@ (strength-pump (->c :credit 1 {:stealth 1}) 7 :end-of-encounter)]})) (defcard "Takobi" - {:events [{:event :subroutines-broken + {:special {:auto-place-counter :always} + :events [{:event :subroutines-broken :optional {:req (req (:all-subs-broken target)) :prompt (msg "Place 1 power counter on " (:title card) "?") :autoresolve (get-autoresolve :auto-place-counter) diff --git a/test/clj/game/cards/programs_test.clj b/test/clj/game/cards/programs_test.clj index 4ebe8a4bc8..a26089feb6 100644 --- a/test/clj/game/cards/programs_test.clj +++ b/test/clj/game/cards/programs_test.clj @@ -8373,7 +8373,6 @@ (run-continue state) (card-ability state :runner corr 0) (click-prompt state :runner "End the run") - (click-prompt state :runner "Yes") (run-continue state) (is (= 1 (get-counters (refresh tako) :power)) "Counter gained from breaking all subs"))))