public TwoToneDrawingGameMode(Lobby lobby, List <ConfigureLobbyRequest.GameModeOptionRequest> gameModeOptions, StandardGameModeOptions standardOptions)
        {
            this.Lobby = lobby;
            GameDuration duration = standardOptions.GameDuration;

            int  maxPossibleTeamCount = 8; // Can go higher than this in extreme circumstances.
            bool useSingleColor       = (bool)gameModeOptions[(int)GameModeOptionsEnum.useSingleColor].ValueParsed;
            int  numLayers            = (int)gameModeOptions[(int)GameModeOptionsEnum.numLayers].ValueParsed;
            int  numPlayers           = lobby.GetAllUsers().Count();

            if (numLayers * 2 > numPlayers)
            {
                numLayers = numPlayers / 2;
            }
            int numRounds            = Math.Min(TwoToneDrawingConstants.MaxNumRounds[duration], numPlayers);
            int numDrawingsPerPlayer = Math.Min(TwoToneDrawingConstants.DrawingsPerPlayer[duration], numRounds);
            int numTeamsLowerBound   = Math.Max(2, 1 * numPlayers / (numRounds * numLayers));                                       // Lower bound.
            int numTeamsUpperBound   = Math.Min(maxPossibleTeamCount, numDrawingsPerPlayer * numPlayers / (numRounds * numLayers)); // Upper bound.
            int numTeams             = Math.Max(numTeamsLowerBound, numTeamsUpperBound);                                            // Possible for lower bound to be higher than upper bound. that is okay.


            //int drawingsPerPlayer = numRounds * numLayers * numTeams / numPlayers;

            TimeSpan?setupTimer   = null;
            TimeSpan?drawingTimer = null;
            TimeSpan?votingTimer  = null;

            if (standardOptions.TimerEnabled)
            {
                setupTimer   = TwoToneDrawingConstants.SetupTimer[duration];
                drawingTimer = TwoToneDrawingConstants.PerDrawingTimer[duration].MultipliedBy(numDrawingsPerPlayer);
                votingTimer  = TwoToneDrawingConstants.VotingTimer[duration];
            }

            Setup = new Setup_GS(
                lobby: lobby,
                challengeTrackers: this.SubChallenges,
                useSingleColor: useSingleColor,
                numLayersPerTeam: numLayers,
                numTeamsPerPrompt: numTeams,
                numRounds: numRounds,
                setupTimer: setupTimer,
                drawingTimer: drawingTimer);

            StateChain GamePlayLoopGenerator()
            {
                List <ChallengeTracker> challenges = SubChallenges.Keys.OrderBy(_ => Rand.Next()).ToList();
                StateChain chain = new StateChain(
                    stateGenerator: (int counter) =>
                {
                    if (counter < challenges.Count)
                    {
                        return(new StateChain(stateGenerator: (int i) => {
                            switch (i)
                            {
                            case 0: return GetVotingAndRevealState(challenges[counter], votingTimer);

                            case 1: return ((counter == challenges.Count - 1) ? new ScoreBoardGameState(lobby, "Final Scores") : new ScoreBoardGameState(lobby));

                            default: return null;
                            }
                        }));
                    }
                    else
                    {
                        return(null);
                    }
                });

                chain.Transition(this.Exit);
                return(chain);
            }

            Setup.Transition(GamePlayLoopGenerator);
            this.Entrance.Transition(Setup);
        }
