Skip to content

Commit

Permalink
MVP for breaking all subroutines
Browse files Browse the repository at this point in the history
  • Loading branch information
lostgeek authored and NoahTheDuke committed Jul 29, 2019
1 parent 76e7558 commit ad48e61
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 30 deletions.
86 changes: 57 additions & 29 deletions src/clj/game/cards/programs.clj
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,11 @@
(or (= "ICE" subtype)
(has-subtype? current-ice subtype))
true)))
:label (str (build-cost-str (if (number? cost) [:credit cost] cost))
": break "
:break n
:cost (if (number? cost)
[:credit cost]
cost)
:label (str "break "
(when (> n 1) "up to ")
(if (pos? n) n "any number of")
(when subtype (str " " subtype))
Expand All @@ -90,32 +93,55 @@
auto-pump routine in core, IF we are encountering a rezzed ice with a subtype
we can break."
{:effect
(req (let [abs (filter #(not= (:dynamic %) :auto-pump) (:abilities card))
pumpabi (some #(when (:pump %) %) abs)
pumpcst (when pumpabi (second (drop-while #(and (not= % :credit)
(not= % "credit"))
(:cost pumpabi))))
current-ice (when-not (get-in @state [:run :ending]) (get-card state current-ice))
strdif (when (and (get-strength current-ice)
(get-strength card))
(max 0 (- (get-strength current-ice)
(get-strength card))))
pumpnum (when (and strdif
(:pump pumpabi))
(int (Math/ceil (/ strdif (:pump pumpabi)))))]
(update! state side
(assoc card :abilities
(if (and pumpcst
pumpnum
(rezzed? current-ice)
(or (some #(has-subtype? current-ice %) (:breaks card))
(= (first (:breaks card)) "All"))
(pos? pumpnum))
(vec (cons {:dynamic :auto-pump
:cost [:credit (* pumpcst pumpnum)]
:label (str "Match strength of " (:title current-ice))}
abs))
abs)))))})
(req (doall (let [abs (filter #(and (not= (:dynamic %) :auto-pump)
(not= (:dynamic %) :auto-pump-and-break))
(:abilities (card-def card)))
pumpabi (some #(when (:pump %) %) abs)
pumpcst (when pumpabi (second (drop-while #(and (not= % :credit)
(not= % "credit"))
(:cost pumpabi))))
current-ice (when-not (get-in @state [:run :ending]) (get-card state current-ice))
strdif (when current-ice (max 0 (- (or (:current-strength current-ice) (:strength current-ice))
(or (:current-strength card) (:strength card)))))
pumpnum (when strdif (int (Math/ceil (/ strdif (:pump pumpabi 1)))))
total-pump-cost (when (and pumpnum pumpabi)
(merge-costs (repeat pumpnum (:cost pumpabi))))
breakabi (some #(when (:break %) %) abs)
nsubs (when (:subroutines current-ice)
(count (remove :broken (:subroutines current-ice))))
some-already-broken (not= (:subroutines current-ice)
(remove :broken (:subroutines current-ice)))
subs-broken-at-once (when breakabi (:break breakabi))
times-break (when (and nsubs subs-broken-at-once)
(if (pos? subs-broken-at-once)
(/ nsubs subs-broken-at-once)
1))
total-break-cost (when (and times-break breakabi)
(repeat times-break (:cost breakabi)))
total-cost (merge-costs (conj total-pump-cost total-break-cost))]
(update! state side
(assoc card :abilities
(if (and pumpcst
pumpnum
(rezzed? current-ice)
(or (some #(has-subtype? current-ice %) (:breaks card))
(= (first (:breaks card)) "All")))
(vec (concat (when (and (pos? nsubs)
(can-pay? state side eid card total-cost))
[{:dynamic :auto-pump-and-break
:cost (first total-cost) ; ToDo: this should be refactored at some point to take the whole total-cost seq
; Since cost deduction is done in play-auto-pump-and-break, this isn't so important
:label (str (if (pos? pumpnum)
"Match strength and fully break "
"Fully break ")
(:title current-ice))}])
(when (and (pos? pumpnum)
(can-pay? state side eid card total-pump-cost))
[{:dynamic :auto-pump
:cost (first total-pump-cost)
:label (str "Match strength of " (:title current-ice))}])
abs))
abs))))))})

;; Takes a vector of ice subtypes that can be broken (or ["All"] for
;; AI breakers) and a card definition, and returns a new card definition that
Expand Down Expand Up @@ -195,7 +221,9 @@
" for the remainder of the run"
(= duration :all-turn)
" for the remainder of the turn"))
:cost [:credit cost]
:cost (if (number? cost)
[:credit cost]
cost)
:effect (effect (pump card strength duration))
:pump strength}))

Expand Down
51 changes: 50 additions & 1 deletion src/clj/game/core/actions.clj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
name-zone play-instant purge make-run runner-install trash
update-breaker-strength update-ice-in-server update-run-ice win can-run?
can-run-server? can-score? say play-sfx base-mod-size free-mu
reset-all-subs! resolve-subroutine! resolve-unbroken-subs!)
reset-all-subs! resolve-subroutine! resolve-unbroken-subs! break-all-subroutines!)

;;; Neutral actions
(defn play
Expand Down Expand Up @@ -337,6 +337,54 @@
"the strength of " (:title card) " to "
(:current-strength (get-card state card))))))))

