Skip to content

Commit

Permalink
Refactor sub initialization and firing
Browse files Browse the repository at this point in the history
  • Loading branch information
NoahTheDuke committed Jun 7, 2019
1 parent 99108f3 commit 57102f6
Show file tree
Hide file tree
Showing 12 changed files with 112 additions and 83 deletions.
3 changes: 2 additions & 1 deletion project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@

;; Misc
:test-paths ["test/clj"]
:eftest {:report eftest.report.pretty/report}
:eftest {:report eftest.report.pretty/report
:fast-fail? true}

:ring {:handler web.api/app}

Expand Down
4 changes: 2 additions & 2 deletions src/clj/game/cards/assets.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2090,9 +2090,9 @@
(rezzed? %))
(all-installed state :corp)))
(remove-one [cid state ice]
(remove-extra-subs state :corp cid ice))
(remove-extra-subs! state :corp ice cid))
(add-one [cid state ice]
(add-extra-sub state :corp cid ice 0 new-sub))
(add-extra-sub! state :corp ice new-sub cid 0))
(update-all [state func]
(doseq [i (all-rezzed-bios state)]
(func state i)))]
Expand Down
32 changes: 16 additions & 16 deletions src/clj/game/cards/ice.clj
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,22 @@
;;; Runner abilites for breaking subs
(defn runner-pay-or-break
"Ability to break a subroutine by spending a resource (Bioroids, Negotiator, etc)"
[cost subs label]
[cost qty label]
(let [cost-str (build-cost-str [cost])
subs-str (quantify subs "subroutine")]
subs-str (quantify qty "subroutine")]
{:cost cost
:label (str label " " subs-str)
:effect (req (system-msg state :runner (str "spends " cost-str " to " label " " subs-str " on " (:title card))))}))

(defn runner-break
"Ability to break a subroutine by spending a resource (Bioroids, Negotiator, etc)"
[cost subs]
(runner-pay-or-break cost subs "break"))
[cost qty]
(runner-pay-or-break cost qty "break"))

(defn runner-pay
"Ability to pay to avoid a subroutine by spending a resource (Popup Window, Turing, etc)"
[cost subs]
(runner-pay-or-break cost subs "pay for"))
[cost qty]
(runner-pay-or-break cost qty "pay for"))

