Example #1
0
        public static void Control(PhysicsValues physicsValues, GameDuration elapsedDuration, Entity entity)
        {
            // initialize Behavior stores if necessary
            if (!_activeBehavior.ContainsKey(entity))
            {
                Behavior defaultBehavior = InitializeBehaviors(entity);

                _activeBehavior.Add(entity, defaultBehavior);
            }

            Behavior current = _activeBehavior[entity];

            // update the duration the active Behavior has been running
            current.AddToActiveDuration(elapsedDuration);

            // store all relevant data in BehaviorContext
            var context = new BehaviorContext(physicsValues, elapsedDuration);

            // if the minimum running duration of the current Behavior has passed, look for another applicable Behavior
            if (current.ActiveDuration > current.MinimumDuration())
            {
                foreach (Behavior b in _possibleBehaviors[entity])
                {
                    // we only look for *other* Behaviors
                    if (current.Equals(b))
                    {
                        continue;
                    }

                    // determine the other Behavior's current priority
                    var otherPrio = b.DeterminePriority(context);

                    // only consider other Behavior if it's applicable
                    if (otherPrio == BehaviorPriority.NA)
                    {
                        continue;
                    }

                    // switch to other Behavior depending on relation between priorities
                    var currentPrio = current.DeterminePriority(context);
                    if (otherPrio / (currentPrio + otherPrio) > Rng.NextDouble())
                    {
                        // reset the current Behavior, as it might become active again later
                        current.Reset();

                        // change active Behavior to new one
                        _activeBehavior[entity] = b;
                        current = b;

                        ////Console.WriteLine("Entity {0} switched to behavior {1}", entity, b);
                    }
                }
            }

            // let the active Behavior control the entity
            var position = entity.Get <PositionComponent>();

            current.Behave(context, position);
            entity.Set(position);
        }
Example #2
0
 private void SetDefaults()
 {
     SetBoard();
     StatusOfGame = GameStatus.DuringGame;
     GameTime     = new GameDuration();
     gameStarter  = new GameStarter(this);
 }
Example #3
0
        public OptionsCategory OptionExecuting()
        {
            Timer = new GameDuration();
            Timer.Start();
            PlayingGame();
            Timer.Stop();
            DisplayResult();

            var ProgramExecution = new DecisionOnFurtherCourseOfProgram(this);

            return(ProgramExecution.UserDecidesWhatToDoNext());
        }
        private void SetDefaults()
        {
            Timer = new GameDuration();

            RandomPINnumbers = new int[4];
            var random = new Random();

            for (int i = 0; i < RandomPINnumbers.Length; ++i)
            {
                RandomPINnumbers[i] = random.Next(0, 10);
            }
        }
Example #5
0
        private void UpdateBuildAction(GameDuration elapsedDuration)
        {
            if (_placementCooldown > GameDuration.Zero)
            {
                _placementCooldown -= elapsedDuration;
            }

            var result = World.CastRay(
                PositionData.Placement.Pos + new EntityOffset(0, PhysicsValues.PlayerEyeHeight, 0),
                (EntityOffset)PositionData.Placement.Orientation,
                PhysicsValues.MiningDistance);

            if (result == null)
            {
                HighlightedBlock = null;
                _miningTime      = GameDuration.Zero;
            }
            else
            {
                if (RayCastResult.FaceEquals(HighlightedBlock, result) &&
                    _controller.IsKeyPressed(GameKey.Primary))
                {
                    _miningTime += elapsedDuration;

                    if (_miningTime.Seconds >= PhysicsValues.MiningTime)
                    {
                        _blockUpdates.Add(new BlockUpdateData
                        {
                            Pos      = result.BlockPos,
                            Material = 0,
                        });
                    }
                }
                else
                {
                    _miningTime = GameDuration.Zero;

                    if (_placementCooldown <= GameDuration.Zero && _controller.IsKeyPressed(GameKey.Secondary))
                    {
                        _placementCooldown.Seconds = PhysicsValues.PlacementCooldown;
                        _blockUpdates.Add(new BlockUpdateData
                        {
                            Pos      = result.BlockPos + result.Normal,
                            Material = 1,
                        });
                    }
                }

                HighlightedBlock = result;
            }
        }
