From 697a3c221bb5f8f81ab7d0a6268f18792b734319 Mon Sep 17 00:00:00 2001 From: NB Kelly Date: Sat, 8 Feb 2025 12:29:09 +1300 Subject: [PATCH] can pay to rez/rez cost validation for cards --- src/clj/game/cards/assets.clj | 40 +++++++++++++++++++------------ src/clj/game/cards/operations.clj | 16 ++++++------- src/clj/game/cards/upgrades.clj | 22 ++++++++--------- src/clj/game/core/rezzing.clj | 13 ++++++++++ 4 files changed, 56 insertions(+), 35 deletions(-) diff --git a/src/clj/game/cards/assets.clj b/src/clj/game/cards/assets.clj index 4a6fda84de..49f06fd887 100644 --- a/src/clj/game/cards/assets.clj +++ b/src/clj/game/cards/assets.clj @@ -47,7 +47,7 @@ [game.core.prompts :refer [cancellable]] [game.core.props :refer [add-counter add-icon add-prop remove-icon set-prop]] [game.core.revealing :refer [reveal]] - [game.core.rezzing :refer [derez rez]] + [game.core.rezzing :refer [can-pay-to-rez? derez rez]] [game.core.runs :refer [end-run]] [game.core.say :refer [system-msg]] [game.core.servers :refer [is-remote? target-server zone->name]] @@ -1042,7 +1042,10 @@ :effect (effect (update! (dissoc card :ebc-rezzed)))}] :abilities [{:async true :once :per-turn - :choices {:card (complement rezzed?)} + :choices {:req (req (and (corp? target) + (not (rezzed? target)) + (can-pay-to-rez? state side (assoc eid :source card) + target {:cost-bonus -1})))} :label "Rez a card, lowering the cost by 1 [Credits] (start of turn)" :msg (msg "rez " (:title target)) :effect (req (wait-for (rez state side target {:no-warning true :cost-bonus -1}) @@ -2264,23 +2267,30 @@ :effect (effect (as-agenda card 1))}]}) (defcard "Quarantine System" - (letfn [(rez-ice [cnt] {:prompt "Choose a piece of ice to rez" - :async true - :choices {:card #(and (ice? %) - (not (rezzed? %)))} - :msg (msg "rez " (:title target)) - :waiting-prompt true - :effect (req (let [agenda (last (:rfg corp)) - ap (:agendapoints agenda 0)] - (wait-for (rez state side target {:no-warning true :cost-bonus (* ap -2)}) - (if (< cnt 3) - (continue-ability state side (rez-ice (inc cnt)) card nil) - (effect-completed state side eid)))))})] + (letfn [(rez-ice [cnt discount] + {:prompt (str "Choose a piece of ice to rez, paying " discount " [Credits] less") + :async true + :choices {:req (req (and (ice? target) + (can-pay-to-rez? state side (assoc eid :source card) + target {:cost-bonus (- discount)}) + (not (rezzed? target))))} + :msg (msg "rez " (:title target)) + :waiting-prompt true + :effect (req (wait-for (rez state side target {:no-warning true :cost-bonus (- discount)}) + (if (< cnt 3) + (continue-ability + state side + (rez-ice (inc cnt) discount) + card nil) + (effect-completed state side eid))))})] {:abilities [{:label "Forfeit agenda to rez up to 3 pieces of ice with a 2 [Credit] discount per agenda point" :req (req (pos? (count (:scored corp)))) :cost [(->c :forfeit)] :async true - :effect (req (continue-ability state side (rez-ice 1) card nil))}]})) + :effect (req (continue-ability + state side + (rez-ice 1 (* 2 (:agendapoints (last (:rfg corp)) 0))) + card nil))}]})) (defcard "Raman Rai" {:events [{:event :corp-draw diff --git a/src/clj/game/cards/operations.clj b/src/clj/game/cards/operations.clj index 4e59034911..37bb41bde1 100644 --- a/src/clj/game/cards/operations.clj +++ b/src/clj/game/cards/operations.clj @@ -41,7 +41,7 @@ [game.core.props :refer [add-counter add-prop]] [game.core.purging :refer [purge]] [game.core.revealing :refer [reveal reveal-loud]] - [game.core.rezzing :refer [derez rez]] + [game.core.rezzing :refer [can-pay-to-rez? derez rez]] [game.core.runs :refer [end-run make-run]] [game.core.say :refer [system-msg]] [game.core.servers :refer [is-remote? remote->name zone->name]] @@ -821,16 +821,16 @@ :async true :effect (req (doseq [c targets] (derez state side c {:source-card card})) - (let [discount (* -3 (count targets))] + (let [discount (* 3 (count targets))] (continue-ability state side {:async true - :prompt "Choose a card to rez" - :choices {:card #(and (installed? %) - (corp? %) - (not (rezzed? %)) - (not (agenda? %)))} - :effect (req (rez state side eid target {:cost-bonus discount}))} + :prompt (str "Choose a card to rez, paying " discount " [Credits] less") + :choices {:req (req (and (every-pred installed? corp? (complement rezzed?) + installed? (complement agenda?)) + (can-pay-to-rez? state side (assoc eid :source card) + target {:cost-bonus (- discount)})))} + :effect (req (rez state side eid target {:cost-bonus (- discount)}))} card nil)))}}) (defcard "Door to Door" diff --git a/src/clj/game/cards/upgrades.clj b/src/clj/game/cards/upgrades.clj index 095ee002e0..54e886aa64 100644 --- a/src/clj/game/cards/upgrades.clj +++ b/src/clj/game/cards/upgrades.clj @@ -41,7 +41,7 @@ [game.core.props :refer [add-counter add-prop set-prop]] [game.core.purging :refer [purge]] [game.core.revealing :refer [reveal]] - [game.core.rezzing :refer [rez derez]] + [game.core.rezzing :refer [can-pay-to-rez? rez derez]] [game.core.runs :refer [end-run force-ice-encounter jack-out redirect-run set-next-phase start-next-phase]] [game.core.say :refer [system-msg]] @@ -128,9 +128,8 @@ :optional {:req (req (and (ice? (:card context)) (protecting-same-server? card (:card context)) - (can-pay? state side (assoc eid :source card :source-type :rez) - (:card context) nil - [(->c :credit (rez-cost state side (:card context) {:cost-bonus -3}))]))) + (can-pay-to-rez? state side (assoc eid :source card) + (:card context) {:cost-bonus -3}))) :prompt "Rez ice with rez cost lowered by 3?" :yes-ability {:msg (msg "lower the rez cost of " (:title (:card context)) " by 3 [Credits]") :async true @@ -214,15 +213,17 @@ :events [{:event :pass-all-ice :optional {:req (req (and this-server - (some #(can-pay? state side (assoc eid :source card :source-type :rez) % nil - [(->c :credit (rez-cost state side % {:cost-bonus -7}))]) + (some #(can-pay-to-rez? state side (assoc eid :source card) + % {:cost-bonus -7}) (:hosted card)))) :prompt "Rez and force the Runner to encounter a hosted piece of ice?" :waiting-prompt true :yes-ability {:async true :prompt "Choose a hosted piece of Bioroid ice to rez" - :choices (req (:hosted card)) + :choices (req (filter #(can-pay-to-rez? state side (assoc eid :source card) + % {:cost-bonus -7}) + (:hosted card))) :msg (msg "lower the rez cost of " (:title target) " by 7 [Credits] and force the Runner to encounter it") :effect (req (wait-for (rez state side target {:cost-bonus -7}) (let [ice (:card async-result)] @@ -1662,16 +1663,13 @@ (not (same-card? target card)) (some #(and (not (rezzed? %)) (not (agenda? %)) - (can-pay? state side (assoc eid :source card :source-type :rez) % nil - [(->c :credit (install-cost state side % {:cost-bonus -2}))])) + (can-pay-to-rez? state side (assoc eid :source card) % {:cost-bonus -2})) (all-installed state :corp))))) :prompt "Rez another card paying 2 [Credits] less?" :yes-ability {:prompt "Choose a card to rez" :choices {:req (req (and (not (rezzed? target)) (not (agenda? target)) - (can-pay? state side (assoc eid :source card :source-type :rez) - target nil - [(->c :credit (rez-cost state side target {:cost-bonus -2}))])))} + (can-pay-to-rez? state side (assoc eid :source card) target {:cost-bonus -2})))} :msg (msg "rez " (:title target) ", lowering the rez cost by 2 [Credits]") :async true :effect (effect (rez eid target {:cost-bonus -2}))}}}]}) diff --git a/src/clj/game/core/rezzing.clj b/src/clj/game/core/rezzing.clj index 05df142fa8..5736fe0b45 100644 --- a/src/clj/game/core/rezzing.clj +++ b/src/clj/game/core/rezzing.clj @@ -94,6 +94,19 @@ (continue state side nil)) (complete-with-result state side eid {:card (get-card state card)}))))))))) +(defn can-pay-to-rez? + ([state side eid card] (can-pay-to-rez? state side eid card nil)) + ([state side eid card args] + (let [eid (assoc eid :source-type :rez) + card (get-card state card) + costs (get-rez-cost state side card args) + alternative-cost (when (and card + (not (is-disabled? state side card))) + (:alternative-cost (card-def card)))] + (or (and alternative-cost + (can-pay? state side eid card nil alternative-cost)) + (can-pay? state side eid card nil costs))))) + (defn rez "Rez a corp card." ([state side eid card] (rez state side eid card nil))