From 0b7f70e6f8a1d8f799c27110ef854dff2fa06a89 Mon Sep 17 00:00:00 2001 From: Wind2009-Louse Date: Thu, 12 Oct 2023 17:24:55 +0800 Subject: [PATCH] Update executor --- Game/AI/Decks/AltergeistExecutor.cs | 58 +++++++++++++++++---- Game/AI/Decks/DogmatikaExecutor.cs | 15 +++--- Game/AI/Decks/ExosisterExecutor.cs | 40 +++++++++++---- Game/AI/Decks/SwordsoulExecutor.cs | 31 ++++++++--- Game/AI/Decks/TrickstarExecutor.cs | 79 +++++++++++++++++++++++------ Game/AI/Decks/WitchcraftExecutor.cs | 42 ++++++++++----- Game/AI/DefaultExecutor.cs | 22 ++++++++ 7 files changed, 223 insertions(+), 64 deletions(-) diff --git a/Game/AI/Decks/AltergeistExecutor.cs b/Game/AI/Decks/AltergeistExecutor.cs index 066f8e10..93b14c35 100644 --- a/Game/AI/Decks/AltergeistExecutor.cs +++ b/Game/AI/Decks/AltergeistExecutor.cs @@ -3,6 +3,7 @@ using WindBot; using WindBot.Game; using WindBot.Game.AI; +using System.Linq; namespace WindBot.Game.AI.Decks { @@ -324,23 +325,37 @@ public int GetTotalATK(IList list) public int SelectSTPlace(ClientCard card=null, bool avoid_Impermanence = false) { - List list = new List { 0, 1, 2, 3, 4 }; + if (card == null) card = Card; + List list = new List(); + for (int seq = 0; seq < 5; ++seq) + { + if (Bot.SpellZone[seq] == null) + { + if (card != null && card.Location == CardLocation.Hand && avoid_Impermanence && Impermanence_list.Contains(seq)) continue; + list.Add(seq); + } + } int n = list.Count; while (n-- > 1) { - int index = Program.Rand.Next(n + 1); - int temp = list[index]; - list[index] = list[n]; - list[n] = temp; + int index = Program.Rand.Next(list.Count); + int nextIndex = (index + Program.Rand.Next(list.Count - 1)) % list.Count; + int tempInt = list[index]; + list[index] = list[nextIndex]; + list[nextIndex] = tempInt; } - foreach (int seq in list) + if (avoid_Impermanence && Bot.GetMonsters().Any(c => c.IsFaceup() && !c.IsDisabled())) { - int zone = (int)System.Math.Pow(2, seq); - if (Bot.SpellZone[seq] == null) + foreach (int seq in list) { - if (card != null && card.Location == CardLocation.Hand && avoid_Impermanence && Impermanence_list.Contains(seq)) continue; - return zone; - }; + ClientCard enemySpell = Enemy.SpellZone[4 - seq]; + if (enemySpell != null && enemySpell.IsFacedown()) continue; + return (int)System.Math.Pow(2, seq); + } + } + foreach (int seq in list) + { + return (int)System.Math.Pow(2, seq); } return 0; } @@ -2656,6 +2671,27 @@ public override void OnNewTurn() attacked_Meluseek.Clear(); } + public override void OnChaining(int player, ClientCard card) + { + if (card == null) return; + + if (player == 1) + { + if (card.IsCode(_CardId.InfiniteImpermanence)) + { + for (int i = 0; i < 5; ++i) + { + if (Enemy.SpellZone[i] == card) + { + Impermanence_list.Add(4-i); + break; + } + } + } + } + base.OnChaining(player, card); + } + public bool MonsterRepos() { if (Card.Attack == 0) return (Card.IsAttack()); diff --git a/Game/AI/Decks/DogmatikaExecutor.cs b/Game/AI/Decks/DogmatikaExecutor.cs index 4b6f5f78..1f40e322 100644 --- a/Game/AI/Decks/DogmatikaExecutor.cs +++ b/Game/AI/Decks/DogmatikaExecutor.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.Linq; using System; -using System.CodeDom; -using System.Security.AccessControl; namespace WindBot.Game.AI.Decks { @@ -1098,8 +1096,8 @@ public override void OnMove(int cardId, int previousControler, int previousLocat public override ClientCard OnSelectAttacker(IList attackers, IList defenders) { - if (attackers.Count() > 0) return attackers[attackers.Count() - 1]; - return null; + if (attackers.Count() > 0) return attackers.OrderBy(card => card.Attack).FirstOrDefault(); + return base.OnSelectAttacker(attackers, defenders); } public override BattlePhaseAction OnSelectAttackTarget(ClientCard attacker, IList defenders) @@ -1113,6 +1111,9 @@ public override BattlePhaseAction OnSelectAttackTarget(ClientCard attacker, ILis if (attacker.RealPower > defender.RealPower) return AI.Attack(attacker, defender); + + if (attacker.RealPower == defender.RealPower && defender.IsAttack() && Bot.GetMonsterCount() >= Enemy.GetMonsterCount()) + return AI.Attack(attacker, defender); } if (attacker.CanDirectAttack) @@ -2031,7 +2032,7 @@ public bool SinfulSpoilsOfDoom_RcielaActivate() } // decrease attack - if (Bot.UnderAttack && !onlyAlbaZoa && (Bot.BattlingMonster?.GetDefensePower() ?? 0) <= (Enemy.BattlingMonster?.GetDefensePower() ?? 0)) + if (Bot.UnderAttack && !onlyAlbaZoa && (Bot.BattlingMonster?.GetDefensePower() ?? 0) <= (Enemy.BattlingMonster?.GetDefensePower() ?? 0) && Duel.LastChainPlayer != 0) { activateFlag = true; } @@ -2425,7 +2426,7 @@ public bool DogmatikaPunishmentActivate() if (targetCard == null || extraToDiscard == null) { bool check1 = DefaultOnBecomeTarget(); - bool check2 = Bot.UnderAttack && (Bot.BattlingMonster?.GetDefensePower() ?? 0) <= (Enemy.BattlingMonster?.GetDefensePower() ?? 0); + bool check2 = Bot.UnderAttack && (Bot.BattlingMonster?.GetDefensePower() ?? 0) <= (Enemy.BattlingMonster?.GetDefensePower() ?? 0) && Duel.LastChainPlayer != 0;; bool check3 = Duel.Player == 1 && Duel.Phase == DuelPhase.End && Duel.LastChainPlayer != 0; bool check4 = Duel.Player == 1 && avoid2Monster && Enemy.GetMonsterCount() >= 2 && Duel.LastChainPlayer != 0; Logger.DebugWriteLine("===punishment check flag: " + check1 + " " + check2 + " " + check3 + " " + check4); @@ -2820,7 +2821,7 @@ public bool MonsterRepos() if (Card.IsAttack() && enemyBetter) return true; - if (Card.IsDefense() && !enemyBetter && selfAttack >= Card.Defense) + if (Card.IsDefense() && !enemyBetter) return true; return false; } diff --git a/Game/AI/Decks/ExosisterExecutor.cs b/Game/AI/Decks/ExosisterExecutor.cs index 03f1517f..396121ed 100644 --- a/Game/AI/Decks/ExosisterExecutor.cs +++ b/Game/AI/Decks/ExosisterExecutor.cs @@ -629,25 +629,42 @@ public bool CheckWhetherNegated(bool disablecheck = true){ /// Whether need to avoid set in this place public void SelectSTPlace(ClientCard card = null, bool avoidImpermanence = false, List avoidList = null) { - List list = new List { 0, 1, 2, 3, 4 }; + if (card == null) card = Card; + List list = new List(); + for (int seq = 0; seq < 5; ++seq) + { + if (Bot.SpellZone[seq] == null) + { + if (card != null && card.Location == CardLocation.Hand && avoidImpermanence && infiniteImpermanenceList.Contains(seq)) continue; + if (avoidList != null && avoidList.Contains(seq)) continue; + list.Add(seq); + } + } int n = list.Count; while (n-- > 1) { - int index = Program.Rand.Next(n + 1); - int temp = list[index]; - list[index] = list[n]; - list[n] = temp; + int index = Program.Rand.Next(list.Count); + int nextIndex = (index + Program.Rand.Next(list.Count - 1)) % list.Count; + int tempInt = list[index]; + list[index] = list[nextIndex]; + list[nextIndex] = tempInt; } - foreach (int seq in list) + if (avoidImpermanence && Bot.GetMonsters().Any(c => c.IsFaceup() && !c.IsDisabled())) { - int zone = (int)System.Math.Pow(2, seq); - if (Bot.SpellZone[seq] == null) + foreach (int seq in list) { - if (card != null && card.Location == CardLocation.Hand && avoidImpermanence && infiniteImpermanenceList.Contains(seq)) continue; - if (avoidList != null && avoidList.Contains(seq)) continue; + ClientCard enemySpell = Enemy.SpellZone[4 - seq]; + if (enemySpell != null && enemySpell.IsFacedown()) continue; + int zone = (int)System.Math.Pow(2, seq); AI.SelectPlace(zone); return; - }; + } + } + foreach (int seq in list) + { + int zone = (int)System.Math.Pow(2, seq); + AI.SelectPlace(zone); + return; } AI.SelectPlace(0); } @@ -816,6 +833,7 @@ public override void OnChainEnd() public override void OnNewTurn() { + if (Duel.Turn <= 1) calledbytheGraveCount.Clear(); enemyActivateMaxxC = false; enemyActivateLockBird = false; infiniteImpermanenceList.Clear(); diff --git a/Game/AI/Decks/SwordsoulExecutor.cs b/Game/AI/Decks/SwordsoulExecutor.cs index e9a967fc..29433a6d 100644 --- a/Game/AI/Decks/SwordsoulExecutor.cs +++ b/Game/AI/Decks/SwordsoulExecutor.cs @@ -700,6 +700,7 @@ public override IList OnSelectCard(IList cards, int min, public override void OnNewTurn() { + if (Duel.Turn <= 1) calledbytheGraveCount.Clear(); enemyActivateMaxxC = false; enemyActivateLockBird = false; @@ -780,7 +781,17 @@ public override void OnChainEnd() /// Whether need to avoid set in this place public void SelectSTPlace(ClientCard card = null, bool avoidImpermanence = false, List avoidList = null) { - List list = new List { 0, 1, 2, 3, 4 }; + if (card == null) card = Card; + List list = new List(); + for (int seq = 0; seq < 5; ++seq) + { + if (Bot.SpellZone[seq] == null) + { + if (card != null && card.Location == CardLocation.Hand && avoidImpermanence && infiniteImpermanenceList.Contains(seq)) continue; + if (avoidList != null && avoidList.Contains(seq)) continue; + list.Add(seq); + } + } int n = list.Count; while (n-- > 1) { @@ -790,16 +801,22 @@ public void SelectSTPlace(ClientCard card = null, bool avoidImpermanence = false list[index] = list[nextIndex]; list[nextIndex] = tempInt; } - foreach (int seq in list) + if (avoidImpermanence && Bot.GetMonsters().Any(c => c.IsFaceup() && !c.IsDisabled())) { - int zone = (int)System.Math.Pow(2, seq); - if (Bot.SpellZone[seq] == null) + foreach (int seq in list) { - if (card != null && card.Location == CardLocation.Hand && avoidImpermanence && infiniteImpermanenceList.Contains(seq)) continue; - if (avoidList != null && avoidList.Contains(seq)) continue; + ClientCard enemySpell = Enemy.SpellZone[4 - seq]; + if (enemySpell != null && enemySpell.IsFacedown()) continue; + int zone = (int)System.Math.Pow(2, seq); AI.SelectPlace(zone); return; - }; + } + } + foreach (int seq in list) + { + int zone = (int)System.Math.Pow(2, seq); + AI.SelectPlace(zone); + return; } AI.SelectPlace(0); } diff --git a/Game/AI/Decks/TrickstarExecutor.cs b/Game/AI/Decks/TrickstarExecutor.cs index 2e79cfad..d5ddaadc 100644 --- a/Game/AI/Decks/TrickstarExecutor.cs +++ b/Game/AI/Decks/TrickstarExecutor.cs @@ -3,6 +3,7 @@ using WindBot; using WindBot.Game; using WindBot.Game.AI; +using System.Linq; namespace WindBot.Game.AI.Decks { @@ -67,6 +68,7 @@ public int getLinkMarker(int id) return 1; } + List Impermanence_list = new List(); bool NormalSummoned = false; ClientCard stage_locked = null; bool pink_ss = false; @@ -190,21 +192,39 @@ public bool Five_Rainbow() return false; } - public int SelectSTPlace() + public int SelectSTPlace(ClientCard card = null, bool avoid_Impermanence = false) { - List list = new List { 0, 1, 2, 3, 4 }; + if (card == null) card = Card; + List list = new List(); + for (int seq = 0; seq < 5; ++seq) + { + if (Bot.SpellZone[seq] == null) + { + if (card != null && card.Location == CardLocation.Hand && avoid_Impermanence && Impermanence_list.Contains(seq)) continue; + list.Add(seq); + } + } int n = list.Count; while (n-- > 1) { - int index = Program.Rand.Next(n + 1); - int temp = list[index]; - list[index] = list[n]; - list[n] = temp; + int index = Program.Rand.Next(list.Count); + int nextIndex = (index + Program.Rand.Next(list.Count - 1)) % list.Count; + int tempInt = list[index]; + list[index] = list[nextIndex]; + list[nextIndex] = tempInt; } - foreach(int seq in list) + if (avoid_Impermanence && Bot.GetMonsters().Any(c => c.IsFaceup() && !c.IsDisabled())) { - int zone = (int)System.Math.Pow(2, seq); - if (Bot.SpellZone[seq] == null) return zone; + foreach (int seq in list) + { + ClientCard enemySpell = Enemy.SpellZone[4 - seq]; + if (enemySpell != null && enemySpell.IsFacedown()) continue; + return (int)System.Math.Pow(2, seq); + } + } + foreach (int seq in list) + { + return (int)System.Math.Pow(2, seq); } return 0; } @@ -505,7 +525,7 @@ public bool GalaxyCyclone() if (selected == null) return false; AI.SelectCard(selected); - AI.SelectPlace(SelectSTPlace()); + AI.SelectPlace(SelectSTPlace(Card, true)); return true; } @@ -526,13 +546,13 @@ public bool Feather_Act() if (self_card.IsCode(CardId.Galaxy)) return false; } - AI.SelectPlace(SelectSTPlace()); + AI.SelectPlace(SelectSTPlace(Card, true)); return true; } // activate when more than 2 cards if (Enemy.GetSpellCount() <= 1) return false; - AI.SelectPlace(SelectSTPlace()); + AI.SelectPlace(SelectSTPlace(Card, true)); return true; } @@ -627,7 +647,7 @@ public bool Pot_Act() if (!spell_trap_activate()) return false; if (Bot.Deck.Count > 15) { - AI.SelectPlace(SelectSTPlace()); + AI.SelectPlace(SelectSTPlace(Card, true)); return true; } return false; @@ -1003,7 +1023,7 @@ public bool Crown_eff() if (!spell_trap_activate()) return false; if (Duel.Phase <= DuelPhase.Main1 && Ts_reborn()) { - AI.SelectPlace(SelectSTPlace()); + AI.SelectPlace(SelectSTPlace(Card, true)); return true; } return false; @@ -1634,14 +1654,14 @@ public bool DarkHole_eff() { if (enemy.IsMonsterDangerous()) { - AI.SelectPlace(SelectSTPlace()); + AI.SelectPlace(SelectSTPlace(Card, true)); return true; } if (enemy.IsFaceup() && (enemy.GetDefensePower() > bestenemy)) bestenemy = enemy.GetDefensePower(); } if (bestPower <= bestenemy) { - AI.SelectPlace(SelectSTPlace()); + AI.SelectPlace(SelectSTPlace(Card, true)); return true; } } @@ -1697,6 +1717,11 @@ public override bool OnSelectHand() public override void OnNewTurn() { + if (Duel.Turn <= 1) + { + GraveCall_count = 0; + GraveCall_id = 0; + } NormalSummoned = false; stage_locked = null; pink_ss = false; @@ -1705,6 +1730,7 @@ public override void OnNewTurn() white_eff_used = false; lockbird_useful = false; lockbird_used = false; + Impermanence_list.Clear(); if (GraveCall_count > 0) { if (--GraveCall_count <= 0) @@ -1714,6 +1740,27 @@ public override void OnNewTurn() } } + public override void OnChaining(int player, ClientCard card) + { + if (card == null) return; + + if (player == 1) + { + if (card.IsCode(_CardId.InfiniteImpermanence)) + { + for (int i = 0; i < 5; ++i) + { + if (Enemy.SpellZone[i] == card) + { + Impermanence_list.Add(4-i); + break; + } + } + } + } + base.OnChaining(player, card); + } + public override BattlePhaseAction OnSelectAttackTarget(ClientCard attacker, IList defenders) { ClientCard lowestattack = null; diff --git a/Game/AI/Decks/WitchcraftExecutor.cs b/Game/AI/Decks/WitchcraftExecutor.cs index b977c8ac..0b66222a 100644 --- a/Game/AI/Decks/WitchcraftExecutor.cs +++ b/Game/AI/Decks/WitchcraftExecutor.cs @@ -269,6 +269,7 @@ public override void OnChaining(int player, ClientCard card) // new turn reset public override void OnNewTurn() { + if (Duel.Turn <= 1) CalledbytheGraveCount.Clear(); CrossoutDesignatorTarget = 0; MadameVerreGainedATK = false; summoned = false; @@ -858,27 +859,44 @@ public bool NegatedCheck(bool disablecheck = true){ /// Card to set(default current card) /// Whether need to avoid InfiniteImpermanence /// Whether need to avoid set in this place - public void SelectSTPlace(ClientCard card = null, bool avoid_Impermanence = false, List avoid_list=null) + public void SelectSTPlace(ClientCard card = null, bool avoid_Impermanence = false, List avoid_list = null) { - List list = new List { 0, 1, 2, 3, 4 }; + if (card == null) card = Card; + List list = new List(); + for (int seq = 0; seq < 5; ++seq) + { + if (Bot.SpellZone[seq] == null) + { + if (card != null && card.Location == CardLocation.Hand && avoid_Impermanence && Impermanence_list.Contains(seq)) continue; + if (avoid_list != null && avoid_list.Contains(seq)) continue; + list.Add(seq); + } + } int n = list.Count; while (n-- > 1) { - int index = Program.Rand.Next(n + 1); - int temp = list[index]; - list[index] = list[n]; - list[n] = temp; + int index = Program.Rand.Next(list.Count); + int nextIndex = (index + Program.Rand.Next(list.Count - 1)) % list.Count; + int tempInt = list[index]; + list[index] = list[nextIndex]; + list[nextIndex] = tempInt; } - foreach (int seq in list) + if (avoid_Impermanence && Bot.GetMonsters().Any(c => c.IsFaceup() && !c.IsDisabled())) { - int zone = (int)System.Math.Pow(2, seq); - if (Bot.SpellZone[seq] == null) + foreach (int seq in list) { - if (card != null && card.Location == CardLocation.Hand && avoid_Impermanence && Impermanence_list.Contains(seq)) continue; - if (avoid_list != null && avoid_list.Contains(seq)) continue; + ClientCard enemySpell = Enemy.SpellZone[4 - seq]; + if (enemySpell != null && enemySpell.IsFacedown()) continue; + int zone = (int)System.Math.Pow(2, seq); AI.SelectPlace(zone); return; - }; + } + } + foreach (int seq in list) + { + int zone = (int)System.Math.Pow(2, seq); + AI.SelectPlace(zone); + return; } AI.SelectPlace(0); } diff --git a/Game/AI/DefaultExecutor.cs b/Game/AI/DefaultExecutor.cs index b5730d5e..ccae0938 100644 --- a/Game/AI/DefaultExecutor.cs +++ b/Game/AI/DefaultExecutor.cs @@ -177,6 +177,12 @@ protected class _CardId public const int DuelLinkDragonTheDuelDragon = 60025883; public const int DuelDragonToken = 60025884; public const int SeleneQueenOfTheMasterMagicians = 45819647; + public const int TheWingedDragonofRaSphereMode = 10000080; + + public const int RockOfTheVanquisher = 28168628; + public const int SpiralDischarge = 29477860; + public const int GaiaTheDragonChampion = 66889139; + public const int CrusadiaVanguard = 55312487; } protected class _Setcode @@ -193,9 +199,11 @@ protected class _Setcode public const int Performapal = 0x9f; public const int FurHire = 0x114; public const int Altergeist = 0x103; + public const int Crusadia = 0x116; public const int Endymion = 0x12a; public const int AncientWarriors = 0x137; public const int RescueACE = 0x18b; + public const int VanquishSoul = 0x195; } protected DefaultExecutor(GameAI ai, Duel duel) @@ -273,6 +281,8 @@ protected DefaultExecutor(GameAI ai, Duel duel) {_CardId.Number48ShadowLich, (defender, list) => list.Any(monster => monster.IsCode(_CardId.PhantomToken))}, {_CardId.DuelLinkDragonTheDuelDragon, (defender, list) => list.Any(monster => monster.IsCode(_CardId.DuelDragonToken))}, {_CardId.SeleneQueenOfTheMasterMagicians, (defender, list) => list.Any(monster => monster.HasSetcode(_Setcode.Endymion))}, + + {_CardId.TheWingedDragonofRaSphereMode, (defender, list) => true} }; /// @@ -404,6 +414,18 @@ public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender if (defender.HasSetcode(_Setcode.EarthboundImmortal) && !defender.IsDisabled()) return false; + if (Enemy.HasInMonstersZone(_CardId.RockOfTheVanquisher, true) && Enemy.GetMonsters().Any(card => card.HasSetcode(_Setcode.VanquishSoul))) + { + if (defender.HasPosition(CardPosition.FaceDown)) return false; + if (Enemy.GetMonsters().Any(card => card.IsFaceup() && card.Attack > defender.Attack)) return false; + } + + if (Enemy.HasInSpellZone(_CardId.SpiralDischarge, true) && Enemy.HasInMonstersZone(_CardId.GaiaTheDragonChampion) && !defender.IsCode(_CardId.GaiaTheDragonChampion)) + return false; + + if (Enemy.HasInSpellZone(_CardId.CrusadiaVanguard, true) && Enemy.GetMonsters().Any(card => card.HasSetcode(_Setcode.Crusadia) && card.HasType(CardType.Link)) && !defender.HasType(CardType.Link)) + return false; + return true; }