(defn play-auto-pump-and-break
"Use play-auto-pump and then break all available subroutines"
[state side args]
(let [run (:run @state)
card (get-card state (:card args))
eid (make-eid state {:source card :source-type :ability})
run-ice (get-run-ices state)
ice-cnt (count run-ice)
ice-idx (dec (:position run 0))
in-range (and (pos? ice-cnt) (< -1 ice-idx ice-cnt))
current-ice (when (and run in-range) (get-card state (run-ice ice-idx)))
pumpabi (some #(when (:pump %) %) (:abilities (card-def card)))
strdif (when current-ice (max 0 (- (or (:current-strength current-ice) (:strength current-ice))
(or (:current-strength card) (:strength card)))))
pumpnum (when strdif (int (Math/ceil (/ strdif (:pump pumpabi 1)))))
total-pump-cost (merge-costs (repeat pumpnum (:cost pumpabi)))
breakabi (some #(when (:break %) %) (:abilities (card-def card)))
nsubs (when (:subroutines current-ice)
(count (remove :broken (:subroutines current-ice))))
some-already-broken (not= (:subroutines current-ice)
(remove :broken (:subroutines current-ice)))
subs-broken-at-once (when breakabi (:break breakabi))
times-break (when (and nsubs subs-broken-at-once)
(if (pos? subs-broken-at-once)
(/ nsubs subs-broken-at-once)
1))
total-break-cost (when (and times-break breakabi)
(repeat times-break (:cost breakabi)))
total-cost (merge-costs (conj total-pump-cost total-break-cost))]
(when (can-pay? state side eid card (:title card) total-cost)
(wait-for (pay-sync state side (make-eid state eid) card total-cost)
(dotimes [n pumpnum] (resolve-ability state side (dissoc pumpabi :cost :msg) (get-card state card) nil))
(break-all-subroutines! state current-ice)
(system-msg state side (if (pos? pumpnum)
(str (build-spend-msg async-result "increase")
"the strength of " (:title card) " to "
(:current-strength (get-card state card))
" and break all " nsubs " subroutines on "
(:title current-ice))
(str (build-spend-msg async-result "use")
(:title card)
" to break "
(if some-already-broken
"the remaining "
"all ")
nsubs " subroutines on "
(:title current-ice))))))))

(defn play-copy-ability
"Play an ability from another card's definition."
[state side {:keys [card source index] :as args}]
Expand All @@ -349,6 +397,7 @@

(def dynamic-abilities
{"auto-pump" play-auto-pump
"auto-pump-and-break" play-auto-pump-and-break
"copy" play-copy-ability})

(defn play-dynamic-ability
Expand Down
51 changes: 51 additions & 0 deletions test/clj/game_test/engine/costs.clj
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,54 @@
(click-prompt state :runner "Place 1 [Credits]")
(is (= 5 (:current-strength (refresh cor))) "Corroder is at 5 strength")
(is (= (- cre 2) (:credit (get-runner))) "Spent 2 (+1 from Cloak) to pump")))))

(deftest pump-and-break
(testing "Basic test"
(do-game
(new-game {:runner {:hand ["Corroder"]}
:corp {:hand ["Hive"]}})
(play-from-hand state :corp "Hive" "HQ")
(take-credits state :corp)
(core/gain state :runner :credit 10)
(play-from-hand state :runner "Corroder")
(run-on state :hq)
(let [cor (get-program state 0)
hive (get-ice state :hq 0)]
(is (= 2 (:current-strength (refresh cor))) "Corroder starts at 2 strength")
(core/play-dynamic-ability state :runner {:dynamic "auto-pump-and-break" :card (refresh cor)})
(is (= 3 (:current-strength (refresh cor))) "Corroder now at 3 strength")
(is (empty? (remove :broken (:subroutines (refresh hive)))) "Hive is now fully broken"))))
(testing "Auto-pump first"
(do-game
(new-game {:runner {:hand ["Corroder"]}
:corp {:hand ["Hive"]}})
(play-from-hand state :corp "Hive" "HQ")
(take-credits state :corp)
(core/gain state :runner :credit 10)
(play-from-hand state :runner "Corroder")
(run-on state :hq)
(let [cor (get-program state 0)
hive (get-ice state :hq 0)]
(core/play-dynamic-ability state :runner {:dynamic "auto-pump" :card (refresh cor)})
(is (= 3 (:current-strength (refresh cor))) "Corroder now at 3 strength")
(core/play-dynamic-ability state :runner {:dynamic "auto-pump-and-break" :card (refresh cor)})
(is (empty? (remove :broken (:subroutines (refresh hive)))) "Hive is now fully broken"))))
(testing "Auto-pump and break some subs manually first"
(do-game
(new-game {:runner {:hand ["Corroder"]}
:corp {:hand ["Hive"]}})
(play-from-hand state :corp "Hive" "HQ")
(take-credits state :corp)
(core/gain state :runner :credit 10)
(play-from-hand state :runner "Corroder")
(run-on state :hq)
(let [cor (get-program state 0)
hive (get-ice state :hq 0)]
(core/play-dynamic-ability state :runner {:dynamic "auto-pump" :card (refresh cor)})
(is (= 3 (:current-strength (refresh cor))) "Corroder is now at 3 strength")
(card-ability state :runner (refresh cor) 0)
(click-prompt state :runner "End the run")
(click-prompt state :runner "Done")
(is (= 4 (count (remove :broken (:subroutines (refresh hive))))) "Only broken 1 sub")
(core/play-dynamic-ability state :runner {:dynamic "auto-pump-and-break" :card (refresh cor)})
(is (empty? (remove :broken (:subroutines (refresh hive)))) "Hive is now fully broken")))))

0 comments on commit ad48e61

Please sign in to comment.