From 1f258c951570da460ea7b2b0c2a0a02df321e859 Mon Sep 17 00:00:00 2001 From: CookieCoder15 <40507205+CookieCoder15@users.noreply.github.com> Date: Sat, 3 Oct 2020 19:21:37 +1000 Subject: [PATCH 1/7] Started Happy Ending House Rule --- client/src/elm/MassiveDecks/Game/Rules.elm | 6 + .../src/elm/MassiveDecks/Models/Decoders.elm | 6 + .../src/elm/MassiveDecks/Models/Encoders.elm | 6 + .../Pages/Lobby/Configure/Model.elm | 1 + .../Lobby/Configure/Rules/HouseRules.elm | 2 + .../Rules/HouseRules/HappyEnding.elm | 31 + .../Rules/HouseRules/HappyEnding/Model.elm | 6 + .../Configure/Rules/HouseRules/Model.elm | 2 + client/src/elm/MassiveDecks/Pages/Start.elm | 1 + client/src/elm/MassiveDecks/Strings.elm | 2 + .../elm/MassiveDecks/Strings/Languages/De.elm | 8 + .../Strings/Languages/DeXInformal.elm | 8 + .../Strings/Languages/En/Internal.elm | 6 + .../elm/MassiveDecks/Strings/Languages/Id.elm | 8 + .../elm/MassiveDecks/Strings/Languages/It.elm | 8 + .../elm/MassiveDecks/Strings/Languages/Pl.elm | 8 + .../MassiveDecks/Strings/Languages/PtBR.elm | 8 + .../src/elm/MassiveDecks/Strings/Render.elm | 3 + server/decks/cah-base-en.deck.json5 | 551 ------------------ server/src/ts/action/validation.validator.ts | 24 +- server/src/ts/games/rules.ts | 10 +- server/src/ts/games/rules/houseRules.ts | 4 +- server/src/ts/timeout/round-start.ts | 16 +- 23 files changed, 159 insertions(+), 566 deletions(-) create mode 100644 client/src/elm/MassiveDecks/Pages/Lobby/Configure/Rules/HouseRules/HappyEnding.elm create mode 100644 client/src/elm/MassiveDecks/Pages/Lobby/Configure/Rules/HouseRules/HappyEnding/Model.elm diff --git a/client/src/elm/MassiveDecks/Game/Rules.elm b/client/src/elm/MassiveDecks/Game/Rules.elm index f94454f5..886ebf03 100644 --- a/client/src/elm/MassiveDecks/Game/Rules.elm +++ b/client/src/elm/MassiveDecks/Game/Rules.elm @@ -1,5 +1,6 @@ module MassiveDecks.Game.Rules exposing ( ComedyWriter + , HappyEnding , HouseRules , NeverHaveIEver , PackingHeat @@ -31,6 +32,7 @@ type alias HouseRules = , reboot : Maybe Reboot , comedyWriter : Maybe ComedyWriter , neverHaveIEver : Maybe NeverHaveIEver + , happyEnding : Maybe HappyEnding } @@ -73,3 +75,7 @@ type alias ComedyWriter = type alias NeverHaveIEver = {} + + +type alias HappyEnding = + {} diff --git a/client/src/elm/MassiveDecks/Models/Decoders.elm b/client/src/elm/MassiveDecks/Models/Decoders.elm index 75bd723d..79ebbcfc 100644 --- a/client/src/elm/MassiveDecks/Models/Decoders.elm +++ b/client/src/elm/MassiveDecks/Models/Decoders.elm @@ -410,6 +410,7 @@ houseRules = |> Json.optional "reboot" (reboot |> Json.map Just) Nothing |> Json.optional "comedyWriter" (comedyWriter |> Json.map Just) Nothing |> Json.optional "neverHaveIEver" (neverHaveIEver |> Json.map Just) Nothing + |> Json.optional "happyEnding" (happyEnding |> Json.map Just) Nothing comedyWriter : Json.Decoder Rules.ComedyWriter @@ -429,6 +430,11 @@ neverHaveIEver = {} |> Json.succeed +happyEnding : Json.Decoder Rules.HappyEnding +happyEnding = + {} |> Json.succeed + + reboot : Json.Decoder Rules.Reboot reboot = Json.map Rules.Reboot diff --git a/client/src/elm/MassiveDecks/Models/Encoders.elm b/client/src/elm/MassiveDecks/Models/Encoders.elm index 12a61bd3..bbdd87d7 100644 --- a/client/src/elm/MassiveDecks/Models/Encoders.elm +++ b/client/src/elm/MassiveDecks/Models/Encoders.elm @@ -117,6 +117,7 @@ houseRules h = , h.reboot |> Maybe.map (\r -> ( "reboot", reboot r )) , h.comedyWriter |> Maybe.map (\c -> ( "comedyWriter", comedyWriter c )) , h.neverHaveIEver |> Maybe.map (\n -> ( "neverHaveIEver", neverHaveIEver n )) + , h.happyEnding |> Maybe.map (\e -> ( "happyEnding", happyEnding e )) -- TODO: Workout what to do since "h" is taken. ] ) @@ -141,6 +142,11 @@ neverHaveIEver _ = Json.object [] +happyEnding : Rules.HappyEnding -> Json.Value +happyEnding _ = + Json.object [] + + comedyWriter : Rules.ComedyWriter -> Json.Value comedyWriter { number, exclusive } = Json.object [ ( "number", number |> Json.int ), ( "exclusive", exclusive |> Json.bool ) ] diff --git a/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Model.elm b/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Model.elm index 2d7d53f9..0b76cf99 100644 --- a/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Model.elm +++ b/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Model.elm @@ -71,6 +71,7 @@ fake = , reboot = Nothing , comedyWriter = Nothing , neverHaveIEver = Nothing + , happyEnding = Nothing } , stages = { mode = Rules.Soft diff --git a/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Rules/HouseRules.elm b/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Rules/HouseRules.elm index 9fe76905..6193451e 100644 --- a/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Rules/HouseRules.elm +++ b/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Rules/HouseRules.elm @@ -5,6 +5,7 @@ import MassiveDecks.Pages.Lobby.Configure.Configurable as Configurable import MassiveDecks.Pages.Lobby.Configure.Configurable.Editor as Editor import MassiveDecks.Pages.Lobby.Configure.Configurable.Model exposing (Configurable) import MassiveDecks.Pages.Lobby.Configure.Rules.HouseRules.ComedyWriter as ComedyWriter +import MassiveDecks.Pages.Lobby.Configure.Rules.HouseRules.HappyEnding as HappyEnding import MassiveDecks.Pages.Lobby.Configure.Rules.HouseRules.Model exposing (..) import MassiveDecks.Pages.Lobby.Configure.Rules.HouseRules.NeverHaveIEver as NeverHaveIEver import MassiveDecks.Pages.Lobby.Configure.Rules.HouseRules.PackingHeat as PackingHeat @@ -24,5 +25,6 @@ all = , Reboot.all |> Configurable.wrap RebootId (.reboot >> Just) (\v p -> { p | reboot = v }) , ComedyWriter.all |> Configurable.wrap ComedyWriterId (.comedyWriter >> Just) (\v p -> { p | comedyWriter = v }) , NeverHaveIEver.all |> Configurable.wrap NeverHaveIEverId (.neverHaveIEver >> Just) (\v p -> { p | neverHaveIEver = v }) + , HappyEnding.all |> Configurable.wrap HappyEndingId (.happyEnding >> Just) (\v p -> { p | happyEnding = v }) ] } diff --git a/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Rules/HouseRules/HappyEnding.elm b/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Rules/HouseRules/HappyEnding.elm new file mode 100644 index 00000000..a9deed35 --- /dev/null +++ b/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Rules/HouseRules/HappyEnding.elm @@ -0,0 +1,31 @@ +module MassiveDecks.Pages.Lobby.Configure.Rules.HouseRules.HappyEnding exposing (all) + +import MassiveDecks.Components.Form.Message as Message +import MassiveDecks.Game.Rules as Rules +import MassiveDecks.Pages.Lobby.Configure.Configurable as Configurable +import MassiveDecks.Pages.Lobby.Configure.Configurable.Editor as Editor +import MassiveDecks.Pages.Lobby.Configure.Configurable.Model exposing (Configurable) +import MassiveDecks.Pages.Lobby.Configure.Configurable.Validator as Validator +import MassiveDecks.Pages.Lobby.Configure.Rules.HouseRules.HappyEnding.Model exposing (..) +import MassiveDecks.Strings as Strings + + +all : Configurable Id (Maybe Rules.HappyEnding) model msg +all = + Configurable.group + { id = All + , editor = Editor.group Nothing False False + , children = + [ enabled |> Configurable.wrapAsToggle {} + ] + } + + +enabled : Configurable Id Bool model msg +enabled = + Configurable.value + { id = Enabled + , editor = Editor.bool Strings.HouseRuleHappyEnding + , validator = Validator.none + , messages = always [ Message.info Strings.HouseRuleHappyEndingDescription ] + } diff --git a/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Rules/HouseRules/HappyEnding/Model.elm b/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Rules/HouseRules/HappyEnding/Model.elm new file mode 100644 index 00000000..740e1f3a --- /dev/null +++ b/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Rules/HouseRules/HappyEnding/Model.elm @@ -0,0 +1,6 @@ +module MassiveDecks.Pages.Lobby.Configure.Rules.HouseRules.HappyEnding.Model exposing (Id(..)) + + +type Id + = All + | Enabled diff --git a/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Rules/HouseRules/Model.elm b/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Rules/HouseRules/Model.elm index b6adae43..afa07bb2 100644 --- a/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Rules/HouseRules/Model.elm +++ b/client/src/elm/MassiveDecks/Pages/Lobby/Configure/Rules/HouseRules/Model.elm @@ -2,6 +2,7 @@ module MassiveDecks.Pages.Lobby.Configure.Rules.HouseRules.Model exposing (Id(.. import MassiveDecks.Pages.Lobby.Configure.Rules.HouseRules.ComedyWriter.Model as ComedyWriter import MassiveDecks.Pages.Lobby.Configure.Rules.HouseRules.NeverHaveIEver.Model as NeverHaveIEver +import MassiveDecks.Pages.Lobby.Configure.Rules.HouseRules.HappyEnding.Model as HappyEnding import MassiveDecks.Pages.Lobby.Configure.Rules.HouseRules.PackingHeat.Model as PackingHeat import MassiveDecks.Pages.Lobby.Configure.Rules.HouseRules.Rando.Model as Rando import MassiveDecks.Pages.Lobby.Configure.Rules.HouseRules.Reboot.Model as Reboot @@ -14,3 +15,4 @@ type Id | ComedyWriterId ComedyWriter.Id | RebootId Reboot.Id | NeverHaveIEverId NeverHaveIEver.Id + | HappyEndingId HappyEnding.Id diff --git a/client/src/elm/MassiveDecks/Pages/Start.elm b/client/src/elm/MassiveDecks/Pages/Start.elm index 80421cca..2eedae0d 100644 --- a/client/src/elm/MassiveDecks/Pages/Start.elm +++ b/client/src/elm/MassiveDecks/Pages/Start.elm @@ -583,6 +583,7 @@ houseRules = , ( Strings.HouseRuleRandoCardrissian, Strings.HouseRuleRandoCardrissianDescription ) , ( Strings.HouseRuleComedyWriter, Strings.HouseRuleComedyWriterDescription ) , ( Strings.HouseRuleNeverHaveIEver, Strings.HouseRuleNeverHaveIEverDescription ) + , ( Strings.HouseRuleHappyEnding, Strings.HouseRuleHappyEnding ) ] diff --git a/client/src/elm/MassiveDecks/Strings.elm b/client/src/elm/MassiveDecks/Strings.elm index ec871230..231f0784 100644 --- a/client/src/elm/MassiveDecks/Strings.elm +++ b/client/src/elm/MassiveDecks/Strings.elm @@ -116,6 +116,8 @@ type MdString | HouseRuleRandoCardrissianNumberDescription -- A description of the setting for the number of bots added to the game. | HouseRuleNeverHaveIEver -- The name of the house rule where players can discard cards, sharing the discarded card. | HouseRuleNeverHaveIEverDescription -- A description of the house rule where players can discard cards, sharing the discarded card. + | HouseRuleHappyEnding -- The name of the house rule where the game ends with the haiku card. + | HouseRuleHappyEndingDescription -- A description of the house rule where the game ends with the haiku card. | MustBeMoreThanOrEqualValidationError { min : Int } -- An error when a configuration value must be more than or equal to the given value. | MustBeLessThanOrEqualValidationError { max : Int } -- An error when a configuration value must be less than or equal to the given value. | SetValue { value : Int } -- A description of the action of resolving a problem by setting the value to the given one. diff --git a/client/src/elm/MassiveDecks/Strings/Languages/De.elm b/client/src/elm/MassiveDecks/Strings/Languages/De.elm index e9672d7a..39012e50 100644 --- a/client/src/elm/MassiveDecks/Strings/Languages/De.elm +++ b/client/src/elm/MassiveDecks/Strings/Languages/De.elm @@ -346,6 +346,14 @@ translate _ mdString = , Text "eingestehen: die Karte wird öffentlich geteilt." ] + -- TODO: Translate + HouseRuleHappyEnding -> + [ Missing ] + + -- TODO: Translate + HouseRuleHappyEndingDescription -> + [ Missing ] + MustBeMoreThanOrEqualValidationError { min } -> [ Text "Der Wert muss mindestens ", Text (String.fromInt min), Text " betragen." ] diff --git a/client/src/elm/MassiveDecks/Strings/Languages/DeXInformal.elm b/client/src/elm/MassiveDecks/Strings/Languages/DeXInformal.elm index 2d95f293..151e5164 100644 --- a/client/src/elm/MassiveDecks/Strings/Languages/DeXInformal.elm +++ b/client/src/elm/MassiveDecks/Strings/Languages/DeXInformal.elm @@ -346,6 +346,14 @@ translate _ mdString = , Text "eingestehen: die Karte wird öffentlich geteilt." ] + -- TODO: Translate + HouseRuleHappyEnding -> + [ Missing ] + + -- TODO: Translate + HouseRuleHappyEndingDescription -> + [ Missing ] + MustBeMoreThanOrEqualValidationError { min } -> [ Text "Der Wert muss mindestens ", Text (String.fromInt min), Text " betragen." ] diff --git a/client/src/elm/MassiveDecks/Strings/Languages/En/Internal.elm b/client/src/elm/MassiveDecks/Strings/Languages/En/Internal.elm index ba732199..973d3167 100644 --- a/client/src/elm/MassiveDecks/Strings/Languages/En/Internal.elm +++ b/client/src/elm/MassiveDecks/Strings/Languages/En/Internal.elm @@ -301,6 +301,12 @@ translate _ mdString = , Text "ignorance: the card is shared publicly." ] + HouseRuleHappyEnding -> + [ Text "Happy Ending" ] + + HouseRuleHappyEndingDescription -> + [ Text "When the game ends, the final round is a 'Make a Haiku' black card." ] + MustBeMoreThanOrEqualValidationError { min } -> [ Text "The value must be at least ", Text (String.fromInt min), Text "." ] diff --git a/client/src/elm/MassiveDecks/Strings/Languages/Id.elm b/client/src/elm/MassiveDecks/Strings/Languages/Id.elm index a381c043..e713936e 100644 --- a/client/src/elm/MassiveDecks/Strings/Languages/Id.elm +++ b/client/src/elm/MassiveDecks/Strings/Languages/Id.elm @@ -336,6 +336,14 @@ translate _ mdString = , Text "ketidaktahuan: kartu dibagikan secara publik." ] + -- TODO: Translate + HouseRuleHappyEnding -> + [ Missing ] + + -- TODO: Translate + HouseRuleHappyEndingDescription -> + [ Missing ] + MustBeMoreThanOrEqualValidationError { min } -> [ Text "Nilai minimal harus ", Text (String.fromInt min), Text "." ] diff --git a/client/src/elm/MassiveDecks/Strings/Languages/It.elm b/client/src/elm/MassiveDecks/Strings/Languages/It.elm index 81121e91..719bf590 100644 --- a/client/src/elm/MassiveDecks/Strings/Languages/It.elm +++ b/client/src/elm/MassiveDecks/Strings/Languages/It.elm @@ -350,6 +350,14 @@ translate _ mdString = HouseRuleNeverHaveIEverDescription -> [ Missing ] + -- TODO: Translate + HouseRuleHappyEnding -> + [ Missing ] + + -- TODO: Translate + HouseRuleHappyEndingDescription -> + [ Missing ] + MustBeMoreThanOrEqualValidationError { min } -> [ Text "Il valore deve essere almeno ", Text (String.fromInt min), Text "." ] diff --git a/client/src/elm/MassiveDecks/Strings/Languages/Pl.elm b/client/src/elm/MassiveDecks/Strings/Languages/Pl.elm index 52ed975e..3a9201cc 100644 --- a/client/src/elm/MassiveDecks/Strings/Languages/Pl.elm +++ b/client/src/elm/MassiveDecks/Strings/Languages/Pl.elm @@ -379,6 +379,14 @@ translate maybeDeclCase mdString = , Text "ignorancję: wyrzucona karta będzie publicznie widoczna." ] + -- TODO: Translate + HouseRuleHappyEnding -> + [ Missing ] + + -- TODO: Translate + HouseRuleHappyEndingDescription -> + [ Missing ] + MustBeMoreThanOrEqualValidationError { min } -> [ Text "Wartość musi być większa lub równa ", Text (String.fromInt min), Text "." ] diff --git a/client/src/elm/MassiveDecks/Strings/Languages/PtBR.elm b/client/src/elm/MassiveDecks/Strings/Languages/PtBR.elm index c2ef28bb..84ce214f 100644 --- a/client/src/elm/MassiveDecks/Strings/Languages/PtBR.elm +++ b/client/src/elm/MassiveDecks/Strings/Languages/PtBR.elm @@ -346,6 +346,14 @@ translate _ mdString = , Text "ignorância: a carta é compartilhada publicamente." ] + -- TODO: Translate + HouseRuleHappyEnding -> + [ Missing ] + + -- TODO: Translate + HouseRuleHappyEndingDescription -> + [ Missing ] + MustBeMoreThanOrEqualValidationError { min } -> [ Text "O valor deve ser ao menos ", Text (String.fromInt min), Text "." ] diff --git a/client/src/elm/MassiveDecks/Strings/Render.elm b/client/src/elm/MassiveDecks/Strings/Render.elm index e84074bf..68f6101d 100644 --- a/client/src/elm/MassiveDecks/Strings/Render.elm +++ b/client/src/elm/MassiveDecks/Strings/Render.elm @@ -211,6 +211,9 @@ enhanceHtml context mdString unenhanced = HouseRuleNeverHaveIEver -> prefixed unenhanced Icon.trash + HouseRuleHappyEnding -> + prefixed unenhanced Icon.smile + RereadGames -> [ Html.blankA [ HtmlA.class "no-wrap", HtmlA.href "https://www.rereadgames.com/" ] unenhanced ] diff --git a/server/decks/cah-base-en.deck.json5 b/server/decks/cah-base-en.deck.json5 index 1be13424..93644b66 100644 --- a/server/decks/cah-base-en.deck.json5 +++ b/server/decks/cah-base-en.deck.json5 @@ -5,332 +5,6 @@ language: "en", author: "Cards Against Humanity", calls: [ - [ - [ - "Hey Reddit! I’m ", - { - transform: "Capitalize", - }, - ".", - ], - ["Ask me anything."], - ], - [ - ["Introducing X-treme Baseball!"], - ["It’s like baseball, but with ", {}, "!"], - ], - [ - ["What is Batman’s guilty pleasure?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [["TSA guidelines now prohibit ", {}, " on airplanes."]], - [ - [ - "Next from J.K. Rowling: ", - { - text: "Harry Potter and the Chamber of ", - style: "Em", - }, - { - transform: "Capitalize", - style: "Em", - }, - ".", - ], - ], - [ - ["That’s right, I killed ", {}, "."], - ["How, you ask?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - [ - "I’m sorry professor, but I couldn’t complete my homework because of ", - {}, - ".", - ], - ], - [["And the Academy Award for ", {}, " goes to ", {}, "."]], - [["Dude, do not go in that bathroom."], ["There’s ", {}, " in there."]], - [ - ["How did I lose my virginity?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - [ - "It’s a pity that kids these days are all getting involved with ", - {}, - ".", - ], - ], - [ - [ - "Step 1: ", - { - transform: "Capitalize", - }, - ".", - ], - [ - "Step 2: ", - { - transform: "Capitalize", - }, - ".", - ], - ["Step 3: Profit."], - ], - [ - [ - { - transform: "Capitalize", - }, - ".", - ], - ["Becha can’t have just one!"], - ], - [["Kids, I don’t need drugs to get high. I’m high on ", {}, "."]], - [["For my next trick, I will pull ", {}, " out of ", {}, "."]], - [ - [ - "While the United States raced the Soviet Union to the moon, the Mexican government funneled millions of pesos into research on ", - {}, - ".", - ], - ], - [ - [ - "In the new Disney Channel Original Movie, Hannah Montana struggles with ", - {}, - " for the first time.", - ], - ], - [ - ["What’s my secret power?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - [ - "I’m going on a cleanse this week. Nothing but kale juice and ", - {}, - ".", - ], - ], - [ - [ - { - transform: "Capitalize", - }, - " + ", - { - transform: "Capitalize", - }, - ], - [ - " = ", - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - [ - "When Pharaoh remained unmoved, Moses called down a Plague of ", - {}, - ".", - ], - ], - [ - [ - "Just once, I’d like to hear you say “Thanks, Mom. Thanks for ", - {}, - ".”", - ], - ], - [ - ["Daddy, why is mommy crying?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [["When I was tripping on acid, ", {}, " turned into ", {}, "."]], - [["50% of all marriages end in ", {}, "."]], - [ - [ - "My fellow Americans: Before this decade is out, we ", - { - text: "will", - style: "Em", - }, - ", have ", - {}, - " on the moon.", - ], - ], - [ - [ - "This season at Steppenwolf, Samuel Beckett’s classic existential play: ", - { - text: "Waiting for", - style: "Em", - }, - { - style: "Em", - }, - ".", - ], - ], - [["Instead of coal, Santa now gives the bad children ", {}, "."]], - [ - [ - "Life for American Indians was forever changed when the White Man introduced them to ", - {}, - ".", - ], - ], - [ - [ - "What’s Teach for America using to inspire inner city students to succeed?", - ], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [["Maybe she’s born with it."], ["Maybe it’s ", {}, "."]], - [ - ["What is George W. Bush thinking about right now?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [["White people like ", {}, "."]], - [ - [ - { - transform: "Capitalize", - }, - " is a slippery slope that leads to ", - {}, - ".", - ], - ], - [ - ["Why do I hurt all over?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [["A romantic, candlelit dinner would be incomplete without ", {}, "."]], - [ - ["Just saw this upsetting video! Please retweet!!"], - [ - "#stop", - { - transform: "Capitalize", - }, - ], - ], - [ - [ - "Fun tip! When your man asks you to go down on him, try surprising him with ", - {}, - " instead.", - ], - ], - [["The class field trip was completely ruined by ", {}, "."]], - [ - ["What’s a girl’s best friend?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - [ - "Dear Abby, I’m having some trouble with ", - {}, - " and would like your advice.", - ], - ], - [ - [ - "In M. Night Shyamalan’s new movie, Bruce Willis discovers that ", - {}, - " had really been ", - {}, - " all along.", - ], - ], - [ - [ - "When I am President of the United States, I will create the Department of ", - {}, - ".", - ], - ], - [ - ["What are my parents hiding from me?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - ["What never fails to liven up the party?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - [ - "IF you like ", - { - transform: "UpperCase", - }, - ",", - ], - ["YOU MIGHT BE A REDNECK."], - ], [ ["Make a haiku."], [ @@ -352,231 +26,6 @@ ".", ], ], - [ - ["What made my first kiss so awkward?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - [ - "Hey guys, welcome to Chili’s! Would you like to start the night off right with ", - {}, - "?", - ], - ], - [["I got 99 problems but ", {}, " ain’t one."]], - [ - [ - { - transform: "Capitalize", - }, - ".", - ], - ["It’s a trap!"], - ], - [ - [ - "Bravo’s new reality show features eight washed-up celebrities living with ", - {}, - ".", - ], - ], - [ - ["What would grandma find disturbing, yet oddly charming?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - [ - { - transform: "Capitalize", - }, - ".", - ], - ["That was so metal."], - ], - [["I never truly understood ", {}, " until I encountered ", {}, "."]], - [["During sex, I like to think about ", {}, "."]], - [ - ["What ended my last relationship?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - ["What’s that sound?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - [ - "Uh, hey guys, I know this was my idea, but I’m having serious doubts about ", - {}, - ".", - ], - ], - [ - ["Why am I sticky?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - [ - "I’m no doctor but I’m pretty sure what you’re suffering from is called “", - {}, - ".”", - ], - ], - [ - ["What’s there a ton of in heaven?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - [ - "After four platinum albums and three Grammys, it’s time to get back to my roots, to what inspired me to make music in the first place: ", - {}, - ".", - ], - ], - [ - ["What will always get you laid?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - [ - "They said we were crazy. They said we couldn’t put ", - {}, - " inside of ", - {}, - ".", - ], - ["They were wrong."], - ], - [["Lifetime® presents “", {}, ": the Story of ", {}, ".”"]], - [ - [ - { - transform: "Capitalize", - }, - ": kid-tested, mother-approved.", - ], - ], - [ - ["Why can’t I sleep at night?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - ["What’s that smell?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - [ - "After eight years in the White House, how is Obama finally letting loose?", - ], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], - [ - ["This is the way the world ends"], - ["This is the way the world ends"], - ["Not with a bang but with ", {}, "."], - ], - [["Coming to Broadway this season, ", {}, ": The Musical."]], - [ - ["Here is the church"], - ["Here is the steeple"], - ["Open the doors"], - ["And there is", {}, "."], - ], - [["But before I kill you, Mr. Bond, I must show you ", {}, "."]], - [ - [ - "Studies show that lab rats navigate mazes 50% faster after being exposed to ", - {}, - ".", - ], - ], - [ - ["What’s the next superhero/sidekick duo?"], - [ - { - transform: "Capitalize", - }, - "/", - { - transform: "Capitalize", - }, - ".", - ], - ], - [["Next on ESPN2, the World Series of ", {}, "."]], - [ - [ - "When I am a billionaire, I shall erect a 50-foot statue to commemorate ", - {}, - ".", - ], - ], - [ - [ - "Military historians remember Alexander the Great for his brilliant use of ", - {}, - " against the Persians.", - ], - ], - [ - ["War!"], - ["What is it good for?"], - [ - { - transform: "Capitalize", - }, - ".", - ], - ], ], responses: [ "silence", diff --git a/server/src/ts/action/validation.validator.ts b/server/src/ts/action/validation.validator.ts index a9c4c3b5..2ddc0173 100644 --- a/server/src/ts/action/validation.validator.ts +++ b/server/src/ts/action/validation.validator.ts @@ -524,6 +524,18 @@ export const Schema = { 'Configuration for the "Never Have I Ever" house rule.\nThis rule allows players to discard cards, but everyone else in the game can see the discarded card.', type: "object", }, + HappyEnding: { + $ref: "#/definitions/HappyEnding_1", + description: + 'Configuration for the "Happy Ending" house rule.\nWhen the game ends, the final round is a "Make a Haiku" black card.', + }, + HappyEnding_1: { + additionalProperties: false, + defaultProperties: [], + description: + 'Configuration for the "Happy Ending" house rule.\nWhen the game ends, the final round is a "Make a Haiku" black card.', + type: "object", + }, PackingHeat: { $ref: "#/definitions/PackingHeat_1", description: 'Configuration for the "Packing Heat" house rule.', @@ -1055,12 +1067,12 @@ export function validate(typeName: string): (value: unknown) => any { if (!valid) { throw new Error( "Invalid " + - typeName + - ": " + - ajv.errorsText( - validator.errors!.filter((e: any) => e.keyword !== "if"), - { dataVar: typeName } - ) + typeName + + ": " + + ajv.errorsText( + validator.errors!.filter((e: any) => e.keyword !== "if"), + { dataVar: typeName } + ) ); } diff --git a/server/src/ts/games/rules.ts b/server/src/ts/games/rules.ts index 37e2abac..313f38c9 100644 --- a/server/src/ts/games/rules.ts +++ b/server/src/ts/games/rules.ts @@ -86,7 +86,7 @@ export interface Stages { /** * Configuration for the "Packing Heat" house rule. */ -export interface PackingHeat {} +export interface PackingHeat { } /** * Configuration for the "Reboot the Universe" house rule. @@ -125,13 +125,19 @@ export interface ComedyWriter { * Configuration for the "Never Have I Ever" house rule. * This rule allows players to discard cards, but everyone else in the game can see the discarded card. */ -export interface NeverHaveIEver {} +export interface NeverHaveIEver { } export const censor = (rules: Rules): Public => ({ ...rules, houseRules: HouseRules.censor(rules.houseRules), }); +/** + * Configuration for the "Happy Ending" house rule. + * When the game ends, the final round is a 'Make a Haiku' black card. + */ +export interface HappyEnding { } + /** * Create rules from some defaults. * Importantly this doesn't correctly set up the rando house rule, use Rando.create after-the-fact. diff --git a/server/src/ts/games/rules/houseRules.ts b/server/src/ts/games/rules/houseRules.ts index ffc8931e..2616f794 100644 --- a/server/src/ts/games/rules/houseRules.ts +++ b/server/src/ts/games/rules/houseRules.ts @@ -1,4 +1,4 @@ -import { PackingHeat, Reboot, ComedyWriter, NeverHaveIEver } from "../rules"; +import { PackingHeat, Reboot, ComedyWriter, NeverHaveIEver, HappyEnding } from "../rules"; import * as Rando from "./rando"; /** @@ -10,6 +10,7 @@ export interface HouseRules { comedyWriter?: ComedyWriter; rando: Rando.Rando; neverHaveIEver?: NeverHaveIEver; + happyEnding?: HappyEnding; } /** @@ -21,6 +22,7 @@ export interface Public { comedyWriter?: ComedyWriter; rando?: Rando.Public; neverHaveIEver?: NeverHaveIEver; + happyEnding?: HappyEnding; } export const censor = (houseRules: HouseRules): Public => ({ diff --git a/server/src/ts/timeout/round-start.ts b/server/src/ts/timeout/round-start.ts index a7f67278..b81c215f 100644 --- a/server/src/ts/timeout/round-start.ts +++ b/server/src/ts/timeout/round-start.ts @@ -39,13 +39,17 @@ export const handle: Timeout.Handler = ( } } if (winners.length > 0) { - lobbyGame.winner = winners; - events.push(Event.targetAll(GameEnded.of(...winners))); + if (lobbyGame.rules.houseRules.happyEnding) { + // TODO: Check if happy ending has already happened. + } else { + lobbyGame.winner = winners; + events.push(Event.targetAll(GameEnded.of(...winners))); - return { - inLobby, - events, - }; + return { + inLobby, + events, + }; + } } } From 6a49e3636ed11a19460b4cc29b5ce14723291469 Mon Sep 17 00:00:00 2001 From: CookieCoder15 <40507205+CookieCoder15@users.noreply.github.com> Date: Sat, 3 Oct 2020 20:53:20 +1000 Subject: [PATCH 2/7] Added Happy Ending rule to config. --- server/config.json5 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/config.json5 b/server/config.json5 index f8b9e0b2..557a7982 100644 --- a/server/config.json5 +++ b/server/config.json5 @@ -61,7 +61,8 @@ // reboot: { cost: 1 }, // comedyWriter: { number: 300, exclusive: true }, // rando: { number: 1 }, - // neverHaveIEver: {} + // neverHaveIEver: {}, + // happyEnding: {} }, stages: { timeLimitMode: "Soft", From f4f785a24cdadaca34d7fba1df7ea5d4ac1cda6e Mon Sep 17 00:00:00 2001 From: CookieCoder15 <40507205+CookieCoder15@users.noreply.github.com> Date: Sun, 4 Oct 2020 08:41:55 +1100 Subject: [PATCH 3/7] Regenerated validation.validator.ts --- server/src/ts/action/validation.validator.ts | 39 +++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/server/src/ts/action/validation.validator.ts b/server/src/ts/action/validation.validator.ts index 2ddc0173..6ee36a92 100644 --- a/server/src/ts/action/validation.validator.ts +++ b/server/src/ts/action/validation.validator.ts @@ -383,6 +383,18 @@ export const Schema = { required: ["action", "card", "text"], type: "object", }, + HappyEnding: { + $ref: "#/definitions/HappyEnding_1", + description: + "Configuration for the \"Happy Ending\" house rule.\nWhen the game ends, the final round is a 'Make a Haiku' black card.", + }, + HappyEnding_1: { + additionalProperties: false, + defaultProperties: [], + description: + "Configuration for the \"Happy Ending\" house rule.\nWhen the game ends, the final round is a 'Make a Haiku' black card.", + type: "object", + }, Id: { description: "A unique id for an instance of a card.", type: "string", @@ -524,18 +536,6 @@ export const Schema = { 'Configuration for the "Never Have I Ever" house rule.\nThis rule allows players to discard cards, but everyone else in the game can see the discarded card.', type: "object", }, - HappyEnding: { - $ref: "#/definitions/HappyEnding_1", - description: - 'Configuration for the "Happy Ending" house rule.\nWhen the game ends, the final round is a "Make a Haiku" black card.', - }, - HappyEnding_1: { - additionalProperties: false, - defaultProperties: [], - description: - 'Configuration for the "Happy Ending" house rule.\nWhen the game ends, the final round is a "Make a Haiku" black card.', - type: "object", - }, PackingHeat: { $ref: "#/definitions/PackingHeat_1", description: 'Configuration for the "Packing Heat" house rule.', @@ -639,6 +639,9 @@ export const Schema = { comedyWriter: { $ref: "#/definitions/ComedyWriter", }, + happyEnding: { + $ref: "#/definitions/HappyEnding", + }, neverHaveIEver: { $ref: "#/definitions/NeverHaveIEver", }, @@ -1067,12 +1070,12 @@ export function validate(typeName: string): (value: unknown) => any { if (!valid) { throw new Error( "Invalid " + - typeName + - ": " + - ajv.errorsText( - validator.errors!.filter((e: any) => e.keyword !== "if"), - { dataVar: typeName } - ) + typeName + + ": " + + ajv.errorsText( + validator.errors!.filter((e: any) => e.keyword !== "if"), + { dataVar: typeName } + ) ); } From 92c8c67f0a892f91e92acfb0239b820e405763d8 Mon Sep 17 00:00:00 2001 From: CookieCoder15 <40507205+CookieCoder15@users.noreply.github.com> Date: Sun, 4 Oct 2020 09:09:58 +1100 Subject: [PATCH 4/7] Happy Ending Rule Triggers One Extra Round --- client/src/elm/MassiveDecks/Models/Encoders.elm | 2 +- server/src/ts/games/game.ts | 11 +++++++++++ server/src/ts/timeout/round-start.ts | 6 ++++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/client/src/elm/MassiveDecks/Models/Encoders.elm b/client/src/elm/MassiveDecks/Models/Encoders.elm index bbdd87d7..15aa2de6 100644 --- a/client/src/elm/MassiveDecks/Models/Encoders.elm +++ b/client/src/elm/MassiveDecks/Models/Encoders.elm @@ -117,7 +117,7 @@ houseRules h = , h.reboot |> Maybe.map (\r -> ( "reboot", reboot r )) , h.comedyWriter |> Maybe.map (\c -> ( "comedyWriter", comedyWriter c )) , h.neverHaveIEver |> Maybe.map (\n -> ( "neverHaveIEver", neverHaveIEver n )) - , h.happyEnding |> Maybe.map (\e -> ( "happyEnding", happyEnding e )) -- TODO: Workout what to do since "h" is taken. + , h.happyEnding |> Maybe.map (\e -> ( "happyEnding", happyEnding e )) ] ) diff --git a/server/src/ts/games/game.ts b/server/src/ts/games/game.ts index ca103cb7..29ad8065 100644 --- a/server/src/ts/games/game.ts +++ b/server/src/ts/games/game.ts @@ -28,6 +28,7 @@ export interface Public { rules: Rules.Public; winner?: string[]; paused?: boolean; + happyEnding?: boolean; } /** @@ -42,6 +43,7 @@ export class Game { public readonly rules: Rules.Rules; public winner?: User.Id[]; public paused: boolean; + public happyEnding: boolean; private constructor( round: Round.Round, @@ -50,6 +52,7 @@ export class Game { decks: Decks.Decks, rules: Rules.Rules, paused = false, + happyEnding = false, history: PublicRound.Complete[] | undefined = undefined, winner: User.Id[] | undefined = undefined ) { @@ -60,6 +63,7 @@ export class Game { this.decks = decks; this.rules = rules; this.paused = paused; + this.happyEnding = happyEnding; this.winner = winner; } @@ -71,6 +75,7 @@ export class Game { decks: this.decks, rules: this.rules, paused: this.paused, + happyEnding: this.happyEnding, history: this.history, winner: this.winner, }; @@ -87,6 +92,7 @@ export class Game { }, game.rules, game.paused, + game.happyEnding, game.history, game.winner ); @@ -220,6 +226,7 @@ export class Game { rules: Rules.censor(this.rules), ...(this.winner === undefined ? {} : { winner: this.winner }), ...(this.paused ? { paused: true } : {}), + ...(this.happyEnding ? { happyEnding: true } : {}), }; } @@ -249,6 +256,10 @@ export class Game { events.push(Event.targetAll(PauseStateChanged.continued)); } const [call] = this.decks.calls.replace(this.round.call); + if (lobby.game?.happyEnding) { + // const [call] = + // TODO: Work out how to send Haiku card here. + } const roundId = this.round.id + 1; const playersInRound = new Set( wu(this.playerOrder).filter((id) => diff --git a/server/src/ts/timeout/round-start.ts b/server/src/ts/timeout/round-start.ts index b81c215f..5a269bbb 100644 --- a/server/src/ts/timeout/round-start.ts +++ b/server/src/ts/timeout/round-start.ts @@ -39,8 +39,10 @@ export const handle: Timeout.Handler = ( } } if (winners.length > 0) { - if (lobbyGame.rules.houseRules.happyEnding) { - // TODO: Check if happy ending has already happened. + if (lobbyGame.rules.houseRules.happyEnding && !lobbyGame.happyEnding) { + // If game finished and happy ending is enable and hasn't happened yet, + // set happy ending flag to true. One more round will happen now. + lobbyGame.happyEnding = true; } else { lobbyGame.winner = winners; events.push(Event.targetAll(GameEnded.of(...winners))); From 47094e37cf4ae2303f6c266ae0cef0d8edbc57e3 Mon Sep 17 00:00:00 2001 From: CookieCoder15 <40507205+CookieCoder15@users.noreply.github.com> Date: Sun, 4 Oct 2020 09:42:07 +1100 Subject: [PATCH 5/7] Fix Base Deck Accidentally pushed changes to this deck. --- server/decks/cah-base-en.deck.json5 | 551 ++++++++++++++++++++++++++++ 1 file changed, 551 insertions(+) diff --git a/server/decks/cah-base-en.deck.json5 b/server/decks/cah-base-en.deck.json5 index 93644b66..1be13424 100644 --- a/server/decks/cah-base-en.deck.json5 +++ b/server/decks/cah-base-en.deck.json5 @@ -5,6 +5,332 @@ language: "en", author: "Cards Against Humanity", calls: [ + [ + [ + "Hey Reddit! I’m ", + { + transform: "Capitalize", + }, + ".", + ], + ["Ask me anything."], + ], + [ + ["Introducing X-treme Baseball!"], + ["It’s like baseball, but with ", {}, "!"], + ], + [ + ["What is Batman’s guilty pleasure?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [["TSA guidelines now prohibit ", {}, " on airplanes."]], + [ + [ + "Next from J.K. Rowling: ", + { + text: "Harry Potter and the Chamber of ", + style: "Em", + }, + { + transform: "Capitalize", + style: "Em", + }, + ".", + ], + ], + [ + ["That’s right, I killed ", {}, "."], + ["How, you ask?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + [ + "I’m sorry professor, but I couldn’t complete my homework because of ", + {}, + ".", + ], + ], + [["And the Academy Award for ", {}, " goes to ", {}, "."]], + [["Dude, do not go in that bathroom."], ["There’s ", {}, " in there."]], + [ + ["How did I lose my virginity?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + [ + "It’s a pity that kids these days are all getting involved with ", + {}, + ".", + ], + ], + [ + [ + "Step 1: ", + { + transform: "Capitalize", + }, + ".", + ], + [ + "Step 2: ", + { + transform: "Capitalize", + }, + ".", + ], + ["Step 3: Profit."], + ], + [ + [ + { + transform: "Capitalize", + }, + ".", + ], + ["Becha can’t have just one!"], + ], + [["Kids, I don’t need drugs to get high. I’m high on ", {}, "."]], + [["For my next trick, I will pull ", {}, " out of ", {}, "."]], + [ + [ + "While the United States raced the Soviet Union to the moon, the Mexican government funneled millions of pesos into research on ", + {}, + ".", + ], + ], + [ + [ + "In the new Disney Channel Original Movie, Hannah Montana struggles with ", + {}, + " for the first time.", + ], + ], + [ + ["What’s my secret power?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + [ + "I’m going on a cleanse this week. Nothing but kale juice and ", + {}, + ".", + ], + ], + [ + [ + { + transform: "Capitalize", + }, + " + ", + { + transform: "Capitalize", + }, + ], + [ + " = ", + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + [ + "When Pharaoh remained unmoved, Moses called down a Plague of ", + {}, + ".", + ], + ], + [ + [ + "Just once, I’d like to hear you say “Thanks, Mom. Thanks for ", + {}, + ".”", + ], + ], + [ + ["Daddy, why is mommy crying?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [["When I was tripping on acid, ", {}, " turned into ", {}, "."]], + [["50% of all marriages end in ", {}, "."]], + [ + [ + "My fellow Americans: Before this decade is out, we ", + { + text: "will", + style: "Em", + }, + ", have ", + {}, + " on the moon.", + ], + ], + [ + [ + "This season at Steppenwolf, Samuel Beckett’s classic existential play: ", + { + text: "Waiting for", + style: "Em", + }, + { + style: "Em", + }, + ".", + ], + ], + [["Instead of coal, Santa now gives the bad children ", {}, "."]], + [ + [ + "Life for American Indians was forever changed when the White Man introduced them to ", + {}, + ".", + ], + ], + [ + [ + "What’s Teach for America using to inspire inner city students to succeed?", + ], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [["Maybe she’s born with it."], ["Maybe it’s ", {}, "."]], + [ + ["What is George W. Bush thinking about right now?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [["White people like ", {}, "."]], + [ + [ + { + transform: "Capitalize", + }, + " is a slippery slope that leads to ", + {}, + ".", + ], + ], + [ + ["Why do I hurt all over?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [["A romantic, candlelit dinner would be incomplete without ", {}, "."]], + [ + ["Just saw this upsetting video! Please retweet!!"], + [ + "#stop", + { + transform: "Capitalize", + }, + ], + ], + [ + [ + "Fun tip! When your man asks you to go down on him, try surprising him with ", + {}, + " instead.", + ], + ], + [["The class field trip was completely ruined by ", {}, "."]], + [ + ["What’s a girl’s best friend?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + [ + "Dear Abby, I’m having some trouble with ", + {}, + " and would like your advice.", + ], + ], + [ + [ + "In M. Night Shyamalan’s new movie, Bruce Willis discovers that ", + {}, + " had really been ", + {}, + " all along.", + ], + ], + [ + [ + "When I am President of the United States, I will create the Department of ", + {}, + ".", + ], + ], + [ + ["What are my parents hiding from me?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + ["What never fails to liven up the party?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + [ + "IF you like ", + { + transform: "UpperCase", + }, + ",", + ], + ["YOU MIGHT BE A REDNECK."], + ], [ ["Make a haiku."], [ @@ -26,6 +352,231 @@ ".", ], ], + [ + ["What made my first kiss so awkward?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + [ + "Hey guys, welcome to Chili’s! Would you like to start the night off right with ", + {}, + "?", + ], + ], + [["I got 99 problems but ", {}, " ain’t one."]], + [ + [ + { + transform: "Capitalize", + }, + ".", + ], + ["It’s a trap!"], + ], + [ + [ + "Bravo’s new reality show features eight washed-up celebrities living with ", + {}, + ".", + ], + ], + [ + ["What would grandma find disturbing, yet oddly charming?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + [ + { + transform: "Capitalize", + }, + ".", + ], + ["That was so metal."], + ], + [["I never truly understood ", {}, " until I encountered ", {}, "."]], + [["During sex, I like to think about ", {}, "."]], + [ + ["What ended my last relationship?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + ["What’s that sound?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + [ + "Uh, hey guys, I know this was my idea, but I’m having serious doubts about ", + {}, + ".", + ], + ], + [ + ["Why am I sticky?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + [ + "I’m no doctor but I’m pretty sure what you’re suffering from is called “", + {}, + ".”", + ], + ], + [ + ["What’s there a ton of in heaven?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + [ + "After four platinum albums and three Grammys, it’s time to get back to my roots, to what inspired me to make music in the first place: ", + {}, + ".", + ], + ], + [ + ["What will always get you laid?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + [ + "They said we were crazy. They said we couldn’t put ", + {}, + " inside of ", + {}, + ".", + ], + ["They were wrong."], + ], + [["Lifetime® presents “", {}, ": the Story of ", {}, ".”"]], + [ + [ + { + transform: "Capitalize", + }, + ": kid-tested, mother-approved.", + ], + ], + [ + ["Why can’t I sleep at night?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + ["What’s that smell?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + [ + "After eight years in the White House, how is Obama finally letting loose?", + ], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + [ + ["This is the way the world ends"], + ["This is the way the world ends"], + ["Not with a bang but with ", {}, "."], + ], + [["Coming to Broadway this season, ", {}, ": The Musical."]], + [ + ["Here is the church"], + ["Here is the steeple"], + ["Open the doors"], + ["And there is", {}, "."], + ], + [["But before I kill you, Mr. Bond, I must show you ", {}, "."]], + [ + [ + "Studies show that lab rats navigate mazes 50% faster after being exposed to ", + {}, + ".", + ], + ], + [ + ["What’s the next superhero/sidekick duo?"], + [ + { + transform: "Capitalize", + }, + "/", + { + transform: "Capitalize", + }, + ".", + ], + ], + [["Next on ESPN2, the World Series of ", {}, "."]], + [ + [ + "When I am a billionaire, I shall erect a 50-foot statue to commemorate ", + {}, + ".", + ], + ], + [ + [ + "Military historians remember Alexander the Great for his brilliant use of ", + {}, + " against the Persians.", + ], + ], + [ + ["War!"], + ["What is it good for?"], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], ], responses: [ "silence", From 4c1562551e3ea9e6c94668ad1124df717a05bccc Mon Sep 17 00:00:00 2001 From: CookieCoder15 <40507205+CookieCoder15@users.noreply.github.com> Date: Sun, 4 Oct 2020 13:36:15 +1100 Subject: [PATCH 6/7] Added "Generated" card source. Added a new card source called "Generated" for cards hardcoded into the game such as the Haiku card in the happy ending house rule. --- client/src/elm/MassiveDecks/Card/Source.elm | 4 +++ .../MassiveDecks/Card/Source/Generated.elm | 32 ++++++++++++++++++ .../elm/MassiveDecks/Card/Source/Model.elm | 4 ++- .../src/elm/MassiveDecks/Models/Decoders.elm | 3 ++ client/src/elm/MassiveDecks/Strings.elm | 1 + .../elm/MassiveDecks/Strings/Languages/De.elm | 4 +++ .../Strings/Languages/DeXInformal.elm | 4 +++ .../Strings/Languages/En/Internal.elm | 3 ++ .../elm/MassiveDecks/Strings/Languages/Id.elm | 4 +++ .../elm/MassiveDecks/Strings/Languages/It.elm | 4 +++ .../elm/MassiveDecks/Strings/Languages/Pl.elm | 4 +++ .../MassiveDecks/Strings/Languages/PtBR.elm | 4 +++ server/src/ts/games/cards/source.ts | 3 +- server/src/ts/games/cards/sources.ts | 4 +++ .../src/ts/games/cards/sources/generated.ts | 15 +++++++++ server/src/ts/games/game.ts | 13 +++++--- server/src/ts/games/rules.ts | 11 ++----- server/src/ts/games/rules/happyEnding.ts | 33 +++++++++++++++++++ server/src/ts/games/rules/houseRules.ts | 7 ++-- server/src/ts/timeout/round-start.ts | 4 +-- 20 files changed, 142 insertions(+), 19 deletions(-) create mode 100644 client/src/elm/MassiveDecks/Card/Source/Generated.elm create mode 100644 server/src/ts/games/cards/sources/generated.ts create mode 100644 server/src/ts/games/rules/happyEnding.ts diff --git a/client/src/elm/MassiveDecks/Card/Source.elm b/client/src/elm/MassiveDecks/Card/Source.elm index 2559c5c1..1df39d27 100644 --- a/client/src/elm/MassiveDecks/Card/Source.elm +++ b/client/src/elm/MassiveDecks/Card/Source.elm @@ -21,6 +21,7 @@ import Html.Attributes as HtmlA import MassiveDecks.Card.Source.BuiltIn as BuiltIn import MassiveDecks.Card.Source.Custom as Player import MassiveDecks.Card.Source.Fake as Fake +import MassiveDecks.Card.Source.Generated as Generated import MassiveDecks.Card.Source.JsonAgainstHumanity as JsonAgainstHumanity import MassiveDecks.Card.Source.ManyDecks as ManyDecks import MassiveDecks.Card.Source.Methods exposing (..) @@ -250,6 +251,9 @@ methods source = Custom -> Player.methods + Generated -> + Generated.methods + Fake fakeName -> Fake.methods fakeName diff --git a/client/src/elm/MassiveDecks/Card/Source/Generated.elm b/client/src/elm/MassiveDecks/Card/Source/Generated.elm new file mode 100644 index 00000000..42d18a7e --- /dev/null +++ b/client/src/elm/MassiveDecks/Card/Source/Generated.elm @@ -0,0 +1,32 @@ +module MassiveDecks.Card.Source.Generated exposing (..) + +import MassiveDecks.Card.Source.Methods as Source +import MassiveDecks.Model exposing (Shared) +import MassiveDecks.Strings as Strings +import MassiveDecks.Strings.Languages as Lang + + +methods : Source.Methods msg +methods = + { name = \() -> Strings.Generated + , logo = \() -> Nothing + , defaultDetails = + \shared -> + { name = name shared + , url = Nothing + , translator = Nothing + , author = Nothing + , language = Nothing + } + , tooltip = \_ -> Nothing + , messages = \() -> [] + } + + + +{- Private -} + + +name : Shared -> String +name shared = + Strings.Generated |> Lang.string shared diff --git a/client/src/elm/MassiveDecks/Card/Source/Model.elm b/client/src/elm/MassiveDecks/Card/Source/Model.elm index c86a5eed..96b12dda 100644 --- a/client/src/elm/MassiveDecks/Card/Source/Model.elm +++ b/client/src/elm/MassiveDecks/Card/Source/Model.elm @@ -29,13 +29,15 @@ type General {-| Details on where game data came from. - `Ex`: External sources are the main sources of cards users can add. - - `Player`: These are cards written by the given player. + - `Custom`: These are cards written by the given player. + - `Generated`: These are cards generated during a game for reasons such as house rules. - `Fake`: These are cards used for presentation outside of a game environment. -} type Source = Ex External | Custom + | Generated | Fake (Maybe String) diff --git a/client/src/elm/MassiveDecks/Models/Decoders.elm b/client/src/elm/MassiveDecks/Models/Decoders.elm index 79ebbcfc..45d09adc 100644 --- a/client/src/elm/MassiveDecks/Models/Decoders.elm +++ b/client/src/elm/MassiveDecks/Models/Decoders.elm @@ -228,6 +228,9 @@ sourceByName name = "Custom" -> Json.succeed Source.Custom + "Generated" -> + Json.succeed Source.Generated + _ -> Json.field "source" Source.generalDecoder |> Json.andThen externalSourceByGeneral |> Json.map Source.Ex diff --git a/client/src/elm/MassiveDecks/Strings.elm b/client/src/elm/MassiveDecks/Strings.elm index 231f0784..5c37e648 100644 --- a/client/src/elm/MassiveDecks/Strings.elm +++ b/client/src/elm/MassiveDecks/Strings.elm @@ -256,6 +256,7 @@ type MdString | JsonAgainstHumanityAbout -- A short description of the JSON Against Humanity source. | BuiltIn -- A term referring to decks of cards that are provided by this instance of the game. | APlayer -- A short description of a generic player in the game in the context of being the author of a card. + | Generated -- A short description of a card generated during the game. | DeckAlreadyAdded -- A description of the problem of the deck already being added to the game configuration. | ConfigureDecks -- A name for the section of the configuration screen for changing the decks for the game. | ConfigureRules -- A name for the section of the configuration screen for changing the rules for the game. diff --git a/client/src/elm/MassiveDecks/Strings/Languages/De.elm b/client/src/elm/MassiveDecks/Strings/Languages/De.elm index 39012e50..c97f558e 100644 --- a/client/src/elm/MassiveDecks/Strings/Languages/De.elm +++ b/client/src/elm/MassiveDecks/Strings/Languages/De.elm @@ -811,6 +811,10 @@ translate _ mdString = APlayer -> [ Text "Ein Spieler" ] + -- TODO: Translate + Generated -> + [ Missing ] + DeckAlreadyAdded -> [ Text "Dieser Kartensatz ist bereits im Spiel." ] diff --git a/client/src/elm/MassiveDecks/Strings/Languages/DeXInformal.elm b/client/src/elm/MassiveDecks/Strings/Languages/DeXInformal.elm index 151e5164..97c8aa62 100644 --- a/client/src/elm/MassiveDecks/Strings/Languages/DeXInformal.elm +++ b/client/src/elm/MassiveDecks/Strings/Languages/DeXInformal.elm @@ -810,6 +810,10 @@ translate _ mdString = APlayer -> [ Text "Ein Spieler" ] + -- TODO: Translate + Generated -> + [ Missing ] + DeckAlreadyAdded -> [ Text "Dieser Kartensatz ist bereits im Spiel." ] diff --git a/client/src/elm/MassiveDecks/Strings/Languages/En/Internal.elm b/client/src/elm/MassiveDecks/Strings/Languages/En/Internal.elm index 973d3167..49f32662 100644 --- a/client/src/elm/MassiveDecks/Strings/Languages/En/Internal.elm +++ b/client/src/elm/MassiveDecks/Strings/Languages/En/Internal.elm @@ -764,6 +764,9 @@ translate _ mdString = APlayer -> [ Text "A Player" ] + Generated -> + [ Text "Generated" ] + DeckAlreadyAdded -> [ Text "This deck is already in the game." ] diff --git a/client/src/elm/MassiveDecks/Strings/Languages/Id.elm b/client/src/elm/MassiveDecks/Strings/Languages/Id.elm index e713936e..ce1aa89a 100644 --- a/client/src/elm/MassiveDecks/Strings/Languages/Id.elm +++ b/client/src/elm/MassiveDecks/Strings/Languages/Id.elm @@ -801,6 +801,10 @@ translate _ mdString = APlayer -> [ Text "Seorang Player" ] + -- TODO: Translate + Generated -> + [ Missing ] + DeckAlreadyAdded -> [ Text "Dek ini sudah ada dalam game." ] diff --git a/client/src/elm/MassiveDecks/Strings/Languages/It.elm b/client/src/elm/MassiveDecks/Strings/Languages/It.elm index 719bf590..886072ad 100644 --- a/client/src/elm/MassiveDecks/Strings/Languages/It.elm +++ b/client/src/elm/MassiveDecks/Strings/Languages/It.elm @@ -825,6 +825,10 @@ translate _ mdString = APlayer -> [ Text "Un giocatore" ] + -- TODO: Translate + Generated -> + [ Missing ] + DeckAlreadyAdded -> [ Text "Questo mazzo è già nel gioco." ] diff --git a/client/src/elm/MassiveDecks/Strings/Languages/Pl.elm b/client/src/elm/MassiveDecks/Strings/Languages/Pl.elm index 3a9201cc..c1142e93 100644 --- a/client/src/elm/MassiveDecks/Strings/Languages/Pl.elm +++ b/client/src/elm/MassiveDecks/Strings/Languages/Pl.elm @@ -913,6 +913,10 @@ translate maybeDeclCase mdString = APlayer -> [ Text "Gracz" ] + -- TODO: Translate + Generated -> + [ Missing ] + DeckAlreadyAdded -> [ Text "Ta talia jest już w grze." ] diff --git a/client/src/elm/MassiveDecks/Strings/Languages/PtBR.elm b/client/src/elm/MassiveDecks/Strings/Languages/PtBR.elm index 84ce214f..fe2ace01 100644 --- a/client/src/elm/MassiveDecks/Strings/Languages/PtBR.elm +++ b/client/src/elm/MassiveDecks/Strings/Languages/PtBR.elm @@ -812,6 +812,10 @@ translate _ mdString = APlayer -> [ Text "Um jogador" ] + -- TODO: Translate + Generated -> + [ Missing ] + DeckAlreadyAdded -> [ Text "Este deck já está no jogo." ] diff --git a/server/src/ts/games/cards/source.ts b/server/src/ts/games/cards/source.ts index c04a565e..e4cebf83 100644 --- a/server/src/ts/games/cards/source.ts +++ b/server/src/ts/games/cards/source.ts @@ -1,6 +1,7 @@ import * as Cache from "../../cache"; import * as Decks from "./decks"; import { Custom } from "./sources/custom"; +import { Generated } from "./sources/generated"; import { BuiltIn } from "./sources/builtIn"; import { ManyDecks } from "./sources/many-decks"; import { JsonAgainstHumanity } from "./sources/json-against-humanity"; @@ -8,7 +9,7 @@ import { JsonAgainstHumanity } from "./sources/json-against-humanity"; /** * A source for a card or deck. */ -export type Source = External | Custom; +export type Source = External | Custom | Generated; /** * An external source for a card or deck. diff --git a/server/src/ts/games/cards/sources.ts b/server/src/ts/games/cards/sources.ts index 85fa90cc..34d7db84 100644 --- a/server/src/ts/games/cards/sources.ts +++ b/server/src/ts/games/cards/sources.ts @@ -7,6 +7,7 @@ import * as BuiltIn from "./sources/builtIn"; import { SourceNotFoundError } from "../../errors/action-execution-error"; import * as ManyDecks from "./sources/many-decks"; import * as JsonAgainstHumanity from "./sources/json-against-humanity"; +import * as Generated from "./sources/generated"; async function loadIfEnabled( config: Config | undefined, @@ -122,6 +123,9 @@ export class Sources { case "Custom": return Player.details(source); + case "Generated": + return Generated.details(source); + default: return await this.resolver(cache, source).details(); } diff --git a/server/src/ts/games/cards/sources/generated.ts b/server/src/ts/games/cards/sources/generated.ts new file mode 100644 index 00000000..59a3c98c --- /dev/null +++ b/server/src/ts/games/cards/sources/generated.ts @@ -0,0 +1,15 @@ +import * as Source from "../source"; + +/** + * A source for cards generated during the game for reasons such as house rules. + */ +export interface Generated { + source: "Generated"; +} + +/** + * Get the details for a given source. + */ +export const details = (_: Generated): Source.Details => ({ + name: "Generated", +}); diff --git a/server/src/ts/games/game.ts b/server/src/ts/games/game.ts index 29ad8065..e98a02ab 100644 --- a/server/src/ts/games/game.ts +++ b/server/src/ts/games/game.ts @@ -19,6 +19,7 @@ import * as Round from "./game/round"; import * as PublicRound from "./game/round/public"; import * as Player from "./player"; import * as Rules from "./rules"; +import { happyEndingCall } from "./rules/happyEnding"; export interface Public { round: PublicRound.Public; @@ -256,10 +257,6 @@ export class Game { events.push(Event.targetAll(PauseStateChanged.continued)); } const [call] = this.decks.calls.replace(this.round.call); - if (lobby.game?.happyEnding) { - // const [call] = - // TODO: Work out how to send Haiku card here. - } const roundId = this.round.id + 1; const playersInRound = new Set( wu(this.playerOrder).filter((id) => @@ -270,6 +267,14 @@ export class Game { (this.round as Round.Base).plays.flatMap((play) => play.play) ); this.round = new Round.Playing(roundId, czar, playersInRound, call); + if (lobby.game?.happyEnding) { + this.round = new Round.Playing( + roundId, + czar, + playersInRound, + happyEndingCall + ); + } const updatedGame = this as Game & { round: Round.Playing }; const atStart = Game.atStartOfRound(server, false, updatedGame); return { diff --git a/server/src/ts/games/rules.ts b/server/src/ts/games/rules.ts index 313f38c9..c8a99928 100644 --- a/server/src/ts/games/rules.ts +++ b/server/src/ts/games/rules.ts @@ -1,5 +1,6 @@ import * as HouseRules from "./rules/houseRules"; import * as Rando from "./rules/rando"; +import * as HappyEnding from "./rules/happyEnding"; /** The rules for a standard game. */ @@ -86,7 +87,7 @@ export interface Stages { /** * Configuration for the "Packing Heat" house rule. */ -export interface PackingHeat { } +export interface PackingHeat {} /** * Configuration for the "Reboot the Universe" house rule. @@ -125,19 +126,13 @@ export interface ComedyWriter { * Configuration for the "Never Have I Ever" house rule. * This rule allows players to discard cards, but everyone else in the game can see the discarded card. */ -export interface NeverHaveIEver { } +export interface NeverHaveIEver {} export const censor = (rules: Rules): Public => ({ ...rules, houseRules: HouseRules.censor(rules.houseRules), }); -/** - * Configuration for the "Happy Ending" house rule. - * When the game ends, the final round is a 'Make a Haiku' black card. - */ -export interface HappyEnding { } - /** * Create rules from some defaults. * Importantly this doesn't correctly set up the rando house rule, use Rando.create after-the-fact. diff --git a/server/src/ts/games/rules/happyEnding.ts b/server/src/ts/games/rules/happyEnding.ts new file mode 100644 index 00000000..ccd555b3 --- /dev/null +++ b/server/src/ts/games/rules/happyEnding.ts @@ -0,0 +1,33 @@ +import * as Card from "../cards/card"; + +/** + * Configuration for the "Happy Ending" house rule. + * When the game ends, the final round is a 'Make a Haiku' black card. + */ +export interface HappyEnding {} + +export const happyEndingCall: Card.Call = { + id: Card.id(), + parts: [ + ["Make a haiku."], + [ + { + transform: "Capitalize", + }, + ",", + ], + [ + { + transform: "Capitalize", + }, + ",", + ], + [ + { + transform: "Capitalize", + }, + ".", + ], + ], + source: { source: "Generated" }, +}; diff --git a/server/src/ts/games/rules/houseRules.ts b/server/src/ts/games/rules/houseRules.ts index 2616f794..11f66f6a 100644 --- a/server/src/ts/games/rules/houseRules.ts +++ b/server/src/ts/games/rules/houseRules.ts @@ -1,5 +1,6 @@ -import { PackingHeat, Reboot, ComedyWriter, NeverHaveIEver, HappyEnding } from "../rules"; +import { PackingHeat, Reboot, ComedyWriter, NeverHaveIEver } from "../rules"; import * as Rando from "./rando"; +import * as HappyEnding from "./happyEnding"; /** * Non-standard rules that can be applied to a game. @@ -10,7 +11,7 @@ export interface HouseRules { comedyWriter?: ComedyWriter; rando: Rando.Rando; neverHaveIEver?: NeverHaveIEver; - happyEnding?: HappyEnding; + happyEnding?: HappyEnding.HappyEnding; } /** @@ -22,7 +23,7 @@ export interface Public { comedyWriter?: ComedyWriter; rando?: Rando.Public; neverHaveIEver?: NeverHaveIEver; - happyEnding?: HappyEnding; + happyEnding?: HappyEnding.HappyEnding; } export const censor = (houseRules: HouseRules): Public => ({ diff --git a/server/src/ts/timeout/round-start.ts b/server/src/ts/timeout/round-start.ts index 5a269bbb..340083f5 100644 --- a/server/src/ts/timeout/round-start.ts +++ b/server/src/ts/timeout/round-start.ts @@ -40,8 +40,8 @@ export const handle: Timeout.Handler = ( } if (winners.length > 0) { if (lobbyGame.rules.houseRules.happyEnding && !lobbyGame.happyEnding) { - // If game finished and happy ending is enable and hasn't happened yet, - // set happy ending flag to true. One more round will happen now. + // If someone has won and the happy ending house rule is enabled but hasn't happened yet, + // set the happy ending flag to true. One more round will happen now. lobbyGame.happyEnding = true; } else { lobbyGame.winner = winners; From 673a6a006ee6bde5a8d6ea3a78ec67790ca1fd5c Mon Sep 17 00:00:00 2001 From: CookieCoder15 <40507205+CookieCoder15@users.noreply.github.com> Date: Sun, 4 Oct 2020 14:08:08 +1100 Subject: [PATCH 7/7] Moved happy ending final round check. --- server/src/ts/games/game.ts | 9 +-------- server/src/ts/games/rules/happyEnding.ts | 4 +++- server/src/ts/timeout/round-start.ts | 9 ++++++--- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/server/src/ts/games/game.ts b/server/src/ts/games/game.ts index e98a02ab..31772c6c 100644 --- a/server/src/ts/games/game.ts +++ b/server/src/ts/games/game.ts @@ -29,7 +29,6 @@ export interface Public { rules: Rules.Public; winner?: string[]; paused?: boolean; - happyEnding?: boolean; } /** @@ -44,7 +43,6 @@ export class Game { public readonly rules: Rules.Rules; public winner?: User.Id[]; public paused: boolean; - public happyEnding: boolean; private constructor( round: Round.Round, @@ -53,7 +51,6 @@ export class Game { decks: Decks.Decks, rules: Rules.Rules, paused = false, - happyEnding = false, history: PublicRound.Complete[] | undefined = undefined, winner: User.Id[] | undefined = undefined ) { @@ -64,7 +61,6 @@ export class Game { this.decks = decks; this.rules = rules; this.paused = paused; - this.happyEnding = happyEnding; this.winner = winner; } @@ -76,7 +72,6 @@ export class Game { decks: this.decks, rules: this.rules, paused: this.paused, - happyEnding: this.happyEnding, history: this.history, winner: this.winner, }; @@ -93,7 +88,6 @@ export class Game { }, game.rules, game.paused, - game.happyEnding, game.history, game.winner ); @@ -227,7 +221,6 @@ export class Game { rules: Rules.censor(this.rules), ...(this.winner === undefined ? {} : { winner: this.winner }), ...(this.paused ? { paused: true } : {}), - ...(this.happyEnding ? { happyEnding: true } : {}), }; } @@ -267,7 +260,7 @@ export class Game { (this.round as Round.Base).plays.flatMap((play) => play.play) ); this.round = new Round.Playing(roundId, czar, playersInRound, call); - if (lobby.game?.happyEnding) { + if (this.rules.houseRules.happyEnding?.inFinalRound) { this.round = new Round.Playing( roundId, czar, diff --git a/server/src/ts/games/rules/happyEnding.ts b/server/src/ts/games/rules/happyEnding.ts index ccd555b3..654a86a0 100644 --- a/server/src/ts/games/rules/happyEnding.ts +++ b/server/src/ts/games/rules/happyEnding.ts @@ -4,7 +4,9 @@ import * as Card from "../cards/card"; * Configuration for the "Happy Ending" house rule. * When the game ends, the final round is a 'Make a Haiku' black card. */ -export interface HappyEnding {} +export interface HappyEnding { + inFinalRound?: boolean; +} export const happyEndingCall: Card.Call = { id: Card.id(), diff --git a/server/src/ts/timeout/round-start.ts b/server/src/ts/timeout/round-start.ts index 340083f5..298e8a36 100644 --- a/server/src/ts/timeout/round-start.ts +++ b/server/src/ts/timeout/round-start.ts @@ -39,10 +39,13 @@ export const handle: Timeout.Handler = ( } } if (winners.length > 0) { - if (lobbyGame.rules.houseRules.happyEnding && !lobbyGame.happyEnding) { + if ( + lobbyGame.rules.houseRules.happyEnding && + !lobbyGame.rules.houseRules.happyEnding.inFinalRound + ) { // If someone has won and the happy ending house rule is enabled but hasn't happened yet, - // set the happy ending flag to true. One more round will happen now. - lobbyGame.happyEnding = true; + // set the final round boolean to true. One more round will happen now. + lobbyGame.rules.houseRules.happyEnding.inFinalRound = true; } else { lobbyGame.winner = winners; events.push(Event.targetAll(GameEnded.of(...winners)));