Skip to content

Commit

Permalink
Merge pull request mtgred#7370 from NoahTheDuke/nb/track-actions-better
Browse files Browse the repository at this point in the history
Track actions in play-ability, add :action flag to ability maps
  • Loading branch information
NoahTheDuke authored Apr 4, 2024
2 parents 60426ff + e231707 commit 0d042ad
Show file tree
Hide file tree
Showing 22 changed files with 200 additions and 149 deletions.
2 changes: 1 addition & 1 deletion src/clj/game/cards/agendas.clj
Original file line number Diff line number Diff line change
Expand Up @@ -1045,7 +1045,7 @@
:stolen he}))

(defcard "Ikawah Project"
{:steal-cost-bonus (req [(->c :credit 2) (->c :click 1)])})
{:steal-cost-bonus (req [(->c :click 1) (->c :credit 2)])})

(defcard "Illicit Sales"
{:on-score
Expand Down
39 changes: 26 additions & 13 deletions src/clj/game/cards/basic.clj
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
;; Card definitions

(defcard "Corp Basic Action Card"
{:abilities [{:label "Gain 1 [Credits]"
{:abilities [{:action true
:label "Gain 1 [Credits]"
:cost [(->c :click)]
:msg "gain 1 [Credits]"
:async true
Expand All @@ -37,7 +38,8 @@
(trigger-event state side :corp-click-credit)
(play-sfx state side "click-credit")
(effect-completed state side eid)))}
{:label "Draw 1 card"
{:action true
:label "Draw 1 card"
:req (req (not-empty (:deck corp)))
:cost [(->c :click)]
:msg "draw 1 card"
Expand All @@ -46,7 +48,8 @@
(swap! state update-in [:stats side :click :draw] (fnil inc 0))
(play-sfx state side "click-card")
(draw state side eid 1))}
{:label "Install 1 agenda, asset, upgrade, or piece of ice from HQ"
{:action true
:label "Install 1 agenda, asset, upgrade, or piece of ice from HQ"
:async true
:req (req (and (not-empty (:hand corp))
(in-hand? target)
Expand All @@ -73,7 +76,8 @@
state side (assoc eid :source server :source-type :corp-install)
target server {:base-cost [(->c :click 1)]
:action :corp-click-install})))}
{:label "Play 1 operation"
{:action true
:label "Play 1 operation"
:async true
:req (req (and (not-empty (:hand corp))
(in-hand? target)
Expand All @@ -82,7 +86,8 @@
target {:base-cost [(->c :click 1)]})))
:effect (req (play-instant state :corp (assoc eid :source :action :source-type :play)
target {:base-cost [(->c :click 1)]}))}
{:label "Advance 1 installed card"
{:action true
:label "Advance 1 installed card"
:cost [(->c :click 1) (->c :credit 1)]
:async true
:msg (msg "advance " (card-str state target))
Expand All @@ -91,7 +96,8 @@
(add-prop (get-card state target) :advance-counter 1)
(play-sfx "click-advance")
(effect-completed eid))}
{:label "Trash 1 resource if the Runner is tagged"
{:action true
:label "Trash 1 resource if the Runner is tagged"
:cost [(->c :click 1) (->c :credit 2)]
:async true
:req (req tagged)
Expand Down Expand Up @@ -140,15 +146,17 @@
(if async-result
(trash state side eid target nil)
(effect-completed state side eid)))))))}
{:label "Purge virus counters"
{:action true
:label "Purge virus counters"
:cost [(->c :click 3)]
:msg "purge all virus counters"
:async true
:effect (req (play-sfx state side "virus-purge")
(purge state side eid))}]})

