diff --git a/src/clj/game/core/set_up.clj b/src/clj/game/core/set_up.clj index 25c0c54fa9..25a457a9f1 100644 --- a/src/clj/game/core/set_up.clj +++ b/src/clj/game/core/set_up.clj @@ -7,13 +7,16 @@ [game.core.diffs :refer [public-states]] [game.core.drawing :refer [draw]] [game.core.eid :refer [make-eid effect-completed]] - [game.core.engine :refer [trigger-event trigger-event-sync]] + [game.core.engine :refer [resolve-ability trigger-event trigger-event-sync]] [game.core.initializing :refer [card-init make-card]] + [game.core.moving :refer [move]] [game.core.player :refer [new-corp new-runner]] [game.core.prompts :refer [clear-wait-prompt show-prompt show-wait-prompt]] [game.core.say :refer [system-msg system-say implementation-msg]] [game.core.shuffling :refer [shuffle-into-deck]] + [game.core.shuffling :refer [shuffle-into-deck shuffle!]] [game.core.state :refer [new-state]] + [game.macros :refer [req wait-for msg continue-ability]] [game.macros :refer [wait-for]] [game.quotes :as quotes] [game.utils :refer [server-card]])) @@ -76,6 +79,40 @@ (-> @state :runner :identity :title)) (show-wait-prompt state :runner "Corp to keep hand or mulligan"))) +(defn- init-hands-first-five [state] + (letfn [(card-not-in-hand? [card hand] + (not (some #(= (:title card) (:title %)) hand))) + (select-card-abi [x] + (when (pos? x) + {:prompt (str "Choose a card to add to hand (" x " remaining), or click 'done' for random cards") + :choices (req (conj (sort-by :title + (filter #(card-not-in-hand? % (get-in @state [side :hand])) + (get-in @state [side :deck]))) "Done")) + :async true + :waiting-prompt true + :msg (msg (if (= target "Done") + (str "add " x " random cards to their " (if (= side :runner) "Grip" "HQ")) + (str "add a card to their " (if (= side :runner) "Grip" "HQ")))) + :effect (req (if (= target "Done") + (do (shuffle! state side :deck) + (draw state side eid x {:suppress-event true})) + (do (move state side target :hand) + (shuffle! state side :deck) + (continue-ability + state side + (select-card-abi (dec x)) + card nil))))}))] + (wait-for (resolve-ability + state :corp + (select-card-abi 5) + (get-in @state [:corp :identity]) nil) + (keep-hand state :corp nil) + (wait-for (resolve-ability + state :runner + (select-card-abi 5) + (get-in @state [:runner :identity]) nil) + (keep-hand state :runner nil))))) + (defn- init-game-state "Initialises the game state" [{:keys [players gameid timer spectatorhands api-access save-replay room] :as game}] @@ -142,7 +179,9 @@ (let [eid (make-eid state)] (wait-for (trigger-event-sync state :corp :pre-start-game nil) (wait-for (trigger-event-sync state :runner :pre-start-game nil) - (init-hands state) + (if-not (:first-five game) + (init-hands state) + (init-hands-first-five state)) (fake-checkpoint state) (effect-completed state nil eid)))) (swap! state assoc :history [(:hist-state (public-states state))]) diff --git a/src/clj/web/lobby.clj b/src/clj/web/lobby.clj index 7243e34d82..b3c5caee7c 100644 --- a/src/clj/web/lobby.clj +++ b/src/clj/web/lobby.clj @@ -22,7 +22,7 @@ [{uid :uid user :user {:keys [gameid now - allow-spectator api-access format mute-spectators password room save-replay + allow-spectator api-access first-five format mute-spectators password room save-replay side singleton spectatorhands timer title] :or {gameid (random-uuid) now (inst/now)}} :options}] @@ -38,6 +38,7 @@ ;; options :allow-spectator allow-spectator :api-access api-access + :first-five first-five :format format :mute-spectators mute-spectators :password (when (not-empty password) (bcrypt/encrypt password)) @@ -109,6 +110,7 @@ [:allow-spectator :api-access :date + :first-five :format :gameid :messages diff --git a/src/cljs/nr/game_row.cljs b/src/cljs/nr/game_row.cljs index 966eb9a597..2dd3bbca1f 100644 --- a/src/cljs/nr/game_row.cljs +++ b/src/cljs/nr/game_row.cljs @@ -128,11 +128,12 @@ (let [c (count (:spectators game))] (when (pos? c) (str " (" (tr [:lobby.spectator-count] c) ")"))))]) -(defn game-format [{fmt :format singleton? :singleton}] +(defn game-format [{fmt :format singleton? :singleton first-five? :first-five}] [:div {:class "game-format"} [:span.format-label (tr [:lobby.format "Format"]) ": "] [:span.format-type (tr-format (slug->format fmt "Unknown"))] - [:span.format-singleton (str (when singleton? " (singleton)"))]]) + [:span.format-singleton (str (when singleton? " (singleton)"))] + [:span.format-first-five (str (when first-five? " (first-five mode)"))]]) (defn players-row [{players :players :as game}] (into diff --git a/src/cljs/nr/new_game.cljs b/src/cljs/nr/new_game.cljs index ceb1cb7710..aee10bba72 100644 --- a/src/cljs/nr/new_game.cljs +++ b/src/cljs/nr/new_game.cljs @@ -11,6 +11,7 @@ (def new-game-keys [:allow-spectator :api-access + :first-five :format :password :room @@ -69,12 +70,18 @@ :checked (= @side-state option)}] (tr-side option)]]))]) -(defn singleton-only [options fmt-state] +(defn singleton-only [options] [:label [:input {:type "checkbox" :checked (:singleton @options) :on-change #(swap! options assoc :singleton (.. % -target -checked))}] (tr [:lobby.singleton "Singleton"])]) +(defn first-five-mode [options] + [:label + [:input {:type "checkbox" :checked (:first-five @options) + :on-change #(swap! options assoc :first-five (.. % -target -checked))}] + (tr [:lobby.first-five "First Five Mode"])]) + (defn format-section [fmt-state options] [:section [:h3 (tr [:lobby.format "Format"])] @@ -85,7 +92,7 @@ (for [[k v] slug->format] ^{:key k} [:option {:value k} (tr-format v)]))] - [singleton-only options fmt-state] + [singleton-only options] [:div.infobox.blue-shade {:style {:display (if (:singleton @options) "block" "none")}} [:p "This will restrict decklists to only those which do not contain any duplicate cards. It is recommended you use the listed singleton-based identities."] @@ -187,6 +194,10 @@ (defn options-section [options user] [:section [:h3 (tr [:lobby.options "Options"])] + [first-five-mode options] + [:div.infobox.blue-shade + {:style {:display (if (:first-five @options) "block" "none")}} + [:p "This will allow each player to choose their starting hand, instead of the regular draw/mulligan system."]] [allow-spectators options] [toggle-hidden-info options] [password-input options] @@ -202,6 +213,7 @@ :title (str (:username @user) "'s game")}) options (r/atom {:allow-spectator true :api-access false + :first-five false :password "" :protected false :save-replay (not= "casual" (:room @lobby-state)) diff --git a/src/cljs/nr/pending_game.cljs b/src/cljs/nr/pending_game.cljs index 562081c4e0..59b5779c51 100644 --- a/src/cljs/nr/pending_game.cljs +++ b/src/cljs/nr/pending_game.cljs @@ -84,6 +84,11 @@ [:div.infobox.blue-shade [:p "This lobby is running in singleton mode. This means decklists will be restricted to only those which do not contain any duplicate cards."]])) +(defn first-five-info-box [current-game] + (when (:first-five @current-game) + [:div.infobox.blue-shade + [:p "This lobby is running in first-five mode. This means that instead of draws and mulligans, players will decide their opening hands."]])) + (defn swap-sides-button [user gameid players] (when (first-user? @players @user) (if (< 1 (count @players)) @@ -191,6 +196,7 @@ [:div.content [:h2 (:title @current-game)] [singleton-info-box current-game] + [first-five-info-box current-game] (when-not (every? :deck @players) [:div.flash-message (tr [:lobby.waiting "Waiting players deck selection"])]) diff --git a/src/css/lobby.styl b/src/css/lobby.styl index ff4cb0669c..2287652b63 100644 --- a/src/css/lobby.styl +++ b/src/css/lobby.styl @@ -134,6 +134,12 @@ color: #ff571a; font-style: bold; + .format-first-five + background-image: linear-gradient(to left, green, yellow, orange, red); + -webkit-background-clip: text; + font-style: bold; + color: transparent; + .format-label font-weight: bold