;;; General subroutines
(def end-the-run
Expand Down Expand Up @@ -220,7 +220,13 @@

;; Card definitions
(def card-definitions
{"Aiki"
{"Afshar"
{:implementation "Breaking both subs not restricted"
:subroutines [{:msg "make the Runner lose 2 [Credits]"
:effect (effect (lose-credits :runner 2))}
end-the-run]}

"Aiki"
{:subroutines [(do-psi {:label "Runner draws 2 cards"
:msg "make the Runner draw 2 cards"
:effect (effect (draw :runner 2)
Expand Down Expand Up @@ -315,9 +321,9 @@
(card-is? % :side :runner))}
:label "Add 1 installed card to the Runner's Grip"
:msg "add 1 installed card to the Runner's Grip"
:effect (effect (clear-wait-prompt :runner)
(move :runner target :hand true)
(system-msg (str "adds " (:title target)
:effect (req (clear-wait-prompt state :runner)
(move state :runner target :hand true)
(system-msg state side (str "adds " (:title target)
" to the Runner's Grip")))
:cancel-effect (effect (clear-wait-prompt :runner)
(effect-completed eid))}
Expand Down Expand Up @@ -353,12 +359,6 @@
:effect (effect (corp-install target nil))
:msg (msg (corp-install-msg target))}]}

"Afshar"
{:implementation "Breaking both subs not restricted"
:subroutines [{:msg "make the Runner lose 2 [Credits]"
:effect (effect (lose-credits :runner 2))}
end-the-run]}

"Ashigaru"
{:abilities [{:label "Gain subroutines"
:msg (msg "gain " (count (:hand corp)) " subroutines")}]
Expand Down
18 changes: 9 additions & 9 deletions src/clj/game/cards/operations.clj
Original file line number Diff line number Diff line change
Expand Up @@ -504,12 +504,12 @@
:choices {:req #(and (ice? %)
(installed? %))}
:msg (msg "give " (card-str state target {:visible false}) " additional text")
:effect (req (add-extra-sub state :corp (:cid card) (get-card state target) -1 new-sub)
:effect (req (add-extra-sub! state :corp (get-card state target) new-sub (:cid card))
(update-ice-strength state side target)
(host state side (get-card state target) (assoc card :zone [:discard] :seen true :condition true)))
:leave-play (req (remove-extra-subs state :corp (:cid card) (:host card)))
:leave-play (req (remove-extra-subs! state :corp (:cid card) (:host card)))
:events {:rez {:req (req (= (:cid target) (:cid (:host card))))
:effect (req (add-extra-sub state :corp (:cid card) (get-card state target) -1 new-sub))}}})
:effect (req (add-extra-sub! state :corp (get-card state target) new-sub (:cid card)))}}})

"Economic Warfare"
{:req (req (and (last-turn? state :runner :successful-run)
Expand Down Expand Up @@ -1795,12 +1795,12 @@
:choices {:req #(and (ice? %) (rezzed? %))}
:msg (msg "make " (card-str state target) " gain Barrier and \"[Subroutine] End the run\"")
:effect (req (update! state side (assoc target :subtype (combine-subtypes true (:subtype target) "Barrier")))
(add-extra-sub state :corp (:cid card) (get-card state target) -1 new-sub)
(add-extra-sub! state :corp (get-card state target) new-sub (:cid card))
(update-ice-strength state side target)
(host state side (get-card state target) (assoc card :zone [:discard] :seen true :condition true)))
:leave-play (req (remove-extra-subs state :corp (:cid card) (:host card)))
:leave-play (req (remove-extra-subs! state :corp (:cid card) (:host card)))
:events {:rez {:req (req (= (:cid target) (:cid (:host card))))
:effect (req (add-extra-sub state :corp (:cid card) (get-card state target) -1 new-sub))}}})
:effect (req (add-extra-sub! state :corp (get-card state target) new-sub (:cid card)))}}})

"Subcontract"
(letfn [(sc [i sccard]
Expand Down Expand Up @@ -2096,11 +2096,11 @@
(rezzed? %))}
:msg (msg "give " (card-str state target) " \"[Subroutine] Do 1 brain damage\" before all its other subroutines")
:sub-effect (do-brain-damage 1)
:effect (req (add-extra-sub state :corp (:cid card) target 0 new-sub)
:effect (req (add-extra-sub! state :corp target new-sub (:cid card) 0)
(host state side (get-card state target) (assoc card :zone [:discard] :seen true :condition true)))
:leave-play (req (remove-extra-subs state :corp (:cid card) (:host card)))
:leave-play (req (remove-extra-subs! state :corp (:host card) (:cid card)))
:events {:rez {:req (req (= (:cid target) (:cid (:host card))))
:effect (req (add-extra-sub state :corp (:cid card) (get-card state target) 0 new-sub))}}})
:effect (req (add-extra-sub! state :corp (get-card state target) new-sub (:cid card) 0))}}})