Example #6
0
        private void MovePlayer(GameDuration elapsedDuration)
        {
            var velocity = new EntityOffset(0, PositionData.Velocity.Y, 0);

            var moveOffset = PhysicsValues.PlayerMovementSpeed * (EntityOffset) new EntityOrientation(PositionData.Placement.Orientation.Horizontal, 0);

            bool isMovingAlong = false, isMovingSideways = false;

            if (_controller.IsKeyPressed(GameKey.Forwards))
            {
                isMovingAlong = true;
                velocity.X   += moveOffset.X;
                velocity.Z   += moveOffset.Z;
            }

            if (_controller.IsKeyPressed(GameKey.Left))
            {
                isMovingSideways = true;
                velocity.X      += moveOffset.Z;
                velocity.Z      -= moveOffset.X;
            }

            if (_controller.IsKeyPressed(GameKey.Backwards))
            {
                isMovingAlong = true;
                velocity.X   -= moveOffset.X;
                velocity.Z   -= moveOffset.Z;
            }

            if (_controller.IsKeyPressed(GameKey.Right))
            {
                isMovingSideways = true;
                velocity.X      -= moveOffset.Z;
                velocity.Z      += moveOffset.X;
            }

            if (isMovingAlong && isMovingSideways)
            {
                velocity.X *= _inverseSqrt2;
                velocity.Z *= _inverseSqrt2;
            }

            if (!PositionData.IsFalling && _controller.IsKeyPressed(GameKey.Jump))
            {
                velocity.Y += GetJumpingSpeed();
            }

            Movement.MoveEntity(PhysicsValues, World, PositionData, elapsedDuration, velocity);
        }
Example #7
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;
                    }
                }));
            }
        }
