From ce6e7a4d7062b56b4d56a228cf6a250c44092be8 Mon Sep 17 00:00:00 2001 From: Oguz Han Asnaz Date: Sat, 29 Jun 2019 20:59:51 +0200 Subject: [PATCH] Handle zero credit costs correctly --- src/clj/game/core/costs.clj | 23 +++++++++++------ test/clj/game_test/engine/costs.clj | 40 +++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/src/clj/game/core/costs.clj b/src/clj/game/core/costs.clj index e2b2550b4a..52824cca2a 100644 --- a/src/clj/game/core/costs.clj +++ b/src/clj/game/core/costs.clj @@ -72,13 +72,18 @@ (defn merge-costs "Combines disparate costs into a single cost per type, except for damage. Damage is not merged as it needs to be individual." - [costs] - (let [clean-costs (add-default-to-costs costs) - plain-costs (remove #(#{:net :meat :brain} (first %)) clean-costs) - damage-costs (filter #(#{:net :meat :brain} (first %)) clean-costs) - reduce-fn (fn [cost-map [cost-type value]] - (update cost-map cost-type (fnil + 0 0) value))] - (mapv vec (concat (reduce reduce-fn {} plain-costs) damage-costs)))) + ([costs] (merge-costs costs false)) + ([costs remove-zero-credit-cost] + (let [clean-costs (add-default-to-costs costs) + plain-costs (remove #(#{:net :meat :brain} (first %)) clean-costs) + damage-costs (filter #(#{:net :meat :brain} (first %)) clean-costs) + reduce-fn (fn [cost-map [cost-type value]] + (update cost-map cost-type (fnil + 0 0) value)) + remove-fn (if remove-zero-credit-cost + #(and (= :credit (first %)) + (zero? (second %))) + (fn [x] false))] + (remove remove-fn (mapv vec (concat (reduce reduce-fn {} plain-costs) damage-costs)))))) (defn- flag-stops-pay? "Checks installed cards to see if payment type is prevented by a flag" @@ -122,7 +127,9 @@ explaining which cost they were unable to pay." ([state side title args] (can-pay? state side (make-eid state) nil title args)) ([state side eid card title & args] - (let [costs (merge-costs (remove #(or (nil? %) (map? %)) args))] + (let [remove-zero-credit-cost (or (and (= (:source-type eid) :corp-install) + (not (ice? card)))) + costs (merge-costs (remove #(or (nil? %) (map? %)) args) remove-zero-credit-cost)] (if (every? #(can-pay-impl state side eid card %) costs) costs (when title diff --git a/test/clj/game_test/engine/costs.clj b/test/clj/game_test/engine/costs.clj index c1bb750ff1..962d7e719d 100644 --- a/test/clj/game_test/engine/costs.clj +++ b/test/clj/game_test/engine/costs.clj @@ -36,3 +36,43 @@ (testing "Net, meat, and brain damage are recognized" (is (= [[:net 1] [:meat 1] [:brain 1]] (core/merge-costs [[:net 1] [:meat 1] [:brain 1]])))))) + +(deftest pay-credits + (testing "Testing several cost messages" + (do-game + (new-game {:runner {:hand ["Diesel" "Daily Casts" "Clot" "Career Fair" "Daily Casts" "Sure Gamble" "Misdirection"]} + :corp {:hand [(qty "Ice Wall" 2) "Turtlebacks" "Beanstalk Royalties" "Hedge Fund" "Project Beale" "Ben Musashi"]}}) + (core/gain state :corp :click 10) + (play-from-hand state :corp "Ice Wall" "HQ") + (is (= "Corp spends [Click] and pays 0 [Credits] to install ICE protecting HQ." (-> @state :log last :text)) "Install ICE, zero cost") + (play-from-hand state :corp "Ice Wall" "HQ") + (is (= "Corp spends [Click] and pays 1 [Credits] to install ICE protecting HQ." (-> @state :log last :text)) "Install ICE, one cost") + (play-from-hand state :corp "Turtlebacks" "New remote") + (is (= "Corp spends [Click] to install a card in Server 1 (new remote)." (-> @state :log last :text)) "Install asset, zero cost") + (play-from-hand state :corp "Ben Musashi" "Server 1") + (is (= "Corp spends [Click] to install a card in Server 1." (-> @state :log last :text)) "Install upgrade, zero cost") + (play-from-hand state :corp "Project Beale" "New remote") + (is (= "Corp spends [Click] to install a card in Server 2 (new remote)." (-> @state :log last :text)) "Install agenda, zero cost") + (play-from-hand state :corp "Beanstalk Royalties") + (is (= "Corp spends [Click] and pays 0 [Credits] to play Beanstalk Royalties." (-> @state :log reverse second :text)) "Play operation, zero cost") + (play-from-hand state :corp "Hedge Fund") + (is (= "Corp spends [Click] and pays 5 [Credits] to play Hedge Fund." (-> @state :log reverse second :text)) "Play operation, five cost") + (take-credits state :corp) + (core/gain state :runner :click 10) + (play-from-hand state :runner "Diesel") + (is (= "Runner spends [Click] and pays 0 [Credits] to play Diesel." (-> @state :log reverse second :text)) "Play event, zero cost") + (play-from-hand state :runner "Sure Gamble") + (is (= "Runner spends [Click] and pays 5 [Credits] to play Sure Gamble." (-> @state :log reverse second :text)) "Play event, five cost") + (play-from-hand state :runner "Clot") + (is (= "Runner spends [Click] and pays 2 [Credits] to install Clot." (-> @state :log last :text)) "Install program, two cost") + (play-from-hand state :runner "Misdirection") + (is (= "Runner spends [Click] and pays 0 [Credits] to install Misdirection." (-> @state :log last :text)) "Install program, zero cost") + (play-from-hand state :runner "Career Fair") + (is (= "Runner spends [Click] and pays 0 [Credits] to play Career Fair." (-> @state :log last :text)) "Play Career Fair, zero cost") + (click-card state :runner (find-card "Daily Casts" (:hand (get-runner)))) + (is (= "Runner pays 0 [Credits] to install Daily Casts." (-> @state :log last :text)) "Choose Daily cast, zero cost install") + (play-from-hand state :runner "Daily Casts") + (is (= "Runner spends [Click] and pays 3 [Credits] to install Daily Casts." (-> @state :log last :text)) "Install resource, three cost") + (run-on state :archives) + (is (= "Runner spends [Click] to make a run on Archives." (-> @state :log last :text)) "Initiate run, zero cost")))) +