(defcard "Runner Basic Action Card"
{:abilities [{:label "Gain 1 [Credits]"
{:abilities [{:action true
:label "Gain 1 [Credits]"
:cost [(->c :click)]
:msg "gain 1 [Credits]"
:async true
Expand All @@ -157,15 +165,17 @@
(trigger-event state side :runner-click-credit)
(play-sfx state side "click-credit")
(effect-completed state side eid)))}
{:label "Draw 1 card"
{:action true
:label "Draw 1 card"
:req (req (not-empty (:deck runner)))
:cost [(->c :click)]
:msg "draw 1 card"
:effect (req (trigger-event state side :runner-click-draw (-> @state side :deck (nth 0)))
(swap! state update-in [:stats side :click :draw] (fnil inc 0))
(play-sfx state side "click-card")
(draw state side eid (+ 1 (use-bonus-click-draws! state))))}
{:label "Install 1 program, resource, or piece of hardware from the grip"
{:action true
:label "Install 1 program, resource, or piece of hardware from the grip"
:async true
:req (req (and (not-empty (:hand runner))
(in-hand? target)
Expand All @@ -179,7 +189,8 @@
state :runner (assoc eid :source :action :source-type :runner-install)
target {:base-cost [(->c :click 1)]
:no-toast true}))}
{:label "Play 1 event"
{:action true
:label "Play 1 event"
:async true
:req (req (and (not-empty (:hand runner))
(in-hand? target)
Expand All @@ -188,10 +199,12 @@
target {:base-cost [(->c :click 1)]})))
:effect (req (play-instant state :runner (assoc eid :source :action :source-type :play)
target {:base-cost [(->c :click 1)]}))}
{:label "Run any server"
{:action true
:label "Run any server"
:async true
:effect (effect (make-run eid target nil {:click-run true}))}
{:label "Remove 1 tag"
{:action true
:label "Remove 1 tag"
:cost [(->c :click 1) (->c :credit 2)]
:msg "remove 1 tag"
:req (req tagged)
Expand Down
20 changes: 5 additions & 15 deletions src/clj/game/cards/hardware.clj
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
(ns game.cards.hardware
(:require
[clojure.set :as set]
[clojure.string :as str]
[game.core.access :refer [access-bonus access-card breach-server
get-only-card-to-access]]
[game.core.actions :refer [play-ability]]
[game.core.board :refer [all-active all-active-installed all-installed]]
[game.core.card :refer [active? corp? event? facedown? get-card get-counters get-title
[game.core.card :refer [corp? event? facedown? get-card get-counters get-title
get-zone hardware? has-subtype? ice? in-deck? in-discard?
in-hand? in-scored? installed? is-type? program? resource? rezzed?
runner? virus-program? faceup?]]
Expand All @@ -20,7 +19,7 @@
[game.core.effects :refer [register-lingering-effect
unregister-effects-for-card unregister-lingering-effects]]
[game.core.eid :refer [effect-completed make-eid make-result]]
[game.core.engine :refer [can-trigger? not-used-once? register-events
[game.core.engine :refer [can-trigger? register-events
register-once register-suppress resolve-ability trigger-event
unregister-floating-events unregister-suppress-by-uuid]]
[game.core.events :refer [event-count first-event? first-run-event? first-trash? no-event?
Expand Down Expand Up @@ -667,18 +666,9 @@
:prompt "Trigger the [Click] ability of the just-installed Caïssa program?"
:yes-ability
{:async true
:effect (effect
(continue-ability
(let [cid (:cid (:card context))]
{:async true
:prompt "Choose the just-installed Caïssa program"
:choices {:card #(= cid (:cid %))}
:msg (msg "trigger the [Click] ability of " (:title target)
" without spending [Click]")
:effect (req (gain-clicks state :runner 1)
(play-ability state side {:card target :ability 0})
(effect-completed state side eid))})
card nil))}}}]})
:effect (effect (play-ability eid {:card (:card context)
:ability 0
:ignore-cost true}))}}}]})

(defcard "Demolisher"
{:static-abilities [(mu+ 1)
Expand Down
6 changes: 3 additions & 3 deletions src/clj/game/cards/identities.clj
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@
{:events [(assoc ability :event :runner-trash :req (req (valid-trash target)))
(assoc ability :event :agenda-stolen :req (req true))]
:abilities [{:label "Look at the top 3 cards of R&D"
:cost [(->c :power 1) (->c :click 1)]
:cost [(->c :click 1) (->c :power 1)]
:msg "look at the top 3 cards of R&D"
:effect (req (let [top (take 3 (:deck corp))]
(wait-for (resolve-ability state side
Expand Down Expand Up @@ -2020,12 +2020,12 @@
{})

(defcard "SYNC: Everything, Everywhere"
{:static-abilities [{:type :card-ability-additional-cost
{:static-abilities [{:type :card-ability-cost
:req (req (and (not (:sync-flipped card))
(same-card? (:card context) (:basic-action-card runner))
(= "Remove 1 tag" (:label (:ability context)))))
:value (->c :credit 1)}
{:type :card-ability-additional-cost
{:type :card-ability-cost
:req (req (and (:sync-flipped card)
(same-card? (:card context) (:basic-action-card corp))
(= "Trash 1 resource if the Runner is tagged" (:label (:ability context)))))
Expand Down
8 changes: 5 additions & 3 deletions src/clj/game/cards/programs.clj
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,7 @@
(letfn [(was-a-runner-card?
[target]
(runner? (:card (first target))))]
{:static-abilities [{:type :card-ability-additional-cost
{:static-abilities [{:type :card-ability-cost
:req (req (and (same-card? card (:card context))
(not (no-event? state side :runner-trash was-a-runner-card?))))
:value (->c :credit -1)}]
Expand Down Expand Up @@ -1904,7 +1904,8 @@
(let [knight-req (req (and (same-card? current-ice (get-nested-host card))
(<= (get-strength current-ice) (get-strength card))))]
{:implementation "[Erratum] Program: Icebreaker - AI - Caïssa - Trojan"
:abilities [{:label "Host on a piece of ice"
:abilities [{:action true
:label "Host on a piece of ice"
:async true
:effect (req (let [k (get-card state card)
hosted (ice? (:host k))
Expand Down Expand Up @@ -3297,7 +3298,8 @@
(defcard "Trope"
{:events [{:event :runner-turn-begins
:effect (effect (add-counter card :power 1))}]
:abilities [{:req (req (not (zone-locked? state :runner :discard)))
:abilities [{:action true
:req (req (not (zone-locked? state :runner :discard)))
:label "shuffle cards from heap into stack"
:async true
:effect
Expand Down
2 changes: 1 addition & 1 deletion src/clj/game/cards/resources.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2054,7 +2054,7 @@
:duration :end-of-run
:effect (effect (enable-server (first (:server target))))}]
{:abilities [{:label "Run a remote server"
:cost [(->c :trash-can) (->c :click 1) (->c :brain 1)]
:cost [(->c :click 1) (->c :trash-can) (->c :brain 1)]
:prompt "Choose a remote server"
:choices (req (cancellable (filter #(can-run-server? state %) remotes)))
:msg (msg "make a run on " target " during which cards in the root of the attacked server lose all abilities")
Expand Down
1 change: 0 additions & 1 deletion src/clj/game/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@
generate-install-list
generate-runnable-zones
move-card
play
play-ability
play-auto-pump
play-auto-pump-and-break
Expand Down
93 changes: 56 additions & 37 deletions src/clj/game/core/actions.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[clojure.stacktrace :refer [print-stack-trace]]
[clojure.string :as string]
[game.core.agendas :refer [update-advancement-requirement update-all-advancement-requirements update-all-agenda-points]]
[game.core.board :refer [get-zones installable-servers]]
[game.core.board :refer [installable-servers]]
[game.core.card :refer [get-agenda-points get-card]]
[game.core.card-defs :refer [card-def]]
[game.core.cost-fns :refer [break-sub-ability-cost card-ability-cost score-additional-cost-bonus]]
Expand All @@ -29,29 +29,40 @@
[game.macros :refer [continue-ability req wait-for]]
[game.utils :refer [dissoc-in quantify remove-once same-card? same-side? server-cards]]))

(defn- update-click-state
"Update :click-states to hold latest 4 moments before performing actions."
[state ability]
(when (or (:action ability)
(= :click (:cost/type (first (:cost ability)))))
(let [state' (dissoc @state :log :history)
click-states (vec (take-last 4 (conj (:click-states state') state')))]
(swap! state assoc :click-states click-states))))

;;; Neutral actions
(defn- do-play-ability [state side card ability ability-idx targets]
(let [cost (seq (card-ability-cost state side ability card targets))
source {:source card
(defn- do-play-ability [state side eid {:keys [card ability ability-idx targets ignore-cost]}]
(let [source {:source card
:source-type :ability
:source-info {:ability-idx ability-idx
:ability-targets targets}}]
:ability-targets targets}}
eid (or eid (make-eid state source))
cost (when-not ignore-cost
(seq (card-ability-cost state side ability card targets)))
ability (assoc ability :cost cost)]
(when (or (nil? cost)
(can-pay? state side (make-eid state source)
card (:title card) cost))
(let [eid (make-eid state source)]
(resolve-ability state side eid (assoc ability :cost cost) card targets)))))
(can-pay? state side eid card (:title card) cost))
(update-click-state state ability)
(resolve-ability state side eid ability card targets))))

(defn play-ability
"Triggers a card's ability using its zero-based index into the card's card-def :abilities vector."
[state side {:keys [card ability targets]}]
(let [card (get-card state card)
abilities (:abilities card)
ab (nth abilities ability)
cannot-play (or (:disabled card)
(any-effects state side :prevent-paid-ability true? card [ab ability]))]
(when-not cannot-play
(do-play-ability state side card ab ability targets))))
([state side args] (play-ability state side nil args))
([state side eid {:keys [card] ability-idx :ability :as args}]
(let [card (get-card state card)
ability (nth (:abilities card) ability-idx)
cannot-play (or (:disabled card)
(any-effects state side :prevent-paid-ability true? card [ability ability-idx]))]
(when-not cannot-play
(do-play-ability state side eid (assoc args :ability-idx ability-idx :ability ability))))))

(defn expend-ability
"Called when the player clicks a card from hand."
Expand All @@ -67,19 +78,25 @@
(when-let [card (get-card state card)]
(case (:type card)
("Event" "Operation")
(play-ability state side {:card (get-in @state [side :basic-action-card]) :ability 3 :targets [card]})
(play-ability state side {:card (get-in @state [side :basic-action-card])
:ability 3
:targets [card]})
("Hardware" "Resource" "Program" "ICE" "Upgrade" "Asset" "Agenda")
(play-ability state side {:card (get-in @state [side :basic-action-card]) :ability 2 :targets [card server]}))))
(play-ability state side {:card (get-in @state [side :basic-action-card])
:ability 2
:targets [card server]}))))

(defn click-draw
"Click to draw."
[state side _]
(play-ability state side {:card (get-in @state [side :basic-action-card]) :ability 1}))
(play-ability state side {:card (get-in @state [side :basic-action-card])
:ability 1}))

(defn click-credit
"Click to gain 1 credit."
[state side _]
(play-ability state side {:card (get-in @state [side :basic-action-card]) :ability 0}))
(play-ability state side {:card (get-in @state [side :basic-action-card])
:ability 0}))

(defn move-card
"Called when the user drags a card from one zone to another."
Expand Down Expand Up @@ -464,25 +481,27 @@

(defn play-corp-ability
"Triggers a runner card's corp-ability using its zero-based index into the card's card-def :corp-abilities vector."
[state side {:keys [card ability targets]}]
(let [card (get-card state card)
cdef (card-def card)
ab (get-in cdef [:corp-abilities ability])
cannot-play (or (:disabled card)
(any-effects state side :prevent-paid-ability true? card [ab ability]))]
(when-not cannot-play
(do-play-ability state side card ab ability targets))))
([state side args] (play-corp-ability state side nil args))
([state side eid {:keys [card] ability-idx :ability :as args}]
(let [card (get-card state card)
cdef (card-def card)
ability (get-in cdef [:corp-abilities ability-idx])
cannot-play (or (:disabled card)
(any-effects state side :prevent-paid-ability true? card [ability ability-idx]))]
(when-not cannot-play
(do-play-ability state side eid (assoc args :ability-idx ability-idx :ability ability))))))

(defn play-runner-ability
"Triggers a corp card's runner-ability using its zero-based index into the card's card-def :runner-abilities vector."
[state side {:keys [card ability targets]}]
(let [card (get-card state card)
cdef (card-def card)
ab (get-in cdef [:runner-abilities ability])
cannot-play (or (:disabled card)
(any-effects state side :prevent-paid-ability true? card [ab ability]))]
(when-not cannot-play
(do-play-ability state side card ab ability targets))))
([state side args] (play-runner-ability state side nil args))
([state side eid {:keys [card] ability-idx :ability :as args}]
(let [card (get-card state card)
cdef (card-def card)
ability (get-in cdef [:runner-abilities ability-idx])
cannot-play (or (:disabled card)
(any-effects state side :prevent-paid-ability true? card [ability ability-idx]))]
(when-not cannot-play
(do-play-ability state side eid (assoc args :ability-idx ability-idx :ability ability))))))

(defn play-subroutine
"Triggers a card's subroutine using its zero-based index into the card's :subroutines vector."
Expand Down
Loading

0 comments on commit 0d042ad

Please sign in to comment.