"Witness Tampering"
{:msg "remove 2 bad publicity"
Expand Down
22 changes: 7 additions & 15 deletions src/clj/game/core/actions.clj
Original file line number Diff line number Diff line change
Expand Up @@ -363,22 +363,14 @@
(let [eid (make-eid state {:source (-> args :card :title)
:source-type :subroutine})]
(play-subroutine state side eid args)))
([state side eid {:keys [card subroutine targets] :as args}]
([state side eid {:keys [card subroutine] :as args}]
(let [card (get-card state card)
sub (nth (:subroutines card) subroutine nil)]
(if (or (nil? sub)
(nil? (:from-cid sub)))
(let [cdef-idx (if (nil? sub) subroutine (-> sub :data :cdef-idx))
cdef (card-def card)
cdef-sub (get-in cdef [:subroutines cdef-idx])
cost (:cost cdef-sub)]
(when (or (nil? cost)
(apply can-pay? state side (:title card) cost))
(when-let [activatemsg (:activatemsg cdef-sub)] (system-msg state side activatemsg))
(resolve-ability state side eid cdef-sub card targets)))
(when-let [sub-card (find-latest state {:cid (:from-cid sub) :side side})]
(when-let [sub-effect (:sub-effect (card-def sub-card))]
(resolve-ability state side eid sub-effect card (assoc (:data sub) :targets targets))))))))
sub (nth (:subroutines card) subroutine nil)
sub-effect (:sub-effect sub)]
(if (and card sub-effect)
(wait-for (pay-sync state side (make-eid state eid) card (:cost sub))
(resolve-ability state side eid sub-effect card nil))
(effect-completed state side eid)))))

