import GameState from "../../../../../GameState" ; import House from "../../../../game-data-structure/House" ; import Game from "../../../../game-data-structure/Game" ; import ExecuteLoanGameState from "../ExecuteLoanGameState" ; import IngameGameState from "../../../../IngameGameState" ; import SimpleChoiceGameState , { SerializedSimpleChoiceGameState } from "../../../../simple-choice-game-state/SimpleChoiceGameState" ; import { ServerMessage } from "../../../../../../messages/ServerMessage" ; import { ClientMessage } from "../../../../../../messages/ClientMessage" ; import Player from "../../../../Player" ; import BetterMap from "../../../../../../utils/BetterMap" ; import ResolveSpymasterGameState , { SerializedResolveSpymasterGameState } from "../../../../resolve-spymaster-game-state/ResolveSpymasterGameState" ; import WesterosCard from "../../../../../ingame-game-state/game-data-structure/westeros-card/WesterosCard" ; import _ from "lodash" ; export default class SpymasterGameState extends GameState < ExecuteLoanGameState , SimpleChoiceGameState | ResolveSpymasterGameState < SpymasterGameState > > { get game ( ) : Game { return this . parentGameState . game ; } get executeLoanGameState ( ) : ExecuteLoanGameState { return this . parentGameState ; } get ingame ( ) : IngameGameState { return this . parentGameState . ingame ; } get choices ( ) : BetterMap < string , number > { const choices = new BetterMap < string , number > ( ) ; choices . set ( "Ignore" , - 1 ) ; const deckNames = [ "First" , "Second" , "Third" , "Fourth" ] ; for ( let i = 0 ; i < this . game . westerosDecks . length ; i ++ ) { const deck = this . game . westerosDecks [ i ] ; if ( deck . filter ( wc => ! wc . discarded ) . length > 0 ) { choices . set ( deckNames [ i ] , i ) ; } } return choices ; } firstStart ( house ) { this . setChildGameState ( new SimpleChoiceGameState ( this ) ) . firstStart ( house , "Select a Westeros deck" , this . choices . keys ) ; } getTopTwoCardsOfDeck ( deckId ) { return _ . take ( this . game . westerosDecks [ deckId ] . filter ( wc => ! wc . discarded ) , 2 ) ; } onSimpleChoiceGameStateEnd ( choice ) { const house = this . childGameState . house ; this . setChildGameState ( new ResolveSpymasterGameState ( this ) ) . firstStart ( house , this . choices . values [ choice ] , this . getTopTwoCardsOfDeck ( this . choices . values [ choice ] ) ) ; } onResolveSpymasterFinish ( house , westerosDeckId , westerosCardsForTopOfDeck , westerosCardsForBottomOfDeck ) { const westerosDeck = this . game . westerosDecks [ westerosDeckId ] ; const topTwoCardsOfDeck = this . getTopTwoCardsOfDeck ( westerosDeckId ) ; const concatenatedForCheck = westerosCardsForTopOfDeck . concat ( westerosCardsForBottomOfDeck ) ; if ( _ . intersection ( topTwoCardsOfDeck , concatenatedForCheck ) . length != topTwoCardsOfDeck . length ) { throw new Error ( `Spymaster crashed due to an inconsistent deck ${ westerosDeckId }!` ) ; } const discardedCards = westerosDeck . filter ( wc => wc . discarded ) ; const availableCards = _ . without ( westerosDeck , ... discardedCards . concat ( topTwoCardsOfDeck ) ) ; const newWesterosDeck = _ . concat ( westerosCardsForTopOfDeck , availableCards , westerosCardsForBottomOfDeck , discardedCards ) ; if ( westerosDeck . length != newWesterosDeck . length ) { throw new Error ( `Spymaster corrupted deck ${ westerosDeckId }` ) ; } this . game . westerosDecks [ westerosDeckId ] = newWesterosDeck ; this . ingame . broadcastWesterosDecks ( ) ; this . ingame . log ( { type : "spymaster-executed" , house : house . id , westerosDeckI : westerosDeckId , westerosCardsCountForTopOfDeck : westerosCardsForTopOfDeck . length , westerosCardsCountForBottomOfDeck : westerosCardsForBottomOfDeck . length } , westerosCardsForTopOfDeck . length == 1 ) ; this . executeLoanGameState . onExecuteLoanFinish ( house ) ; } onServerMessage ( message ) { this . childGameState . onServerMessage ( message ) ; } onPlayerMessage ( player , message ) { this . childGameState . onPlayerMessage ( player , message ) ; } serializeToClient ( admin , player ) { return { type : "spymaster" , childGameState : this . childGameState . serializeToClient ( admin , player ) } ; } static deserializeFromServer ( parent , data ) { const gameState = new SpymasterGameState ( parent ) ; gameState . childGameState = gameState . deserializeChildGameState ( data . childGameState ) ; return gameState ; } deserializeChildGameState ( data ) { switch ( data . type ) { case "simple-choice" : return SimpleChoiceGameState . deserializeFromServer ( this , data ) ; case "resolve-spymaster" : return ResolveSpymasterGameState . deserializeFromServer ( this , data ) ; default : throw new Error ( "Invalid child game state for Spymaster" ) ; } } } export interface SerializedSpymasterGameState { type : "spymaster" ; childGameState : SerializedSimpleChoiceGameState | SerializedResolveSpymasterGameState ; }