Skip to content

Commit 53cc2d7

Browse files
committed
Merge branch 'NBKelly-automata-release'
2 parents 9633c6d + fc6202c commit 53cc2d7

31 files changed

+2079
-93
lines changed

src/clj/game/cards/agendas.clj

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,22 @@
2323
[game.core.eid :refer [effect-completed make-eid]]
2424
[game.core.engine :refer [pay register-events resolve-ability
2525
unregister-events]]
26-
[game.core.events :refer [first-event? no-event? turn-events]]
26+
[game.core.events :refer [first-event? no-event? run-events turn-events]]
2727
[game.core.finding :refer [find-latest]]
2828
[game.core.flags :refer [in-runner-scored? is-scored? register-run-flag!
2929
register-turn-flag! when-scored? zone-locked?]]
3030
[game.core.gaining :refer [gain gain-clicks gain-credits lose lose-clicks
3131
lose-credits]]
3232
[game.core.hand-size :refer [corp-hand-size+ runner-hand-size+]]
3333
[game.core.hosting :refer [host]]
34-
[game.core.ice :refer [add-extra-sub! remove-sub! update-all-ice]]
34+
[game.core.ice :refer [add-extra-sub! remove-sub! update-all-ice update-all-icebreakers]]
3535
[game.core.initializing :refer [card-init]]
3636
[game.core.installing :refer [corp-install corp-install-list
3737
corp-install-msg]]
3838
[game.core.moving :refer [forfeit mill move move-zone swap-cards swap-ice
3939
trash trash-cards]]
4040
[game.core.optional :refer [get-autoresolve set-autoresolve]]
41+
[game.core.payment :refer [can-pay?]]
4142
[game.core.prompts :refer [cancellable clear-wait-prompt show-wait-prompt]]
4243
[game.core.props :refer [add-counter add-prop]]
4344
[game.core.purging :refer [purge]]
@@ -805,6 +806,14 @@
805806
(defcard "Freedom of Information"
806807
{:advancement-requirement (req (- (count-tags state)))})
807808

809+
(defcard "Fujii Asset Retrieval"
810+
{:stolen {:async true
811+
:msg "do 2 net damage"
812+
:effect (effect (damage eid :net 2 {:card card}))}
813+
:on-score {:async true
814+
:msg "do 2 net damage"
815+
:effect (effect (damage eid :net 2 {:card card}))}})
816+
808817
(defcard "Genetic Resequencing"
809818
{:on-score {:choices {:card in-scored?}
810819
:msg (msg "place 1 agenda counter on " (:title target))
@@ -1269,6 +1278,18 @@
12691278
(defcard "Ontological Dependence"
12701279
{:advancement-requirement (req (- (or (get-in @state [:runner :brain-damage]) 0)))})
12711280

1281+
(defcard "Oracle Thinktank"
1282+
{:stolen {:msg "give the Runner 1 tag"
1283+
:async true
1284+
:effect (effect (gain-tags eid 1))}
1285+
:abilities [{:cost [:click 1 :tag 1]
1286+
:msg "shuffle itself into R&D"
1287+
:label "Shuffle into R&D"
1288+
:effect (effect (move :corp card :deck nil)
1289+
(shuffle! :corp :deck)
1290+
(update-all-agenda-points))}]
1291+
:flags {:has-abilities-when-stolen true}})
1292+
12721293
(defcard "Orbital Superiority"
12731294
{:on-score
12741295
{:msg (msg (if (is-tagged? state) "do 4 meat damage" "give the Runner 1 tag"))
@@ -1679,6 +1700,12 @@
16791700
:async true
16801701
:effect (effect (gain-tags eid 1))}}}]})
16811702

1703+
(defcard "Salvo Testing"
1704+
{:events [{:event :agenda-scored
1705+
:async true
1706+
:msg "do 1 core damage"
1707+
:effect (effect (damage eid :brain 1 {:card card}))}]})
1708+
16821709
(defcard "SDS Drone Deployment"
16831710
{:steal-cost-bonus (req [:program 1])
16841711
:on-score {:req (req (seq (all-installed-runner-type state :program)))
@@ -1743,6 +1770,16 @@
17431770
:msg "do 2 meat damage"
17441771
:effect (effect (damage eid :meat 2 {:card card}))}})
17451772

