/// <summary> /// Called when the AI can chain (activate) a card. /// </summary> /// <param name="cards">List of activable cards.</param> /// <param name="descs">List of effect descriptions.</param> /// <param name="forced">You can't return -1 if this param is true.</param> /// <returns>Index of the activated card or -1.</returns> public int OnSelectChain(IList <ClientCard> cards, IList <int> descs, bool forced) { foreach (CardExecutor exec in Executor.Executors) { for (int i = 0; i < cards.Count; ++i) { ClientCard card = cards[i]; if (ShouldExecute(exec, card, ExecutorType.Activate, descs[i])) { if (last_card != null && card.Equals(last_card)) { last_ct++; if (last_ct > 6) { continue; } } else { last_ct = 1; last_card = card; } _dialogs.SendChaining(card.Name); return(i); } } } // If we're forced to chain, we chain the first card. However don't do anything. return(forced ? 0 : -1); }
/// <summary> /// Called when the AI has to do something during the main phase. /// </summary> /// <param name="main">A lot of informations about the available actions.</param> /// <returns>A new MainPhaseAction containing the action to do.</returns> public MainPhaseAction OnSelectIdleCmd(MainPhase main) { Executor.SetMain(main); foreach (CardExecutor exec in Executor.Executors) { if (exec.Type == ExecutorType.GoToEndPhase && main.CanEndPhase && exec.Func()) // check if should enter end phase directly { _dialogs.SendEndTurn(); return(new MainPhaseAction(MainPhaseAction.MainAction.ToEndPhase)); } if (exec.Type == ExecutorType.GoToBattlePhase && main.CanBattlePhase && exec.Func()) // check if should enter battle phase directly { return(new MainPhaseAction(MainPhaseAction.MainAction.ToBattlePhase)); } // NOTICE: GoToBattlePhase and GoToEndPhase has no "card" can be accessed to ShouldExecute(), so instead use exec.Func() to check ... // enter end phase and enter battle pahse is in higher priority. for (int i = 0; i < main.ActivableCards.Count; ++i) { ClientCard card = main.ActivableCards[i]; if (ShouldExecute(exec, card, ExecutorType.Activate, main.ActivableDescs[i])) { if (last_card != null && card.Equals(last_card)) { last_ct++; if (last_ct > 6) { continue; } } else { last_ct = 1; last_card = card; } _dialogs.SendActivate(card.Name); return(new MainPhaseAction(MainPhaseAction.MainAction.Activate, card.ActionActivateIndex[main.ActivableDescs[i]])); } } foreach (ClientCard card in main.MonsterSetableCards) { if (ShouldExecute(exec, card, ExecutorType.MonsterSet)) { _dialogs.SendSetMonster(); return(new MainPhaseAction(MainPhaseAction.MainAction.SetMonster, card.ActionIndex)); } } foreach (ClientCard card in main.ReposableCards) { if (ShouldExecute(exec, card, ExecutorType.Repos)) { return(new MainPhaseAction(MainPhaseAction.MainAction.Repos, card.ActionIndex)); } } foreach (ClientCard card in main.SpecialSummonableCards) { if (ShouldExecute(exec, card, ExecutorType.SpSummon)) { return(new MainPhaseAction(MainPhaseAction.MainAction.SpSummon, card.ActionIndex)); } } foreach (ClientCard card in main.SummonableCards) { if (ShouldExecute(exec, card, ExecutorType.Summon)) { return(new MainPhaseAction(MainPhaseAction.MainAction.Summon, card.ActionIndex)); } if (ShouldExecute(exec, card, ExecutorType.SummonOrSet)) { if (Executor.Util.IsAllEnemyBetter(true) && Executor.Util.IsAllEnemyBetterThanValue(card.Attack + 300, false) && main.MonsterSetableCards.Contains(card)) { _dialogs.SendSetMonster(); return(new MainPhaseAction(MainPhaseAction.MainAction.SetMonster, card.ActionIndex)); } return(new MainPhaseAction(MainPhaseAction.MainAction.Summon, card.ActionIndex)); } } foreach (ClientCard card in main.SpellSetableCards) { if (ShouldExecute(exec, card, ExecutorType.SpellSet)) { return(new MainPhaseAction(MainPhaseAction.MainAction.SetSpell, card.ActionIndex)); } } } if (main.CanBattlePhase && Duel.Fields[0].HasAttackingMonster()) { return(new MainPhaseAction(MainPhaseAction.MainAction.ToBattlePhase)); } _dialogs.SendEndTurn(); return(new MainPhaseAction(MainPhaseAction.MainAction.ToEndPhase)); }
/// <summary> /// Called when the AI has to do something during the battle phase. /// </summary> /// <param name="battle">Informations about usable cards.</param> /// <returns>A new BattlePhaseAction containing the action to do.</returns> public BattlePhaseAction OnSelectBattleCmd(BattlePhase battle) { Executor.SetBattle(battle); foreach (CardExecutor exec in Executor.Executors) { if (exec.Type == ExecutorType.GoToMainPhase2 && battle.CanMainPhaseTwo && exec.Func()) // check if should enter main phase 2 directly { return(ToMainPhase2()); } if (exec.Type == ExecutorType.GoToEndPhase && battle.CanEndPhase && exec.Func()) // check if should enter end phase directly { return(ToEndPhase()); } for (int i = 0; i < battle.ActivableCards.Count; ++i) { ClientCard card = battle.ActivableCards[i]; if (ShouldExecute(exec, card, ExecutorType.Activate, battle.ActivableDescs[i])) { if (last_card != null && card.Equals(last_card)) { last_ct++; if (last_ct > 6) { continue; } } else { last_ct = 0; last_card = card; } _dialogs.SendChaining(card.Name); return(new BattlePhaseAction(BattlePhaseAction.BattleAction.Activate, card.ActionIndex)); } } } // Sort the attackers and defenders, make monster with higher attack go first. List <ClientCard> attackers = new List <ClientCard>(battle.AttackableCards); attackers.Sort(CardContainer.CompareCardAttack); attackers.Reverse(); List <ClientCard> defenders = new List <ClientCard>(Duel.Fields[1].GetMonsters()); defenders.Sort(CardContainer.CompareDefensePower); defenders.Reverse(); // Let executor decide which card should attack first. ClientCard selected = Executor.OnSelectAttacker(attackers, defenders); if (selected != null && attackers.Contains(selected)) { attackers.Remove(selected); attackers.Insert(0, selected); } // Check for the executor. BattlePhaseAction result = Executor.OnBattle(attackers, defenders); if (result != null) { return(result); } if (attackers.Count == 0) { return(ToMainPhase2()); } if (defenders.Count == 0) { // Attack with the monster with the lowest attack first for (int i = attackers.Count - 1; i >= 0; --i) { ClientCard attacker = attackers[i]; if (attacker.Attack > 0) { return(Attack(attacker, null)); } } } else { for (int k = 0; k < attackers.Count; ++k) { ClientCard attacker = attackers[k]; attacker.IsLastAttacker = (k == attackers.Count - 1); result = Executor.OnSelectAttackTarget(attacker, defenders); if (result != null) { return(result); } } } if (!battle.CanMainPhaseTwo) { return(Attack(attackers[0], (defenders.Count == 0) ? null : defenders[0])); } return(ToMainPhase2()); }