public void ShouldWin_WhenRandomValueNotGreaterThanWinProbability()
        {
            // arrange
            var options = new AttackOptions();

            var(originalPlayer, actualPlayer) = PlayerFixture.CreateClonedPlayers();
            var(mockCalculator, mockRandom)   = SetupRandomAndCalc(0.7, 0.7);

            var sut = CreateSut(
                player: actualPlayer,
                calculator: mockCalculator,
                random: mockRandom,
                options: options);
            // act
            var result = sut.Handle(new AttackCommand());

            // assert result
            result.Should().BeOfType <OkResult>();
            result.Message.Should().ContainEquivalentOf("win");
            // assert player state change
            actualPlayer.Health.Should()
            .Be(originalPlayer.Health - (int)(options.WinHealthReduceRate * originalPlayer.Health));
            actualPlayer.Coins.Should()
            .Be(originalPlayer.Coins + options.WinBonusCoins);
        }
Example #2
0
        public PwMatchCommand GenerateLobbyCommand()
        {
            PwMatchCommand command;

            if (Challenge == null)
            {
                command = new PwMatchCommand(PwMatchCommand.ModeType.Attack)
                {
                    Options         = AttackOptions.Select(x => x.ToVoteOption(PwMatchCommand.ModeType.Attack)).ToList(),
                    DeadlineSeconds = (int)GetAttackDeadline().Subtract(DateTime.UtcNow).TotalSeconds,
                    AttackerFaction = AttackingFaction.Shortcut
                };
            }
            else
            {
                command = new PwMatchCommand(PwMatchCommand.ModeType.Defend)
                {
                    Options = new List <PwMatchCommand.VoteOption> {
                        Challenge.ToVoteOption(PwMatchCommand.ModeType.Defend)
                    },
                    DeadlineSeconds  = (int)GetAcceptDeadline().Subtract(DateTime.UtcNow).TotalSeconds,
                    AttackerFaction  = AttackingFaction.Shortcut,
                    DefenderFactions = GetDefendingFactions(Challenge).Select(x => x.Shortcut).ToList()
                };
            }
            return(command);
        }
 private BossAttack SelectNextAttack()
 {
     //get current attack options from phase
     options = GetNextOptions(phase);
     //get current attack from options
     return(options.GetNextAttack());
 }
Example #4
0
 /// <summary>
 ///     Invoked from web page
 /// </summary>
 /// <param name="planet"></param>
 public void AddAttackOption(Planet planet)
 {
     if (!AttackOptions.Any(x => x.PlanetID == planet.PlanetID) && Challenge == null && planet.OwnerFactionID != AttackingFaction.FactionID)
     {
         InternalAddOption(planet);
         UpdateLobby();
     }
 }
Example #5
0
 protected override void OnPrimaryAttackEvent(AttackEventType Type, AttackOptions Options)
 {
     /* Just damage surrondings */
     if (AttackEventType.Mid != Type)
     {
         return;
     }
     Owner.AttackSurroundings(Owner.DamageEquation);
 }
Example #6
0
        private void ResetAttackOptions()
        {
            AttackOptions.Clear();
            AttackerSideChangeTime = DateTime.UtcNow;
            Challenge     = null;
            ChallengeTime = null;

            using (var db = new ZkDataContext())
            {
                var gal      = db.Galaxies.First(x => x.IsDefault);
                var cnt      = 6;
                var attacker = db.Factions.Single(x => x.FactionID == AttackingFaction.FactionID);
                var planets  =
                    gal.Planets.Where(x => x.OwnerFactionID != AttackingFaction.FactionID)
                    .OrderByDescending(x => x.PlanetFactions.Where(y => y.FactionID == AttackingFaction.FactionID).Sum(y => y.Dropships))
                    .ThenByDescending(x => x.PlanetFactions.Where(y => y.FactionID == AttackingFaction.FactionID).Sum(y => y.Influence))
                    .ToList();
                // list of planets by attacker's influence

                foreach (var planet in planets)
                {
                    if (planet.CanMatchMakerPlay(attacker))
                    {
                        // pick only those where you can actually attack atm
                        InternalAddOption(planet);
                        cnt--;
                    }
                    if (cnt == 0)
                    {
                        break;
                    }
                }

                if (!AttackOptions.Any(y => y.TeamSize == 2))
                {
                    var planet = planets.FirstOrDefault(x => (x.TeamSize == 2) && x.CanMatchMakerPlay(attacker));
                    if (planet != null)
                    {
                        InternalAddOption(planet);
                    }
                }

                // make sure some option always exists
                if (!AttackOptions.Any())
                {
                    foreach (var planet in planets.Take(6))
                    {
                        InternalAddOption(planet);
                    }
                }
            }

            UpdateLobby();

            server.GhostChanSay(AttackingFaction.Shortcut, "It's your turn! Select a planet to attack");
        }