Example #8
0
        public FriendQuizGameMode(Lobby lobby, List <ConfigureLobbyRequest.GameModeOptionRequest> gameModeOptions, StandardGameModeOptions standardOptions)
        {
            GameDuration duration = standardOptions.GameDuration;
            double       questionPoolMultiplier = 2.5; // Question pool is X times bigger than number of questions per person.

            int numQuestionsToAnswer = (int)gameModeOptions[(int)GameModeOptionsEnum.NumAnswerQuestions].ValueParsed;
            int numRounds            = Math.Min(lobby.GetAllUsers().Count(), FriendQuizConstants.MaxUserRounds[duration]);
            int numQuestionSetup     = (int)(numQuestionsToAnswer * questionPoolMultiplier / numRounds) + 1; // How many questions each user should contribute.

            TimeSpan?setupTimer     = null;
            TimeSpan?answeringTimer = null;
            TimeSpan?votingTimer    = null;

            if (standardOptions.TimerEnabled)
            {
                setupTimer     = FriendQuizConstants.SetupTimer[duration];
                answeringTimer = FriendQuizConstants.AnsweringTimer[duration];
                votingTimer    = FriendQuizConstants.VotingTimer[duration];
            }

            Dictionary <User, List <Question> > usersToAssignedQuestions = new Dictionary <User, List <Question> >();
            int maxNumAssigned = 1; // Variable for tracking user with most questions.

            StateChain gameStateChain = new StateChain(stateGenerator: (int counter) =>
            {
                if (counter == 0)
                {
                    setupTimer = setupTimer?.Multiply(numQuestionSetup);
                    return(new Setup_GS(
                               lobby: lobby,
                               roundTracker: RoundTracker,
                               numExpectedPerUser: numQuestionSetup,
                               setupDuration: setupTimer));
                }
                else if (counter == 1)
                {
                    List <UserQuestionsHolder> userQuestionsHolders = lobby.GetAllUsers().Select(user => new UserQuestionsHolder(user, numQuestionsToAnswer)).ToList();
                    List <Question> randomizedQuestions             = RoundTracker.Questions.OrderBy(_ => Rand.Next()).ToList();
                    List <IGroup <Question> > assignments           = MemberHelpers <Question> .Assign(userQuestionsHolders.Cast <IConstraints <Question> >().ToList(), randomizedQuestions, lobby.GetAllUsers().Count);

                    var pairings = userQuestionsHolders.Zip(assignments);

                    foreach ((UserQuestionsHolder holder, IGroup <Question> questions) in pairings)
                    {
                        if (questions.Members.Count() > maxNumAssigned)
                        {
                            maxNumAssigned = questions.Members.Count();
                        }
                        // Makes a copy of the questions so that it can handle multiple people answering the same question without them both overriding the same object
                        usersToAssignedQuestions.Add(holder.QuestionedUser, questions.Members.Select(question => new Question(question)
                        {
                            MainUser = holder.QuestionedUser
                        }).ToList());
                    }

                    answeringTimer = answeringTimer?.Multiply(maxNumAssigned);

                    return(new AnswerQuestion_GS(
                               lobby: lobby,
                               usersToAssignedQuestions: usersToAssignedQuestions,
                               answerTimeDuration: answeringTimer));
                }
                else if (counter == 2)
                {
                    votingTimer = votingTimer?.Multiply(maxNumAssigned);

                    List <User> randomizedUsers = usersToAssignedQuestions.Keys
                                                  .OrderBy(_ => Rand.Next())
                                                  .ToList()        // Probably not needed, but just in case.
                                                  .Take(numRounds) // Number of rounds is limited based on game duration.
                                                  .ToList();

                    return(GetUserQueryStateChain(randomizedUsers));
                }
                else
                {
                    return(null);
                }
            });


            this.Entrance.Transition(gameStateChain);
            gameStateChain.Transition(this.Exit);

            StateChain GetUserQueryStateChain(List <User> users)
            {
                List <State> chain = new List <State>();

                foreach (User user in users)
                {
                    List <Question> nonAbstainedQuestions = usersToAssignedQuestions[user].Where(question => !question.Abstained).ToList();
                    if (nonAbstainedQuestions.Count > 0)
                    {
                        chain.Add(new StateChain(stateGenerator: (int counter) =>
                        {
                            if (counter == 0)
                            {
                                return(new SliderQueryAndReveal(
                                           lobby: lobby,
                                           objectsToQuery: nonAbstainedQuestions,
                                           usersToQuery: lobby.GetAllUsers().Where(lobbyUser => lobbyUser != user).ToList(),
                                           queryTime: votingTimer)
                                {
                                    QueryPromptTitle = $"How do you think {user.DisplayName} answered these questions?",
                                    QueryPromptDescription = "The tighter the range of your guess, the more points if you're correct",
                                    QueryViewOverrides = new UnityViewOverrides()
                                    {
                                        Title = $"How do you think {user.DisplayName} answered these questions?",
                                    },
                                    RevealViewOverrides = new UnityViewOverrides()
                                    {
                                        Title = $"This is how {user.DisplayName} answered those questions.",
                                    },
                                    QueryExitListener = CountQueries,
                                });
                            }
                            else if (counter == 1)
                            {
                                if (user == users.Last())
                                {
                                    return(new ScoreBoardGameState(lobby, "Final Scores"));
                                }
                                else
                                {
                                    return(new ScoreBoardGameState(lobby));
                                }
                            }
                            else
                            {
                                return(null);
                            }
                        }));
                    }
                }
                return(new StateChain(chain));
            }
        }
Example #9
0
 public BehaviorContext(PhysicsValues physicsValues, GameDuration elapsedDuration)
 {
     PhysicsValues   = physicsValues;
     ElapsedDuration = elapsedDuration;
 }
        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 #11
0
 /// <summary>
 /// Adds the given duration to this Behavior's ActiveDuration.
 /// </summary>
 /// <param name="duration">The duration to add.</param>
 public void AddToActiveDuration(GameDuration duration)
 {
     _behaviorDuration += duration;
 }
Example #12
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Behavior"/> class.
 /// </summary>
 /// <param name="entity">The entity controlled by this behavior.</param>
 public Behavior(Entity entity)
 {
     _entity           = entity;
     _behaviorDuration = new GameDuration(0);
 }
