예제 #1
0
        public override void Visit(AttackCreatureAction action)
        {
            Player caller = this.GameManager.GetPlayer(action.Caller);

            // Check caller player is alive and it is its main turn
            if (!caller.IsAlive || GameManager.ActiveCharacter != action.Caller || !GameManager.IsMainTurn)
            {
                throw new CallerCannotPlayException();
            }

            // Check playedCard can attack and has enough EP
            if (caller.GetCardFromId(action.PlayedCardId, Place.OUTER) == null &&
                (caller.GetCardFromId(action.PlayedCardId, Place.INNER) == null && caller.InnerAttackAllowed))
            {
                throw new InvalidCardLocationException();
            }
            CreatureCard card = (CreatureCard)(caller.GetCardFromId(action.PlayedCardId, Place.OUTER) ?? caller.GetCardFromId(action.PlayedCardId, Place.INNER));

            if (card.Energy < card.Attack.Cost)
            {
                throw new NotEnoughEPAvailableException();
            }

            // Looking that the creature is not protected
            foreach (User p in GameManager.UserDict.Values)
            {
                if (p.Player.GetCardFromId(action.Target.CardId, Place.INNER) != null)
                {
                    if (p.Player.IsShieldMaidenProtected)
                    {
                        throw new InvalidCardLocationException();
                    }
                }
            }
        }
예제 #2
0
        public void CantAttackNotExistingCreatureCreature()
        {
            var state  = CreateCreatureAttackReadyState();
            var action = new AttackCreatureAction("1", 0, -1);

            Assert.False(action.CanApply(state));
            action = new AttackCreatureAction("1", 0, 1);
            Assert.False(action.CanApply(state));
        }
예제 #3
0
        public void CantAttackCreatureWithoutCreature()
        {
            var state  = CreateCreatureAttackReadyState();
            var action = new AttackCreatureAction("1", -1, 0);

            Assert.False(action.CanApply(state));
            action = new AttackCreatureAction("1", 1, 0);
            Assert.False(action.CanApply(state));
        }
예제 #4
0
        public void CantAttackCreatueByInactiveCreature()
        {
            var state    = CreateCreatureAttackReadyState();
            var userCard = state.Users[0].TableSet[0];

            userCard.Actions = 0;
            var action = new AttackCreatureAction("1", 0, 0);

            Assert.False(action.CanApply(state));
        }
예제 #5
0
        public void CreatureAttackSpentActions()
        {
            var state    = CreateCreatureAttackReadyState();
            var userCard = state.Users[0].TableSet[0];
            var action   = new AttackCreatureAction("1", 0, 0);

            Assert.True(action.CanApply(state));
            action.Apply(state);
            Assert.True(userCard.Actions < userCard.MaxActions);
        }
예제 #6
0
파일: GameUI.cs 프로젝트: KonH/CardGame
    void OnEnemyTableCardClick(int index)
    {
        var selectTargetState = State as PlayerSelectTargetState;

        if (selectTargetState != null)
        {
            State = new PlayerTurnState();
            var action = new AttackCreatureAction("", selectTargetState.TableIndex, index);
            Game.ApplyAction(action);
        }
    }
예제 #7
0
        public void CreatureLostHealth()
        {
            var state     = CreateCreatureAttackReadyState();
            var userCard  = state.Users[0].TableSet[0];
            var enemyCard = state.Users[1].TableSet[0];

            enemyCard.Health = enemyCard.MaxHealth = userCard.Damage + 1;
            var action = new AttackCreatureAction("1", 0, 0);

            Assert.True(action.CanApply(state));
            action.Apply(state);
            Assert.True(enemyCard.Health == enemyCard.MaxHealth - userCard.Damage);
        }
        public void AttackCreatureTest()
        {
            CreatureGenerator generator      = new CreatureGenerator();
            ICreature         humanCreature  = generator.GenerateCreature(CreatureTypes.Human);
            ICreature         goblinCreature = generator.GenerateCreature(CreatureTypes.Goblin);

            AttackCreatureActionParameter parameter = new AttackCreatureActionParameter()
            {
                AttackingCreature = humanCreature,
                DefendingCreature = goblinCreature,
            };

            AttackCreatureAction attackAction = new AttackCreatureAction();
            IActionResult        result       = attackAction.Execute(parameter);

            Assert.IsTrue(result.Success);

            Assert.IsTrue(humanCreature.Health <= 0 || goblinCreature.Health <= 0);
        }