Example #7
0
 public AttackCommandHandler(
     IPlayerStore playerStore,
     IRandom random,
     IFormulaCalculator calculator,
     IOptions <AttackOptions> options)
     : base(playerStore, random)
 {
     _calculator = calculator;
     _options    = options.Value;
 }
Example #8
0
    public Func <GameObject, GameObject, bool> GetAttack(string attack)
    {
        AttackOptions attackType = GetAttackOption(attack);

        Debug.Log("Attack Type: " + attackType);
        if (ContainAttack(attackType))
        {
            return(AttackDic[attackType]);
        }
        return(null);
    }
Example #9
0
        private async Task StartChallenge(AttackOption attackOption)
        {
            Challenge     = attackOption;
            ChallengeTime = DateTime.UtcNow;
            AttackOptions.Clear();
            await UpdateLobby();

            await server.Broadcast(attackOption.Attackers, new PwAttackingPlanet()
            {
                PlanetID = attackOption.PlanetID
            });
        }
Example #10
0
 private void InternalAddOption(Planet planet)
 {
     AttackOptions.Add(new AttackOption
     {
         PlanetID        = planet.PlanetID,
         Map             = planet.Resource.InternalName,
         OwnerFactionID  = planet.OwnerFactionID,
         Name            = planet.Name,
         TeamSize        = planet.TeamSize,
         PlanetImage     = planet.Resource?.MapPlanetWarsIcon,
         IconSize        = planet.Resource?.PlanetWarsIconSize ?? 0,
         StructureImages = planet.PlanetStructures.Select(x => x.IsActive ? x.StructureType.MapIcon : x.StructureType.DisabledMapIcon).ToList()
     });
 }
Example #11
0
 public BotCommandHandler(
     IPlayerStore playerStore,
     IRandom random,
     IFormulaCalculator calculator,
     IOptions <AttackOptions> attackOptions,
     IOptions <PurchaseWeaponOptions> purchaseWeaponOptions,
     IOptions <PurchaseHealingOptions> purchaseHealingOptions
     ) : base(playerStore, random)
 {
     _calculator    = calculator;
     _attackOptions = attackOptions.Value;
     _purchaseWeaponHandlerOptions  = purchaseWeaponOptions.Value;
     _purchaseHealingHandlerOptions = purchaseHealingOptions.Value;
 }
Example #12
0
        private async Task JoinPlanetAttack(int targetPlanetId, string userName)
        {
            var attackOption = AttackOptions.Find(x => x.PlanetID == targetPlanetId);

            if (attackOption != null)
            {
                var conus = server.ConnectedUsers.Get(userName);
                var user  = conus?.User;
                if (user != null)
                {
                    using (var db = new ZkDataContext())
                    {
                        var account = db.Accounts.Find(user.AccountID);
                        if ((account != null) && (account.FactionID == AttackingFaction.FactionID) && account.CanPlayerPlanetWars())
                        {
                            // remove existing user from other options
                            foreach (var aop in AttackOptions.Where(x => x.PlanetID != targetPlanetId))
                            {
                                aop.Attackers.RemoveAll(x => x == userName);
                            }

                            // add user to this option
                            if (attackOption.Attackers.Count < attackOption.TeamSize && !attackOption.Attackers.Contains(userName))
                            {
                                attackOption.Attackers.Add(user.Name);
                                await server.GhostChanSay(user.Faction, $"{userName} joins attack on {attackOption.Name}");

                                await conus.SendCommand(new PwJoinPlanetSuccess()
                                {
                                    PlanetID = targetPlanetId
                                });

                                if (attackOption.Attackers.Count == attackOption.TeamSize)
                                {
                                    await StartChallenge(attackOption);
                                }
                                else
                                {
                                    await UpdateLobby();
                                }
                            }
                        }
                    }
                }
            }
        }