;;; Corp actions
(defn trash-resource
Expand Down
53 changes: 39 additions & 14 deletions src/clj/game/core/ice.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,52 @@
(declare card-flag?)

;;; Ice subroutine functions
(defn add-extra-sub
(defn add-sub
([ice sub] (add-sub ice sub (:cid ice) -1))
([ice sub cid] (add-sub ice sub cid -1))
([ice sub cid idx]
(let [new-sub {:label (make-label sub)
:from-cid cid
:sub-effect sub}
curr-subs (:subroutines ice [])
offset (if (= -1 idx) (count curr-subs) idx)
new-subs (apply conj (subvec curr-subs 0 offset) new-sub (subvec curr-subs offset))]
(assoc ice :subroutines new-subs))))

(defn add-sub!
([state side ice sub] (update! state :corp (add-sub ice sub (:cid ice) -1)))
([state side ice sub cid] (update! state :corp (add-sub ice sub cid -1)))
([state side ice sub cid idx] (update! state :corp (add-sub ice sub cid idx))))

(defn remove-sub
"Removes a single sub from"
[ice sub]
(let [curr-subs (:subroutines ice)
new-subs (if (number? sub)
(apply conj (subvec curr-subs 0 sub) (subvec curr-subs (inc sub)))
(remove-once #(= sub %) curr-subs))]
(assoc ice :subroutines new-subs)))

(defn remove-sub!
[state side ice sub]
(update! state :corp (remove-sub ice sub)))

(defn add-extra-sub!
"Add a run time subroutine to a piece of ice (Warden, Sub Boost, etc). -1 as the idx adds to the end."
[state side cid ice idx sub]
(let [new-sub (assoc sub :from-cid cid)
curr-subs (vec (:subroutines ice))
offset (if (= -1 idx) (count curr-subs) idx)
new-subs (apply conj (subvec curr-subs 0 offset) new-sub (subvec curr-subs offset))]
(update! state :corp
(-> ice
(assoc :subroutines new-subs)
(assoc-in [:special :extra-subs] true)))))
([state side ice sub] (add-extra-sub! state side ice sub (:cid ice) -1))
([state side ice sub cid] (add-extra-sub! state side ice sub cid -1))
([state side ice sub cid idx]
(add-sub! state side (assoc-in ice [:special :extra-subs] true) sub cid idx)))

(defn remove-extra-subs
(defn remove-extra-subs!
"Remove runtime subroutines assigned from the given cid from a piece of ice."
[state side cid ice]
[state side ice cid]
(let [curr-subs (:subroutines ice)
new-subs (remove #(= cid (:from-cid %)) curr-subs)
extra-subs (some #(not (nil? (:from-cid %))) new-subs)]
extra-subs (some #(= (:cid ice) (:from-cid %)) new-subs)]
(update! state :corp
(-> ice
(assoc :subroutines new-subs)
(assoc :subroutines (vec new-subs))
(assoc-in [:special :extra-subs] extra-subs)))))

;;; Ice strength functions
Expand Down
14 changes: 2 additions & 12 deletions src/clj/game/core/installing.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

(declare available-mu free-mu host in-play? install-locked? make-rid rez run-flag?
installable-servers server->zone set-prop system-msg turn-flag?
update-breaker-strength update-ice-strength update-run-ice use-mu)
update-breaker-strength update-ice-strength update-run-ice use-mu add-sub)

;;;; Functions for the installation and deactivation of cards.

Expand All @@ -12,6 +12,7 @@
[card keep-counter]
(let [c (dissoc card :current-strength :abilities :subroutines :runner-abilities :corp-abilities :rezzed :special :new
:added-virus-counter :subtype-target :sifr-used :sifr-target :pump :server-target)
c (assoc c :subroutines (subroutines-init card (card-def card)))
c (if keep-counter c (dissoc c :counter :rec-counter :advance-counter :extra-advance-counter))]
c))

Expand Down Expand Up @@ -70,15 +71,6 @@
(for [ab (:runner-abilities cdef)]
(assoc (select-keys ab [:cost]) :label (make-label ab))))

(defn- subroutines-init
"Initialised the subroutines associated with the card, these work as abilities"
[cdef]
(map-indexed (fn [idx sub]
{:label (make-label sub)
:from-cid nil
:data {:cdef-idx idx}})
(:subroutines cdef)))

(defn card-init
"Initializes the abilities and events of the given card."
([state side card] (card-init state side card {:resolve-effect true :init-data true}))
Expand All @@ -89,11 +81,9 @@
abilities (ability-init cdef)
run-abs (runner-ability-init cdef)
corp-abs (corp-ability-init cdef)
subroutines (subroutines-init cdef)
c (merge card
(when init-data (:data cdef))
{:abilities abilities
:subroutines subroutines
:runner-abilities run-abs
:corp-abilities corp-abs})
c (if (number? recurring) (assoc c :rec-counter recurring) c)
Expand Down
13 changes: 11 additions & 2 deletions src/clj/game/core/turns.clj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(in-ns 'game.core)

(declare all-active card-flag-fn? clear-turn-register! clear-wait-prompt create-deck hand-size keep-hand mulligan
show-wait-prompt turn-message in-hand?)
show-wait-prompt turn-message in-hand? add-sub)

(def game-states (atom {}))

Expand Down Expand Up @@ -121,12 +121,21 @@
(init-hands state)))))
state))

(defn- subroutines-init
"Initialised the subroutines associated with the card, these work as abilities"
[card cdef]
(->> (:subroutines cdef)
(reduce (fn [ice sub] (add-sub ice sub (:cid ice) -1)) card)
:subroutines))

(defn make-card
"Makes or remakes (with current cid) a proper card from a server card"
([card] (make-card card (make-cid)))
([card cid]
(-> card
(assoc :cid cid :implementation (card-implemented card))
(assoc :cid cid
:implementation (card-implemented card)
:subroutines (subroutines-init (assoc card :cid cid) (card-def card)))
(dissoc :setname :text :_id :influence :number :influencelimit :factioncost))))

(defn create-deck
Expand Down
4 changes: 2 additions & 2 deletions test/clj/game_test/cards/assets.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4236,11 +4236,11 @@
(is (= 1 (count (:subroutines (refresh kak)))) "Kakugo starts with 1 sub")
(core/rez state :corp eli)
(is (= 2 (count (:subroutines (refresh eli)))) "Eli 2.0 starts with 2 subs")
(is (zero? (count (:subroutines (refresh ichi)))) "Unrezzed Ichi 2.0 starts with 0 subs")
(is (= 2 (count (:subroutines (refresh ichi)))) "Unrezzed Ichi 2.0 starts with 2 subs")
(core/rez state :corp wf)
(is (= 1 (count (:subroutines (refresh kak)))) "Kakugo stays at 1 sub")
(is (= 3 (count (:subroutines (refresh eli)))) "Eli 2.0 gains 1 sub")
(is (zero? (count (:subroutines (refresh ichi)))) "Unrezzed Ichi 2.0 stays at 0 subs")
(is (= 2 (count (:subroutines (refresh ichi)))) "Unrezzed Ichi 2.0 stays at 2 subs")
(core/rez state :corp ichi)
(is (= 1 (count (:subroutines (refresh kak)))) "Kakugo stays at 1 sub")
(is (= 3 (count (:subroutines (refresh eli)))) "Eli 2.0 stays at 1 sub")
Expand Down
18 changes: 16 additions & 2 deletions test/clj/game_test/cards/ice.clj
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
(deftest archangel
;; Archangel - accessing from R&D does not cause run to hang.
(do-game
(new-game {:corp {:deck ["Archangel" "Hedge Fund"]}
(new-game {:corp {:deck ["Archangel"]
:hand ["Hedge Fund"]}
:runner {:deck ["Bank Job"]}})
(starting-hand state :corp ["Hedge Fund"])
(take-credits state :corp)
(play-from-hand state :runner "Bank Job")
(run-empty-server state :rd)
Expand Down Expand Up @@ -760,6 +760,20 @@
(card-subroutine state :corp hydra 2)
(is (not (:run @state)) "Hydra sub 3 ended the run when Runner is tagged")))))

(deftest ice-wall
;; Ice Wall
(do-game
(new-game {:corp {:deck [(qty "Hedge Fund" 5)]
:hand ["Ice Wall"]}})
(play-from-hand state :corp "Ice Wall" "New remote")
(let [iw (get-ice state :remote1 0)]
(core/rez state :corp iw)
(take-credits state :corp)
(run-on state :remote1)
(is (:run @state))
(card-subroutine state :corp iw 0)
(is (nil? (:run @state))))))

(deftest iq
;; IQ - Rez cost and strength equal to cards in HQ
(do-game
Expand Down
6 changes: 3 additions & 3 deletions test/clj/game_test/cards/identities.clj
Original file line number Diff line number Diff line change
Expand Up @@ -277,14 +277,14 @@
(is (= 1 (core/access-count state :runner :rd-access)) "Should only access 1 from missed psi game")))
(testing "Shiro interaction: second sub should give Akiko 2 accesses"
(do-game
(new-game {:corp {:deck [(qty "Hedge Fund" 10) "Shiro"]}
(new-game {:corp {:deck [(qty "Hedge Fund" 10)]
:hand ["Shiro"]}
:runner {:id "Akiko Nisei: Head Case"
:deck [(qty "Sure Gamble" 3)]}})
(starting-hand state :corp ["Shiro"])
(play-from-hand state :corp "Shiro" "New remote")
(take-credits state :corp)
(let [shiro (get-ice state :remote1 0)]
(core/rez state :corp shiro)
(take-credits state :corp)
(run-on state :remote1)
(card-subroutine state :corp shiro 1)
(click-prompt state :corp "0 [Credits]")
Expand Down
8 changes: 3 additions & 5 deletions test/clj/game_test/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,9 @@

(defn card-subroutine
"Trigger a piece of ice's subroutine with the 0-based index."
([state side card ability] (card-subroutine state side card ability nil))
([state side card ability targets]
(core/play-subroutine state side {:card (core/get-card state card)
:subroutine ability
:targets targets})))
[state side card ability]
(core/play-subroutine state side {:card (core/get-card state card)
:subroutine ability}))

(defn card-side-ability
([state side card ability] (card-side-ability state side card ability nil))
Expand Down

0 comments on commit 57102f6

Please sign in to comment.