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(); } } } }
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)); }
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)); }
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)); }
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); }
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); } }
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); }
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); } }
/// <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))); } }