Example #13
0
 protected override void OnSecondaryAttackEvent(AttackEventType Type, AttackOptions Options)
 {
     /* Only do damage at the end of the animation. */
     if (Type != AttackEventType.End)
     {
         return;
     }
     /* Do damage to everything in the surroundings. */
     Owner.AttackSurroundings(Owner.DamageEquation * 1.25f * Options.DamageModifier, delegate(IEntity Mob)
     {
         /* 1 in 5 chance to knock for 3 seconds. */
         if (Utils.Rng.Next(0, 5) == 1 && Options.Charge > .5f)
         {
             Mob.KnockForSeconds(3);
         }
     });
 }
        private static AttackCommandHandler CreateSut(
            Player player                 = null,
            IPlayerStore playerStore      = null,
            IRandom random                = null,
            IFormulaCalculator calculator = null,
            AttackOptions options         = null)
        {
            player      = player ?? PlayerFixture.CreateDefaultPlayer();
            playerStore = playerStore ?? Substitute.For <IPlayerStore>();
            playerStore.GetPlayer().Returns(player);
            random     = random ?? Substitute.For <IRandom>();
            calculator = calculator ?? Substitute.For <IFormulaCalculator>();

            var optionsSnapshot = Substitute.For <IOptionsSnapshot <AttackOptions> >();

            optionsSnapshot.Value.Returns(options ?? new AttackOptions());

            return(new AttackCommandHandler(playerStore, random, calculator, optionsSnapshot));
        }
        public void ShouldCallFormulaCalculator_WithFormulaFromOptions()
        {
            // arrange
            var(_, actualPlayer) = PlayerFixture.CreateClonedPlayers();
            var mockCalculator = Substitute.For <IFormulaCalculator>();
            var options        = new AttackOptions {
                WinProbFormula = "formula"
            };

            var sut = CreateSut(
                player: actualPlayer,
                calculator: mockCalculator,
                options: options);

            // act
            sut.Handle(new AttackCommand());
            // assert
            mockCalculator.Received().Calculate("formula", Arg.Any <FormulaContext>());
        }
Example #16
0
        public PwMatchCommand GenerateLobbyCommand()
        {
            PwMatchCommand command = null;

            try
            {
                if (GlobalConst.PlanetWarsMode != PlanetWarsModes.Running)
                {
                    return(new PwMatchCommand(PwMatchCommand.ModeType.Clear));
                }

                if (Challenge == null)
                {
                    command = new PwMatchCommand(PwMatchCommand.ModeType.Attack)
                    {
                        Options         = AttackOptions.Select(x => x.ToVoteOption(PwMatchCommand.ModeType.Attack)).ToList(),
                        Deadline        = GetAttackDeadline(),
                        DeadlineSeconds = (int)GetAttackDeadline().Subtract(DateTime.UtcNow).TotalSeconds,
                        AttackerFaction = AttackingFaction.Shortcut
                    }
                }
                ;
                else
                {
                    command = new PwMatchCommand(PwMatchCommand.ModeType.Defend)
                    {
                        Options = new List <PwMatchCommand.VoteOption> {
                            Challenge.ToVoteOption(PwMatchCommand.ModeType.Defend)
                        },
                        Deadline         = GetAcceptDeadline(),
                        DeadlineSeconds  = (int)GetAcceptDeadline().Subtract(DateTime.UtcNow).TotalSeconds,
                        AttackerFaction  = AttackingFaction.Shortcut,
                        DefenderFactions = GetDefendingFactions(Challenge).Select(x => x.Shortcut).ToList()
                    }
                };
            }
            catch (Exception ex)
            {
                Trace.TraceError("PlanetWars {0}: {1}", nameof(GenerateLobbyCommand), ex);
            }
            return(command);
        }