Example #13
0
 public BehaviorContext(PhysicsValues physicsValues, GameDuration elapsedDuration, IEnumerable <Entity> otherEntities)
 {
     PhysicsValues   = physicsValues;
     ElapsedDuration = elapsedDuration;
     OtherEntities   = otherEntities;
 }
Example #14
0
        public static void MoveEntity(PhysicsValues physicsValues, World world, PositionData positionData, GameDuration elapsedDuration, EntityOffset offset)
        {
            offset.Y -= 0.5 * elapsedDuration.Seconds * physicsValues.Gravity;
            if (MoveY(physicsValues, world, positionData, offset.Y * elapsedDuration.Seconds))
            {
                positionData.IsFalling = false;
            }
            else
            {
                if (!positionData.IsFalling)
                {
                    /* Re-evaluate the fall from the apparent position. */
                    positionData.InternalPos = positionData.Placement.Pos;
                    MoveY(physicsValues, world, positionData, offset.Y * elapsedDuration.Seconds);
                    positionData.IsFalling = true;
                }
            }

            if (positionData.IsFalling)
            {
                offset.Y -= 0.5 * elapsedDuration.Seconds * physicsValues.Gravity;
            }
            else
            {
                if (Math.Abs(offset.Y) > Math.Sqrt(2 * physicsValues.Gravity * physicsValues.TerminalHeight))
                {
                    Respawn(positionData);
                }

                offset.Y = 0;
            }

            if (offset.X != 0 || offset.Z != 0)
            {
                long savedY = positionData.InternalPos.Y;
                if (!positionData.IsFalling && world[(BlockPos)positionData.InternalPos - BlockOffset.UnitY] != 0)
                {
                    // Temporarily move the character up a block so that it can climb up stairs.
                    MoveY(physicsValues, world, positionData, 1);
                }

                EntityPos positionBeforeMovement = positionData.InternalPos;
                double    moveX = offset.X * elapsedDuration.Seconds;
                double    moveZ = offset.Z * elapsedDuration.Seconds;

                if (offset.X > offset.Z)
                {
                    MoveX(physicsValues, world, positionData, moveX);
                    MoveZ(physicsValues, world, positionData, moveZ);
                }
                else
                {
                    MoveZ(physicsValues, world, positionData, moveZ);
                    MoveX(physicsValues, world, positionData, moveX);
                }

                var moveDelta = positionData.InternalPos - positionBeforeMovement;
                moveX -= moveDelta.X;
                moveZ -= moveDelta.Z;

                if (!positionData.IsFalling)
                {
                    // Attempt to move the character back down to the ground in case we didn't climb a stair.
                    MoveY(physicsValues, world, positionData, (savedY - positionData.InternalPos.Y) / (double)(1L << 32));

                    savedY = positionData.InternalPos.Y;

                    // Attempt to move the caracter down an additional block so that it can walk down stairs.
                    if (!MoveY(physicsValues, world, positionData, -((1L << 32) + 1) / (double)(1L << 32)))
                    {
                        positionData.InternalPos.Y = savedY;
                        positionData.IsFalling     = true;
                    }
                }

                // Attempt to continue movement at this new (lower) Y position.
                if (offset.X > offset.Z)
                {
                    if (MoveX(physicsValues, world, positionData, moveX))
                    {
                        offset.X = 0;
                    }
                    if (MoveZ(physicsValues, world, positionData, moveZ))
                    {
                        offset.Z = 0;
                    }
                }
                else
                {
                    if (MoveZ(physicsValues, world, positionData, moveZ))
                    {
                        offset.Z = 0;
                    }
                    if (MoveX(physicsValues, world, positionData, moveX))
                    {
                        offset.X = 0;
                    }
                }
            }

            positionData.Velocity = offset;
            SetPositionFromCollisionPosition(physicsValues, world, positionData);
        }
        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);
        }
 public HardCodedGameFactory(IOptions <GameDuration> options)
 {
     _options = options.Value;
 }