Example #2
0
        public ImposterDrawingGameMode(Lobby lobby, List <ConfigureLobbyRequest.GameModeOptionRequest> gameModeOptions, StandardGameModeOptions standardOptions)
        {
            this.Lobby = lobby;
            TimeSpan?    writingTimer = null;
            TimeSpan?    drawingTimer = null;
            TimeSpan?    votingTimer  = null;
            GameDuration duration     = standardOptions.GameDuration;

            if (standardOptions.TimerEnabled)
            {
                writingTimer = ImposterDrawingConstants.WritingTimer[duration];
                drawingTimer = ImposterDrawingConstants.DrawingTimer[duration];
                votingTimer  = ImposterDrawingConstants.VotingTimer[duration];
            }
            List <Prompt> prompts            = new List <Prompt>();
            int           numRounds          = Math.Min(ImposterDrawingConstants.MaxNumRounds[duration], this.Lobby.GetAllUsers().Count);
            int           numDrawingsPerUser = Math.Min(ImposterDrawingConstants.MaxDrawingsPerPlayer[duration], numRounds - 1);

            numRounds = Math.Min(numRounds, (this.Lobby.GetAllUsers().Count - 1) * numDrawingsPerUser / ImposterDrawingConstants.MinNumPlayersPerRound);
            int playersPerPrompt = Math.Min(ImposterDrawingConstants.MaxNumPlayersPerRound, this.Lobby.GetAllUsers().Count - 1);

            playersPerPrompt = Math.Min(playersPerPrompt, this.Lobby.GetAllUsers().Count *numDrawingsPerUser / numRounds + 1);
            Setup            = new Setup_GS(
                lobby: lobby,
                promptsToPopulate: prompts,
                writingTimeDuration: writingTimer,
                drawingTimeDuration: drawingTimer,
                numDrawingsPerUser: numDrawingsPerUser,
                numRounds: numRounds,
                maxPlayersPerPrompt: playersPerPrompt);
            StateChain CreateGamePlayLoop()
            {
                List <State> stateList = new List <State>();

                foreach (Prompt prompt in prompts)
                {
                    stateList.Add(GetImposterLoop(prompt, prompt == prompts.Last()));
                }
                StateChain gamePlayChain = new StateChain(states: stateList);

                gamePlayChain.Transition(this.Exit);
                return(gamePlayChain);
            }

            this.Entrance.Transition(Setup);
            Setup.Transition(CreateGamePlayLoop);

            StateChain GetImposterLoop(Prompt prompt, bool lastRound = false)
            {
                return(new StateChain(
                           stateGenerator: (int counter) =>
                {
                    if (counter == 0)
                    {
                        return GetVotingAndRevealState(prompt, (prompt.UsersToDrawings.Values.Any(val => val == null)), votingTimer);
                    }
                    if (counter == 1)
                    {
                        if (lastRound)
                        {
                            return new ScoreBoardGameState(lobby, "Final Scores");
                        }
                        else
                        {
                            return new ScoreBoardGameState(lobby);
                        }
                    }
                    else
                    {
                        return null;
                    }
                }));
            }
        }
        public MimicGameMode(Lobby lobby, List <ConfigureLobbyRequest.GameModeOptionRequest> gameModeOptions, StandardGameModeOptions standardOptions)
        {
            GameDuration duration = standardOptions.GameDuration;
            int          numStartingDrawingsPerUser = 1;
            int          maxDrawingsBeforeVoteInput = (int)gameModeOptions[(int)GameModeOptions.MaxDrawingsBeforeVote].ValueParsed;
            int          maxVoteDrawings            = 12; // Everybody's drawing should show up, but it gets a little prohibitive past 12 so limit it here.
            TimeSpan?    drawingTimer = null;
            TimeSpan?    votingTimer  = null;

            if (standardOptions.TimerEnabled)
            {
                drawingTimer = MimicConstants.DrawingTimer[duration];
                votingTimer  = MimicConstants.VotingTimer[duration];
            }
            TimeSpan?extendedDrawingTimer = drawingTimer.MultipliedBy(MimicConstants.MimicTimerMultiplier);
            int      numPlayers           = lobby.GetAllUsers().Count();
            int      numRounds            = Math.Min(MimicConstants.MaxRounds[duration], numPlayers);

            this.Lobby = lobby;

            Setup = new Setup_GS(
                lobby: lobby,
                drawings: Drawings,
                numDrawingsPerUser: numStartingDrawingsPerUser,
                drawingTimeDuration: drawingTimer);
            List <UserDrawing> randomizedDrawings = new List <UserDrawing>();

            Setup.AddExitListener(() =>
            {
                randomizedDrawings = this.Drawings
                                     .OrderBy(_ => Rand.Next())
                                     .ToList()
                                     .Take(numRounds) // Limit number of rounds based on game duration.
                                     .ToList();
            });
            StateChain CreateGamePlayLoop()
            {
                bool       timeToShowScores = true;
                StateChain gamePlayLoop     = new StateChain(stateGenerator: (int counter) =>
                {
                    if (randomizedDrawings.Count > 0)
                    {
                        StateChain CreateMultiRoundLoop()
                        {
                            int maxDrawingsBeforeVote = Math.Min(maxDrawingsBeforeVoteInput, randomizedDrawings.Count);
                            if (randomizedDrawings.Count == 0)
                            {
                                throw new Exception("Something went wrong while setting up the game");
                            }
                            List <RoundTracker> roundTrackers = new List <RoundTracker>();
                            return(new StateChain(stateGenerator: (int counter) =>
                            {
                                if (counter < maxDrawingsBeforeVote)
                                {
                                    UserDrawing originalDrawing = randomizedDrawings.First();
                                    randomizedDrawings.RemoveAt(0);

                                    RoundTracker drawingsRoundTracker = new RoundTracker();
                                    roundTrackers.Add(drawingsRoundTracker);
                                    drawingsRoundTracker.originalDrawer = originalDrawing.Owner;
                                    drawingsRoundTracker.UsersToUserDrawings.AddOrUpdate(originalDrawing.Owner, originalDrawing, (User user, UserDrawing drawing) => originalDrawing);

                                    DisplayOriginal_GS displayGS = new DisplayOriginal_GS(
                                        lobby: lobby,
                                        displayTimeDuration: MimicConstants.MemorizeTimerLength,
                                        displayDrawing: originalDrawing);
                                    CreateMimics_GS mimicsGS = new CreateMimics_GS(
                                        lobby: lobby,
                                        roundTracker: drawingsRoundTracker,
                                        drawingTimeDuration: extendedDrawingTimer
                                        );
                                    mimicsGS.AddExitListener(() =>
                                    {
                                        List <User> randomizedUsersToDisplay = new List <User>();
                                        List <User> randomizedKeys = drawingsRoundTracker.UsersToUserDrawings.Keys.OrderBy(_ => Rand.Next()).ToList();
                                        for (int i = 0; i < maxVoteDrawings && i < randomizedKeys.Count; i++)
                                        {
                                            randomizedUsersToDisplay.Add(randomizedKeys[i]);
                                        }
                                        if (!randomizedUsersToDisplay.Contains(drawingsRoundTracker.originalDrawer))
                                        {
                                            randomizedUsersToDisplay.RemoveAt(0);
                                            randomizedUsersToDisplay.Add(drawingsRoundTracker.originalDrawer);
                                        }
                                        randomizedUsersToDisplay = randomizedUsersToDisplay.OrderBy(_ => Rand.Next()).ToList();
                                        drawingsRoundTracker.UsersToDisplay = randomizedUsersToDisplay;
                                    });
                                    return new StateChain(states: new List <State>()
                                    {
                                        displayGS, mimicsGS
                                    }, exit: null);
                                }
                                else if (counter < maxDrawingsBeforeVote * 2)
                                {
                                    return GetVotingAndRevealState(roundTrackers[counter - maxDrawingsBeforeVote], votingTimer);
                                }
                                else
                                {
                                    return null;
                                }
                            }));
                        }
                        return(CreateMultiRoundLoop());
                    }
                    else
                    {
                        if (timeToShowScores)
                        {
                            timeToShowScores = false;
                            return(new ScoreBoardGameState(
                                       lobby: lobby,
                                       title: "Final Scores"));
                        }
                        else
                        {
                            //Ends the chain
                            return(null);
                        }
                    }
                });

                gamePlayLoop.Transition(this.Exit);
                return(gamePlayLoop);
            }

            this.Entrance.Transition(Setup);
            Setup.Transition(CreateGamePlayLoop);
        }