예제 #1
0
        public static UpdateRoadModel SetRoadState(MainPage page, RoadCtrl road, RoadState newState, RoadRaceTracking raceTracker)
        {
            RoadState oldState = road.RoadState;

            if (newState == oldState)
            {
                throw new Exception("Why are you updating the road state to be the same state it already is?");
            }

            UpdateRoadModel model = new UpdateRoadModel()
            {
                Page            = page,
                Player          = page.CurrentPlayer,
                PlayerIndex     = page.CurrentPlayer.AllPlayerIndex,
                PlayerName      = page.CurrentPlayer.PlayerName,
                OldState        = page.NewGameState,
                Action          = CatanAction.UpdatedRoadState,
                RoadIndex       = road.Index,
                OldRoadState    = road.RoadState,
                NewRoadState    = newState,
                GameIndex       = page.GameContainer.CurrentGame.Index,
                OldRaceTracking = raceTracker
            };

            road.RoadState = newState;
            switch (newState)
            {
            case RoadState.Unowned:
                if (oldState == RoadState.Ship)
                {
                    model.Player.GameData.Ships.Remove(road);
                }
                else
                {
                    model.Player.GameData.Roads.Remove(road);
                }

                road.Owner  = null;
                road.Number = -1;
                break;

            case RoadState.Road:
                road.Number = model.Player.GameData.Roads.Count;     // undo-able
                model.Player.GameData.Roads.Add(road);
                road.Owner = model.Player;
                break;

            case RoadState.Ship:
                model.Player.GameData.Roads.Remove(road);     // can't be a ship if you aren't a road
                model.Player.GameData.Ships.Add(road);
                break;

            default:
                break;
            }

            string           raceTrackCopy  = JsonSerializer.Serialize <RoadRaceTracking>(raceTracker);
            RoadRaceTracking newRaceTracker = JsonSerializer.Deserialize <RoadRaceTracking>(raceTrackCopy);

            //await AddLogEntry(CurrentPlayer, GameState, CatanAction.UpdatedRoadState, true, logType, road.Number, new LogRoadUpdate(_gameView.CurrentGame.Index, road, oldState, road.RoadState));
            CalculateAndSetLongestRoad(page, newRaceTracker);

            model.NewRaceTracking = newRaceTracker;

            return(model);
        }
예제 #2
0
        /// <summary>
        ///         this looks at the global state of all the roads and makes sure that it
        ///         1. keeps track of who gets to a road count >= 5 first
        ///         2. makes sure that the right player gets the longest road
        ///         3. works when an Undo action happens
        ///         5. works when a road is "broken"
        /// </summary>
        private static void CalculateAndSetLongestRoad(MainPage page, RoadRaceTracking raceTracking)
        {
            var PlayingPlayers = page.MainPageModel.PlayingPlayers;

            //
            //  make the compiler error go away
            // await Task.Delay(0);

            PlayerModel        longestRoadPlayer = null;
            int                maxRoads          = -1;
            List <PlayerModel> tiedPlayers       = new List <PlayerModel>();

            try
            {
                raceTracking.BeginChanges();
                //
                //  first loop over the players and find the set of players that have the longest road
                //
                foreach (PlayerModel p in PlayingPlayers)
                {
                    if (p.GameData.HasLongestRoad)
                    {
                        longestRoadPlayer = p;  // this one currently has the longest road bit -- it may or may not be correct now
                    }
                    // calculate the longest road each player has -- we do this for *every* road/bulding state transition as one person can impact another (e.g. break a road)
                    p.GameData.LongestRoad = page.CalculateLongestRoad(p, p.GameData.RoadsAndShips);

                    //
                    //  remove any tracking for roads greater than their current longest road
                    //  e.g. if they had a road of length 7 and somebody broke it, remove the
                    //  entries that said they had built roads of length 5+
                    for (int i = p.GameData.LongestRoad + 1; i < page.GameContainer.CurrentGame.MaxRoads; i++)
                    {
                        raceTracking.RemovePlayer(p, i);
                    }


                    if (p.GameData.LongestRoad >= 5)
                    {
                        //
                        //  Now we add everybody who has more than 5 rows to the "race" tracking --
                        //  this has a Dictionary<int, List> where the list is ordered by road count
                        raceTracking.AddPlayer(p, p.GameData.LongestRoad); // throws away duplicates
                    }
                    if (p.GameData.LongestRoad > maxRoads)
                    {
                        tiedPlayers.Clear();
                        tiedPlayers.Add(p);
                        maxRoads = p.GameData.LongestRoad;
                    }
                    else if (p.GameData.LongestRoad == maxRoads)
                    {
                        tiedPlayers.Add(p);
                    }
                }

                //
                //  somebody had longest road, but they are not tied for max roads - turn off the bit
                if (longestRoadPlayer != null && !tiedPlayers.Contains(longestRoadPlayer))
                {
                    longestRoadPlayer.GameData.HasLongestRoad = false;
                    longestRoadPlayer = null;
                }

                //
                //  can't have longest road if there aren't enough of them
                if (maxRoads < 5) // "5" is a "magic" Catan number - you need at least 5 roads to get Longest Road
                {
                    if (longestRoadPlayer != null)
                    {
                        longestRoadPlayer.GameData.HasLongestRoad = false;
                    }
                    return;
                }

                //
                //  if only one person has longest road
                if (tiedPlayers.Count == 1)
                {
                    tiedPlayers[0].GameData.HasLongestRoad = true;
                    return;
                }

                //
                //  more than one player has it -- give it to the one that has won the tie
                //  first turn it off for everybody...this is needed because somebody might
                //  be tied, but second in the race. they get the next number of roads and then undo it.
                //  we need to give the longest road back to the first player to get to the road count
                foreach (PlayerModel p in tiedPlayers)
                {
                    p.GameData.HasLongestRoad = false;
                }
                //
                //  now turn it on for the winner!
                raceTracking.GetRaceWinner(maxRoads).GameData.HasLongestRoad = true;
            }
            finally
            {
                //
                //  this pattern makes it so we can change race tracking multiple times but only end up with
                //  one log write
                raceTracking.EndChanges(page.CurrentPlayer, page.GameState, LogType.Normal);
            }
        }