Example #17
0
        /// <summary>
        ///     Invoked from web page
        /// </summary>
        /// <param name="planet"></param>
        public void AddAttackOption(Planet planet)
        {
            try
            {
                if (GlobalConst.PlanetWarsMode != PlanetWarsModes.Running)
                {
                    return;
                }

                if (!AttackOptions.Any(x => x.PlanetID == planet.PlanetID) && (Challenge == null) &&
                    (planet.OwnerFactionID != AttackingFaction.FactionID))
                {
                    InternalAddOption(planet);
                    UpdateLobby();
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError("PlanetWars error adding option {0}: {1}", planet, ex);
            }
        }
Example #18
0
        List <Faction> GetDefendingFactions(AttackOption target)
        {
            if (target.OwnerFactionID != null)
            {
                return new List <Faction> {
                           factions.Find(x => x.FactionID == target.OwnerFactionID)
                }
            }
            ;
            return(factions.Where(x => x != AttackingFaction).ToList());
        }

        void JoinPlanetAttack(int targetPlanetId, string userName)
        {
            AttackOption attackOption = AttackOptions.Find(x => x.PlanetID == targetPlanetId);

            if (attackOption != null)
            {
                User user;

                if (tas.ExistingUsers.TryGetValue(userName, out user))
                {
                    var     db      = new ZkDataContext();
                    Account account = Account.AccountByLobbyID(db, user.LobbyID);
                    if (account != null && account.FactionID == AttackingFaction.FactionID && account.CanPlayerPlanetWars())
                    {
                        // remove existing user from other options
                        foreach (AttackOption aop in AttackOptions)
                        {
                            aop.Attackers.RemoveAll(x => x == userName);
                        }

                        // add user to this option
                        if (attackOption.Attackers.Count < attackOption.TeamSize)
                        {
                            attackOption.Attackers.Add(user.Name);
                            tas.Say(TasClient.SayPlace.Channel, user.Faction, string.Format("{0} joins attack on {1}", userName, attackOption.Name), true);

                            if (attackOption.Attackers.Count == attackOption.TeamSize)
                            {
                                StartChallenge(attackOption);
                            }
                            else
                            {
                                UpdateLobby();
                            }
                        }
                    }
                }
            }
        }

        void JoinPlanetDefense(int targetPlanetID, string userName)
        {
            if (Challenge != null && Challenge.PlanetID == targetPlanetID && Challenge.Defenders.Count < Challenge.TeamSize)
            {
                User user;
                if (tas.ExistingUsers.TryGetValue(userName, out user))
                {
                    var     db      = new ZkDataContext();
                    Account account = Account.AccountByLobbyID(db, user.LobbyID);
                    if (account != null && GetDefendingFactions(Challenge).Any(y => y.FactionID == account.FactionID) && account.CanPlayerPlanetWars())
                    {
                        if (!Challenge.Defenders.Any(y => y == user.Name))
                        {
                            Challenge.Defenders.Add(user.Name);
                            tas.Say(TasClient.SayPlace.Channel, user.Faction, string.Format("{0} joins defense of {1}", userName, Challenge.Name), true);

                            if (Challenge.Defenders.Count == Challenge.TeamSize)
                            {
                                AcceptChallenge();
                            }
                            else
                            {
                                UpdateLobby();
                            }
                        }
                    }
                }
            }
        }

        void RecordPlanetwarsLoss(AttackOption option)
        {
            if (option.OwnerFactionID != null)
            {
                if (option.OwnerFactionID == missedDefenseFactionID)
                {
                    missedDefenseCount++;
                }
                else
                {
                    missedDefenseCount     = 0;
                    missedDefenseFactionID = option.OwnerFactionID.Value;
                }
            }


            var message = string.Format("{0} won because nobody tried to defend", AttackingFaction.Name);

            foreach (var fac in factions)
            {
                tas.Say(TasClient.SayPlace.Channel, fac.Shortcut, message, true);
            }


            var text = new StringBuilder();

            try
            {
                var           db        = new ZkDataContext();
                List <string> playerIds = option.Attackers.Select(x => x).Union(option.Defenders.Select(x => x)).ToList();


                PlanetWarsTurnHandler.EndTurn(option.Map, null, db, 0, db.Accounts.Where(x => playerIds.Contains(x.Name) && x.Faction != null).ToList(), text, null, db.Accounts.Where(x => option.Attackers.Contains(x.Name) && x.Faction != null).ToList());
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());
                text.Append(ex);
            }
        }

        void ResetAttackOptions()
        {
            AttackOptions.Clear();
            AttackerSideChangeTime = DateTime.UtcNow;
            Challenge     = null;
            ChallengeTime = null;

            using (var db = new ZkDataContext())
            {
                var gal      = db.Galaxies.First(x => x.IsDefault);
                int cnt      = 2;
                var attacker = db.Factions.Single(x => x.FactionID == AttackingFaction.FactionID);
                var planets  = gal.Planets.Where(x => x.OwnerFactionID != AttackingFaction.FactionID).OrderByDescending(x => x.PlanetFactions.Where(y => y.FactionID == AttackingFaction.FactionID).Sum(y => y.Dropships)).ThenByDescending(x => x.PlanetFactions.Where(y => y.FactionID == AttackingFaction.FactionID).Sum(y => y.Influence)).ToList();
                // list of planets by attacker's influence

                foreach (var planet in planets)
                {
                    if (planet.CanMatchMakerPlay(attacker))
                    {
                        // pick only those where you can actually attack atm
                        InternalAddOption(planet);
                        cnt--;
                    }
                    if (cnt == 0)
                    {
                        break;
                    }
                }

                if (!AttackOptions.Any(y => y.TeamSize == 2))
                {
                    var planet = planets.FirstOrDefault(x => x.TeamSize == 2 && x.CanMatchMakerPlay(attacker));
                    if (planet != null)
                    {
                        InternalAddOption(planet);
                    }
                }
            }

            UpdateLobby();

            tas.Say(TasClient.SayPlace.Channel, AttackingFaction.Shortcut, "It's your turn! Select a planet to attack", true);
        }

        void InternalAddOption(Planet planet)
        {
            AttackOptions.Add(new AttackOption
            {
                PlanetID       = planet.PlanetID,
                Map            = planet.Resource.InternalName,
                OwnerFactionID = planet.OwnerFactionID,
                Name           = planet.Name,
                TeamSize       = planet.TeamSize,
            });
        }

        void SaveStateToDb()
        {
            var    db  = new ZkDataContext();
            Galaxy gal = db.Galaxies.First(x => x.IsDefault);

            gal.MatchMakerState = JsonConvert.SerializeObject((MatchMakerState)this);

            gal.AttackerSideCounter    = AttackerSideCounter;
            gal.AttackerSideChangeTime = AttackerSideChangeTime;
            db.SubmitAndMergeChanges();
        }

        void StartChallenge(AttackOption attackOption)
        {
            Challenge     = attackOption;
            ChallengeTime = DateTime.UtcNow;
            AttackOptions.Clear();
            UpdateLobby();
        }

        void TasOnChannelUserAdded(object sender, TasEventArgs args)
        {
            string  chan     = args.ServerParams[0];
            string  userName = args.ServerParams[1];
            Faction faction  = factions.FirstOrDefault(x => x.Shortcut == chan);

            if (faction != null)
            {
                var db  = new ZkDataContext();
                var acc = Account.AccountByName(db, userName);
                if (acc != null && acc.CanPlayerPlanetWars())
                {
                    UpdateLobby(userName);
                }
            }
        }

        /// <summary>
        ///     Intercept channel messages for attacking/defending
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        void TasOnPreviewSaid(object sender, CancelEventArgs <TasSayEventArgs> args)
        {
            if (args.Data.Text.StartsWith("!") && (args.Data.Place == TasSayEventArgs.Places.Channel || args.Data.Place == TasSayEventArgs.Places.Normal) &&
                args.Data.Origin == TasSayEventArgs.Origins.Player && args.Data.UserName != GlobalConst.NightwatchName)
            {
                int targetPlanetId;
                if (int.TryParse(args.Data.Text.Substring(1), out targetPlanetId))
                {
                    JoinPlanet(args.Data.UserName, targetPlanetId);
                }
            }
        }

        /// <summary>
        ///     Remove/reduce poll count due to lobby quits
        /// </summary>
        void TasOnUserRemoved(object sender, TasEventArgs args)
        {
            if (Challenge == null)
            {
                if (AttackOptions.Count > 0)
                {
                    string userName   = args.ServerParams[0];
                    int    sumRemoved = 0;
                    foreach (AttackOption aop in AttackOptions)
                    {
                        sumRemoved += aop.Attackers.RemoveAll(x => x == userName);
                    }
                    if (sumRemoved > 0)
                    {
                        UpdateLobby();
                    }
                }
            }
            else
            {
                string userName = args.ServerParams[0];
                if (Challenge.Defenders.RemoveAll(x => x == userName) > 0)
                {
                    UpdateLobby();
                }
            }
        }

        void TimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
        {
            try
            {
                if (Challenge == null)
                {
                    // attack timer
                    if (DateTime.UtcNow > GetAttackDeadline())
                    {
                        AttackerSideCounter++;
                        ResetAttackOptions();
                    }
                }
                else
                {
                    // accept timer
                    if (DateTime.UtcNow > GetAcceptDeadline())
                    {
                        if (Challenge.Defenders.Count >= Challenge.Attackers.Count - 1 && Challenge.Defenders.Count > 0)
                        {
                            AcceptChallenge();
                        }
                        else
                        {
                            RecordPlanetwarsLoss(Challenge);
                            AttackerSideCounter++;
                            ResetAttackOptions();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());
            }
        }
Example #19
0
        private async Task CreateAndPlayGameToEnd(GameCreationOptions gameCreationOptions)
        {
            var gameHistory = new Dictionary <int, Game>();

            var defaultPlayClient = await ApiClient.GetAuthenticatedClientDefaultUser <PlayClient>();

            var gameClients = new List <Tuple <GameClient, PlayClient, string> >();

            for (int i = 0; i < gameCreationOptions.NumberOfTeams * gameCreationOptions.NumberOfPlayersPerTeam - 1; ++i)
            {
                var gameClient = await ApiClient.GetAuthenticatedClient <GameClient>(i + 1);

                var playClient = await ApiClient.GetAuthenticatedClient <PlayClient>(i + 1);

                gameClients.Add(Tuple.Create(gameClient, playClient, "TestUser" + (i + 1)));
            }

            this.Log("Create game");
            var gameSummary = await this.clientDefault.PostAsync(gameCreationOptions);

            foreach (var gameClient in gameClients)
            {
                this.Log("Find game");
                await this.EnsureGameDoesShowInOpenList(gameClient.Item1, gameSummary.Id);

                this.Log("Join game for player");
                await gameClient.Item1.PostJoinAsync(gameSummary.Id, null);
            }

            this.Log("Make sure game has disappeared from open list");
            await this.EnsureGameDoesNotShowInOpenList(gameClients.First().Item1, gameSummary.Id);

            this.Log("Make sure game is now listed as active");
            IEnumerable <GameSummary> myGames = await clientDefault.GetMyAsync();

            var gameSummary2 = myGames.FirstOrDefault(x => x.Id == gameSummary.Id);

            Assert.IsNotNull(gameSummary2);
            Assert.AreEqual(GameState.Active, gameSummary2.State);
            Assert.IsTrue(gameSummary2.Teams.Any(), "No teams in summary");
            Assert.IsTrue(gameSummary2.Teams.SelectMany(x => x.Players).Any(), "No players in teams");
            Assert.IsNotNull(gameSummary2.CurrentPlayer);

            this.Log("Get game for default player");
            var gameDefault = await this.clientDefault.GetAsync(gameSummary.Id);

            Assert.IsNotNull(gameDefault.Teams);
            Assert.IsTrue(gameDefault.Teams.Any());
            Assert.IsNotNull(gameDefault.Map);
            Assert.AreEqual(PlayState.PlaceUnits, gameDefault.PlayState);

            this.Log("Get map template");
            var mapTemplateClient = await ApiClient.GetClient <MapClient>();

            var mapTemplate = await mapTemplateClient.GetMapTemplateAsync(gameDefault.MapTemplate);

            while (gameDefault.State == GameState.Active)
            {
                bool placeOnlyTurn = false;

                this.Log("Begin of turn");

                var currentPlayerId = gameDefault.CurrentPlayer.Id;
                var currentTeamId   = gameDefault.CurrentPlayer.TeamId;

                this.Log("\tCurrent player:{0} - {1}", currentPlayerId, currentTeamId);

                PlayClient playClient;
                GameClient gameClient;
                var        player = gameClients.FirstOrDefault(x => x.Item3 == gameDefault.CurrentPlayer.Name);
                if (player == null)
                {
                    gameClient = this.clientDefault;
                    playClient = defaultPlayClient;
                }
                else
                {
                    gameClient = player.Item1;
                    playClient = player.Item2;
                }

                var gameState = await gameClient.GetAsync(gameDefault.Id);

                {
                    // Place units
                    this.Log("Placing units - player {0} - {1}", currentPlayerId, gameDefault.UnitsToPlace);
                    var     ownCountries = gameState.Map.Countries.Where(x => x.TeamId == currentTeamId);
                    Country ownCountry;
                    if (ownCountries.Count() == 1)
                    {
                        ownCountry = ownCountries.First();
                    }
                    else
                    {
                        ownCountry = ownCountries.FirstOrDefault(x =>
                                                                 gameDefault.Map.Countries.Any(
                                                                     y => y.TeamId != currentTeamId &&
                                                                     mapTemplate
                                                                     .Connections
                                                                     .Any(c => c.Origin == x.Identifier && c.Destination == y.Identifier)));
                    }

                    if (ownCountry == null)
                    {
                        Assert.Fail("No connected, enemy country found");
                    }

                    var placeOptions = new[] {
                        new PlaceUnitsOptions
                        {
                            CountryIdentifier = ownCountry.Identifier,
                            NumberOfUnits     = gameState.UnitsToPlace
                        }
                    };

                    var placeResponse = await playClient.PostPlaceAsync(gameDefault.Id, placeOptions);

                    this.ApplyMapUpdates(gameState.Map, placeResponse.CountryUpdates);

                    if (placeResponse.State != GameState.Active)
                    {
                        break;
                    }

                    if (placeResponse.CurrentPlayer.Id != currentPlayerId)
                    {
                        this.Log("Place only turn");
                        placeOnlyTurn = true;
                    }
                }

                // Attack
                if (gameState.TurnCounter > 3)
                {
                    bool breakExecution = false;

                    for (int a = 0; a < gameState.Options.AttacksPerTurn; ++a)
                    {
                        var ownCountries = gameState.Map.Countries.Where(x => x.TeamId == currentTeamId);
                        var ownCountry   = ownCountries.FirstOrDefault(x =>
                                                                       x.Units > gameState.Options.MinUnitsPerCountry &&
                                                                       gameState.Map.Countries.Any(y => y.TeamId != currentTeamId &&
                                                                                                   mapTemplate
                                                                                                   .Connections
                                                                                                   .Any(c => c.Origin == x.Identifier && c.Destination == y.Identifier)));
                        if (ownCountry == null)
                        {
                            this.Log("Cannot find own country");

                            // Abort attack
                            break;
                        }

                        // Find enemy country
                        var enemyCountries = gameState.Map.Countries.Where(x => x.TeamId != currentTeamId);
                        var enemyCountry   = enemyCountries.FirstOrDefault(x => mapTemplate
                                                                           .Connections.Any(c =>
                                                                                            c.Origin == ownCountry.Identifier &&
                                                                                            c.Destination == x.Identifier));
                        if (enemyCountry == null)
                        {
                            Assert.Fail("Cannot find enemy country connected to selected own country");
                        }

                        var numberOfUnits = ownCountry.Units - gameState.Options.MinUnitsPerCountry;
                        if (playClient != defaultPlayClient)
                        {
                            numberOfUnits = 1;
                        }

                        var attackOptions = new AttackOptions()
                        {
                            OriginCountryIdentifier      = ownCountry.Identifier,
                            DestinationCountryIdentifier = enemyCountry.Identifier,
                            NumberOfUnits = numberOfUnits
                        };

                        this.Log("Attack from {0} to {1} with {2} units",
                                 attackOptions.OriginCountryIdentifier,
                                 attackOptions.DestinationCountryIdentifier,
                                 attackOptions.NumberOfUnits);

                        var attackResult = await playClient.PostAttackAsync(gameState.Id, attackOptions);

                        if (attackResult.ActionResult == Result.Successful)
                        {
                            this.Log("\tAttack successful, units left {0}", attackResult.CountryUpdates.First(x => x.Identifier == attackOptions.DestinationCountryIdentifier).Units);
                        }
                        else
                        {
                            this.Log("\tAttack failed");
                        }

                        this.ApplyMapUpdates(gameState.Map, attackResult.CountryUpdates);

                        if (attackResult.State != GameState.Active)
                        {
                            breakExecution = true;
                            break;
                        }
                    }

                    if (breakExecution)
                    {
                        break;
                    }
                }

                // Move
                {
                }

                if (!placeOnlyTurn)
                {
                    // Record turn
                    gameHistory.Add(gameState.TurnCounter, await gameClient.GetAsync(gameSummary.Id));

                    // End turn
                    this.Log("End turn");
                    await playClient.PostEndTurnAsync(gameState.Id);
                }

                gameDefault = await this.clientDefault.GetAsync(gameSummary.Id);

                if (gameDefault.State == GameState.Ended)
                {
                    break;
                }

                Assert.IsTrue(
                    gameDefault.CurrentPlayer.Id != currentPlayerId,
                    "Current player did not switch");

                if (gameDefault.TurnCounter > 50)
                {
                    foreach (var p in gameDefault.Teams.SelectMany(x => x.Players))
                    {
                        this.Log("Player {0} has {1} countries",
                                 p.Name,
                                 gameDefault.Map.Countries.Count(x => x.PlayerId == p.Id));
                    }

                    Assert.Inconclusive("Turn counter to high, possibly no end?");
                }
            }

            this.Log("Game ended");

            // Refresh
            gameDefault = await this.clientDefault.GetAsync(gameSummary.Id);

            Assert.IsTrue(
                gameDefault.Teams.SelectMany(x => x.Players)
                .Any(x => x.Outcome == PlayerOutcome.Won &&
                     x.State == PlayerState.InActive),
                "No winner after game has ended");
            Assert.IsTrue(
                gameDefault.Teams.SelectMany(x => x.Players)
                .Any(x => x.Outcome == PlayerOutcome.Defeated &&
                     x.State == PlayerState.InActive),
                "No loser after game has ended");

            // Output debug information
            foreach (var player in gameDefault.Teams.SelectMany(x => x.Players))
            {
                this.Log("Player {0} result {1}", player.Name, player.Outcome);
            }

            this.Log("Verifying history");

            var historyClient = await ApiClient.GetAuthenticatedClientDefaultUser <HistoryClient>();

            foreach (var gameHistoryEntry in gameHistory)
            {
                this.Log("Get history for turn {0}", gameHistoryEntry.Key);

                var historyTurn = await historyClient.GetTurnAsync(gameHistoryEntry.Value.Id, gameHistoryEntry.Value.TurnCounter);

                // Verify players
                foreach (var player in gameHistoryEntry.Value.Teams.SelectMany(x => x.Players))
                {
                    var historyPlayer = historyTurn.Game.Teams.SelectMany(x => x.Players).FirstOrDefault(x => x.Id == player.Id);
                    Assert.IsNotNull(historyPlayer);

                    Assert.AreEqual(player.State, historyPlayer.State);
                    Assert.AreEqual(player.Outcome, historyPlayer.Outcome);
                }

                // Verify map
                foreach (var country in gameHistoryEntry.Value.Map.Countries)
                {
                    var historyCountry = historyTurn.Game.Map.Countries.FirstOrDefault(x => x.Identifier == country.Identifier);
                    Assert.IsNotNull(historyCountry);

                    Assert.AreEqual(country.Units, historyCountry.Units);
                    Assert.AreEqual(country.PlayerId, historyCountry.PlayerId);
                    Assert.AreEqual(country.TeamId, historyCountry.TeamId);
                }
            }
        }
Example #20
0
 public bool ContainAttack(AttackOptions attack)
 {
     return(AttackDic.ContainsKey(attack));
 }
Example #21
0
        public IActionResult PostAttack(long gameId, [FromBody] AttackOptions options)
        {
            var gameActionResult = this.playService.Attack(gameId, options.OriginCountryIdentifier, options.DestinationCountryIdentifier, options.NumberOfUnits);

            return(this.Ok(gameActionResult));
        }