|
9 | 9 | update-all-agenda-points]]
|
10 | 10 | [game.core.bad-publicity :refer [bad-publicity-prevent gain-bad-publicity
|
11 | 11 | 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 |
13 | 13 | installable-servers]]
|
14 | 14 | [game.core.card :refer [agenda? asset? can-be-advanced? corp? event?
|
15 | 15 | faceup? fake-identity? get-advancement-requirement
|
|
27 | 27 | [game.core.engine :refer [pay register-events resolve-ability]]
|
28 | 28 | [game.core.events :refer [first-event? no-event? turn-events]]
|
29 | 29 | [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 |
31 | 32 | register-turn-flag! release-zone]]
|
32 | 33 | [game.core.gaining :refer [gain gain-clicks gain-credits lose lose-clicks
|
33 | 34 | lose-credits]]
|
|
47 | 48 | [game.core.props :refer [add-counter add-icon add-prop remove-icon set-prop]]
|
48 | 49 | [game.core.revealing :refer [reveal]]
|
49 | 50 | [game.core.rezzing :refer [derez rez]]
|
| 51 | + [game.core.runs :refer [end-run]] |
50 | 52 | [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]] |
53 | 55 | [game.core.shuffling :refer [shuffle! shuffle-into-deck
|
54 | 56 | shuffle-into-rd-effect]]
|
55 | 57 | [game.core.tags :refer [gain-tags]]
|
|
94 | 96 | :msg "add itself to the Runner's score area as an agenda worth 2 agenda points"
|
95 | 97 | :effect (req (as-agenda state :runner card 2))})
|
96 | 98 |
|
| 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 | + |
97 | 119 | ;; Card definitions
|
98 | 120 |
|
99 | 121 | (defcard "Adonis Campaign"
|
|
279 | 301 | :effect (req (wait-for (gain-credits state side 1)
|
280 | 302 | (lose-credits state :runner eid 1)))}]})
|
281 | 303 |
|
| 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 | + |
282 | 353 | (defcard "Bass CH1R180G4"
|
283 | 354 | {:abilities [{:cost [:click 1 :trash-can]
|
284 | 355 | :msg "gain [Click][Click]"
|
285 | 356 | :effect (effect (gain-clicks 2))}]})
|
286 | 357 |
|
| 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 | + |
287 | 370 | (defcard "Bio-Ethics Association"
|
288 | 371 | (let [ability {:req (req unprotected)
|
289 | 372 | :async true
|
|
612 | 695 | (defcard "Cybernetics Court"
|
613 | 696 | {:constant-effects [(corp-hand-size+ 4)]})
|
614 | 697 |
|
| 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 | + |
615 | 715 | (defcard "Daily Business Show"
|
616 | 716 | {:derezzed-events [corp-rez-toast]
|
617 | 717 | :events [(first-time-draw-bonus :corp 1)
|
|
889 | 989 | :msg "add itself to their score area as an agenda worth 3 agenda points"
|
890 | 990 | :effect (req (as-agenda state :corp card 3))}]}))
|
891 | 991 |
|
| 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 | + |
892 | 1025 | (defcard "Franchise City"
|
893 | 1026 | {:events [{:event :access
|
894 | 1027 | :req (req (agenda? target))
|
895 | 1028 | :msg "add itself to their score area as an agenda worth 1 agenda point"
|
896 | 1029 | :effect (req (as-agenda state :corp card 1))}]})
|
897 | 1030 |
|
| 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 | + |
898 | 1061 | (defcard "Full Immersion RecStudio"
|
899 | 1062 | {:can-host (req (and (or (asset? target) (agenda? target))
|
900 | 1063 | (> 2 (count (:hosted card)))))
|
|
2653 | 2816 | :leave-play (req (gain state :runner :click-per-turn 1))
|
2654 | 2817 | :on-trash executive-trash-effect})
|
2655 | 2818 |
|
| 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 | + |
2656 | 2847 | (defcard "Wall to Wall"
|
2657 | 2848 | (let [all [{:msg "gain 1 [Credits]"
|
2658 | 2849 | :async true
|
|
0 commit comments