1773+
(defcard "Slash and Burn Agriculture"
1774+
{:expend {:req (req (some #(can-be-advanced? %) (all-installed state :corp)))
1775+
:cost [:credit 1]
1776+
:choices {:card #(can-be-advanced? %)}
1777+
:msg (msg "place 2 advancement counters on " (card-str state target))
1778+
:async true
1779+
:effect (req
1780+
(add-prop state :corp target :advance-counter 2 {:placed true})
1781+
(effect-completed state side eid))}})
1782+
17461783
(defcard "SSL Endorsement"
17471784
(let [add-credits (effect (add-counter card :credit 9))]
17481785
{:flags {:has-events-when-stolen true}
@@ -1793,6 +1830,34 @@
17931830
:effect (effect (show-wait-prompt (str (side-str (other-side side)) " to trash a card for Standoff"))
17941831
(continue-ability :runner (stand :runner) card nil))}}))
17951832

1833+
(defcard "Stegodon MK IV"
1834+
{:events [{:event :run
1835+
:async true
1836+
:effect
1837+
(req (let [rezzed-targets
1838+
(seq (filter #(and (ice? %)
1839+
(rezzed? %)
1840+
(not= (first (:server target)) (second (get-zone %))))
1841+
(all-installed state :corp)))]
1842+
(if-not (empty? rezzed-targets)
1843+
(continue-ability
1844+
state side
1845+
{:prompt "derez a card in/protecting another server?"
1846+
:choices {:req (req (some #{target} rezzed-targets))}
1847+
:once :per-turn
1848+
:msg (msg "derezzes " (:title target) " to gain 1[Credit]")
1849+
:async true
1850+
:effect (effect (derez target)
1851+
(gain-credits eid 1))}
1852+
card nil)
1853+
(effect-completed state side eid))))}]
1854+
:leave-play (effect (update-all-icebreakers))
1855+
:constant-effects [{:type :breaker-strength
1856+
:value -2
1857+
:req (req (and run
1858+
(has-subtype? target "Icebreaker")
1859+
(not-empty (run-events state side :derez))))}]})
1860+
17961861
(defcard "Sting!"
17971862
(letfn [(count-opp-stings [state side]
17981863
(count (filter #(= (:title %) "Sting!") (get-in @state [(other-side side) :scored]))))]

src/clj/game/cards/assets.clj

Lines changed: 195 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
update-all-agenda-points]]
1010
[game.core.bad-publicity :refer [bad-publicity-prevent gain-bad-publicity
1111
lose-bad-publicity]]
12-
[game.core.board :refer [all-active-installed all-installed
12+
[game.core.board :refer [all-active-installed all-installed get-remotes
1313
installable-servers]]
1414
[game.core.card :refer [agenda? asset? can-be-advanced? corp? event?
1515
faceup? fake-identity? get-advancement-requirement
@@ -27,7 +27,8 @@
2727
[game.core.engine :refer [pay register-events resolve-ability]]
2828
[game.core.events :refer [first-event? no-event? turn-events]]
2929
[game.core.expose :refer [expose-prevent]]
30-
[game.core.flags :refer [lock-zone prevent-current prevent-draw
30+
[game.core.flags :refer [enable-run-on-server lock-zone prevent-current prevent-run-on-server
31+
prevent-draw
3132
register-turn-flag! release-zone]]
3233
[game.core.gaining :refer [gain gain-clicks gain-credits lose lose-clicks
3334
lose-credits]]
@@ -47,9 +48,10 @@
4748
[game.core.props :refer [add-counter add-icon add-prop remove-icon set-prop]]
4849
[game.core.revealing :refer [reveal]]
4950
[game.core.rezzing :refer [derez rez]]
51+
[game.core.runs :refer [end-run]]
5052
[game.core.say :refer [system-msg]]
51-
[game.core.servers :refer [is-remote? zone->name]]
52-
[game.core.set-aside :refer [swap-set-aside-cards]]
53+
[game.core.servers :refer [is-central? is-remote? target-server zone->name]]
54+
[game.core.set-aside :refer [get-set-aside set-aside-for-me swap-set-aside-cards]]
5355
[game.core.shuffling :refer [shuffle! shuffle-into-deck
5456
shuffle-into-rd-effect]]
5557
[game.core.tags :refer [gain-tags]]
@@ -94,6 +96,26 @@
9496
:msg "add itself to the Runner's score area as an agenda worth 2 agenda points"
9597
:effect (req (as-agenda state :runner card 2))})
9698

99+
(defn return-to-top
100+
"returns a set of cards to the top of the deck"
101+
([set-aside-cards] (return-to-top set-aside-cards false))
102+
([set-aside-cards reveal]
103+
{:prompt "choose a card to put ontop of R&D"
104+
:req (req (not (zero? (count set-aside-cards))))
105+
:choices {:min 1
106+
:max 1
107+
:req (req (some #(same-card? % target) set-aside-cards))}
108+
:async true
109+
:waiting-prompt "corp to return cards to R&D"
110+
:msg (msg "place " (if reveal (:title target) "a card") " ontop of R&D")
111+
:effect (req (move state :corp target :deck {:front true})
112+
(let [rem (seq (filter #(not (same-card? target %)) set-aside-cards))]
113+
(if (not (empty? rem))
114+
(continue-ability state side
115+
(return-to-top rem reveal)
116+
card nil)
117+
(effect-completed state side eid))))}))
118+
97119
;; Card definitions
98120

99121
(defcard "Adonis Campaign"
@@ -279,11 +301,72 @@
279301
:effect (req (wait-for (gain-credits state side 1)
280302
(lose-credits state :runner eid 1)))}]})
281303

304+
(defcard "B-1001"
305+
{:abilities [{:req (req (not this-server))
306+
:cost [:tag 1]
307+
:msg "end the run"
308+
:effect (effect (end-run eid card))}]})
309+
310+
(defcard "Balanced Coverage"
311+
(let [name-abi
312+
{:prompt "Choose a card type"
313+
:waiting-prompt "corp to choose a card type"
314+
:choices ["Operation" "Asset" "Upgrade" "ICE" "Agenda"]
315+
:async true
316+
:msg (msg "choose the card type " target)
317+
:effect (req (let [named-type target
318+
top-card (first (:deck corp))]
319+
(if (= (:type top-card) named-type)
320+
(continue-ability
321+
state side
322+
{:prompt (msg "The top card is " (:title top-card))
323+
:choices ["Reveal" "No Thanks"]
324+
:async true
325+
:msg (msg (if (= target "No Thanks")
326+
"look at the top card of R&D"
327+
(str "reveal " (:title top-card)
328+
" from the top of R&D and gain 2[Credits]")))
329+
:effect (req (if-not (= target "No Thanks")
330+
(wait-for (reveal state side (make-eid state eid) top-card)
331+
(gain-credits state :corp eid 2))
332+
(do (system-msg state side "declines to reveal a card")
333+
(effect-completed state side eid))))}
334+
card nil)
335+
(continue-ability
336+
state side
337+
{:prompt (msg "The top card is " (:title top-card))
338+
:choices ["Never lucky"]
339+
:msg "look at the top card of R&D"
340+
:effect (effect (system-msg "declines to reveal a card"))}
341+
card nil))))}
342+
ability {:label "look at the top card (start of turn)"
343+
:once :per-turn
344+
:async true
345+
:effect (req (continue-ability
346+
state side
347+
name-abi
348+
card nil))}]
349+
{:derezzed-events [corp-rez-toast]
350+
:events [(assoc ability :event :corp-turn-begins)]
351+
:abilities [ability]}))
352+
282353
(defcard "Bass CH1R180G4"
283354
{:abilities [{:cost [:click 1 :trash-can]
284355
:msg "gain [Click][Click]"
285356
:effect (effect (gain-clicks 2))}]})
286357

358+
(defcard "Behold!"
359+
{:flags {:rd-reveal (req true)}
360+
:access {:optional
361+
{:req (req (not (in-discard? card)))
362+
:waiting-prompt "Corp to choose an option"
363+
:prompt "Pay 4 [Credits] to give 2 tags?"
364+
:no-ability {:effect (effect (system-msg "declines to use Behold!"))}
365+
:yes-ability {:async true
366+
:cost [:credit 4]
367+
:msg "give the runner 2 tags"
368+
:effect (req (gain-tags state :corp eid 2))}}}})
369+
287370
(defcard "Bio-Ethics Association"
288371
(let [ability {:req (req unprotected)
289372
:async true
@@ -612,6 +695,23 @@
612695
(defcard "Cybernetics Court"
613696
{:constant-effects [(corp-hand-size+ 4)]})
614697

698+
(defcard "Cybersand Harvester"
699+
{:events [{:event :rez
700+
:req (req (ice? (:card context)))
701+
:msg "place 2 [Credits] on itself"
702+
:effect (effect (add-counter :corp card :credit 2))}]
703+
:abilities [{:async true
704+
:effect (effect (add-counter card :credit -1)
705+
(gain-credits eid 1))
706+
:msg "take 1 hosted [Credits]"}
707+
{:label "Take all hosted credits"
708+
:cost [:trash-can]
709+
:msg (msg "trash itself and gain " (get-counters card :credit) " [Credits]")
710+
:async true
711+
:effect (effect (gain-credits eid (get-counters card :credit)))}]
712+
:interactions {:pay-credits {:req (req (and (= :corp-install (:source-type eid))))
713+
:type :credit}}})
714+
615715
(defcard "Daily Business Show"
616716
{:derezzed-events [corp-rez-toast]
617717
:events [(first-time-draw-bonus :corp 1)
@@ -889,12 +989,75 @@
889989
:msg "add itself to their score area as an agenda worth 3 agenda points"
890990
:effect (req (as-agenda state :corp card 3))}]}))
891991

992+
(defcard "Federal Fundraising"
993+
(let [draw-ab {:optional {:req (req unprotected)
994+
:prompt "draw a cards?"
995+
:yes-ability {:msg "draw a card"
996+
:async true
997+
:effect (effect (draw eid 1))}
998+
:no-ability {:msg "decline to draw cards"}}}
999+
ability
1000+
{:once :per-turn
1001+
:req (req (:corp-phase-12 @state))
1002+
:interactive (req true)
1003+
:label "look at the top 3 cards"
1004+
:optional
1005+
{:prompt "look at the top 3 cards?"
1006+
:no-ability
1007+
{:msg (msg "declines to look at the top 3 cards")
1008+
:effect (req (continue-ability state side draw-ab card nil))}
1009+
:yes-ability
1010+
{:msg (msg "rearrange the top 3 cards of R&D")
1011+
:async true
1012+
:effect (req (set-aside-for-me state :corp eid (take 3 (:deck corp)))
1013+
(wait-for (resolve-ability state side
1014+
(return-to-top (get-set-aside state :corp eid))
1015+
card nil)
1016+
(continue-ability
1017+
state side
1018+
draw-ab
1019+
card nil)))}}}]
1020+
{:derezzed-events [corp-rez-toast]
1021+
:flags {:corp-phase-12 (req true)}
1022+
:events [(assoc ability :event :corp-turn-begins)]
1023+
:abilities [ability]}))
1024+
8921025
(defcard "Franchise City"
8931026
{:events [{:event :access
8941027
:req (req (agenda? target))
8951028
:msg "add itself to their score area as an agenda worth 1 agenda point"
8961029
:effect (req (as-agenda state :corp card 1))}]})
8971030

1031+
(defcard "Front Company"
1032+
;; TODO - this type of effect (prevent x server run) should be doable as a floating effect
1033+
(let [prevent (req (apply prevent-run-on-server
1034+
state card (map first (get-remotes state))))
1035+
allow (req (apply enable-run-on-server
1036+
state card (map first (get-remotes state))))
1037+
allow-if (req (when (zero? (count (filter #(and (rezzed? %)
1038+
(= (:title %) (:title card))
1039+
(not (same-card? % card)))
1040+
(all-installed state :corp))))
1041+
(apply enable-run-on-server
1042+
state card (map first (get-remotes state)))))]
1043+
{:rez-req (req (= (:active-player @state) :corp))
1044+
:on-rez {:req (req (no-event? state side :run #(is-central? (:server (:first %)))))
1045+
:effect prevent}
1046+
:uninstall allow-if
1047+
:derez-effect {:effect allow-if}
1048+
:events [{:event :run
1049+
:req (req (is-central? (:server target)))
1050+
:effect allow}
1051+
{:event :run
1052+
:req (req (and (= :archives (target-server context))
1053+
(first-event? state :runner :run #(= :archives (target-server (first %))))
1054+
unprotected))
1055+
:msg "do 2 net damage"
1056+
:async true
1057+
:effect (effect (damage eid :net 2))}
1058+
{:event :runner-phase-12
1059+
:effect prevent}]}))
1060+
8981061
(defcard "Full Immersion RecStudio"
8991062
{:can-host (req (and (or (asset? target) (agenda? target))
9001063
(> 2 (count (:hosted card)))))
@@ -2653,6 +2816,34 @@
26532816
:leave-play (req (gain state :runner :click-per-turn 1))
26542817
:on-trash executive-trash-effect})
26552818

2819+
(defcard "Wage Workers"
2820+
;; note - for some reason, clicking for a credit and drawing a card register the same on
2821+
;; the all-events (corp-spent-click)
2822+
;; this means we need to do some of this the hard way
2823+
(let [payoff {:label "Gain [Click]"
2824+
:msg "gain [Click]"
2825+
:effect (effect (gain-clicks 1))}
2826+
event-builder (fn [key]
2827+
{:event key
2828+
:async true
2829+
:req (req (= 3 (count (turn-events state side key))))
2830+
:effect (req (continue-ability
2831+
state side
2832+
payoff
2833+
card nil))})
2834+
all-events (fn [state side] (turn-events state side :corp-spent-click))
2835+
three-of (fn [cid idx state side]
2836+
(= 3 (count (filter #(and (= (first (first %)) cid)
2837+
(= (last %) idx))
2838+
(all-events state side)))))]
2839+
{:events [{:event :corp-spent-click
2840+
:async true
2841+
:effect (req (let [cid (first target)
2842+
ability-idx (:ability-idx (:source-info eid))]
2843+
(if (three-of cid ability-idx state side)
2844+
(continue-ability state side payoff card nil)
2845+
(effect-completed state side eid))))}]}))
2846+
26562847
(defcard "Wall to Wall"
26572848
(let [all [{:msg "gain 1 [Credits]"
26582849
:async true

0 commit comments

Comments
 (0)