예제 #9
0
        public override void Visit(AttackCreatureAction action)
        {
            Player       target       = GameManager.GetPlayer(action.Target.Character);
            Player       caller       = GameManager.GetPlayer(action.Caller);
            CreatureCard attackedCard = (CreatureCard)(target.GetCardFromId(action.Target.CardId, Place.INNER) ?? target.GetCardFromId(action.Target.CardId, Place.OUTER));
            CreatureCard playedCard   = (CreatureCard)(caller.GetCardFromId(action.PlayedCardId, Place.INNER) ?? caller.GetCardFromId(action.PlayedCardId, Place.OUTER));

            playedCard.Energy -= playedCard.Attack.Cost;
            AttacksVisitor attackVisitor = new AttacksVisitor(GameManager, caller, action.Target, playedCard);
            int            attackPower   = playedCard.Attack.Visit(attackVisitor);

            attackedCard.Health -= attackPower;

            //handle death
            if (attackedCard.Health <= 0)
            {
                (target.GetCardFromId(attackedCard.Id, Place.INNER) == null ? target.Outer : target.Inner).Remove(attackedCard);

                GameManager.Graveyard.Add(attackedCard);
            }

            foreach (CharacterEnum dest in GameManager.UserDict.Keys.ToList())
            {
                GameManager.UserDict[dest].Write(new ResponseMessage(new AttackCreatureResponse(action.Caller, action.Target.Character, playedCard, attackedCard)));
            }

            foreach (KeyValuePair <CharacterEnum, Response> kvp in attackVisitor.SuccessiveResponse)
            {
                GameManager.UserDict[kvp.Key].Write(new ResponseMessage(kvp.Value));
            }

            if (!target.IsAlive)
            {
                GameManager.KillPlayer(caller.Character, target.Character);
            }
        }