Example #17
0
 /// <summary>
 /// Resets this Behavior.
 /// </summary>
 public void Reset()
 {
     _behaviorDuration = new GameDuration(0);
 }
        public BattleReadyGameMode(Lobby lobby, List <ConfigureLobbyRequest.GameModeOptionRequest> gameModeOptions, StandardGameModeOptions standardOptions)
        {
            GameDuration duration = standardOptions.GameDuration;

            this.Lobby = lobby;
            int numRounds  = BattleReadyConstants.NumRounds[duration];
            int numPlayers = lobby.GetAllUsers().Count();

            TimeSpan?setupDrawingTimer = null;
            TimeSpan?setupPromptTimer  = null;
            TimeSpan?creationTimer     = null;
            TimeSpan?votingTimer       = null;

            int numOfEachPartInHand = (int)gameModeOptions[(int)GameModeOptionsEnum.NumEachPartInHand].ValueParsed;

            int numPromptsPerRound  = Math.Min(numPlayers, BattleReadyConstants.MaxNumSubRounds[duration]);
            int minDrawingsRequired = numOfEachPartInHand * 3; // the amount to make one playerHand to give everyone

            int expectedPromptsPerUser  = (int)Math.Ceiling(1.0 * numPromptsPerRound * numRounds / lobby.GetAllUsers().Count);
            int expectedDrawingsPerUser = Math.Max((minDrawingsRequired / numPlayers + 1) * 2, BattleReadyConstants.NumDrawingsPerPlayer[duration]);

            if (standardOptions.TimerEnabled)
            {
                setupDrawingTimer = BattleReadyConstants.SetupPerDrawingTimer[duration];
                setupPromptTimer  = BattleReadyConstants.SetupPerPromptTimer[duration];
                creationTimer     = BattleReadyConstants.PerCreationTimer[duration];
                votingTimer       = BattleReadyConstants.VotingTimer[duration];
            }

            SetupDrawings_GS setupDrawing = new SetupDrawings_GS(
                lobby: lobby,
                drawings: this.Drawings,
                numExpectedPerUser: expectedDrawingsPerUser,
                setupDurration: setupDrawingTimer * expectedDrawingsPerUser);

            SetupPrompts_GS setupPrompt = new SetupPrompts_GS(
                lobby: lobby,
                prompts: Prompts,
                numExpectedPerUser: expectedPromptsPerUser,
                setupDuration: setupPromptTimer);

            List <Prompt> battlePrompts = new List <Prompt>();
            IReadOnlyList <PeopleUserDrawing> headDrawings = new List <PeopleUserDrawing>();
            IReadOnlyList <PeopleUserDrawing> bodyDrawings = new List <PeopleUserDrawing>();
            IReadOnlyList <PeopleUserDrawing> legsDrawings = new List <PeopleUserDrawing>();

            setupDrawing.AddExitListener(() =>
            {
                // Trim extra prompts/drawings.
                headDrawings = Drawings.ToList().FindAll((drawing) => drawing.Type == BodyPartType.Head);
                bodyDrawings = Drawings.ToList().FindAll((drawing) => drawing.Type == BodyPartType.Body);
                legsDrawings = Drawings.ToList().FindAll((drawing) => drawing.Type == BodyPartType.Legs);
            });
            int numPromptsPerUserPerRound = 0; // Set during below exit listener.

            setupPrompt.AddExitListener(() =>
            {
                battlePrompts      = MemberHelpers <Prompt> .Select_Ordered(Prompts.OrderBy(prompt => prompt.CreationTime).ToList(), numPromptsPerRound * numRounds);
                numRounds          = (battlePrompts.Count - 1) / numPromptsPerRound + 1;
                numPromptsPerRound = (int)Math.Ceiling(1.0 * battlePrompts.Count / numRounds);

                numPromptsPerUserPerRound = Math.Max(1, numPromptsPerRound / 2);
                int maxNumUsersPerPrompt  = Math.Min(12, (int)Math.Ceiling(1.0 * numPlayers * numPromptsPerUserPerRound / numPromptsPerRound));

                foreach (Prompt prompt in battlePrompts)
                {
                    prompt.MaxMemberCount = maxNumUsersPerPrompt;
                }
            });

            List <GameState> creationGameStates     = new List <GameState>();
            List <GameState> votingGameStates       = new List <GameState>();
            List <GameState> voteRevealedGameStates = new List <GameState>();
            List <GameState> scoreboardGameStates   = new List <GameState>();

            int countRounds = 0;

            #region GameState Generators
            GameState CreateContestantCreationGamestate()
            {
                RoundTracker.ResetRoundVariables();
                List <Prompt> prompts = battlePrompts.Take(numPromptsPerRound).ToList();

                battlePrompts.RemoveRange(0, prompts.Count);

                List <IGroup <User> > assignments = MemberHelpers <User> .Assign(
                    prompts.Cast <IConstraints <User> >().ToList(),
                    lobby.GetAllUsers().ToList(),
                    duplicateMembers : (int)Math.Ceiling((1.0 * prompts.Count / numPromptsPerRound) * numPromptsPerUserPerRound));

                var pairings = prompts.Zip(assignments);

                foreach ((Prompt prompt, IGroup <User> users) in pairings)
                {
                    foreach (User user in users.Members)
                    {
                        prompt.UsersToUserHands.TryAdd(user, new Prompt.UserHand
                        {
                            // Users have even probabilities regardless of how many drawings they submitted.
                            HeadChoices = MemberHelpers <PeopleUserDrawing> .Select_DynamicWeightedRandom(headDrawings, numOfEachPartInHand),
                            BodyChoices = MemberHelpers <PeopleUserDrawing> .Select_DynamicWeightedRandom(bodyDrawings, numOfEachPartInHand),
                            LegChoices  = MemberHelpers <PeopleUserDrawing> .Select_DynamicWeightedRandom(legsDrawings, numOfEachPartInHand),
                            Owner       = user
                        });

                        if (!RoundTracker.UsersToAssignedPrompts.ContainsKey(user))
                        {
                            RoundTracker.UsersToAssignedPrompts.Add(user, new List <Prompt>());
                        }
                        RoundTracker.UsersToAssignedPrompts[user].Add(prompt);
                    }
                }

                GameState toReturn = new ContestantCreation_GS(
                    lobby: lobby,
                    roundTracker: RoundTracker,
                    creationDuration: creationTimer);

                toReturn.Transition(CreateVotingGameStates(prompts));
                return(toReturn);
            }

            Func <StateChain> CreateVotingGameStates(List <Prompt> roundPrompts)
            {
                return(() =>
                {
                    StateChain voting = new StateChain(
                        stateGenerator: (int counter) =>
                    {
                        if (counter < roundPrompts.Count)
                        {
                            Prompt roundPrompt = roundPrompts[counter];

                            return GetVotingAndRevealState(roundPrompt, votingTimer);
                        }
                        else
                        {
                            // Stops the chain.
                            return null;
                        }
                    });
                    voting.Transition(CreateScoreGameState(roundPrompts));
                    return voting;
                });
            }

            Func <GameState> CreateScoreGameState(List <Prompt> roundPrompts)
            {
                return(() =>
                {
                    List <Person> winnersPeople = roundPrompts.Select((prompt) => (Person)prompt.UsersToUserHands[prompt.Winner]).ToList();

                    countRounds++;
                    GameState displayPeople = new DisplayPeople_GS(
                        lobby: lobby,
                        title: "Here are your winners",
                        peopleList: winnersPeople,
                        imageTitle: (person) => roundPrompts[winnersPeople.IndexOf(person)].Text,
                        imageHeader: (person) => person.Name
                        );

                    if (battlePrompts.Count <= 0)
                    {
                        GameState finalScoreBoard = new ScoreBoardGameState(
                            lobby: lobby,
                            title: "Final Scores");
                        displayPeople.Transition(finalScoreBoard);
                        finalScoreBoard.Transition(this.Exit);
                    }
                    else
                    {
                        GameState scoreBoard = new ScoreBoardGameState(
                            lobby: lobby);
                        displayPeople.Transition(scoreBoard);
                        scoreBoard.Transition(CreateContestantCreationGamestate);
                    }
                    return displayPeople;
                });
            }

            #endregion

            this.Entrance.Transition(setupDrawing);
            setupDrawing.Transition(setupPrompt);
            setupPrompt.Transition(CreateContestantCreationGamestate);
        }