예제 #10
0
        /// <summary>
        /// Main Function: Iterate over all the possible action in the main turn, evaluating them with each possible target
        /// </summary>
        /// <param name="gm"></param>
        /// <returns> Returns the best action possible</returns>
        private KeyValuePair <Double, PlayerAction> Think(GameManager gm)
        {
            GameManager                toUse       = CreateGameManagerAndStuff(gm);
            Player                     me          = toUse.UserDict[CharacterEnum.AMARU].Player;
            LimitedList <Card>         myCards     = me.Hand;
            LimitedList <CreatureCard> myWarZone   = me.Outer;
            LimitedList <CreatureCard> myInnerZone = me.Inner;

            //Initializing all the actions doable
            List <KeyValuePair <Double, PlayerAction> > listPossibleActions = new List <KeyValuePair <double, PlayerAction> >();

            foreach (Card c in myCards)
            {
                try
                {
                    if (c.Cost > me.Mana)
                    {
                        continue;
                    }

                    if (c is CreatureCard && myWarZone.Count < AmaruConstants.OUTER_MAX_SIZE)
                    {
                        PlayACreatureFromHandAction myIntention = new PlayACreatureFromHandAction(CharacterEnum.AMARU, c.Id, Place.OUTER, Player.Outer.Count);
                        Double valueOfGoal = SimulateAndEvaluate(toUse, myIntention);
                        listPossibleActions.Add(new KeyValuePair <Double, PlayerAction>(valueOfGoal, myIntention));
                    }
                    else if (c is CreatureCard && myInnerZone.Count < AmaruConstants.INNER_MAX_SIZE)
                    {
                        PlayACreatureFromHandAction myIntention = new PlayACreatureFromHandAction(CharacterEnum.AMARU, c.Id, Place.INNER, Player.Inner.Count);
                        Double valueOfGoal = SimulateAndEvaluate(toUse, myIntention);
                        listPossibleActions.Add(new KeyValuePair <Double, PlayerAction>(valueOfGoal, myIntention));
                    }
                    else if (c is SpellCard)
                    {
                        //Amaru hasn't spell cards requiring targets
                        PlayASpellFromHandAction myIntention = new PlayASpellFromHandAction(CharacterEnum.AMARU, c.Id, null);
                        Double valueOfGoal = SimulateAndEvaluate(toUse, myIntention);
                        listPossibleActions.Add(new KeyValuePair <Double, PlayerAction>(valueOfGoal, myIntention));
                    }
                }
                catch (Exception e)
                {
                    Log("Eccezione " + e.ToString());
                    Log(c.Name);
                }
            }

            //Data Structure containing all the possible targets for an attack
            List <CardTarget>   allAcceptableTargets      = new List <CardTarget>();
            List <PlayerTarget> allAcceptablePlayerTarget = new List <PlayerTarget>();

            //Data Structure containing all the possible target for a generic ability
            List <Target> abilityTarget = new List <Target>();

            foreach (KeyValuePair <CharacterEnum, User> pair in toUse.UserDict.ToArray())
            {
                Player player = pair.Value.Player;
                foreach (CreatureCard cd in player.Outer)
                {
                    allAcceptableTargets.Add(new CardTarget(pair.Key, cd));
                    abilityTarget.Add(new CardTarget(pair.Key, cd));
                }
                foreach (CreatureCard cd in player.Inner)
                {
                    abilityTarget.Add(new CardTarget(pair.Key, cd));

                    if (!pair.Value.Player.IsShieldMaidenProtected)
                    {
                        allAcceptableTargets.Add(new CardTarget(pair.Key, cd));
                    }
                }
                if (!player.IsImmune)
                {
                    abilityTarget.Add(new PlayerTarget(pair.Key));
                    if (!player.IsShieldUpProtected)
                    {
                        allAcceptablePlayerTarget.Add(new PlayerTarget(pair.Key));
                    }
                }
            }

            //All the possible attacks
            foreach (CreatureCard c in myWarZone)
            {
                //some pruning
                if (c.Energy == 0 || c.Attack is null)
                {
                    continue;
                }

                foreach (CardTarget cTarget in allAcceptableTargets)
                {
                    try
                    {
                        AttackCreatureAction myIntention = new AttackCreatureAction(CharacterEnum.AMARU, c.Id, Property.ATTACK, cTarget);
                        Double valueOfGoal = SimulateAndEvaluate(toUse, myIntention);
                        listPossibleActions.Add(new KeyValuePair <Double, PlayerAction>(valueOfGoal, myIntention));
                    }
                    catch (Exception e)
                    {
                        Log("Eccezione " + e.ToString());
                        Log("ATTACCANTE " + c.Name);
                        Log(cTarget.Card.Name);
                    }
                }
                foreach (PlayerTarget pTarget in allAcceptablePlayerTarget)
                {
                    try
                    {
                        AttackPlayerAction myIntention = new AttackPlayerAction(CharacterEnum.AMARU, c.Id, Property.ATTACK, pTarget);
                        Double             valueOfGoal = SimulateAndEvaluate(toUse, myIntention);
                        listPossibleActions.Add(new KeyValuePair <Double, PlayerAction>(valueOfGoal, myIntention));
                    }
                    catch (Exception e)
                    {
                        Log("Eccezione Player" + e.ToString());
                        Log("ATTACCANTE " + c.Name);
                    }
                }
            }

            //All the possible abilities with their own specific targets combinations
            foreach (CreatureCard cd in myWarZone.Concat(myInnerZone))
            {
                //Some Pruning
                if (cd.Ability is null || cd.Ability.Cost > cd.Energy)
                {
                    continue;
                }

                int numTarget = cd.Ability.NumTarget;

                //Avoid searching for targets if numtarget == 0
                if (numTarget == 0)
                {
                    try
                    {
                        UseAbilityAction myIntention = new UseAbilityAction(CharacterEnum.AMARU, cd.Id, target: null);
                        Double           valueOfGoal = SimulateAndEvaluate(toUse, myIntention);
                        listPossibleActions.Add(new KeyValuePair <Double, PlayerAction>(valueOfGoal, myIntention));
                    }
                    catch (Exception e)
                    {
                        Log("Eccezione Abilità" + e.ToString());
                        Log(cd.Name);
                    }
                    continue;
                }

                //Looking for all the proper targets for the ability
                List <Target> targetDiscerned = new List <Target>();
                foreach (Target t in abilityTarget)
                {
                    targetVisitor.Target = t;
                    if (cd.Ability.Visit(targetVisitor) >= 0)
                    {
                        targetDiscerned.Add(t);
                    }
                }

                //I have to generate all the possible combinations of available targets. Following the rules of the game i have to do it without repetition.
                List <Combinations <Target> > targetsCombined = new List <Combinations <Target> >();
                for (int i = 1; i <= numTarget; i++)
                {
                    targetsCombined.Add(new Combinations <Target>(targetDiscerned, i, GenerateOption.WithoutRepetition));
                }

                //iterate all the possible combinations to evaluate the ability on that particular target
                foreach (List <Target> lt in targetsCombined.SelectMany(x => x))
                {
                    try
                    {
                        UseAbilityAction myIntention = new UseAbilityAction(CharacterEnum.AMARU, cd.Id, lt);
                        double           valueOfGoal = SimulateAndEvaluate(toUse, myIntention);
                        listPossibleActions.Add(new KeyValuePair <Double, PlayerAction>(valueOfGoal, myIntention));
                    }
                    catch (Exception e)
                    {
                        Log("Eccezione Player" + e.ToString());
                        Log(cd.Name);
                    }
                }
            }
            //order the possible actions depending on their value
            listPossibleActions = listPossibleActions.OrderByDescending(x => x.Key).ToList();
            if (listPossibleActions.Count > 0)
            {
//                Log("Best Choice");
//                Log(listPossibleActions[0].ToString());
                return(listPossibleActions[0]);
            }
            else
            {
                return(new KeyValuePair <double, PlayerAction>(Double.MinValue, new EndTurnAction(CharacterEnum.AMARU, -1, false)));
            }
        }