From 57927d865dc6dc8dc6ada863577cf4b3db081c92 Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Wed, 20 Dec 2023 21:31:34 +0800 Subject: [PATCH 01/21] Floowandereeze initial commit --- Decks/AI_Floowandereeze.ydk | 59 +++++++ Game/AI/Decks/FloowandereezeExecutor.cs | 211 ++++++++++++++++++++++++ WindBot.csproj | 1 + WindBot.sln | 4 +- 4 files changed, 273 insertions(+), 2 deletions(-) create mode 100644 Decks/AI_Floowandereeze.ydk create mode 100644 Game/AI/Decks/FloowandereezeExecutor.cs diff --git a/Decks/AI_Floowandereeze.ydk b/Decks/AI_Floowandereeze.ydk new file mode 100644 index 00000000..02e3b900 --- /dev/null +++ b/Decks/AI_Floowandereeze.ydk @@ -0,0 +1,59 @@ +#created by SkildX +#main +53212882 +80611581 +80611581 +69327790 +29587993 +91800273 +91800273 +91800273 +54334420 +54334420 +54334420 +80433039 +18940725 +18940725 +18940725 +17827173 +18144507 +25311006 +35269904 +35269904 +73628505 +84211599 +84211599 +84211599 +98645731 +98645731 +98645731 +14087893 +14087893 +14087893 +69087397 +69087397 +69087397 +55521751 +28126717 +28126717 +28126717 +41215808 +87639778 +87639778 +#extra +90448279 +90448279 +26096328 +56910167 +56910167 +72167543 +72167543 +58058134 +27240101 +27240101 +48608796 +48608796 +98127546 +75147529 +41999284 +!side diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs new file mode 100644 index 00000000..1c7674bc --- /dev/null +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -0,0 +1,211 @@ +using YGOSharp.OCGWrapper.Enums; +using System.Collections.Generic; +using System; +using System.Linq; + +namespace WindBot.Game.AI.Decks +{ + [Deck("Floowandereeze", "AI_Floowandereeze")] + class FloowandereezeExecutor : DefaultExecutor + { + public class CardId + { + public const int Snowl = 53212882; + public const int Empen = 80611581; + public const int RaizaMegaMonarch = 69327790; + public const int Avian = 29587993; + public const int DimensionShifter = 91800273; + public const int Eglen = 54334420; + public const int Stri = 80433039; + public const int Robina = 18940725; + public const int Toccan = 17827173; + + // spells + public const int HarpiesFeatherDuster = 18144507; + public const int TrippleTacticsTalent = 25311006; + public const int TrippleTacticsThrust = 35269904; + public const int Terraforming = 73628505; + public const int PotOfProsperity = 84211599; + public const int PotOfDuality = 98645731; + public const int BookOfMoon = 14087893; + public const int AdventOfAdventure = 69087397; + public const int UnexploredWinds = 55521751; + + // Traps + public const int MagnificentMap = 28126717; + public const int DreamingTown = 41215808; + public const int HarpiesFeatherStorm = 87639778; + + // extra + public const int Zeus = 90448279; + public const int JuggernautLiebe = 26096328; + public const int GustavMax = 56910167; + public const int DowneredMagician = 72167543; + public const int SlackerdMagician = 58058134; + public const int AssembeledNightingale = 48608796; + public const int UnderworldGoddess = 98127546; + public const int Linkuriboh = 41999284; + } + + public FloowandereezeExecutor(GameAI ai, Duel duel) + : base(ai, duel) + { + AddExecutor(ExecutorType.Activate, CardId.DimensionShifter); + + AddExecutor(ExecutorType.Activate, CardId.PotOfDuality, PotOfDualityActivate); + AddExecutor(ExecutorType.Summon, CardId.HarpiesFeatherDuster, DefaultHarpiesFeatherDusterFirst); + + AddExecutor(ExecutorType.Summon, CardId.Robina); + AddExecutor(ExecutorType.Activate, CardId.Robina, RobinaEffect); + AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenEffect); + + // Chain block for strongest effect monster + AddExecutor(ExecutorType.Activate, CardId.Empen, EmpenEffect); + AddExecutor(ExecutorType.Activate, CardId.Robina, RobinaBanishedEffect); + AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenBanishedEffect); + + AddExecutor(ExecutorType.SpellSet, CardId.DreamingTown, DreamingTownSet); + AddExecutor(ExecutorType.Activate, CardId.DreamingTown); + AddExecutor(ExecutorType.SpellSet, CardId.HarpiesFeatherStorm); + AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherStorm); + } + + private bool DreamingTownSet() + { + return Bot.HasInHand(CardId.Robina); + } + + private bool PotOfDualityActivate() + { + if (!Bot.HasInHand(CardId.Robina)) + { + AI.SelectCard(CardId.Robina); + return true; + } + else if (!Bot.HasInHand(CardId.Eglen)) + { + AI.SelectCard(CardId.Robina); + return true; + } + else + { + int[] otherPrefferedCards = new int[] + { + CardId.Stri, + CardId.Toccan + }; + + AI.SelectCard(otherPrefferedCards); + return true; + } + } + + private bool RobinaBanishedEffect() + { + if (Bot.HasInBanished(CardId.Robina) && Card.Location != CardLocation.MonsterZone) + return true; + return false; + } + + private bool EglenBanishedEffect() + { + if (Bot.HasInBanished(CardId.Eglen) && Card.Location != CardLocation.MonsterZone) + return true; + return false; + } + + private bool RobinaEffect() + { + if (Card.Location == CardLocation.MonsterZone) + { + if (!(Bot.HasInHandOrHasInMonstersZone(CardId.Eglen) || Bot.HasInBanished(CardId.Eglen))) + { + AI.SelectCard(CardId.Eglen); + AI.SelectNextCard(CardId.Eglen); + + return true; + } + else + { + int[] otherPrefferedCards = new int[] + { + CardId.Stri, + CardId.Toccan, + CardId.Robina + }; + + if (Bot.HasInHand(CardId.Eglen)) + { + AI.SelectCard(CardId.Eglen); + } + else + { + AI.SelectCard(otherPrefferedCards); + AI.SelectNextCard(otherPrefferedCards); + } + + return true; + } + } + + return false; + } + + private bool EmpenEffect() + { + List other_prefferedCards = new List(); + + other_prefferedCards.AddRange(new List { + CardId.UnexploredWinds, + CardId.AdventOfAdventure + }); + + if (!(Bot.HasInHandOrInSpellZoneOrInGraveyard(CardId.DreamingTown) || Bot.HasInBanished(CardId.DreamingTown))) + { + AI.SelectCard(CardId.DreamingTown); + return true; + } + else + { + AI.SelectCard(other_prefferedCards); + return true; + } + } + + private bool EglenEffect() + { + List materials = new List(); + materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).ToList(); + + int[] prefferedCards = new int[] + { + CardId.Empen, + CardId.Snowl, + CardId.Avian + }; + + if (!Bot.HasInHandOrHasInMonstersZone(CardId.Empen)) + { + // Fetch empen from deck + AI.SelectCard(CardId.Empen); + AI.SelectNextCard(CardId.Empen); + + AI.SelectMaterials(materials); + + return true; + } + else + { + AI.SelectCard(prefferedCards); + AI.SelectMaterials(prefferedCards); + + return true; + } + } + } + + + + + +} diff --git a/WindBot.csproj b/WindBot.csproj index 5b50096e..8d70c9d4 100644 --- a/WindBot.csproj +++ b/WindBot.csproj @@ -57,6 +57,7 @@ + diff --git a/WindBot.sln b/WindBot.sln index 721077a1..ab5ded86 100644 --- a/WindBot.sln +++ b/WindBot.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.960 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34316.72 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindBot", "WindBot.csproj", "{3E7FAF67-A27D-4A61-B161-93AD4414183E}" EndProject From df733f2564e388636cf6668c8486da5e20da0be9 Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Thu, 21 Dec 2023 23:47:47 +0800 Subject: [PATCH 02/21] added some executors --- Game/AI/Decks/FloowandereezeExecutor.cs | 273 +++++++++++++++++++++--- 1 file changed, 247 insertions(+), 26 deletions(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index 1c7674bc..5700e3ad 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System; using System.Linq; +using System.Web.UI; +using System.Security.Policy; namespace WindBot.Game.AI.Decks { @@ -45,6 +47,7 @@ public class CardId public const int AssembeledNightingale = 48608796; public const int UnderworldGoddess = 98127546; public const int Linkuriboh = 41999284; + public const int Fucho = 27240101; } public FloowandereezeExecutor(GameAI ai, Duel duel) @@ -53,23 +56,170 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.DimensionShifter); AddExecutor(ExecutorType.Activate, CardId.PotOfDuality, PotOfDualityActivate); - AddExecutor(ExecutorType.Summon, CardId.HarpiesFeatherDuster, DefaultHarpiesFeatherDusterFirst); + AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherDuster, DefaultHarpiesFeatherDusterFirst); + + AddExecutor(ExecutorType.Activate, CardId.AdventOfAdventure, AdventOfAdventureEffect); + AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, MagnificentMapActivate); + AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, Active_MagnificentMapActivate); + + AddExecutor(ExecutorType.SpSummon, CardId.Fucho, FuchoSpSummon); + AddExecutor(ExecutorType.Activate, CardId.Fucho); + AddExecutor(ExecutorType.SpSummon, CardId.GustavMax, JuggernautGustavMaxOverlay); + AddExecutor(ExecutorType.Activate, CardId.GustavMax); + AddExecutor(ExecutorType.SpSummon, CardId.JuggernautLiebe); + AddExecutor(ExecutorType.Activate, CardId.JuggernautLiebe); + AddExecutor(ExecutorType.SpSummon, CardId.Zeus); AddExecutor(ExecutorType.Summon, CardId.Robina); AddExecutor(ExecutorType.Activate, CardId.Robina, RobinaEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenEffect); + AddExecutor(ExecutorType.Activate, CardId.Toccan, ToccanEffect); + AddExecutor(ExecutorType.Activate, CardId.Stri); // Chain block for strongest effect monster AddExecutor(ExecutorType.Activate, CardId.Empen, EmpenEffect); + AddExecutor(ExecutorType.Activate, CardId.Snowl, SnowBattle); AddExecutor(ExecutorType.Activate, CardId.Robina, RobinaBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenBanishedEffect); + AddExecutor(ExecutorType.Activate, CardId.Eglen, ToccanBanishedEffect); AddExecutor(ExecutorType.SpellSet, CardId.DreamingTown, DreamingTownSet); AddExecutor(ExecutorType.Activate, CardId.DreamingTown); + AddExecutor(ExecutorType.Activate, CardId.DreamingTown, DreamingTownGraveyardActivate); + AddExecutor(ExecutorType.SpellSet, CardId.HarpiesFeatherStorm); AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherStorm); } + private bool FuchoSpSummon() + { + AI.SelectPlace(Zones.ExtraMonsterZones); + AI.SelectPosition(CardPosition.Attack); + return !(Bot.HasInExtra(CardId.Fucho) || Bot.HasInMonstersZone(CardId.Fucho)); + } + + private bool JuggernautGustavMaxOverlay() + { + AI.SelectPlace(Zones.ExtraMonsterZones); + return true; + } + + private bool robina_NormalSummonEffectActivated = false, + eglen_NormalSummonEffectActivated = false; + public override void OnNewTurn() + { + robina_NormalSummonEffectActivated = false; + eglen_NormalSummonEffectActivated = false; + + base.OnNewTurn(); + } + + private bool DreamingTownGraveyardActivate() + { + return Card.Location == CardLocation.Grave && Util.IsAllEnemyBetter() && (Duel.Phase == DuelPhase.Main1 || Duel.Phase == DuelPhase.Main2); + } + + private bool ToccanBanishedEffect() + { + ClientCard robina = Bot.Banished.GetFirstMatchingCard(card => card.IsCode(CardId.Robina)); + ClientCard eglen = Bot.Banished.GetFirstMatchingCard(card => card.IsCode(CardId.Eglen)); + + + if (Duel.CurrentChain.Contains(robina) || Duel.CurrentChain.Contains(eglen)) + { + if (!(Card.Location == CardLocation.MonsterZone || Card.Location == CardLocation.Grave || Card.Location == CardLocation.Hand)) + return true; + } + + return false; + } + + private bool ToccanEffect() + { + if (Card.Location == CardLocation.MonsterZone) + { + + int[] preffererdCards = Bot.Banished.GetMatchingCards(card => + card.Level > 6 + || card.IsCode(CardId.MagnificentMap) + || card.IsCode(CardId.UnexploredWinds) + ).Select(c => c.Id).ToArray(); + + if (Bot.HasInBanished(CardId.Robina)) AI.SelectCard(CardId.Robina); + + + if (Bot.HasInBanished(CardId.DreamingTown)) AI.SelectCard(CardId.DreamingTown); + else AI.SelectCard(preffererdCards); + + + return true; + } + + return false; + } + + private bool Active_MagnificentMapActivate() + { + if (Card.Location == CardLocation.SpellZone) + { + int[] reveal = Bot.Hand.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); + + if (!Bot.HasInHand(CardId.Robina)) + { + AI.SelectCard(reveal); + AI.SelectNextCard(CardId.Robina); + } + else + { + AI.SelectCard(reveal); + + if (!Bot.HasInHandOrInGraveyard(CardId.Toccan) || !Bot.HasInBanished(CardId.Toccan)) + AI.SelectCard(CardId.Toccan); + else AI.SelectNextCard(reveal); + } + + return true; + } + + return false; + } + + private bool MagnificentMapActivate() + { + return !Bot.HasInSpellZone(CardId.MagnificentMap) && Card.Location == CardLocation.Hand; + } + + private bool AdventOfAdventureEffect() + { + int[] cost = Bot.Hand.GetMatchingCards(card => card.Level == 1 && !card.IsCode(CardId.Robina)).Select(c => c.Id).ToArray(); + + if (!Bot.HasInHand(CardId.Robina) && cost.Count() > 0) + { + AI.SelectCard(cost); // pay cost + AI.SelectNextCard(CardId.Robina); + + return true; + } + + int hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.HasAttribute(CardAttribute.Wind) && card.Level > 6).Count(); + + // Search unexplored winds + if (Bot.HasInHand(CardId.Robina) && Bot.HasInHand(CardId.Eglen) && hand_bossMonsters > 0 && cost.Count() > 0) + { + AI.SelectCard(cost); // pay cost + + if(!Bot.HasInHand(CardId.UnexploredWinds)) + AI.SelectNextCard(CardId.UnexploredWinds); + + if (!Bot.HasInHandOrInSpellZone(CardId.MagnificentMap)) + AI.SelectNextCard(CardId.MagnificentMap); + + return true; + } + + return false; + } + private bool DreamingTownSet() { return Bot.HasInHand(CardId.Robina); @@ -87,6 +237,11 @@ private bool PotOfDualityActivate() AI.SelectCard(CardId.Robina); return true; } + else if (!Bot.HasInHandOrInSpellZone(CardId.MagnificentMap)) + { + AI.SelectCard(CardId.MagnificentMap); + return true; + } else { int[] otherPrefferedCards = new int[] @@ -102,15 +257,29 @@ private bool PotOfDualityActivate() private bool RobinaBanishedEffect() { - if (Bot.HasInBanished(CardId.Robina) && Card.Location != CardLocation.MonsterZone) - return true; + + ClientCard empen = Bot.MonsterZone.GetFirstMatchingCard(card => card.IsCode(CardId.Empen)); + + if (Duel.CurrentChain.Contains(empen)) + { + if (!(Card.Location == CardLocation.MonsterZone || Card.Location == CardLocation.Grave || Card.Location == CardLocation.Hand)) + return true; + } + return false; } private bool EglenBanishedEffect() { - if (Bot.HasInBanished(CardId.Eglen) && Card.Location != CardLocation.MonsterZone) - return true; + ClientCard robina = Bot.Banished.GetFirstMatchingCard(card => card.IsCode(CardId.Robina)); + + if (Duel.CurrentChain.Contains(robina)) + { + if (!(Card.Location == CardLocation.MonsterZone || Card.Location == CardLocation.Grave || Card.Location == CardLocation.Hand)) + return true; + } + + return false; } @@ -144,8 +313,12 @@ private bool RobinaEffect() AI.SelectNextCard(otherPrefferedCards); } + robina_NormalSummonEffectActivated = true; + return true; } + + } return false; @@ -163,6 +336,34 @@ private bool EmpenEffect() if (!(Bot.HasInHandOrInSpellZoneOrInGraveyard(CardId.DreamingTown) || Bot.HasInBanished(CardId.DreamingTown))) { AI.SelectCard(CardId.DreamingTown); + + // decided whether to normal summon or not + bool decision = Empen_NormalSummonAgain(); + + AI.SelectYesNo(decision); + + if (decision && Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 1) + { + List prefferedMonster = new List(); + int[] materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); + + if (Bot.HasInHand(CardId.Avian)) prefferedMonster.Add(CardId.Avian); + else if (Bot.HasInHand(CardId.Snowl)) prefferedMonster.Add(CardId.Snowl); + else + prefferedMonster.AddRange(new List { + CardId.RaizaMegaMonarch + }); + + AI.SelectNextCard(prefferedMonster); + } + else + { + int[] hand_Level1_Monsters = Bot.Hand.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); + + if (Bot.HasInHand(CardId.Robina)) AI.SelectNextCard(CardId.Robina); + else AI.SelectNextCard(hand_Level1_Monsters); + } + return true; } else @@ -172,35 +373,55 @@ private bool EmpenEffect() } } - private bool EglenEffect() + private bool Empen_NormalSummonAgain() { - List materials = new List(); - materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).ToList(); + return Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 1 || !robina_NormalSummonEffectActivated || !eglen_NormalSummonEffectActivated; + } - int[] prefferedCards = new int[] + private bool EglenEffect() + { + if (Card.Location == CardLocation.MonsterZone) { - CardId.Empen, - CardId.Snowl, - CardId.Avian - }; + List materials = new List(); + materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).ToList(); - if (!Bot.HasInHandOrHasInMonstersZone(CardId.Empen)) - { - // Fetch empen from deck - AI.SelectCard(CardId.Empen); - AI.SelectNextCard(CardId.Empen); + int[] prefferedCards = new int[] + { + CardId.Avian + }; - AI.SelectMaterials(materials); + if (!Bot.HasInHandOrHasInMonstersZone(CardId.Empen)) + { + // Fetch empen from deck + AI.SelectCard(CardId.Empen); + AI.SelectNextCard(CardId.Empen); - return true; - } - else - { - AI.SelectCard(prefferedCards); - AI.SelectMaterials(prefferedCards); + AI.SelectMaterials(materials); - return true; + return true; + } + else + { + if (Bot.HasInHand(CardId.Snowl)) + { + AI.SelectCard(CardId.Snowl); + AI.SelectNextCard(CardId.Snowl); + + AI.SelectMaterials(materials); + } + else + { + AI.SelectCard(prefferedCards); + AI.SelectMaterials(materials); + } + + eglen_NormalSummonEffectActivated = true; + + return true; + } } + + return false; } } From 311bac06b84293e93ff4e4989d5c9aa4a610dfb3 Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Fri, 29 Dec 2023 16:16:21 +0800 Subject: [PATCH 03/21] Added executors to some cards TODO: 1. Empen battle behaviour 2. Empen Normal Summon behaviour 3. XYZ Zeus combo 4. Stri banishing DreamingTown should not execute. --- Game/AI/Decks/FloowandereezeExecutor.cs | 211 +++++++++++++++++++++--- 1 file changed, 191 insertions(+), 20 deletions(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index 5700e3ad..e402e32f 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -1,9 +1,7 @@ using YGOSharp.OCGWrapper.Enums; using System.Collections.Generic; -using System; using System.Linq; -using System.Web.UI; -using System.Security.Policy; +using System; namespace WindBot.Game.AI.Decks { @@ -55,22 +53,36 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) { AddExecutor(ExecutorType.Activate, CardId.DimensionShifter); + AddExecutor(ExecutorType.Activate, CardId.BookOfMoon, BookOfMoonActivate); AddExecutor(ExecutorType.Activate, CardId.PotOfDuality, PotOfDualityActivate); + AddExecutor(ExecutorType.Activate, CardId.PotOfProsperity, PotOfProsperityActivate); AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherDuster, DefaultHarpiesFeatherDusterFirst); AddExecutor(ExecutorType.Activate, CardId.AdventOfAdventure, AdventOfAdventureEffect); + AddExecutor(ExecutorType.Activate, CardId.Terraforming, TerraformingActivate); AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, MagnificentMapActivate); AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, Active_MagnificentMapActivate); + AddExecutor(ExecutorType.Activate, CardId.UnexploredWinds, UnexploredWindsActivate); + + AddExecutor(ExecutorType.Activate, CardId.Snowl, SnowlActivate); + AddExecutor(ExecutorType.Activate, CardId.Avian, AvianActivate); + AddExecutor(ExecutorType.SpSummon, CardId.Fucho, FuchoSpSummon); AddExecutor(ExecutorType.Activate, CardId.Fucho); AddExecutor(ExecutorType.SpSummon, CardId.GustavMax, JuggernautGustavMaxOverlay); AddExecutor(ExecutorType.Activate, CardId.GustavMax); - AddExecutor(ExecutorType.SpSummon, CardId.JuggernautLiebe); + AddExecutor(ExecutorType.SpSummon, CardId.JuggernautLiebe, JuggernautLiebeSummon); AddExecutor(ExecutorType.Activate, CardId.JuggernautLiebe); AddExecutor(ExecutorType.SpSummon, CardId.Zeus); + AddExecutor(ExecutorType.Activate, CardId.Zeus, ZeusEffect); + AddExecutor(ExecutorType.Summon, CardId.Robina); + AddExecutor(ExecutorType.Summon, CardId.Eglen, EglenSummon); + AddExecutor(ExecutorType.Summon, CardId.Toccan, ToccanSummon); + + AddExecutor(ExecutorType.Activate, CardId.Robina, RobinaEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenEffect); AddExecutor(ExecutorType.Activate, CardId.Toccan, ToccanEffect); @@ -78,7 +90,6 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) // Chain block for strongest effect monster AddExecutor(ExecutorType.Activate, CardId.Empen, EmpenEffect); - AddExecutor(ExecutorType.Activate, CardId.Snowl, SnowBattle); AddExecutor(ExecutorType.Activate, CardId.Robina, RobinaBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, ToccanBanishedEffect); @@ -91,11 +102,141 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherStorm); } + private bool ToccanSummon() + { + return !(eglen_NormalSummonEffectActivated || robina_NormalSummonEffectActivated); + } + + private bool UnexploredWindsActivate() + { + if (Card.Location == CardLocation.Hand) + { + List hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.Level > 6).ToList(); + + if (hand_bossMonsters.Count() > 0) + return true; + } + else if (Card.Location == CardLocation.SpellZone) + { + if(!Bot.Hand.ContainsMonsterWithLevel(1)) + return true; + } + + return false; + } + + private bool EglenSummon() + { + if (!(Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina))) + return true; + + return false; + } + + private bool SnowlActivate() + { + if (Duel.Player == 0 && (Duel.Phase == DuelPhase.Main1 || Duel.Phase == DuelPhase.Main2) && !(robina_NormalSummonEffectActivated || eglen_NormalSummonEffectActivated)) + return true; + else if ((Duel.Player == 1 && (Duel.Phase == DuelPhase.Main1 || Duel.Phase == DuelPhase.Main2 || Duel.Phase == DuelPhase.Battle) && ActivateDescription == Util.GetStringId(CardId.Snowl, 0))) + return true; + + return false; + } + + private bool PotOfProsperityActivate() + { + if (Bot.ExtraDeck.Count <= 3) return false; + + AI.SelectOption(2); // banish 6 + + List cardsId = new List(); + + if (!Bot.HasInHand(CardId.Robina) || !Bot.HasInBanished(CardId.Robina)) + cardsId.Add(CardId.Robina); + if (Bot.HasInBanished(CardId.DreamingTown)) + cardsId.Add(CardId.Toccan); + if (Bot.HasInGraveyard(CardId.Empen) || Bot.HasInGraveyard(CardId.Snowl) || Bot.HasInGraveyard(CardId.Avian) || Bot.HasInGraveyard(CardId.RaizaMegaMonarch)) + cardsId.Add(CardId.Stri); + + if (!Bot.HasInHandOrInSpellZone(CardId.DreamingTown)) + cardsId.Add(CardId.DreamingTown); + if (!Bot.HasInHandOrInSpellZone(CardId.UnexploredWinds)) + cardsId.Add(CardId.UnexploredWinds); + if (!Bot.HasInHand(CardId.MagnificentMap)) + { + cardsId.Add(CardId.Terraforming); + cardsId.Add(CardId.MagnificentMap); + } + + AI.SelectCard(cardsId); + return true; + } + + //public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender) + //{ + // if (!defender.IsMonsterHasPreventActivationEffectInBattle()) + // { + // if (attacker.Attribute == (int)CardAttribute.Light && Bot.HasInHand(CardId.Honest)) + // attacker.RealPower = attacker.RealPower + defender.Attack; + // } + // return base.OnPreBattleBetween(attacker, defender); + //} + + private bool AvianActivate() + { + if (Duel.LastChainPlayer == 1) + { + if (Bot.HasInMonstersZone(CardId.Empen)) AI.SelectCard(Util.GetBestEnemySpell(true)); + else AI.SelectCard(Util.GetBestEnemyCard(true)); + + return true; + } + + return false; + } + + private bool TerraformingActivate() + { + if (!Bot.HasInHandOrInSpellZone(CardId.MagnificentMap)) + return true; + + return false; + } + + private bool ZeusEffect() + { + ClientCard enemy_bestCard = Util.GetBestEnemyCard(true, true); + + if (enemy_bestCard != null) + return true; + + return false; + } + + private bool JuggernautLiebeSummon() + { + AI.SelectPlace(Zones.ExtraMonsterZones); + return true; + + } + + private bool BookOfMoonActivate() + { + ClientCard enemy_bestCard = Util.GetBestEnemyMonster(true, true); + + if (enemy_bestCard != null) { + AI.SelectCard(enemy_bestCard); + return true; + } + + return false; + } + private bool FuchoSpSummon() { AI.SelectPlace(Zones.ExtraMonsterZones); AI.SelectPosition(CardPosition.Attack); - return !(Bot.HasInExtra(CardId.Fucho) || Bot.HasInMonstersZone(CardId.Fucho)); + return !Bot.HasInMonstersZone(CardId.Fucho); } private bool JuggernautGustavMaxOverlay() @@ -191,7 +332,11 @@ private bool MagnificentMapActivate() private bool AdventOfAdventureEffect() { - int[] cost = Bot.Hand.GetMatchingCards(card => card.Level == 1 && !card.IsCode(CardId.Robina)).Select(c => c.Id).ToArray(); + int[] cost; + + if(!Bot.Hand.ContainsMonsterWithLevel(1)) + cost = Bot.Hand.GetMatchingCards(card => card.Level > 5 && !card.IsCode(CardId.Robina)).Select(c => c.Id).ToArray(); + else cost = Bot.Hand.GetMatchingCards(card => card.Level == 1 && !card.IsCode(CardId.Robina)).Select(c => c.Id).ToArray(); if (!Bot.HasInHand(CardId.Robina) && cost.Count() > 0) { @@ -222,7 +367,7 @@ private bool AdventOfAdventureEffect() private bool DreamingTownSet() { - return Bot.HasInHand(CardId.Robina); + return Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina); } private bool PotOfDualityActivate() @@ -257,10 +402,9 @@ private bool PotOfDualityActivate() private bool RobinaBanishedEffect() { - ClientCard empen = Bot.MonsterZone.GetFirstMatchingCard(card => card.IsCode(CardId.Empen)); - if (Duel.CurrentChain.Contains(empen)) + if (Duel.CurrentChain.Contains(empen) || !Bot.HasInHand(CardId.Robina)) { if (!(Card.Location == CardLocation.MonsterZone || Card.Location == CardLocation.Grave || Card.Location == CardLocation.Hand)) return true; @@ -342,6 +486,7 @@ private bool EmpenEffect() AI.SelectYesNo(decision); + //SP summon boss monsters if (decision && Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 1) { List prefferedMonster = new List(); @@ -360,8 +505,32 @@ private bool EmpenEffect() { int[] hand_Level1_Monsters = Bot.Hand.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); - if (Bot.HasInHand(CardId.Robina)) AI.SelectNextCard(CardId.Robina); - else AI.SelectNextCard(hand_Level1_Monsters); + if (Bot.HasInHand(CardId.Stri) + && ( + Bot.HasInGraveyard(CardId.Empen) + || Bot.HasInGraveyard(CardId.Snowl) + || Bot.HasInGraveyard(CardId.Avian) + || Bot.HasInGraveyard(CardId.RaizaMegaMonarch) + || Bot.HasInBanished(CardId.UnexploredWinds) + || Bot.HasInBanished(CardId.DreamingTown) + )) + { + AI.SelectNextCard(CardId.Stri); + } else if ( + Bot.HasInHand(CardId.Stri) + && ( + Bot.HasInBanished(CardId.Empen) + || Bot.HasInBanished(CardId.Snowl) + || Bot.HasInBanished(CardId.Avian) + || Bot.HasInBanished(CardId.RaizaMegaMonarch) + || Bot.HasInBanished(CardId.UnexploredWinds) + || Bot.HasInBanished(CardId.DreamingTown) + )) + { + AI.SelectNextCard(CardId.Toccan); + } + + else AI.SelectNextCard(CardId.Robina); } return true; @@ -382,30 +551,32 @@ private bool EglenEffect() { if (Card.Location == CardLocation.MonsterZone) { - List materials = new List(); - materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).ToList(); + List materials = new List(); + materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1) + .Select(x => x.Id) + .ToList(); int[] prefferedCards = new int[] { - CardId.Avian + CardId.Snowl }; if (!Bot.HasInHandOrHasInMonstersZone(CardId.Empen)) { // Fetch empen from deck AI.SelectCard(CardId.Empen); - AI.SelectNextCard(CardId.Empen); + // Summon empen + AI.SelectNextCard(CardId.Empen); AI.SelectMaterials(materials); - return true; } else { - if (Bot.HasInHand(CardId.Snowl)) + if (!Bot.HasInHand(CardId.Avian)) { - AI.SelectCard(CardId.Snowl); - AI.SelectNextCard(CardId.Snowl); + AI.SelectCard(CardId.Avian); + AI.SelectNextCard(CardId.Avian); AI.SelectMaterials(materials); } From df85f7aa57acfb634c1b432203141be3a4981027 Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Sat, 30 Dec 2023 00:41:42 +0800 Subject: [PATCH 04/21] additional executors --- Game/AI/Decks/FloowandereezeExecutor.cs | 215 +++++++++++++++++++++--- 1 file changed, 194 insertions(+), 21 deletions(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index e402e32f..7c86314a 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -52,23 +52,25 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) : base(ai, duel) { AddExecutor(ExecutorType.Activate, CardId.DimensionShifter); - AddExecutor(ExecutorType.Activate, CardId.BookOfMoon, BookOfMoonActivate); AddExecutor(ExecutorType.Activate, CardId.PotOfDuality, PotOfDualityActivate); AddExecutor(ExecutorType.Activate, CardId.PotOfProsperity, PotOfProsperityActivate); AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherDuster, DefaultHarpiesFeatherDusterFirst); + AddExecutor(ExecutorType.Activate, CardId.TrippleTacticsTalent, TrippleTacticsTalentActivate); + AddExecutor(ExecutorType.Activate, CardId.AdventOfAdventure, AdventOfAdventureEffect); AddExecutor(ExecutorType.Activate, CardId.Terraforming, TerraformingActivate); AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, MagnificentMapActivate); AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, Active_MagnificentMapActivate); AddExecutor(ExecutorType.Activate, CardId.UnexploredWinds, UnexploredWindsActivate); + AddExecutor(ExecutorType.Activate, CardId.TrippleTacticsThrust, TrippleTacticsThrustActivate); - AddExecutor(ExecutorType.Activate, CardId.Snowl, SnowlActivate); - AddExecutor(ExecutorType.Activate, CardId.Avian, AvianActivate); - - + // XYZ Summons + AddExecutor(ExecutorType.SpSummon, CardId.AssembeledNightingale, AssembeledNightingaleSpSummon); + AddExecutor(ExecutorType.SpSummon, CardId.DowneredMagician); AddExecutor(ExecutorType.SpSummon, CardId.Fucho, FuchoSpSummon); + AddExecutor(ExecutorType.Activate, CardId.Fucho); AddExecutor(ExecutorType.SpSummon, CardId.GustavMax, JuggernautGustavMaxOverlay); AddExecutor(ExecutorType.Activate, CardId.GustavMax); @@ -77,6 +79,12 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.SpSummon, CardId.Zeus); AddExecutor(ExecutorType.Activate, CardId.Zeus, ZeusEffect); + AddExecutor(ExecutorType.Summon, CardId.Snowl, SnowlSummon); + AddExecutor(ExecutorType.Summon, CardId.Avian, AvianSummon); + AddExecutor(ExecutorType.Summon, CardId.RaizaMegaMonarch, RaizaMegaMonarchSummon); + + AddExecutor(ExecutorType.Activate, CardId.Snowl, SnowlActivate); + AddExecutor(ExecutorType.Activate, CardId.Avian, AvianActivate); AddExecutor(ExecutorType.Summon, CardId.Robina); AddExecutor(ExecutorType.Summon, CardId.Eglen, EglenSummon); @@ -86,13 +94,15 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.Robina, RobinaEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenEffect); AddExecutor(ExecutorType.Activate, CardId.Toccan, ToccanEffect); - AddExecutor(ExecutorType.Activate, CardId.Stri); + AddExecutor(ExecutorType.Activate, CardId.Stri, StriEffect); // Chain block for strongest effect monster AddExecutor(ExecutorType.Activate, CardId.Empen, EmpenEffect); AddExecutor(ExecutorType.Activate, CardId.Robina, RobinaBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, ToccanBanishedEffect); + AddExecutor(ExecutorType.Activate, CardId.Stri, StriBanishedEffect); + AddExecutor(ExecutorType.SpellSet, CardId.DreamingTown, DreamingTownSet); AddExecutor(ExecutorType.Activate, CardId.DreamingTown); @@ -102,6 +112,162 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherStorm); } + private bool StriBanishedEffect() + { + ClientCard robina = Bot.Banished.GetFirstMatchingCard(card => card.IsCode(CardId.Robina)); + + if (!(Card.Location == CardLocation.MonsterZone || Card.Location == CardLocation.Grave || Card.Location == CardLocation.Hand)) + return true; + + return false; + } + + private bool StriEffect() + { + if (Card.Location == CardLocation.MonsterZone) + { + + List prefferedCards = new List() + { + CardId.UnexploredWinds + }; + + if (Enemy.Graveyard.GetDangerousMonster() != null) + prefferedCards.Add(Enemy.Graveyard.GetDangerousMonster().Id); + + AI.SelectCard(prefferedCards); + + if (Bot.HasInHand(CardId.Toccan) && Bot.Banished.Count() > 0) AI.SelectCard(CardId.Toccan); + else + { + AI.SelectCard(Bot.Hand.GetMatchingCards(card => card.Level > 5).Select(c => c.Id).ToList()); + AI.SelectThirdCard(Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToList()); + } + + return true; + } + + return false; + } + + private bool TrippleTacticsTalentActivate() + { + if (Bot.MonsterZone.Count() > 1) + AI.SelectOption(1); + else if (Util.IsAllEnemyBetter()) + AI.SelectOption(2); + else + { + AI.SelectOption(3); + AI.SelectNextCard(Enemy.Hand.GetDangerousMonster()); + } + + return true; + } + + private bool robina_NormalSummonEffectActivated = false, + eglen_NormalSummonEffectActivated = false, + PotOfProsperityActivated = false; + + private bool TrippleTacticsThrustActivate() + { + if (Bot.Deck.GetCardCount(CardId.TrippleTacticsTalent) != 0) AI.SelectCard(CardId.TrippleTacticsTalent); + else if (!(Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina))) AI.SelectCard(CardId.AdventOfAdventure); + else if (!Bot.HasInSpellZone(CardId.MagnificentMap)) AI.SelectCard(CardId.MagnificentMap); + else AI.SelectCard(new List { CardId.BookOfMoon, CardId.HarpiesFeatherDuster, CardId.UnexploredWinds }); + + return true; + } + + //public override bool OnSelectYesNo(long desc) + //{ + // if (desc == Util.GetStringId(CardId.AssembeledNightingale, 0)) + // { + // activate_pre_PressuredPlanetWraitsoth = true; + // } + // return base.OnSelectYesNo(desc); + //} + + private bool AssembeledNightingaleSpSummon() + { + if (Bot.HasInMonstersZone(CardId.AssembeledNightingale) || Bot.HasInMonstersZone(CardId.Zeus)) return false; + + AI.SelectPlace(Zones.ExtraMonsterZones); + AI.SelectPosition(CardPosition.Attack); + + // Direct Attack + if (Duel.Player == 0 && Duel.Phase == DuelPhase.BattleStart) + AI.SelectYesNo(true); + + return true; + } + + private bool RaizaMegaMonarchSummon() + { + if (ActivateDescription == Util.GetStringId(CardId.RaizaMegaMonarch,0) && Util.IsAllEnemyBetter() && Enemy.GetFieldCount() > 1) + { + // Target 1 card on the field + AI.SelectCard(Util.GetBestEnemyCard(false, true)); + + // Target card on bot's graveyard + List prefferedCards = Bot.Graveyard.Select(c => c.Id).ToList(); + AI.SelectNextCard(prefferedCards); + + // Target another card if it's tributted with Winged monster + if (prefferedCards.Count() > 0) + { + AI.OnSelectYesNo(1); + AI.SelectNextCard(prefferedCards); + } + else AI.OnSelectYesNo(0); + + return true; + } + + return false; + } + + private bool AvianSummon() + { + return UnexploredWindsTribute(); + } + + private bool SnowlSummon() + { + return UnexploredWindsTribute(); + } + + public override int OnSelectOption(IList options) + { + // Unexplored Winds Option + if (options.Count == 2 && options[1] == Util.GetStringId(CardId.UnexploredWinds, 0)) + return 2; + return base.OnSelectOption(options); + } + + + private bool UnexploredWindsTribute() + { + ClientCard enemyCard = Util.GetBestEnemyCard(); + ClientCard myMonster = Util.GetWorstBotMonster(true); + + if (Bot.HasInSpellZone(CardId.UnexploredWinds) && enemyCard != null) + { + List materials = new List + { + enemyCard.Id, + myMonster.Id + }; + + // tribute summon using opponent's cards + AI.SelectMaterials(materials); + + return true; + } + + return false; + } + private bool ToccanSummon() { return !(eglen_NormalSummonEffectActivated || robina_NormalSummonEffectActivated); @@ -110,15 +276,10 @@ private bool ToccanSummon() private bool UnexploredWindsActivate() { if (Card.Location == CardLocation.Hand) - { - List hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.Level > 6).ToList(); - - if (hand_bossMonsters.Count() > 0) - return true; - } + return true; else if (Card.Location == CardLocation.SpellZone) { - if(!Bot.Hand.ContainsMonsterWithLevel(1)) + if (!Bot.Hand.ContainsMonsterWithLevel(1)) return true; } @@ -169,6 +330,8 @@ private bool PotOfProsperityActivate() } AI.SelectCard(cardsId); + + PotOfProsperityActivated = true; return true; } @@ -207,7 +370,7 @@ private bool ZeusEffect() { ClientCard enemy_bestCard = Util.GetBestEnemyCard(true, true); - if (enemy_bestCard != null) + if (enemy_bestCard != null && Util.IsAllEnemyBetter()) return true; return false; @@ -222,6 +385,9 @@ private bool JuggernautLiebeSummon() private bool BookOfMoonActivate() { + if (!(Duel.Player == 0)) return false; + if(!(Util.IsChainTarget(Card) && Duel.CurrentChain.Contains(Card) && Duel.LastChainPlayer == 1)) return false; + ClientCard enemy_bestCard = Util.GetBestEnemyMonster(true, true); if (enemy_bestCard != null) { @@ -234,6 +400,8 @@ private bool BookOfMoonActivate() private bool FuchoSpSummon() { + if (Bot.HasInExtra(CardId.AssembeledNightingale)) return false; + AI.SelectPlace(Zones.ExtraMonsterZones); AI.SelectPosition(CardPosition.Attack); return !Bot.HasInMonstersZone(CardId.Fucho); @@ -245,12 +413,12 @@ private bool JuggernautGustavMaxOverlay() return true; } - private bool robina_NormalSummonEffectActivated = false, - eglen_NormalSummonEffectActivated = false; + public override void OnNewTurn() { robina_NormalSummonEffectActivated = false; eglen_NormalSummonEffectActivated = false; + PotOfProsperityActivated = false; base.OnNewTurn(); } @@ -314,7 +482,7 @@ private bool Active_MagnificentMapActivate() { AI.SelectCard(reveal); - if (!Bot.HasInHandOrInGraveyard(CardId.Toccan) || !Bot.HasInBanished(CardId.Toccan)) + if (!(Bot.HasInHandOrInGraveyard(CardId.Toccan) || Bot.HasInBanished(CardId.Toccan))) AI.SelectCard(CardId.Toccan); else AI.SelectNextCard(reveal); } @@ -367,7 +535,7 @@ private bool AdventOfAdventureEffect() private bool DreamingTownSet() { - return Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina); + return Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina) || Bot.HasInHandOrHasInMonstersZone(CardId.Eglen) || Bot.HasInBanished(CardId.Eglen); } private bool PotOfDualityActivate() @@ -431,7 +599,7 @@ private bool RobinaEffect() { if (Card.Location == CardLocation.MonsterZone) { - if (!(Bot.HasInHandOrHasInMonstersZone(CardId.Eglen) || Bot.HasInBanished(CardId.Eglen))) + if (!Bot.HasInHand(CardId.Eglen) && !eglen_NormalSummonEffectActivated) { AI.SelectCard(CardId.Eglen); AI.SelectNextCard(CardId.Eglen); @@ -447,9 +615,12 @@ private bool RobinaEffect() CardId.Robina }; - if (Bot.HasInHand(CardId.Eglen)) + int[] hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.Level > 5).Select(c => c.Id).ToArray(); + + if (hand_bossMonsters.Count() > 0) { - AI.SelectCard(CardId.Eglen); + AI.SelectCard(hand_bossMonsters); + AI.SelectMaterials(Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray()); } else { @@ -457,6 +628,8 @@ private bool RobinaEffect() AI.SelectNextCard(otherPrefferedCards); } + + robina_NormalSummonEffectActivated = true; return true; From d9866eda99760949b0a0e1156b26f32a7abae090 Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Sat, 30 Dec 2023 13:58:33 +0800 Subject: [PATCH 05/21] WIP: empen normal summon another monster --- Game/AI/Decks/FloowandereezeExecutor.cs | 93 ++++++++++++++++++------- 1 file changed, 66 insertions(+), 27 deletions(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index 7c86314a..af28cef0 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -56,21 +56,13 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.PotOfDuality, PotOfDualityActivate); AddExecutor(ExecutorType.Activate, CardId.PotOfProsperity, PotOfProsperityActivate); AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherDuster, DefaultHarpiesFeatherDusterFirst); - AddExecutor(ExecutorType.Activate, CardId.TrippleTacticsTalent, TrippleTacticsTalentActivate); - - - AddExecutor(ExecutorType.Activate, CardId.AdventOfAdventure, AdventOfAdventureEffect); - AddExecutor(ExecutorType.Activate, CardId.Terraforming, TerraformingActivate); - AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, MagnificentMapActivate); - AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, Active_MagnificentMapActivate); - AddExecutor(ExecutorType.Activate, CardId.UnexploredWinds, UnexploredWindsActivate); AddExecutor(ExecutorType.Activate, CardId.TrippleTacticsThrust, TrippleTacticsThrustActivate); + AddExecutor(ExecutorType.Activate, CardId.TrippleTacticsTalent, TrippleTacticsTalentActivate); // XYZ Summons AddExecutor(ExecutorType.SpSummon, CardId.AssembeledNightingale, AssembeledNightingaleSpSummon); AddExecutor(ExecutorType.SpSummon, CardId.DowneredMagician); AddExecutor(ExecutorType.SpSummon, CardId.Fucho, FuchoSpSummon); - AddExecutor(ExecutorType.Activate, CardId.Fucho); AddExecutor(ExecutorType.SpSummon, CardId.GustavMax, JuggernautGustavMaxOverlay); AddExecutor(ExecutorType.Activate, CardId.GustavMax); @@ -79,6 +71,13 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.SpSummon, CardId.Zeus); AddExecutor(ExecutorType.Activate, CardId.Zeus, ZeusEffect); + AddExecutor(ExecutorType.Activate, CardId.AdventOfAdventure, AdventOfAdventureEffect); + AddExecutor(ExecutorType.Activate, CardId.Terraforming, TerraformingActivate); + AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, MagnificentMapActivate); + AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, Active_MagnificentMapActivate); + AddExecutor(ExecutorType.Activate, CardId.UnexploredWinds, UnexploredWindsActivate); + AddExecutor(ExecutorType.SpellSet, CardId.DreamingTown, DreamingTownSet); + AddExecutor(ExecutorType.Summon, CardId.Snowl, SnowlSummon); AddExecutor(ExecutorType.Summon, CardId.Avian, AvianSummon); AddExecutor(ExecutorType.Summon, CardId.RaizaMegaMonarch, RaizaMegaMonarchSummon); @@ -102,9 +101,6 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, ToccanBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Stri, StriBanishedEffect); - - - AddExecutor(ExecutorType.SpellSet, CardId.DreamingTown, DreamingTownSet); AddExecutor(ExecutorType.Activate, CardId.DreamingTown); AddExecutor(ExecutorType.Activate, CardId.DreamingTown, DreamingTownGraveyardActivate); @@ -144,6 +140,8 @@ private bool StriEffect() AI.SelectThirdCard(Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToList()); } + stri_NormalSummonEffectActivated = true; + return true; } @@ -167,7 +165,11 @@ private bool TrippleTacticsTalentActivate() private bool robina_NormalSummonEffectActivated = false, eglen_NormalSummonEffectActivated = false, - PotOfProsperityActivated = false; + stri_NormalSummonEffectActivated = false, + toccan_NormalSummonEffectActivated = false; + + + private bool PotOfProsperityActivated = false; private bool TrippleTacticsThrustActivate() { @@ -419,6 +421,8 @@ public override void OnNewTurn() robina_NormalSummonEffectActivated = false; eglen_NormalSummonEffectActivated = false; PotOfProsperityActivated = false; + stri_NormalSummonEffectActivated = false; + toccan_NormalSummonEffectActivated = false; base.OnNewTurn(); } @@ -460,6 +464,7 @@ private bool ToccanEffect() if (Bot.HasInBanished(CardId.DreamingTown)) AI.SelectCard(CardId.DreamingTown); else AI.SelectCard(preffererdCards); + stri_NormalSummonEffectActivated = true; return true; } @@ -469,7 +474,7 @@ private bool ToccanEffect() private bool Active_MagnificentMapActivate() { - if (Card.Location == CardLocation.SpellZone) + if (Card.Location == CardLocation.SpellZone && !(Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina))) { int[] reveal = Bot.Hand.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); @@ -480,7 +485,7 @@ private bool Active_MagnificentMapActivate() } else { - AI.SelectCard(reveal); + AI.SelectCard(CardId.Robina); if (!(Bot.HasInHandOrInGraveyard(CardId.Toccan) || Bot.HasInBanished(CardId.Toccan))) AI.SelectCard(CardId.Toccan); @@ -500,11 +505,13 @@ private bool MagnificentMapActivate() private bool AdventOfAdventureEffect() { + if (Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina)) + return false; + int[] cost; - if(!Bot.Hand.ContainsMonsterWithLevel(1)) - cost = Bot.Hand.GetMatchingCards(card => card.Level > 5 && !card.IsCode(CardId.Robina)).Select(c => c.Id).ToArray(); - else cost = Bot.Hand.GetMatchingCards(card => card.Level == 1 && !card.IsCode(CardId.Robina)).Select(c => c.Id).ToArray(); + if(!Bot.Hand.ContainsMonsterWithLevel(1)) cost = Bot.Hand.GetMatchingCards(card => card.Level > 5 && !card.IsCode(CardId.Robina)).Select(c => c.Id).ToArray(); + else cost = Bot.Hand.GetMatchingCards(card => card.Level == 1 && !(card.IsCode(CardId.Robina) || card.IsCode(CardId.Eglen))).Select(c => c.Id).ToArray(); if (!Bot.HasInHand(CardId.Robina) && cost.Count() > 0) { @@ -599,7 +606,7 @@ private bool RobinaEffect() { if (Card.Location == CardLocation.MonsterZone) { - if (!Bot.HasInHand(CardId.Eglen) && !eglen_NormalSummonEffectActivated) + if (!Bot.HasInHandOrHasInMonstersZone(CardId.Eglen) || Bot.HasInBanished(CardId.Eglen)) { AI.SelectCard(CardId.Eglen); AI.SelectNextCard(CardId.Eglen); @@ -612,30 +619,42 @@ private bool RobinaEffect() { CardId.Stri, CardId.Toccan, - CardId.Robina + CardId.Robina, + CardId.Eglen }; int[] hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.Level > 5).Select(c => c.Id).ToArray(); + int[] materials = Bot.Hand.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); - if (hand_bossMonsters.Count() > 0) + // summon boss monsters + if (hand_bossMonsters.Count() > 0 && materials.Count() > 1) { AI.SelectCard(hand_bossMonsters); AI.SelectMaterials(Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray()); } + + if (Bot.Deck.GetCardCount(CardId.Toccan) > 0 && Bot.Banished.Count() > 0) + { + AI.SelectCard(CardId.Toccan); + AI.SelectNextCard(CardId.Toccan); + } + else if (Bot.Deck.GetCardCount(CardId.Stri) > 0 && Bot.Graveyard.Count() > 0) + { + AI.SelectCard(CardId.Toccan); + AI.SelectNextCard(CardId.Toccan); + } else { AI.SelectCard(otherPrefferedCards); - AI.SelectNextCard(otherPrefferedCards); + if (!eglen_NormalSummonEffectActivated) AI.SelectNextCard(CardId.Eglen); + else if(!stri_NormalSummonEffectActivated) AI.SelectNextCard(CardId.Stri); + else if(!toccan_NormalSummonEffectActivated) AI.SelectNextCard(CardId.Toccan); } - - robina_NormalSummonEffectActivated = true; return true; } - - } return false; @@ -739,6 +758,12 @@ private bool EglenEffect() // Fetch empen from deck AI.SelectCard(CardId.Empen); + if (Bot.HasInSpellZone(CardId.UnexploredWinds) && Util.GetBestEnemyCard() != null) + { + AI.SelectOption(2); + materials.Add(Util.GetBestEnemyCard().Id); + } + // Summon empen AI.SelectNextCard(CardId.Empen); AI.SelectMaterials(materials); @@ -749,12 +774,26 @@ private bool EglenEffect() if (!Bot.HasInHand(CardId.Avian)) { AI.SelectCard(CardId.Avian); - AI.SelectNextCard(CardId.Avian); + + if (Bot.HasInHand(CardId.Empen)) AI.SelectNextCard(CardId.Empen); + else AI.SelectNextCard(CardId.Avian); + + if (Bot.HasInSpellZone(CardId.UnexploredWinds) && Util.GetBestEnemyCard() != null) + { + AI.SelectOption(2); + materials.Add(Util.GetBestEnemyCard().Id); + } AI.SelectMaterials(materials); } else { + if (Bot.HasInSpellZone(CardId.UnexploredWinds) && Util.GetBestEnemyCard() != null) + { + AI.SelectOption(2); + materials.Add(Util.GetBestEnemyCard().Id); + } + AI.SelectCard(prefferedCards); AI.SelectMaterials(materials); } From 4374350f85399d84142d6415a9de5d5bd15db452 Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Sat, 30 Dec 2023 22:39:07 +0800 Subject: [PATCH 06/21] WIP: Bot not attacking --- Game/AI/Decks/FloowandereezeExecutor.cs | 396 +++++++++++++++--------- 1 file changed, 253 insertions(+), 143 deletions(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index af28cef0..940c5459 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System; +using System.Threading; namespace WindBot.Game.AI.Decks { @@ -46,35 +47,47 @@ public class CardId public const int UnderworldGoddess = 98127546; public const int Linkuriboh = 41999284; public const int Fucho = 27240101; + public const int SkStrikerAceZeke = 75147529; } + // summon actions + private bool robina_NormalSummonEffectActivated = false, + eglen_NormalSummonEffectActivated = false, + stri_NormalSummonEffectActivated = false, + toccan_NormalSummonEffectActivated = false, + ActivateempenBattleEffect = false; + + // spell actions + private bool PotOfProsperityActivated = false; + + // battle phase Actions + private bool SlackerMagicianAttacks = false; + public FloowandereezeExecutor(GameAI ai, Duel duel) : base(ai, duel) { AddExecutor(ExecutorType.Activate, CardId.DimensionShifter); + AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherDuster, DefaultHarpiesFeatherDusterFirst); AddExecutor(ExecutorType.Activate, CardId.BookOfMoon, BookOfMoonActivate); AddExecutor(ExecutorType.Activate, CardId.PotOfDuality, PotOfDualityActivate); AddExecutor(ExecutorType.Activate, CardId.PotOfProsperity, PotOfProsperityActivate); - AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherDuster, DefaultHarpiesFeatherDusterFirst); + AddExecutor(ExecutorType.Activate, CardId.Terraforming, TerraformingActivate); AddExecutor(ExecutorType.Activate, CardId.TrippleTacticsThrust, TrippleTacticsThrustActivate); AddExecutor(ExecutorType.Activate, CardId.TrippleTacticsTalent, TrippleTacticsTalentActivate); // XYZ Summons - AddExecutor(ExecutorType.SpSummon, CardId.AssembeledNightingale, AssembeledNightingaleSpSummon); - AddExecutor(ExecutorType.SpSummon, CardId.DowneredMagician); - AddExecutor(ExecutorType.SpSummon, CardId.Fucho, FuchoSpSummon); - AddExecutor(ExecutorType.Activate, CardId.Fucho); + AddExecutor(ExecutorType.SpSummon, CardId.SlackerdMagician, SlackerdMagicianSpSummon); + AddExecutor(ExecutorType.SpSummon, CardId.DowneredMagician, DowneredMagicianSpSummon); AddExecutor(ExecutorType.SpSummon, CardId.GustavMax, JuggernautGustavMaxOverlay); AddExecutor(ExecutorType.Activate, CardId.GustavMax); AddExecutor(ExecutorType.SpSummon, CardId.JuggernautLiebe, JuggernautLiebeSummon); AddExecutor(ExecutorType.Activate, CardId.JuggernautLiebe); - AddExecutor(ExecutorType.SpSummon, CardId.Zeus); + AddExecutor(ExecutorType.SpSummon, CardId.Zeus, ZeusSpSummon); AddExecutor(ExecutorType.Activate, CardId.Zeus, ZeusEffect); - AddExecutor(ExecutorType.Activate, CardId.AdventOfAdventure, AdventOfAdventureEffect); - AddExecutor(ExecutorType.Activate, CardId.Terraforming, TerraformingActivate); AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, MagnificentMapActivate); AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, Active_MagnificentMapActivate); + AddExecutor(ExecutorType.Activate, CardId.AdventOfAdventure, AdventOfAdventureEffect); AddExecutor(ExecutorType.Activate, CardId.UnexploredWinds, UnexploredWindsActivate); AddExecutor(ExecutorType.SpellSet, CardId.DreamingTown, DreamingTownSet); @@ -97,17 +110,78 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) // Chain block for strongest effect monster AddExecutor(ExecutorType.Activate, CardId.Empen, EmpenEffect); + AddExecutor(ExecutorType.Activate, CardId.Empen, EmpenBattleEffect); + AddExecutor(ExecutorType.Activate, CardId.Robina, RobinaBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, ToccanBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Stri, StriBanishedEffect); - AddExecutor(ExecutorType.Activate, CardId.DreamingTown); + AddExecutor(ExecutorType.Activate, CardId.DreamingTown, DreamingTownActivate); AddExecutor(ExecutorType.Activate, CardId.DreamingTown, DreamingTownGraveyardActivate); AddExecutor(ExecutorType.SpellSet, CardId.HarpiesFeatherStorm); AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherStorm); } + public override BattlePhaseAction OnBattle(IList attackers, IList defenders) + { + return base.OnBattle(attackers, defenders); + } + + public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender) + { + if (attacker.IsCode(CardId.Empen) && defender.RealPower > attacker.RealPower) + { + ActivateempenBattleEffect = true; + return defender.RealPower / 2 < attacker.RealPower && Bot.Hand.Count() > 0; + } + + + return base.OnPreBattleBetween(attacker, defender); + } + + private bool EmpenBattleEffect() + { + // prioritize theres cards as cost (Do not discard Unexplored Winds and Dreaming Town if you can) + List cost = new List(); + + if (Bot.Hand.Count() > 2) + { + cost = Bot.Hand.GetMatchingCards(card => !(card.IsCode(CardId.UnexploredWinds)) || card.IsCode(CardId.DreamingTown)) + .Select(c => c.Id) + .ToList(); + } + else // prioritize saving Empen and consider every card on hand as a cost + cost = Bot.Hand.Select(c => c.Id).ToList(); + + AI.SelectCard(cost); + + return Duel.Phase == DuelPhase.Battle && Bot.Hand.Count() > 0 && ActivateempenBattleEffect; + } + + private bool ZeusSpSummon() + { + AI.SelectPosition(CardPosition.Attack); + AI.SelectPlace(Zones.ExtraMonsterZones); + + return true; + } + + private bool DreamingTownActivate() + { + return Card.Location == CardLocation.SpellZone + && Duel.Player == 1 + && Bot.Hand.ContainsMonsterWithLevel(1); + } + + private bool DowneredMagicianSpSummon() + { + AI.SelectPosition(CardPosition.Attack); + AI.SelectPlace(Zones.ExtraMonsterZones); + + return SlackerMagicianAttacks; + } + private bool StriBanishedEffect() { ClientCard robina = Bot.Banished.GetFirstMatchingCard(card => card.IsCode(CardId.Robina)); @@ -125,12 +199,11 @@ private bool StriEffect() List prefferedCards = new List() { - CardId.UnexploredWinds + CardId.UnexploredWinds, + CardId.AdventOfAdventure, + CardId.MagnificentMap }; - if (Enemy.Graveyard.GetDangerousMonster() != null) - prefferedCards.Add(Enemy.Graveyard.GetDangerousMonster().Id); - AI.SelectCard(prefferedCards); if (Bot.HasInHand(CardId.Toccan) && Bot.Banished.Count() > 0) AI.SelectCard(CardId.Toccan); @@ -163,14 +236,6 @@ private bool TrippleTacticsTalentActivate() return true; } - private bool robina_NormalSummonEffectActivated = false, - eglen_NormalSummonEffectActivated = false, - stri_NormalSummonEffectActivated = false, - toccan_NormalSummonEffectActivated = false; - - - private bool PotOfProsperityActivated = false; - private bool TrippleTacticsThrustActivate() { if (Bot.Deck.GetCardCount(CardId.TrippleTacticsTalent) != 0) AI.SelectCard(CardId.TrippleTacticsTalent); @@ -181,25 +246,18 @@ private bool TrippleTacticsThrustActivate() return true; } - //public override bool OnSelectYesNo(long desc) - //{ - // if (desc == Util.GetStringId(CardId.AssembeledNightingale, 0)) - // { - // activate_pre_PressuredPlanetWraitsoth = true; - // } - // return base.OnSelectYesNo(desc); - //} - - private bool AssembeledNightingaleSpSummon() + private bool SlackerdMagicianSpSummon() { - if (Bot.HasInMonstersZone(CardId.AssembeledNightingale) || Bot.HasInMonstersZone(CardId.Zeus)) return false; + if (Bot.HasInMonstersZone(CardId.SlackerdMagician) || Bot.HasInMonstersZone(CardId.Zeus)) return false; AI.SelectPlace(Zones.ExtraMonsterZones); AI.SelectPosition(CardPosition.Attack); - // Direct Attack if (Duel.Player == 0 && Duel.Phase == DuelPhase.BattleStart) - AI.SelectYesNo(true); + { + SlackerMagicianAttacks = true; + return Card.Attacked; + } return true; } @@ -208,22 +266,8 @@ private bool RaizaMegaMonarchSummon() { if (ActivateDescription == Util.GetStringId(CardId.RaizaMegaMonarch,0) && Util.IsAllEnemyBetter() && Enemy.GetFieldCount() > 1) { - // Target 1 card on the field - AI.SelectCard(Util.GetBestEnemyCard(false, true)); - - // Target card on bot's graveyard - List prefferedCards = Bot.Graveyard.Select(c => c.Id).ToList(); - AI.SelectNextCard(prefferedCards); - - // Target another card if it's tributted with Winged monster - if (prefferedCards.Count() > 0) - { - AI.OnSelectYesNo(1); - AI.SelectNextCard(prefferedCards); - } - else AI.OnSelectYesNo(0); - - return true; + if (Bot.MonsterZone.GetMatchingCards(card => card.Level == 1 && card.HasRace(CardRace.WindBeast)).Count() > 0) + return UnexploredWindsTribute(); } return false; @@ -231,30 +275,28 @@ private bool RaizaMegaMonarchSummon() private bool AvianSummon() { - return UnexploredWindsTribute(); + if(Bot.MonsterZone.GetMatchingCards(card => card.Level == 1 && card.HasRace(CardRace.WindBeast)).Count() > 0) + return UnexploredWindsTribute(); + + return false; } private bool SnowlSummon() { - return UnexploredWindsTribute(); - } + if (Bot.MonsterZone.GetMatchingCards(card => card.Level == 1 && card.HasRace(CardRace.WindBeast)).Count() > 0) + return UnexploredWindsTribute(); - public override int OnSelectOption(IList options) - { - // Unexplored Winds Option - if (options.Count == 2 && options[1] == Util.GetStringId(CardId.UnexploredWinds, 0)) - return 2; - return base.OnSelectOption(options); + return false; } - private bool UnexploredWindsTribute() { ClientCard enemyCard = Util.GetBestEnemyCard(); - ClientCard myMonster = Util.GetWorstBotMonster(true); + ClientCard myMonster = Bot.MonsterZone.GetFirstMatchingFaceupCard(card => card.Level == 1 && card.HasRace(CardRace.WindBeast)); - if (Bot.HasInSpellZone(CardId.UnexploredWinds) && enemyCard != null) + if (Bot.HasInSpellZone(CardId.UnexploredWinds) && enemyCard != null && myMonster != null) { + AI.SelectOption(1); List materials = new List { enemyCard.Id, @@ -281,8 +323,13 @@ private bool UnexploredWindsActivate() return true; else if (Card.Location == CardLocation.SpellZone) { - if (!Bot.Hand.ContainsMonsterWithLevel(1)) + List reveal = Bot.Hand.GetMatchingCards(card => card.Level > 5 && card.HasRace(CardRace.WindBeast)).Select(c => c.Id).ToList(); + + if (!Bot.Hand.ContainsMonsterWithLevel(1) && reveal.Count() > 0) + { + AI.SelectCard(reveal); return true; + } } return false; @@ -310,8 +357,6 @@ private bool PotOfProsperityActivate() { if (Bot.ExtraDeck.Count <= 3) return false; - AI.SelectOption(2); // banish 6 - List cardsId = new List(); if (!Bot.HasInHand(CardId.Robina) || !Bot.HasInBanished(CardId.Robina)) @@ -321,31 +366,67 @@ private bool PotOfProsperityActivate() if (Bot.HasInGraveyard(CardId.Empen) || Bot.HasInGraveyard(CardId.Snowl) || Bot.HasInGraveyard(CardId.Avian) || Bot.HasInGraveyard(CardId.RaizaMegaMonarch)) cardsId.Add(CardId.Stri); - if (!Bot.HasInHandOrInSpellZone(CardId.DreamingTown)) + if (!Bot.HasInHandOrInSpellZoneOrInGraveyard(CardId.DreamingTown) || !Bot.HasInBanished(CardId.DreamingTown)) cardsId.Add(CardId.DreamingTown); - if (!Bot.HasInHandOrInSpellZone(CardId.UnexploredWinds)) + if (!Bot.HasInHandOrInSpellZoneOrInGraveyard(CardId.UnexploredWinds) || !Bot.HasInBanished(CardId.UnexploredWinds)) cardsId.Add(CardId.UnexploredWinds); - if (!Bot.HasInHand(CardId.MagnificentMap)) + if (!Bot.HasInHandOrInSpellZone(CardId.MagnificentMap)) { cardsId.Add(CardId.Terraforming); cardsId.Add(CardId.MagnificentMap); } - AI.SelectCard(cardsId); - PotOfProsperityActivated = true; - return true; + + List extraDeckMaterials = new List + { + new ProsperityMaterials { id = CardId.SlackerdMagician, preserveCopy = true }, + new ProsperityMaterials { id = CardId.Fucho, preserveCopy = false }, + new ProsperityMaterials { id = CardId.AssembeledNightingale, preserveCopy = false }, + new ProsperityMaterials { id = CardId.SkStrikerAceZeke, preserveCopy = false }, + new ProsperityMaterials { id = CardId.Linkuriboh, preserveCopy = false }, + new ProsperityMaterials { id = CardId.DowneredMagician, preserveCopy = true } + }; + + return PotOfProsperityFunction(extraDeckMaterials, cardsId); } - //public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender) - //{ - // if (!defender.IsMonsterHasPreventActivationEffectInBattle()) - // { - // if (attacker.Attribute == (int)CardAttribute.Light && Bot.HasInHand(CardId.Honest)) - // attacker.RealPower = attacker.RealPower + defender.Attack; - // } - // return base.OnPreBattleBetween(attacker, defender); - //} + public class ProsperityMaterials + { + public int id { get; set; } + public bool preserveCopy { get; set; } + } + + private bool PotOfProsperityFunction(List extraDeckMonsters, List cardExavationPriority) + { + // select materials + List banishList = new List(); + + + + foreach (var card in extraDeckMonsters) + { + if (card.preserveCopy) + { + if (Bot.ExtraDeck.GetCardCount(card.id) > 1) + banishList.Add(card.id); + } + else banishList.Add(card.id); + } + + if (banishList.Count > 3) + AI.SelectOption(1); // Banish 6 + else AI.SelectOption(0); // banish 3 + + if (banishList.Count() > 3) + { + AI.SelectCard(banishList); + AI.SelectNextCard(cardExavationPriority); + return true; + } + + return false; + } private bool AvianActivate() { @@ -370,9 +451,11 @@ private bool TerraformingActivate() private bool ZeusEffect() { - ClientCard enemy_bestCard = Util.GetBestEnemyCard(true, true); + if (Duel.CurrentChain.Contains(Card)) return false; // do not chain to self + + ClientCard enemy_bestCard = Util.GetBestEnemyCard(); - if (enemy_bestCard != null && Util.IsAllEnemyBetter()) + if (enemy_bestCard != null && Util.IsAllEnemyBetter(true)) return true; return false; @@ -418,18 +501,28 @@ private bool JuggernautGustavMaxOverlay() public override void OnNewTurn() { + // engine monsters robina_NormalSummonEffectActivated = false; eglen_NormalSummonEffectActivated = false; PotOfProsperityActivated = false; stri_NormalSummonEffectActivated = false; toccan_NormalSummonEffectActivated = false; + //Battle monsters + ActivateempenBattleEffect = false; + + // Battle phase actions + SlackerMagicianAttacks = false; + base.OnNewTurn(); } private bool DreamingTownGraveyardActivate() { - return Card.Location == CardLocation.Grave && Util.IsAllEnemyBetter() && (Duel.Phase == DuelPhase.Main1 || Duel.Phase == DuelPhase.Main2); + return Card.Location == CardLocation.Grave + && Util.IsAllEnemyBetter() + && (Duel.Phase == DuelPhase.Battle) + && Duel.Player == 1; } private bool ToccanBanishedEffect() @@ -505,6 +598,8 @@ private bool MagnificentMapActivate() private bool AdventOfAdventureEffect() { + if (Duel.LastChainPlayer == 0 && Duel.CurrentChain.Contains(Bot.SpellZone.GetFirstMatchingFaceupCard(card => card.IsCode(CardId.MagnificentMap)))) return false; + if (Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina)) return false; @@ -662,81 +757,91 @@ private bool RobinaEffect() private bool EmpenEffect() { - List other_prefferedCards = new List(); + if (Duel.Phase != DuelPhase.Battle) + { + List other_prefferedCards = new List(); - other_prefferedCards.AddRange(new List { - CardId.UnexploredWinds, - CardId.AdventOfAdventure - }); + other_prefferedCards.AddRange(new List { + CardId.UnexploredWinds + }); - if (!(Bot.HasInHandOrInSpellZoneOrInGraveyard(CardId.DreamingTown) || Bot.HasInBanished(CardId.DreamingTown))) - { - AI.SelectCard(CardId.DreamingTown); + if (!(Bot.HasInHandOrInSpellZoneOrInGraveyard(CardId.DreamingTown) || Bot.HasInBanished(CardId.DreamingTown))) + { + AI.SelectCard(CardId.DreamingTown); - // decided whether to normal summon or not - bool decision = Empen_NormalSummonAgain(); + // decided whether to normal summon or not + bool decision = Empen_NormalSummonAgain(); - AI.SelectYesNo(decision); + AI.SelectYesNo(decision); - //SP summon boss monsters - if (decision && Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 1) - { - List prefferedMonster = new List(); - int[] materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); + //SP summon boss monsters + if (decision && Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 1) + { + List prefferedMonster = new List(); + int[] materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); - if (Bot.HasInHand(CardId.Avian)) prefferedMonster.Add(CardId.Avian); - else if (Bot.HasInHand(CardId.Snowl)) prefferedMonster.Add(CardId.Snowl); - else - prefferedMonster.AddRange(new List { + if (Bot.HasInHand(CardId.Avian)) prefferedMonster.Add(CardId.Avian); + else if (Bot.HasInHand(CardId.Snowl)) prefferedMonster.Add(CardId.Snowl); + else + prefferedMonster.AddRange(new List { CardId.RaizaMegaMonarch }); - AI.SelectNextCard(prefferedMonster); - } - else - { - int[] hand_Level1_Monsters = Bot.Hand.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); - - if (Bot.HasInHand(CardId.Stri) - && ( - Bot.HasInGraveyard(CardId.Empen) - || Bot.HasInGraveyard(CardId.Snowl) - || Bot.HasInGraveyard(CardId.Avian) - || Bot.HasInGraveyard(CardId.RaizaMegaMonarch) - || Bot.HasInBanished(CardId.UnexploredWinds) - || Bot.HasInBanished(CardId.DreamingTown) - )) - { - AI.SelectNextCard(CardId.Stri); - } else if ( - Bot.HasInHand(CardId.Stri) - && ( - Bot.HasInBanished(CardId.Empen) - || Bot.HasInBanished(CardId.Snowl) - || Bot.HasInBanished(CardId.Avian) - || Bot.HasInBanished(CardId.RaizaMegaMonarch) - || Bot.HasInBanished(CardId.UnexploredWinds) - || Bot.HasInBanished(CardId.DreamingTown) - )) + AI.SelectNextCard(prefferedMonster); + } + else { - AI.SelectNextCard(CardId.Toccan); + int[] hand_Level1_Monsters = Bot.Hand.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); + + if (Bot.HasInHand(CardId.Stri) + && ( + Bot.HasInGraveyard(CardId.Empen) + || Bot.HasInGraveyard(CardId.Snowl) + || Bot.HasInGraveyard(CardId.Avian) + || Bot.HasInGraveyard(CardId.RaizaMegaMonarch) + || Bot.HasInBanished(CardId.UnexploredWinds) + || Bot.HasInBanished(CardId.DreamingTown) + )) + { + AI.SelectNextCard(CardId.Stri); + } + else if ( + Bot.HasInHand(CardId.Stri) + && ( + Bot.HasInBanished(CardId.Empen) + || Bot.HasInBanished(CardId.Snowl) + || Bot.HasInBanished(CardId.Avian) + || Bot.HasInBanished(CardId.RaizaMegaMonarch) + || Bot.HasInBanished(CardId.UnexploredWinds) + || Bot.HasInBanished(CardId.DreamingTown) + )) + { + AI.SelectNextCard(CardId.Toccan); + } + + else AI.SelectNextCard(CardId.Robina); } - else AI.SelectNextCard(CardId.Robina); + return true; + } + else + { + AI.SelectCard(other_prefferedCards); + return true; } - - return true; - } - else - { - AI.SelectCard(other_prefferedCards); - return true; } + + return false; } private bool Empen_NormalSummonAgain() { - return Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 1 || !robina_NormalSummonEffectActivated || !eglen_NormalSummonEffectActivated; + return Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 1 + || !robina_NormalSummonEffectActivated && Bot.HasInHand(CardId.Robina) + || !eglen_NormalSummonEffectActivated && Bot.HasInHand(CardId.Eglen) + || !stri_NormalSummonEffectActivated && Bot.HasInHand(CardId.Stri) + || !toccan_NormalSummonEffectActivated && Bot.HasInHand(CardId.Toccan); + } private bool EglenEffect() @@ -753,14 +858,19 @@ private bool EglenEffect() CardId.Snowl }; - if (!Bot.HasInHandOrHasInMonstersZone(CardId.Empen)) + if (!Bot.HasInHandOrHasInMonstersZone(CardId.Empen) + || Bot.MonsterZone.GetCardCount(CardId.Empen) > 0 && Duel.Player == 1) { // Fetch empen from deck AI.SelectCard(CardId.Empen); - if (Bot.HasInSpellZone(CardId.UnexploredWinds) && Util.GetBestEnemyCard() != null) + // Tribute opponent's card using Unexplored winds + if (Bot.HasInSpellZone(CardId.UnexploredWinds) && Util.GetBestEnemyCard() != null && Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 0) { - AI.SelectOption(2); + AI.SelectOption(1); + + materials.Clear(); + materials.Add(Bot.MonsterZone.GetFirstMatchingCard(card => card.Level == 1).Id); materials.Add(Util.GetBestEnemyCard().Id); } From 3c7153c46a2a3d69d151422a316ae9d72bfddbb9 Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Sat, 30 Dec 2023 23:46:12 +0800 Subject: [PATCH 07/21] fixes on executors --- Game/AI/Decks/FloowandereezeExecutor.cs | 40 +++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index 940c5459..6fbf61b2 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -3,6 +3,8 @@ using System.Linq; using System; using System.Threading; +using System.Configuration; +using YGOSharp.OCGWrapper; namespace WindBot.Game.AI.Decks { @@ -63,6 +65,9 @@ public class CardId // battle phase Actions private bool SlackerMagicianAttacks = false; + //xyz activations + private bool ZeusActivated = false; + public FloowandereezeExecutor(GameAI ai, Duel duel) : base(ai, duel) { @@ -125,6 +130,24 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) public override BattlePhaseAction OnBattle(IList attackers, IList defenders) { + foreach (ClientCard card in attackers) + { + if (card.IsCode(CardId.Empen)) + { + ClientCard empenTarget = defenders.GetHighestAttackMonster(); + if (empenTarget != null && OnPreBattleBetween(card, empenTarget)) + return AI.Attack(card, empenTarget); + + } + else if (card.IsCode(CardId.SlackerdMagician)) + { + ClientCard slackerTarget = defenders.GetLowestAttackMonster(); + + if (slackerTarget != null && OnPreBattleBetween(card,slackerTarget)) + return AI.Attack(card, slackerTarget); + } + } + return base.OnBattle(attackers, defenders); } @@ -132,10 +155,18 @@ public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender { if (attacker.IsCode(CardId.Empen) && defender.RealPower > attacker.RealPower) { - ActivateempenBattleEffect = true; + if (defender.RealPower > attacker.RealPower) ActivateempenBattleEffect = true; + else ActivateempenBattleEffect = false; + return defender.RealPower / 2 < attacker.RealPower && Bot.Hand.Count() > 0; } - + + if (attacker.IsCode(CardId.SlackerdMagician) && defender.RealPower > attacker.RealPower) + { + int potentialSelfDamage = defender.RealPower - attacker.RealPower; + SlackerMagicianAttacks = Bot.LifePoints > potentialSelfDamage ? true : false; + return Bot.LifePoints > potentialSelfDamage; + } return base.OnPreBattleBetween(attacker, defender); } @@ -451,7 +482,7 @@ private bool TerraformingActivate() private bool ZeusEffect() { - if (Duel.CurrentChain.Contains(Card)) return false; // do not chain to self + if (ZeusActivated && Duel.Player == 0) return false; ClientCard enemy_bestCard = Util.GetBestEnemyCard(); @@ -514,6 +545,9 @@ public override void OnNewTurn() // Battle phase actions SlackerMagicianAttacks = false; + // XYZ Activation + ZeusActivated = false; + base.OnNewTurn(); } From b29d618ea6ec360faee5d9c4b78ef1ca0212ad0d Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Mon, 1 Jan 2024 01:30:20 +0800 Subject: [PATCH 08/21] fixes on empen fixes on Dreamtown --- Game/AI/Decks/FloowandereezeExecutor.cs | 71 ++++++++++++++----------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index 6fbf61b2..7da49305 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -137,7 +137,6 @@ public override BattlePhaseAction OnBattle(IList attackers, IList attacker.RealPower) { if (defender.RealPower > attacker.RealPower) ActivateempenBattleEffect = true; - else ActivateempenBattleEffect = false; + else if (defender.RealPower <= attacker.RealPower) ActivateempenBattleEffect = false; return defender.RealPower / 2 < attacker.RealPower && Bot.Hand.Count() > 0; } @@ -173,21 +172,26 @@ public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender private bool EmpenBattleEffect() { - // prioritize theres cards as cost (Do not discard Unexplored Winds and Dreaming Town if you can) - List cost = new List(); - - if (Bot.Hand.Count() > 2) + if (Duel.Phase == DuelPhase.Battle) { - cost = Bot.Hand.GetMatchingCards(card => !(card.IsCode(CardId.UnexploredWinds)) || card.IsCode(CardId.DreamingTown)) - .Select(c => c.Id) - .ToList(); - } - else // prioritize saving Empen and consider every card on hand as a cost - cost = Bot.Hand.Select(c => c.Id).ToList(); + // prioritize theres cards as cost (Do not discard Unexplored Winds and Dreaming Town if you can) + List cost = new List(); + + if (Bot.Hand.Count() > 2) + { + cost = Bot.Hand.GetMatchingCards(card => !(card.IsCode(CardId.UnexploredWinds)) || card.IsCode(CardId.DreamingTown)) + .Select(c => c.Id) + .ToList(); + } + else // prioritize saving Empen and consider every card on hand as a cost + cost = Bot.Hand.Select(c => c.Id).ToList(); - AI.SelectCard(cost); + AI.SelectCard(cost); - return Duel.Phase == DuelPhase.Battle && Bot.Hand.Count() > 0 && ActivateempenBattleEffect; + return cost.Count() > 0 && ActivateempenBattleEffect; + } + + return false; } private bool ZeusSpSummon() @@ -200,6 +204,9 @@ private bool ZeusSpSummon() private bool DreamingTownActivate() { + if (Bot.HasInHand(CardId.Robina) && !robina_NormalSummonEffectActivated) + AI.SelectCard(CardId.Robina); + return Card.Location == CardLocation.SpellZone && Duel.Player == 1 && Bot.Hand.ContainsMonsterWithLevel(1); @@ -486,8 +493,13 @@ private bool ZeusEffect() ClientCard enemy_bestCard = Util.GetBestEnemyCard(); - if (enemy_bestCard != null && Util.IsAllEnemyBetter(true)) + if (enemy_bestCard != null) + { + if (Duel.Player == 1 && enemy_bestCard.Attack > Card.Attack) + return true; + return true; + } return false; } @@ -554,8 +566,7 @@ public override void OnNewTurn() private bool DreamingTownGraveyardActivate() { return Card.Location == CardLocation.Grave - && Util.IsAllEnemyBetter() - && (Duel.Phase == DuelPhase.Battle) + && Util.IsAllEnemyBetter(true) && Duel.Player == 1; } @@ -740,6 +751,8 @@ private bool RobinaEffect() AI.SelectCard(CardId.Eglen); AI.SelectNextCard(CardId.Eglen); + robina_NormalSummonEffectActivated = true; + return true; } else @@ -870,8 +883,7 @@ private bool EmpenEffect() private bool Empen_NormalSummonAgain() { - return Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 1 - || !robina_NormalSummonEffectActivated && Bot.HasInHand(CardId.Robina) + return !robina_NormalSummonEffectActivated && Bot.HasInHand(CardId.Robina) || !eglen_NormalSummonEffectActivated && Bot.HasInHand(CardId.Eglen) || !stri_NormalSummonEffectActivated && Bot.HasInHand(CardId.Stri) || !toccan_NormalSummonEffectActivated && Bot.HasInHand(CardId.Toccan); @@ -887,11 +899,6 @@ private bool EglenEffect() .Select(x => x.Id) .ToList(); - int[] prefferedCards = new int[] - { - CardId.Snowl - }; - if (!Bot.HasInHandOrHasInMonstersZone(CardId.Empen) || Bot.MonsterZone.GetCardCount(CardId.Empen) > 0 && Duel.Player == 1) { @@ -911,20 +918,27 @@ private bool EglenEffect() // Summon empen AI.SelectNextCard(CardId.Empen); AI.SelectMaterials(materials); + + eglen_NormalSummonEffectActivated = true; + return true; } else { - if (!Bot.HasInHand(CardId.Avian)) + if (!Bot.HasInHand(CardId.Avian) && Duel.Player == 1) { - AI.SelectCard(CardId.Avian); + if (!Bot.HasInHand(CardId.Empen)) AI.SelectCard(CardId.Empen); + else AI.SelectCard(CardId.Avian); + // Normal summon next monster if (Bot.HasInHand(CardId.Empen)) AI.SelectNextCard(CardId.Empen); else AI.SelectNextCard(CardId.Avian); - if (Bot.HasInSpellZone(CardId.UnexploredWinds) && Util.GetBestEnemyCard() != null) + if (Bot.HasInSpellZone(CardId.UnexploredWinds) && Util.GetBestEnemyCard() != null && Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 0) { AI.SelectOption(2); + materials.Clear(); + materials.Add(Bot.MonsterZone.GetFirstMatchingCard(card => card.Level == 1).Id); materials.Add(Util.GetBestEnemyCard().Id); } @@ -937,9 +951,6 @@ private bool EglenEffect() AI.SelectOption(2); materials.Add(Util.GetBestEnemyCard().Id); } - - AI.SelectCard(prefferedCards); - AI.SelectMaterials(materials); } eglen_NormalSummonEffectActivated = true; From 68aedfaa6deb0eeb7ff6233635501426012c25f7 Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Mon, 1 Jan 2024 15:13:21 +0800 Subject: [PATCH 09/21] WIP: fix empen activation of battle phase effect --- Game/AI/Decks/FloowandereezeExecutor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index 7da49305..bdf0faea 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -155,7 +155,7 @@ public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender if (attacker.IsCode(CardId.Empen) && defender.RealPower > attacker.RealPower) { if (defender.RealPower > attacker.RealPower) ActivateempenBattleEffect = true; - else if (defender.RealPower <= attacker.RealPower) ActivateempenBattleEffect = false; + else ActivateempenBattleEffect = false; return defender.RealPower / 2 < attacker.RealPower && Bot.Hand.Count() > 0; } From 4d93dc50cbea68cd7727cf8599c46c94fca5e777 Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Mon, 1 Jan 2024 15:44:05 +0800 Subject: [PATCH 10/21] Fixed empen wasting normal summon resources after resolving search effect --- Game/AI/Decks/FloowandereezeExecutor.cs | 78 ++++++------------------- 1 file changed, 19 insertions(+), 59 deletions(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index bdf0faea..bc3229fe 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -813,69 +813,32 @@ private bool EmpenEffect() }); if (!(Bot.HasInHandOrInSpellZoneOrInGraveyard(CardId.DreamingTown) || Bot.HasInBanished(CardId.DreamingTown))) - { AI.SelectCard(CardId.DreamingTown); + else AI.SelectCard(other_prefferedCards); - // decided whether to normal summon or not - bool decision = Empen_NormalSummonAgain(); + bool decision = Empen_NormalSummonAgain(); - AI.SelectYesNo(decision); + if (decision) + { + AI.SelectYesNo(true); - //SP summon boss monsters - if (decision && Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 1) - { - List prefferedMonster = new List(); - int[] materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); + List prefferedMonster = new List(); + int[] materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); - if (Bot.HasInHand(CardId.Avian)) prefferedMonster.Add(CardId.Avian); - else if (Bot.HasInHand(CardId.Snowl)) prefferedMonster.Add(CardId.Snowl); - else - prefferedMonster.AddRange(new List { + if (Bot.HasInHand(CardId.Empen)) prefferedMonster.Add(CardId.Empen); + else if (Bot.HasInHand(CardId.Snowl)) prefferedMonster.Add(CardId.Snowl); + else if (Bot.HasInHand(CardId.Avian)) prefferedMonster.Add(CardId.Avian); + else + prefferedMonster.AddRange(new List { CardId.RaizaMegaMonarch }); - AI.SelectNextCard(prefferedMonster); - } - else - { - int[] hand_Level1_Monsters = Bot.Hand.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); - - if (Bot.HasInHand(CardId.Stri) - && ( - Bot.HasInGraveyard(CardId.Empen) - || Bot.HasInGraveyard(CardId.Snowl) - || Bot.HasInGraveyard(CardId.Avian) - || Bot.HasInGraveyard(CardId.RaizaMegaMonarch) - || Bot.HasInBanished(CardId.UnexploredWinds) - || Bot.HasInBanished(CardId.DreamingTown) - )) - { - AI.SelectNextCard(CardId.Stri); - } - else if ( - Bot.HasInHand(CardId.Stri) - && ( - Bot.HasInBanished(CardId.Empen) - || Bot.HasInBanished(CardId.Snowl) - || Bot.HasInBanished(CardId.Avian) - || Bot.HasInBanished(CardId.RaizaMegaMonarch) - || Bot.HasInBanished(CardId.UnexploredWinds) - || Bot.HasInBanished(CardId.DreamingTown) - )) - { - AI.SelectNextCard(CardId.Toccan); - } - - else AI.SelectNextCard(CardId.Robina); - } - - return true; - } - else - { - AI.SelectCard(other_prefferedCards); - return true; + AI.SelectNextCard(prefferedMonster); + AI.SelectMaterials(materials); } + else AI.SelectYesNo(false); + + return true; } return false; @@ -883,11 +846,8 @@ private bool EmpenEffect() private bool Empen_NormalSummonAgain() { - return !robina_NormalSummonEffectActivated && Bot.HasInHand(CardId.Robina) - || !eglen_NormalSummonEffectActivated && Bot.HasInHand(CardId.Eglen) - || !stri_NormalSummonEffectActivated && Bot.HasInHand(CardId.Stri) - || !toccan_NormalSummonEffectActivated && Bot.HasInHand(CardId.Toccan); - + return (Bot.Hand.ContainsMonsterWithLevel(8) || Bot.Hand.ContainsMonsterWithLevel(7)) + && Bot.MonsterZone.GetMatchingCardsCount(card => card.Level == 1) > 1; } private bool EglenEffect() From 58913a62fdd3c83e2b674e12114a871e87f7a968 Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Mon, 1 Jan 2024 19:41:29 +0800 Subject: [PATCH 11/21] Improved empen battle effect activation requirements. --- Game/AI/Decks/FloowandereezeExecutor.cs | 181 +++++++++++++++--------- 1 file changed, 114 insertions(+), 67 deletions(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index bc3229fe..c8e880e9 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -5,6 +5,8 @@ using System.Threading; using System.Configuration; using YGOSharp.OCGWrapper; +using YGOSharp.Network.Enums; +using WindBot.Game.AI.Enums; namespace WindBot.Game.AI.Decks { @@ -95,6 +97,11 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.AdventOfAdventure, AdventOfAdventureEffect); AddExecutor(ExecutorType.Activate, CardId.UnexploredWinds, UnexploredWindsActivate); AddExecutor(ExecutorType.SpellSet, CardId.DreamingTown, DreamingTownSet); + AddExecutor(ExecutorType.Activate, CardId.DreamingTown, DreamingTownActivate); + AddExecutor(ExecutorType.Activate, CardId.DreamingTown, DreamingTownGraveyardActivate); + + AddExecutor(ExecutorType.SpellSet, CardId.HarpiesFeatherStorm); + AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherStorm, HarpiesFeatherStormActivate); AddExecutor(ExecutorType.Summon, CardId.Snowl, SnowlSummon); AddExecutor(ExecutorType.Summon, CardId.Avian, AvianSummon); @@ -115,17 +122,16 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) // Chain block for strongest effect monster AddExecutor(ExecutorType.Activate, CardId.Empen, EmpenEffect); - AddExecutor(ExecutorType.Activate, CardId.Empen, EmpenBattleEffect); AddExecutor(ExecutorType.Activate, CardId.Robina, RobinaBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, ToccanBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Stri, StriBanishedEffect); - AddExecutor(ExecutorType.Activate, CardId.DreamingTown, DreamingTownActivate); - AddExecutor(ExecutorType.Activate, CardId.DreamingTown, DreamingTownGraveyardActivate); + } - AddExecutor(ExecutorType.SpellSet, CardId.HarpiesFeatherStorm); - AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherStorm); + private bool HarpiesFeatherStormActivate() + { + return Duel.Player == 1; // activate only on opponent's turn } public override BattlePhaseAction OnBattle(IList attackers, IList defenders) @@ -154,11 +160,12 @@ public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender { if (attacker.IsCode(CardId.Empen) && defender.RealPower > attacker.RealPower) { - if (defender.RealPower > attacker.RealPower) ActivateempenBattleEffect = true; - else ActivateempenBattleEffect = false; + int empenPower = attacker.Attack + defender.RealPower; + int target_preEffectPower = (defender.Attack + defender.RealPower) / 2; - return defender.RealPower / 2 < attacker.RealPower && Bot.Hand.Count() > 0; + return (target_preEffectPower < empenPower) && Bot.Hand.Count() > 0; } + if (attacker.IsCode(CardId.SlackerdMagician) && defender.RealPower > attacker.RealPower) { @@ -170,30 +177,6 @@ public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender return base.OnPreBattleBetween(attacker, defender); } - private bool EmpenBattleEffect() - { - if (Duel.Phase == DuelPhase.Battle) - { - // prioritize theres cards as cost (Do not discard Unexplored Winds and Dreaming Town if you can) - List cost = new List(); - - if (Bot.Hand.Count() > 2) - { - cost = Bot.Hand.GetMatchingCards(card => !(card.IsCode(CardId.UnexploredWinds)) || card.IsCode(CardId.DreamingTown)) - .Select(c => c.Id) - .ToList(); - } - else // prioritize saving Empen and consider every card on hand as a cost - cost = Bot.Hand.Select(c => c.Id).ToList(); - - AI.SelectCard(cost); - - return cost.Count() > 0 && ActivateempenBattleEffect; - } - - return false; - } - private bool ZeusSpSummon() { AI.SelectPosition(CardPosition.Attack); @@ -491,6 +474,8 @@ private bool ZeusEffect() { if (ZeusActivated && Duel.Player == 0) return false; + ZeusActivated = true; + ClientCard enemy_bestCard = Util.GetBestEnemyCard(); if (enemy_bestCard != null) @@ -621,14 +606,17 @@ private bool Active_MagnificentMapActivate() AI.SelectCard(reveal); AI.SelectNextCard(CardId.Robina); } - else - { - AI.SelectCard(CardId.Robina); - if (!(Bot.HasInHandOrInGraveyard(CardId.Toccan) || Bot.HasInBanished(CardId.Toccan))) - AI.SelectCard(CardId.Toccan); - else AI.SelectNextCard(reveal); - } + return true; + } + else if (Card.Location == CardLocation.SpellZone && Bot.HasInHandOrHasInMonstersZone(CardId.Robina)) + { + // reveal robina + AI.SelectCard(CardId.Robina); + + if (!(Bot.HasInHandOrHasInMonstersZone(CardId.Toccan) || Bot.HasInBanished(CardId.Toccan))) + AI.SelectCard(CardId.Toccan); + else AI.SelectNextCard(CardId.Stri); return true; } @@ -757,40 +745,69 @@ private bool RobinaEffect() } else { - int[] otherPrefferedCards = new int[] + if (eglen_NormalSummonEffectActivated) { - CardId.Stri, - CardId.Toccan, - CardId.Robina, - CardId.Eglen - }; + int[] otherPrefferedCards = new int[] + { + CardId.Stri, + CardId.Toccan, + CardId.Robina, + CardId.Eglen + }; - int[] hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.Level > 5).Select(c => c.Id).ToArray(); - int[] materials = Bot.Hand.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); + int[] hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.Level > 5).Select(c => c.Id).ToArray(); + int[] materials = Bot.Hand.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); - // summon boss monsters - if (hand_bossMonsters.Count() > 0 && materials.Count() > 1) - { - AI.SelectCard(hand_bossMonsters); - AI.SelectMaterials(Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray()); - } + // summon boss monsters + if (hand_bossMonsters.Count() > 0 && materials.Count() > 1) + { + AI.SelectCard(hand_bossMonsters); + AI.SelectMaterials(Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray()); + } - if (Bot.Deck.GetCardCount(CardId.Toccan) > 0 && Bot.Banished.Count() > 0) - { - AI.SelectCard(CardId.Toccan); - AI.SelectNextCard(CardId.Toccan); - } - else if (Bot.Deck.GetCardCount(CardId.Stri) > 0 && Bot.Graveyard.Count() > 0) - { - AI.SelectCard(CardId.Toccan); - AI.SelectNextCard(CardId.Toccan); + if (Bot.Deck.GetCardCount(CardId.Toccan) > 0 && Bot.Banished.Count() > 0) + { + AI.SelectCard(CardId.Toccan); + AI.SelectNextCard(CardId.Toccan); + } + else if (Bot.Deck.GetCardCount(CardId.Stri) > 0 && Bot.Graveyard.Count() > 0) + { + AI.SelectCard(CardId.Toccan); + AI.SelectNextCard(CardId.Toccan); + } + else + { + AI.SelectCard(otherPrefferedCards); + if (!eglen_NormalSummonEffectActivated) AI.SelectNextCard(CardId.Eglen); + else if (!stri_NormalSummonEffectActivated) AI.SelectNextCard(CardId.Stri); + else if (!toccan_NormalSummonEffectActivated) AI.SelectNextCard(CardId.Toccan); + } + + return true; } else { - AI.SelectCard(otherPrefferedCards); - if (!eglen_NormalSummonEffectActivated) AI.SelectNextCard(CardId.Eglen); - else if(!stri_NormalSummonEffectActivated) AI.SelectNextCard(CardId.Stri); - else if(!toccan_NormalSummonEffectActivated) AI.SelectNextCard(CardId.Toccan); + List materials = new List(); + materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1) + .Select(x => x.Id) + .ToList(); + + // Tribute opponent's card using Unexplored winds + if (Bot.HasInSpellZone(CardId.UnexploredWinds) && Util.GetBestEnemyCard() != null && Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 0) + { + AI.SelectOption(1); + + materials.Clear(); + materials.Add(Bot.MonsterZone.GetFirstMatchingCard(card => card.Level == 1).Id); + materials.Add(Util.GetBestEnemyCard().Id); + } + + // Summon empen + if(Bot.HasInHand(CardId.Empen)) AI.SelectNextCard(CardId.Empen); + else if(Bot.HasInHand(CardId.Avian)) AI.SelectNextCard(CardId.Empen); + else if (Bot.HasInHand(CardId.Snowl)) AI.SelectNextCard(CardId.Snowl); + + AI.SelectMaterials(materials); } robina_NormalSummonEffectActivated = true; @@ -804,7 +821,7 @@ private bool RobinaEffect() private bool EmpenEffect() { - if (Duel.Phase != DuelPhase.Battle) + if (Duel.Phase == DuelPhase.Main1 || Duel.Phase == DuelPhase.Main2) { List other_prefferedCards = new List(); @@ -840,6 +857,36 @@ private bool EmpenEffect() return true; } + else + { + if (ActivateDescription == Util.GetStringId(CardId.Empen, 1)) + { + ClientCard BestMonster = Util.GetBestEnemyMonster(); + + if (BestMonster != null) + { + // prioritize theres cards as cost (Do not discard Unexplored Winds and Dreaming Town if you can) + List cost = new List(); + + if (Bot.Hand.Count() > 2) + { + cost = Bot.Hand.GetMatchingCards(card => !(card.IsCode(CardId.UnexploredWinds)) || card.IsCode(CardId.DreamingTown)) + .Select(c => c.Id) + .ToList(); + } + else cost = Bot.Hand.Select(c => c.Id).ToList(); + + int strongestMonsterAttack = BestMonster.Attack + BestMonster.RealPower; + int empenPower = Card.Attack + Card.RealPower; + + if (cost.Count() > 0 && strongestMonsterAttack >= empenPower) + { + AI.SelectCard(cost); + return true; + } + } + } + } return false; } From e6be28f15fe78cb083c4443039ccbf0b9017661e Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Wed, 3 Jan 2024 21:25:25 +0800 Subject: [PATCH 12/21] Fixes on Unexplored winds tribute summon behaviours Improved level 1 monsters behaviour --- Game/AI/Decks/FloowandereezeExecutor.cs | 195 ++++++++++++++---------- 1 file changed, 114 insertions(+), 81 deletions(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index c8e880e9..9421d393 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -92,6 +92,11 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.SpSummon, CardId.Zeus, ZeusSpSummon); AddExecutor(ExecutorType.Activate, CardId.Zeus, ZeusEffect); + AddExecutor(ExecutorType.Summon, CardId.Snowl, SnowlSummon); + AddExecutor(ExecutorType.Summon, CardId.Avian, AvianSummon); + AddExecutor(ExecutorType.Summon, CardId.Empen, EmpenSummon); + AddExecutor(ExecutorType.Summon, CardId.RaizaMegaMonarch, RaizaMegaMonarchSummon); + AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, MagnificentMapActivate); AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, Active_MagnificentMapActivate); AddExecutor(ExecutorType.Activate, CardId.AdventOfAdventure, AdventOfAdventureEffect); @@ -103,17 +108,11 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.SpellSet, CardId.HarpiesFeatherStorm); AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherStorm, HarpiesFeatherStormActivate); - AddExecutor(ExecutorType.Summon, CardId.Snowl, SnowlSummon); - AddExecutor(ExecutorType.Summon, CardId.Avian, AvianSummon); - AddExecutor(ExecutorType.Summon, CardId.RaizaMegaMonarch, RaizaMegaMonarchSummon); - AddExecutor(ExecutorType.Activate, CardId.Snowl, SnowlActivate); AddExecutor(ExecutorType.Activate, CardId.Avian, AvianActivate); - AddExecutor(ExecutorType.Summon, CardId.Robina); + AddExecutor(ExecutorType.Summon, CardId.Robina, NormalSummonRobina); AddExecutor(ExecutorType.Summon, CardId.Eglen, EglenSummon); - AddExecutor(ExecutorType.Summon, CardId.Toccan, ToccanSummon); - AddExecutor(ExecutorType.Activate, CardId.Robina, RobinaEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenEffect); @@ -129,6 +128,22 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.Stri, StriBanishedEffect); } + private bool EmpenSummon() + { + return UnexploredWindsTribute(); + } + + // Prefer always first if RPS is won + public override bool OnSelectHand() + { + return true; + } + + private bool NormalSummonRobina() + { + return !robina_NormalSummonEffectActivated; + } + private bool HarpiesFeatherStormActivate() { return Duel.Player == 1; // activate only on opponent's turn @@ -169,7 +184,7 @@ public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender if (attacker.IsCode(CardId.SlackerdMagician) && defender.RealPower > attacker.RealPower) { - int potentialSelfDamage = defender.RealPower - attacker.RealPower; + int potentialSelfDamage = (defender.Attack + defender.RealPower) - (attacker.Attack + attacker.RealPower); SlackerMagicianAttacks = Bot.LifePoints > potentialSelfDamage ? true : false; return Bot.LifePoints > potentialSelfDamage; } @@ -222,18 +237,48 @@ private bool StriEffect() { CardId.UnexploredWinds, CardId.AdventOfAdventure, - CardId.MagnificentMap + CardId.MagnificentMap, + CardId.Robina, + CardId.Eglen, + CardId.Empen, + CardId.Avian, + CardId.Snowl, + CardId.Toccan }; AI.SelectCard(prefferedCards); - if (Bot.HasInHand(CardId.Toccan) && Bot.Banished.Count() > 0) AI.SelectCard(CardId.Toccan); - else + int[] hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.Level > 7).Select(c => c.Id).ToArray(); + + List materials = new List(); + materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1) + .Select(x => x.Id) + .ToList(); + + // Tribute opponent's card using Unexplored winds + if (Bot.HasInSpellZone(CardId.UnexploredWinds) && Util.GetBestEnemyCard() != null && Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 0) { - AI.SelectCard(Bot.Hand.GetMatchingCards(card => card.Level > 5).Select(c => c.Id).ToList()); - AI.SelectThirdCard(Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToList()); + AI.SelectOption(1); + + materials.Clear(); + materials.Add(Bot.MonsterZone.GetFirstMatchingCard(card => card.Level == 1).Id); + materials.Add(Util.GetBestEnemyCard().Id); } + // summon boss monsters + if (hand_bossMonsters.Count() > 0 && materials.Count() > 1) + { + AI.SelectYesNo(true); + + // Summon empen + if (Bot.HasInHand(CardId.Empen)) AI.SelectNextCard(CardId.Empen); + else if (Bot.HasInHand(CardId.Avian)) AI.SelectNextCard(CardId.Avian); + else if (Bot.HasInHand(CardId.Snowl)) AI.SelectNextCard(CardId.Snowl); + + AI.SelectMaterials(materials); + } + else AI.SelectYesNo(false); + stri_NormalSummonEffectActivated = true; return true; @@ -333,11 +378,6 @@ private bool UnexploredWindsTribute() return false; } - private bool ToccanSummon() - { - return !(eglen_NormalSummonEffectActivated || robina_NormalSummonEffectActivated); - } - private bool UnexploredWindsActivate() { if (Card.Location == CardLocation.Hand) @@ -358,10 +398,7 @@ private bool UnexploredWindsActivate() private bool EglenSummon() { - if (!(Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina))) - return true; - - return false; + return Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 1; } private bool SnowlActivate() @@ -574,22 +611,47 @@ private bool ToccanEffect() { if (Card.Location == CardLocation.MonsterZone) { + if (Bot.HasInBanished(CardId.UnexploredWinds)) + AI.SelectCard(CardId.UnexploredWinds); + else if (Bot.HasInBanished(CardId.DreamingTown)) + AI.SelectCard(CardId.DreamingTown); + else + { + AI.SelectNextCard(new int[] { + CardId.AdventOfAdventure, + CardId.Empen, + CardId.Avian, + CardId.MagnificentMap + }); + + toccan_NormalSummonEffectActivated = true; + return true; + } - int[] preffererdCards = Bot.Banished.GetMatchingCards(card => - card.Level > 6 - || card.IsCode(CardId.MagnificentMap) - || card.IsCode(CardId.UnexploredWinds) - ).Select(c => c.Id).ToArray(); - - if (Bot.HasInBanished(CardId.Robina)) AI.SelectCard(CardId.Robina); - - - if (Bot.HasInBanished(CardId.DreamingTown)) AI.SelectCard(CardId.DreamingTown); - else AI.SelectCard(preffererdCards); + // Normal Summon again? + int[] hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.Level > 7).Select(c => c.Id).ToArray(); + int[] materials = Bot.Hand.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); - stri_NormalSummonEffectActivated = true; + // summon boss monsters + if (hand_bossMonsters.Count() > 0 && materials.Count() > 1) + { + AI.SelectYesNo(true); - return true; + AI.SelectCard(hand_bossMonsters); + AI.SelectMaterials(Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray()); + } else if (Bot.Deck.GetCardCount(CardId.Stri) > 0 + && (Bot.HasInGraveyard(CardId.DreamingTown) + || Bot.HasInGraveyard(CardId.UnexploredWinds) + || Bot.HasInGraveyard(CardId.AdventOfAdventure) + || Bot.HasInGraveyard(CardId.Empen) + || Bot.HasInGraveyard(CardId.Avian) + || Bot.HasInGraveyard(CardId.MagnificentMap) + )) + { + AI.SelectYesNo(true); + AI.SelectCard(CardId.Stri); + } + else AI.SelectYesNo(false); } return false; @@ -614,8 +676,8 @@ private bool Active_MagnificentMapActivate() // reveal robina AI.SelectCard(CardId.Robina); - if (!(Bot.HasInHandOrHasInMonstersZone(CardId.Toccan) || Bot.HasInBanished(CardId.Toccan))) - AI.SelectCard(CardId.Toccan); + if (!(Bot.HasInHandOrHasInMonstersZone(CardId.Toccan) || Bot.HasInBanished(CardId.Toccan))) AI.SelectNextCard(CardId.Toccan); + else if (eglen_NormalSummonEffectActivated && !Bot.HasInHand(CardId.Eglen)) AI.SelectNextCard(CardId.Eglen); else AI.SelectNextCard(CardId.Stri); return true; @@ -747,46 +809,8 @@ private bool RobinaEffect() { if (eglen_NormalSummonEffectActivated) { - int[] otherPrefferedCards = new int[] - { - CardId.Stri, - CardId.Toccan, - CardId.Robina, - CardId.Eglen - }; - - int[] hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.Level > 5).Select(c => c.Id).ToArray(); - int[] materials = Bot.Hand.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); - - // summon boss monsters - if (hand_bossMonsters.Count() > 0 && materials.Count() > 1) - { - AI.SelectCard(hand_bossMonsters); - AI.SelectMaterials(Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray()); - } + int[] hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.Level > 7).Select(c => c.Id).ToArray(); - if (Bot.Deck.GetCardCount(CardId.Toccan) > 0 && Bot.Banished.Count() > 0) - { - AI.SelectCard(CardId.Toccan); - AI.SelectNextCard(CardId.Toccan); - } - else if (Bot.Deck.GetCardCount(CardId.Stri) > 0 && Bot.Graveyard.Count() > 0) - { - AI.SelectCard(CardId.Toccan); - AI.SelectNextCard(CardId.Toccan); - } - else - { - AI.SelectCard(otherPrefferedCards); - if (!eglen_NormalSummonEffectActivated) AI.SelectNextCard(CardId.Eglen); - else if (!stri_NormalSummonEffectActivated) AI.SelectNextCard(CardId.Stri); - else if (!toccan_NormalSummonEffectActivated) AI.SelectNextCard(CardId.Toccan); - } - - return true; - } - else - { List materials = new List(); materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1) .Select(x => x.Id) @@ -802,12 +826,21 @@ private bool RobinaEffect() materials.Add(Util.GetBestEnemyCard().Id); } - // Summon empen - if(Bot.HasInHand(CardId.Empen)) AI.SelectNextCard(CardId.Empen); - else if(Bot.HasInHand(CardId.Avian)) AI.SelectNextCard(CardId.Empen); - else if (Bot.HasInHand(CardId.Snowl)) AI.SelectNextCard(CardId.Snowl); + // summon boss monsters + if (hand_bossMonsters.Count() > 0 && materials.Count() > 1) + { + AI.SelectYesNo(true); + + // Summon empen + if (Bot.HasInHand(CardId.Empen)) AI.SelectNextCard(CardId.Empen); + else if (Bot.HasInHand(CardId.Avian)) AI.SelectNextCard(CardId.Avian); + else if (Bot.HasInHand(CardId.Snowl)) AI.SelectNextCard(CardId.Snowl); - AI.SelectMaterials(materials); + AI.SelectMaterials(materials); + } + else AI.SelectYesNo(false); + + return true; } robina_NormalSummonEffectActivated = true; From 15d0b0b991ea25772e1d37ba57a7740e8993f155 Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Fri, 5 Jan 2024 23:26:39 +0800 Subject: [PATCH 13/21] improved robina consistency Fixes: 1. Map & DreamingTown Normal summon chain 2. Zeus special summoning multiple times even the card is present on field. 3. Advent of Adventure consistency fixes --- Game/AI/Decks/FloowandereezeExecutor.cs | 168 +++++++++++++----------- 1 file changed, 94 insertions(+), 74 deletions(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index 9421d393..1e08cb04 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -59,7 +59,8 @@ public class CardId eglen_NormalSummonEffectActivated = false, stri_NormalSummonEffectActivated = false, toccan_NormalSummonEffectActivated = false, - ActivateempenBattleEffect = false; + ActivateempenBattleEffect = false, + MagnificentMapActivated = false; // spell actions private bool PotOfProsperityActivated = false; @@ -83,12 +84,12 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.TrippleTacticsTalent, TrippleTacticsTalentActivate); // XYZ Summons - AddExecutor(ExecutorType.SpSummon, CardId.SlackerdMagician, SlackerdMagicianSpSummon); - AddExecutor(ExecutorType.SpSummon, CardId.DowneredMagician, DowneredMagicianSpSummon); AddExecutor(ExecutorType.SpSummon, CardId.GustavMax, JuggernautGustavMaxOverlay); AddExecutor(ExecutorType.Activate, CardId.GustavMax); AddExecutor(ExecutorType.SpSummon, CardId.JuggernautLiebe, JuggernautLiebeSummon); AddExecutor(ExecutorType.Activate, CardId.JuggernautLiebe); + AddExecutor(ExecutorType.SpSummon, CardId.SlackerdMagician, SlackerdMagicianSpSummon); + AddExecutor(ExecutorType.SpSummon, CardId.DowneredMagician, DowneredMagicianSpSummon); AddExecutor(ExecutorType.SpSummon, CardId.Zeus, ZeusSpSummon); AddExecutor(ExecutorType.Activate, CardId.Zeus, ZeusEffect); @@ -124,7 +125,7 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.Robina, RobinaBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenBanishedEffect); - AddExecutor(ExecutorType.Activate, CardId.Eglen, ToccanBanishedEffect); + AddExecutor(ExecutorType.Activate, CardId.Toccan, ToccanBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Stri, StriBanishedEffect); } @@ -163,8 +164,11 @@ public override BattlePhaseAction OnBattle(IList attackers, IList attackers, IList attacker.RealPower) + int realDefenderPower = defender.Attack + defender.RealPower; + int realAttackerPower = attacker.Attack + attacker.RealPower; + + if (attacker.IsCode(CardId.Empen) && realDefenderPower > realAttackerPower) { int empenPower = attacker.Attack + defender.RealPower; int target_preEffectPower = (defender.Attack + defender.RealPower) / 2; @@ -182,10 +189,9 @@ public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender } - if (attacker.IsCode(CardId.SlackerdMagician) && defender.RealPower > attacker.RealPower) + if (attacker.IsCode(CardId.SlackerdMagician) && realDefenderPower > realAttackerPower) { int potentialSelfDamage = (defender.Attack + defender.RealPower) - (attacker.Attack + attacker.RealPower); - SlackerMagicianAttacks = Bot.LifePoints > potentialSelfDamage ? true : false; return Bot.LifePoints > potentialSelfDamage; } @@ -194,6 +200,8 @@ public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender private bool ZeusSpSummon() { + if (Bot.HasInMonstersZone(CardId.Zeus)) return false; + AI.SelectPosition(CardPosition.Attack); AI.SelectPlace(Zones.ExtraMonsterZones); @@ -207,7 +215,8 @@ private bool DreamingTownActivate() return Card.Location == CardLocation.SpellZone && Duel.Player == 1 - && Bot.Hand.ContainsMonsterWithLevel(1); + && Bot.Hand.ContainsMonsterWithLevel(1) + && !MagnificentMapActivated; } private bool DowneredMagicianSpSummon() @@ -221,9 +230,14 @@ private bool DowneredMagicianSpSummon() private bool StriBanishedEffect() { ClientCard robina = Bot.Banished.GetFirstMatchingCard(card => card.IsCode(CardId.Robina)); + ClientCard eglen = Bot.Banished.GetFirstMatchingCard(card => card.IsCode(CardId.Eglen)); + + if (Duel.CurrentChain.Contains(robina) || Duel.CurrentChain.Contains(eglen)) + { + if (!(Card.Location == CardLocation.MonsterZone || Card.Location == CardLocation.Grave || Card.Location == CardLocation.Hand)) + return true; + } - if (!(Card.Location == CardLocation.MonsterZone || Card.Location == CardLocation.Grave || Card.Location == CardLocation.Hand)) - return true; return false; } @@ -289,9 +303,7 @@ private bool StriEffect() private bool TrippleTacticsTalentActivate() { - if (Bot.MonsterZone.Count() > 1) - AI.SelectOption(1); - else if (Util.IsAllEnemyBetter()) + if (Util.IsAllEnemyBetter()) AI.SelectOption(2); else { @@ -304,17 +316,20 @@ private bool TrippleTacticsTalentActivate() private bool TrippleTacticsThrustActivate() { - if (Bot.Deck.GetCardCount(CardId.TrippleTacticsTalent) != 0) AI.SelectCard(CardId.TrippleTacticsTalent); - else if (!(Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina))) AI.SelectCard(CardId.AdventOfAdventure); - else if (!Bot.HasInSpellZone(CardId.MagnificentMap)) AI.SelectCard(CardId.MagnificentMap); - else AI.SelectCard(new List { CardId.BookOfMoon, CardId.HarpiesFeatherDuster, CardId.UnexploredWinds }); + if (Bot.Deck.GetCardCount(CardId.TrippleTacticsTalent) > 0) AI.SelectCard(CardId.TrippleTacticsTalent); + else if (!(Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina))) + { + if (PotOfProsperityActivated) AI.SelectCard(CardId.PotOfDuality); + else AI.SelectCard(CardId.PotOfProsperity); + } + else AI.SelectCard(new List { CardId.HarpiesFeatherDuster }); return true; } private bool SlackerdMagicianSpSummon() { - if (Bot.HasInMonstersZone(CardId.SlackerdMagician) || Bot.HasInMonstersZone(CardId.Zeus)) return false; + if (Bot.MonsterZone.GetMatchingCardsCount(card => card.HasType(CardType.Xyz)) > 0) return false; AI.SelectPlace(Zones.ExtraMonsterZones); AI.SelectPosition(CardPosition.Attack); @@ -509,9 +524,7 @@ private bool TerraformingActivate() private bool ZeusEffect() { - if (ZeusActivated && Duel.Player == 0) return false; - - ZeusActivated = true; + if (Util.GetLastChainCard() == Card || Duel.Player == 0) return false; ClientCard enemy_bestCard = Util.GetBestEnemyCard(); @@ -536,7 +549,7 @@ private bool JuggernautLiebeSummon() private bool BookOfMoonActivate() { if (!(Duel.Player == 0)) return false; - if(!(Util.IsChainTarget(Card) && Duel.CurrentChain.Contains(Card) && Duel.LastChainPlayer == 1)) return false; + if(Duel.CurrentChain.Contains(Card)) return false; ClientCard enemy_bestCard = Util.GetBestEnemyMonster(true, true); @@ -588,8 +601,7 @@ public override void OnNewTurn() private bool DreamingTownGraveyardActivate() { return Card.Location == CardLocation.Grave - && Util.IsAllEnemyBetter(true) - && Duel.Player == 1; + && Util.IsAllEnemyBetter(); } private bool ToccanBanishedEffect() @@ -597,13 +609,13 @@ private bool ToccanBanishedEffect() ClientCard robina = Bot.Banished.GetFirstMatchingCard(card => card.IsCode(CardId.Robina)); ClientCard eglen = Bot.Banished.GetFirstMatchingCard(card => card.IsCode(CardId.Eglen)); - if (Duel.CurrentChain.Contains(robina) || Duel.CurrentChain.Contains(eglen)) { if (!(Card.Location == CardLocation.MonsterZone || Card.Location == CardLocation.Grave || Card.Location == CardLocation.Hand)) return true; } + return false; } @@ -659,7 +671,7 @@ private bool ToccanEffect() private bool Active_MagnificentMapActivate() { - if (Card.Location == CardLocation.SpellZone && !(Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina))) + if (Card.Location == CardLocation.SpellZone && !(Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina)) && Duel.Player == 0) { int[] reveal = Bot.Hand.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); @@ -671,7 +683,7 @@ private bool Active_MagnificentMapActivate() return true; } - else if (Card.Location == CardLocation.SpellZone && Bot.HasInHandOrHasInMonstersZone(CardId.Robina)) + else if (Card.Location == CardLocation.SpellZone && Bot.HasInHandOrHasInMonstersZone(CardId.Robina) && Duel.Player == 0) { // reveal robina AI.SelectCard(CardId.Robina); @@ -683,7 +695,20 @@ private bool Active_MagnificentMapActivate() return true; } - return false; + if (ActivateDescription == Util.GetStringId(CardId.MagnificentMap, 0) && Duel.Player == 1) + { + int levelOneMonsters = Bot.MonsterZone.GetMatchingCardsCount(card => card.Level == 1); + + if (!robina_NormalSummonEffectActivated) AI.SelectCard(CardId.Robina); + else NormalSummonBossMonsters(); + + MagnificentMapActivated = true; + + return true; + } + + + return false; } private bool MagnificentMapActivate() @@ -694,13 +719,11 @@ private bool MagnificentMapActivate() private bool AdventOfAdventureEffect() { if (Duel.LastChainPlayer == 0 && Duel.CurrentChain.Contains(Bot.SpellZone.GetFirstMatchingFaceupCard(card => card.IsCode(CardId.MagnificentMap)))) return false; - - if (Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina)) - return false; + if (Bot.HasInHandOrHasInMonstersZone(CardId.Robina)) return false; int[] cost; - if(!Bot.Hand.ContainsMonsterWithLevel(1)) cost = Bot.Hand.GetMatchingCards(card => card.Level > 5 && !card.IsCode(CardId.Robina)).Select(c => c.Id).ToArray(); + if(!Bot.Hand.ContainsMonsterWithLevel(1)) cost = Bot.Hand.GetMatchingCards(card => card.Level > 5 || card.Level == 1 && !card.IsCode(CardId.Robina)).Select(c => c.Id).ToArray(); else cost = Bot.Hand.GetMatchingCards(card => card.Level == 1 && !(card.IsCode(CardId.Robina) || card.IsCode(CardId.Eglen))).Select(c => c.Id).ToArray(); if (!Bot.HasInHand(CardId.Robina) && cost.Count() > 0) @@ -796,60 +819,57 @@ private bool RobinaEffect() { if (Card.Location == CardLocation.MonsterZone) { - if (!Bot.HasInHandOrHasInMonstersZone(CardId.Eglen) || Bot.HasInBanished(CardId.Eglen)) + // Search eglen + if (!(Bot.HasInHandOrHasInMonstersZone(CardId.Eglen) || Bot.HasInBanished(CardId.Eglen))) AI.SelectCard(CardId.Eglen); + else if (Bot.HasInHandOrHasInMonstersZone(CardId.Eglen) || Bot.HasInBanished(CardId.Eglen) && Bot.Graveyard.Count() > 0) AI.SelectCard(CardId.Stri); + else AI.SelectCard(CardId.Toccan); + + if (!eglen_NormalSummonEffectActivated) { - AI.SelectCard(CardId.Eglen); + AI.SelectYesNo(true); AI.SelectNextCard(CardId.Eglen); + } else NormalSummonBossMonsters(); - robina_NormalSummonEffectActivated = true; - - return true; - } - else - { - if (eglen_NormalSummonEffectActivated) - { - int[] hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.Level > 7).Select(c => c.Id).ToArray(); + robina_NormalSummonEffectActivated = true; - List materials = new List(); - materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1) - .Select(x => x.Id) - .ToList(); + return true; + } - // Tribute opponent's card using Unexplored winds - if (Bot.HasInSpellZone(CardId.UnexploredWinds) && Util.GetBestEnemyCard() != null && Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 0) - { - AI.SelectOption(1); + return false; + } - materials.Clear(); - materials.Add(Bot.MonsterZone.GetFirstMatchingCard(card => card.Level == 1).Id); - materials.Add(Util.GetBestEnemyCard().Id); - } + public void NormalSummonBossMonsters() + { + int[] hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.Level > 7).Select(c => c.Id).ToArray(); - // summon boss monsters - if (hand_bossMonsters.Count() > 0 && materials.Count() > 1) - { - AI.SelectYesNo(true); + List materials = new List(); + materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1) + .Select(x => x.Id) + .ToList(); - // Summon empen - if (Bot.HasInHand(CardId.Empen)) AI.SelectNextCard(CardId.Empen); - else if (Bot.HasInHand(CardId.Avian)) AI.SelectNextCard(CardId.Avian); - else if (Bot.HasInHand(CardId.Snowl)) AI.SelectNextCard(CardId.Snowl); + // Tribute opponent's card using Unexplored winds + if (Bot.HasInSpellZone(CardId.UnexploredWinds) && Util.GetBestEnemyCard() != null && materials.Count() > 0) + { + AI.SelectOption(1); - AI.SelectMaterials(materials); - } - else AI.SelectYesNo(false); + materials.Clear(); + materials.Add(Bot.MonsterZone.GetFirstMatchingCard(card => card.Level == 1).Id); + materials.Add(Util.GetBestEnemyCard().Id); + } - return true; - } + // summon boss monsters + if (hand_bossMonsters.Count() > 0 && materials.Count() > 1) + { + AI.SelectYesNo(true); - robina_NormalSummonEffectActivated = true; + // Summon empen + if (Bot.HasInHand(CardId.Empen)) AI.SelectCard(CardId.Empen); + else if (Bot.HasInHand(CardId.Avian)) AI.SelectCard(CardId.Avian); + else if (Bot.HasInHand(CardId.Snowl)) AI.SelectCard(CardId.Snowl); - return true; - } + AI.SelectMaterials(materials); } - - return false; + else AI.SelectYesNo(false); } private bool EmpenEffect() From 6d2aaa900f67c7e3b1e5b91253bc92b618272901 Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Sun, 7 Jan 2024 19:15:12 +0800 Subject: [PATCH 14/21] Improvements on executor card usage --- Game/AI/Decks/FloowandereezeExecutor.cs | 269 ++++++++++++++++-------- 1 file changed, 181 insertions(+), 88 deletions(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index 1e08cb04..4e47d32d 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -60,7 +60,8 @@ public class CardId stri_NormalSummonEffectActivated = false, toccan_NormalSummonEffectActivated = false, ActivateempenBattleEffect = false, - MagnificentMapActivated = false; + MagnificentMapActivated = false, + Snowl_Activated = false; // spell actions private bool PotOfProsperityActivated = false; @@ -83,9 +84,26 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.TrippleTacticsThrust, TrippleTacticsThrustActivate); AddExecutor(ExecutorType.Activate, CardId.TrippleTacticsTalent, TrippleTacticsTalentActivate); + // Reposition Monsters + AddExecutor(ExecutorType.Repos, CardId.Empen, BossMonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.Snowl, BossMonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.RaizaMegaMonarch, BossMonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.Avian, BossMonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.DowneredMagician, BossMonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.GustavMax, BossMonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.JuggernautLiebe, BossMonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.Zeus, BossMonsterRepos); + + AddExecutor(ExecutorType.Repos, CardId.Robina, Level1MonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.Eglen, Level1MonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.Stri, Level1MonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.Toccan, Level1MonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.SlackerdMagician, Level1MonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.Fucho, Level1MonsterRepos); + // XYZ Summons AddExecutor(ExecutorType.SpSummon, CardId.GustavMax, JuggernautGustavMaxOverlay); - AddExecutor(ExecutorType.Activate, CardId.GustavMax); + AddExecutor(ExecutorType.Activate, CardId.GustavMax, GustavMaxActivate); AddExecutor(ExecutorType.SpSummon, CardId.JuggernautLiebe, JuggernautLiebeSummon); AddExecutor(ExecutorType.Activate, CardId.JuggernautLiebe); AddExecutor(ExecutorType.SpSummon, CardId.SlackerdMagician, SlackerdMagicianSpSummon); @@ -106,14 +124,14 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.DreamingTown, DreamingTownActivate); AddExecutor(ExecutorType.Activate, CardId.DreamingTown, DreamingTownGraveyardActivate); - AddExecutor(ExecutorType.SpellSet, CardId.HarpiesFeatherStorm); + AddExecutor(ExecutorType.SpellSet, CardId.HarpiesFeatherStorm, HarpiesFeatherStormSet); AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherStorm, HarpiesFeatherStormActivate); AddExecutor(ExecutorType.Activate, CardId.Snowl, SnowlActivate); AddExecutor(ExecutorType.Activate, CardId.Avian, AvianActivate); AddExecutor(ExecutorType.Summon, CardId.Robina, NormalSummonRobina); - AddExecutor(ExecutorType.Summon, CardId.Eglen, EglenSummon); + AddExecutor(ExecutorType.Summon, CardId.Eglen, NormalSummonEglen); AddExecutor(ExecutorType.Activate, CardId.Robina, RobinaEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenEffect); @@ -129,6 +147,38 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.Stri, StriBanishedEffect); } + private bool GustavMaxActivate() + { + return !Card.IsDisabled(); + } + + private bool Level1MonsterRepos() + { + return Util.IsAllEnemyBetter(); + } + + private bool BossMonsterRepos() + { + return !Card.HasPosition(CardPosition.FaceUpAttack); + } + + public override CardPosition OnSelectPosition(int CardID, IList positions) + { + if (CardID == CardId.SlackerdMagician) + { + if (!(Bot.HasInExtra(CardId.Zeus) || Bot.HasInExtra(CardId.DowneredMagician))) + return CardPosition.FaceUpDefence; + else return CardPosition.FaceUpAttack; + } + + return base.OnSelectPosition(CardID, positions); + } + + private bool HarpiesFeatherStormSet() + { + return !Bot.HasInSpellZone(CardId.HarpiesFeatherStorm); + } + private bool EmpenSummon() { return UnexploredWindsTribute(); @@ -142,7 +192,13 @@ public override bool OnSelectHand() private bool NormalSummonRobina() { - return !robina_NormalSummonEffectActivated; + return (!robina_NormalSummonEffectActivated || Snowl_Activated) && !PrioritizeBossMonstersViaUnexploredWindsTribute(); + } + + private bool PrioritizeBossMonstersViaUnexploredWindsTribute() + { + return Bot.SpellZone.GetMatchingCardsCount(card => card.IsCode(CardId.UnexploredWinds) && card.HasPosition(CardPosition.FaceUp)) > 0 + && Bot.MonsterZone.GetMatchingCardsCount(card => card.Level == 1 && card.HasPosition(CardPosition.FaceUp)) > 0; } private bool HarpiesFeatherStormActivate() @@ -164,10 +220,17 @@ public override BattlePhaseAction OnBattle(IList attackers, IList card.IsCode(CardId.Robina)); - ClientCard eglen = Bot.Banished.GetFirstMatchingCard(card => card.IsCode(CardId.Eglen)); - - if (Duel.CurrentChain.Contains(robina) || Duel.CurrentChain.Contains(eglen)) - { - if (!(Card.Location == CardLocation.MonsterZone || Card.Location == CardLocation.Grave || Card.Location == CardLocation.Hand)) - return true; - } - + if (!(Card.Location == CardLocation.MonsterZone || Card.Location == CardLocation.Grave || Card.Location == CardLocation.Hand)) + return true; return false; } @@ -372,7 +428,10 @@ private bool SnowlSummon() private bool UnexploredWindsTribute() { - ClientCard enemyCard = Util.GetBestEnemyCard(); + ClientCard enemyCard; + if (Enemy.SpellZone.Count() > 0) enemyCard = Util.GetBestEnemySpell(); + else enemyCard = Util.GetBestEnemyCard(); + ClientCard myMonster = Bot.MonsterZone.GetFirstMatchingFaceupCard(card => card.Level == 1 && card.HasRace(CardRace.WindBeast)); if (Bot.HasInSpellZone(CardId.UnexploredWinds) && enemyCard != null && myMonster != null) @@ -411,17 +470,46 @@ private bool UnexploredWindsActivate() return false; } - private bool EglenSummon() + private bool NormalSummonEglen() { - return Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 1; + if (Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 0 && Snowl_Activated) return true; + else + { + if ((!Bot.HasInHandOrHasInMonstersZone(CardId.Robina) && !robina_NormalSummonEffectActivated) && !PrioritizeBossMonstersViaUnexploredWindsTribute()) + return true; + } + + return false; } private bool SnowlActivate() { - if (Duel.Player == 0 && (Duel.Phase == DuelPhase.Main1 || Duel.Phase == DuelPhase.Main2) && !(robina_NormalSummonEffectActivated || eglen_NormalSummonEffectActivated)) - return true; - else if ((Duel.Player == 1 && (Duel.Phase == DuelPhase.Main1 || Duel.Phase == DuelPhase.Main2 || Duel.Phase == DuelPhase.Battle) && ActivateDescription == Util.GetStringId(CardId.Snowl, 0))) + // Activated effect: Allows Normal 3 summon in a turn + if (Duel.Player == 0 && (Duel.Phase == DuelPhase.Main1 || Duel.Phase == DuelPhase.Main2)) { + Snowl_Activated = true; return true; + } + + // Quick effect + else if (ActivateDescription == Util.GetStringId(CardId.Snowl, 0)) + { + if (Duel.Player == 1 && !(Duel.Phase == DuelPhase.Main1 || Duel.Phase == DuelPhase.Main2)) + { + List prefferedCost = new List(); + prefferedCost.AddRange(new List { + CardId.Stri, + CardId.Eglen, + CardId.Toccan, + CardId.AdventOfAdventure, + CardId.BookOfMoon, + CardId.TrippleTacticsThrust + }); + + AI.SelectCard(prefferedCost); + + return true; + } + } return false; } @@ -429,6 +517,11 @@ private bool SnowlActivate() private bool PotOfProsperityActivate() { if (Bot.ExtraDeck.Count <= 3) return false; + if(!(Bot.HasInHand(CardId.Robina) + || Bot.HasInHand(CardId.Eglen) + || Bot.HasInHand(CardId.AdventOfAdventure) + || Bot.HasInHand(CardId.PotOfDuality) + )) return false; List cardsId = new List(); @@ -524,17 +617,10 @@ private bool TerraformingActivate() private bool ZeusEffect() { - if (Util.GetLastChainCard() == Card || Duel.Player == 0) return false; - - ClientCard enemy_bestCard = Util.GetBestEnemyCard(); - - if (enemy_bestCard != null) - { - if (Duel.Player == 1 && enemy_bestCard.Attack > Card.Attack) - return true; + if (Util.GetLastChainCard() == Card) return false; + if (Util.IsAllEnemyBetter() || Util.IsChainTarget(Card) && (Duel.Player == 0 || Duel.Player == 1)) return true; - } return false; } @@ -551,9 +637,9 @@ private bool BookOfMoonActivate() if (!(Duel.Player == 0)) return false; if(Duel.CurrentChain.Contains(Card)) return false; - ClientCard enemy_bestCard = Util.GetBestEnemyMonster(true, true); + ClientCard enemy_bestCard = Util.GetBestEnemyCard(true); - if (enemy_bestCard != null) { + if (enemy_bestCard != null && Enemy.MonsterZone.GetMatchingCardsCount(card => card.HasPosition(CardPosition.FaceUp)) > 0) { AI.SelectCard(enemy_bestCard); return true; } @@ -594,6 +680,7 @@ public override void OnNewTurn() // XYZ Activation ZeusActivated = false; + Snowl_Activated = false; base.OnNewTurn(); } @@ -606,15 +693,8 @@ private bool DreamingTownGraveyardActivate() private bool ToccanBanishedEffect() { - ClientCard robina = Bot.Banished.GetFirstMatchingCard(card => card.IsCode(CardId.Robina)); - ClientCard eglen = Bot.Banished.GetFirstMatchingCard(card => card.IsCode(CardId.Eglen)); - - if (Duel.CurrentChain.Contains(robina) || Duel.CurrentChain.Contains(eglen)) - { - if (!(Card.Location == CardLocation.MonsterZone || Card.Location == CardLocation.Grave || Card.Location == CardLocation.Hand)) - return true; - } - + if (!(Card.Location == CardLocation.MonsterZone || Card.Location == CardLocation.Grave || Card.Location == CardLocation.Hand)) + return true; return false; } @@ -627,43 +707,22 @@ private bool ToccanEffect() AI.SelectCard(CardId.UnexploredWinds); else if (Bot.HasInBanished(CardId.DreamingTown)) AI.SelectCard(CardId.DreamingTown); + else if(Bot.HasInBanished(CardId.Empen)) + AI.SelectCard(CardId.Empen); else { - AI.SelectNextCard(new int[] { + AI.SelectCard(new int[] { CardId.AdventOfAdventure, - CardId.Empen, CardId.Avian, CardId.MagnificentMap }); - toccan_NormalSummonEffectActivated = true; return true; } - // Normal Summon again? - int[] hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.Level > 7).Select(c => c.Id).ToArray(); - int[] materials = Bot.Hand.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray(); + NormalSummonBossMonsters(); - // summon boss monsters - if (hand_bossMonsters.Count() > 0 && materials.Count() > 1) - { - AI.SelectYesNo(true); - - AI.SelectCard(hand_bossMonsters); - AI.SelectMaterials(Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Select(c => c.Id).ToArray()); - } else if (Bot.Deck.GetCardCount(CardId.Stri) > 0 - && (Bot.HasInGraveyard(CardId.DreamingTown) - || Bot.HasInGraveyard(CardId.UnexploredWinds) - || Bot.HasInGraveyard(CardId.AdventOfAdventure) - || Bot.HasInGraveyard(CardId.Empen) - || Bot.HasInGraveyard(CardId.Avian) - || Bot.HasInGraveyard(CardId.MagnificentMap) - )) - { - AI.SelectYesNo(true); - AI.SelectCard(CardId.Stri); - } - else AI.SelectYesNo(false); + toccan_NormalSummonEffectActivated = true; } return false; @@ -720,10 +779,11 @@ private bool AdventOfAdventureEffect() { if (Duel.LastChainPlayer == 0 && Duel.CurrentChain.Contains(Bot.SpellZone.GetFirstMatchingFaceupCard(card => card.IsCode(CardId.MagnificentMap)))) return false; if (Bot.HasInHandOrHasInMonstersZone(CardId.Robina)) return false; + if (robina_NormalSummonEffectActivated) return false; int[] cost; - if(!Bot.Hand.ContainsMonsterWithLevel(1)) cost = Bot.Hand.GetMatchingCards(card => card.Level > 5 || card.Level == 1 && !card.IsCode(CardId.Robina)).Select(c => c.Id).ToArray(); + if(!Bot.Hand.ContainsMonsterWithLevel(1)) cost = Bot.Hand.GetMatchingCards(card => (card.Level > 5 || card.Level == 1) && !card.IsCode(CardId.Robina) && !card.IsCode(CardId.Empen) || !card.IsCode(CardId.Avian) || !card.IsCode(CardId.Snowl)).Select(c => c.Id).ToArray(); else cost = Bot.Hand.GetMatchingCards(card => card.Level == 1 && !(card.IsCode(CardId.Robina) || card.IsCode(CardId.Eglen))).Select(c => c.Id).ToArray(); if (!Bot.HasInHand(CardId.Robina) && cost.Count() > 0) @@ -736,16 +796,13 @@ private bool AdventOfAdventureEffect() int hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.HasAttribute(CardAttribute.Wind) && card.Level > 6).Count(); - // Search unexplored winds + // Search Floowandereeze Spell/Trap if (Bot.HasInHand(CardId.Robina) && Bot.HasInHand(CardId.Eglen) && hand_bossMonsters > 0 && cost.Count() > 0) { AI.SelectCard(cost); // pay cost - if(!Bot.HasInHand(CardId.UnexploredWinds)) - AI.SelectNextCard(CardId.UnexploredWinds); - - if (!Bot.HasInHandOrInSpellZone(CardId.MagnificentMap)) - AI.SelectNextCard(CardId.MagnificentMap); + if(!Bot.HasInHand(CardId.UnexploredWinds)) AI.SelectNextCard(CardId.UnexploredWinds); + else AI.SelectNextCard(CardId.MagnificentMap); return true; } @@ -803,15 +860,9 @@ private bool RobinaBanishedEffect() private bool EglenBanishedEffect() { - ClientCard robina = Bot.Banished.GetFirstMatchingCard(card => card.IsCode(CardId.Robina)); - - if (Duel.CurrentChain.Contains(robina)) - { - if (!(Card.Location == CardLocation.MonsterZone || Card.Location == CardLocation.Grave || Card.Location == CardLocation.Hand)) - return true; - } + if (!(Card.Location == CardLocation.MonsterZone || Card.Location == CardLocation.Grave || Card.Location == CardLocation.Hand)) + return true; - return false; } @@ -819,16 +870,34 @@ private bool RobinaEffect() { if (Card.Location == CardLocation.MonsterZone) { + if (Snowl_Activated) return false; + // Search eglen if (!(Bot.HasInHandOrHasInMonstersZone(CardId.Eglen) || Bot.HasInBanished(CardId.Eglen))) AI.SelectCard(CardId.Eglen); else if (Bot.HasInHandOrHasInMonstersZone(CardId.Eglen) || Bot.HasInBanished(CardId.Eglen) && Bot.Graveyard.Count() > 0) AI.SelectCard(CardId.Stri); else AI.SelectCard(CardId.Toccan); + int materials = Bot.MonsterZone.GetMatchingCardsCount(card => card.Level == 1); + + if(materials > 1) + NormalSummonBossMonsters(); + + // Normal summon again if (!eglen_NormalSummonEffectActivated) { AI.SelectYesNo(true); AI.SelectNextCard(CardId.Eglen); - } else NormalSummonBossMonsters(); + } + else if (!toccan_NormalSummonEffectActivated && BanishedRecycleCards().Count() > 0) + { + AI.SelectYesNo(true); + AI.SelectNextCard(CardId.Toccan); + } + else if (!stri_NormalSummonEffectActivated && BanishedRecycleCards().Count() > 0) + { + AI.SelectYesNo(true); + AI.SelectNextCard(CardId.Stri); + } robina_NormalSummonEffectActivated = true; @@ -838,6 +907,25 @@ private bool RobinaEffect() return false; } + public List GraveyardRecycleCards() + { + List recycleCards = Bot.Banished.GetMatchingCards(card => card.IsCode(CardId.UnexploredWinds) + || card.IsCode(CardId.Empen) + || card.IsCode(CardId.Avian)).Select(c => c.Id).ToList(); + + return recycleCards; + } + + public List BanishedRecycleCards() + { + List recycleCards = Bot.Banished.GetMatchingCards(card => card.IsCode(CardId.UnexploredWinds) + || card.IsCode(CardId.DreamingTown) + || card.IsCode(CardId.Empen) + || card.IsCode(CardId.Avian)).Select(c => c.Id).ToList(); + + return recycleCards; + } + public void NormalSummonBossMonsters() { int[] hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.Level > 7).Select(c => c.Id).ToArray(); @@ -854,7 +942,9 @@ public void NormalSummonBossMonsters() materials.Clear(); materials.Add(Bot.MonsterZone.GetFirstMatchingCard(card => card.Level == 1).Id); - materials.Add(Util.GetBestEnemyCard().Id); + + if(Enemy.SpellZone.Count() > 0 && Util.GetBestEnemySpell() != null) materials.Add(Util.GetBestEnemySpell().Id); + else materials.Add(Util.GetBestEnemyCard().Id); } // summon boss monsters @@ -862,10 +952,10 @@ public void NormalSummonBossMonsters() { AI.SelectYesNo(true); - // Summon empen if (Bot.HasInHand(CardId.Empen)) AI.SelectCard(CardId.Empen); else if (Bot.HasInHand(CardId.Avian)) AI.SelectCard(CardId.Avian); else if (Bot.HasInHand(CardId.Snowl)) AI.SelectCard(CardId.Snowl); + else AI.SelectCard(CardId.RaizaMegaMonarch); AI.SelectMaterials(materials); } @@ -946,14 +1036,17 @@ private bool EmpenEffect() private bool Empen_NormalSummonAgain() { - return (Bot.Hand.ContainsMonsterWithLevel(8) || Bot.Hand.ContainsMonsterWithLevel(7)) - && Bot.MonsterZone.GetMatchingCardsCount(card => card.Level == 1) > 1; + return ((Bot.Hand.ContainsMonsterWithLevel(8) || Bot.Hand.ContainsMonsterWithLevel(7)) + && Bot.MonsterZone.GetMatchingCardsCount(card => card.Level == 1) > 1) + || Bot.SpellZone.GetMatchingCardsCount(card => card.IsCode(CardId.UnexploredWinds) && card.HasPosition(CardPosition.FaceUpDefence)) > 0; } private bool EglenEffect() { if (Card.Location == CardLocation.MonsterZone) { + if (Snowl_Activated) return false; + List materials = new List(); materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1) .Select(x => x.Id) From 1fbe89ebd19b7582fe8657e384c574b6e83d786f Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Sun, 7 Jan 2024 21:30:49 +0800 Subject: [PATCH 15/21] Fixes on executor To fix: Empen not activating battle effect --- Game/AI/Decks/FloowandereezeExecutor.cs | 252 +++++++++++++++++++----- 1 file changed, 198 insertions(+), 54 deletions(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index 4e47d32d..a6bd4d69 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -7,6 +7,7 @@ using YGOSharp.OCGWrapper; using YGOSharp.Network.Enums; using WindBot.Game.AI.Enums; +using System.Diagnostics.Eventing.Reader; namespace WindBot.Game.AI.Decks { @@ -59,12 +60,14 @@ public class CardId eglen_NormalSummonEffectActivated = false, stri_NormalSummonEffectActivated = false, toccan_NormalSummonEffectActivated = false, - ActivateempenBattleEffect = false, + ActivateEmpenBattleEffect = false, + ActivateLiebe = false, MagnificentMapActivated = false, Snowl_Activated = false; // spell actions private bool PotOfProsperityActivated = false; + private bool BookOfMoonActivated = false; // battle phase Actions private bool SlackerMagicianAttacks = false; @@ -72,6 +75,9 @@ public class CardId //xyz activations private bool ZeusActivated = false; + List Impermanence_list = new List(); + + public FloowandereezeExecutor(GameAI ai, Duel duel) : base(ai, duel) { @@ -105,8 +111,9 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.SpSummon, CardId.GustavMax, JuggernautGustavMaxOverlay); AddExecutor(ExecutorType.Activate, CardId.GustavMax, GustavMaxActivate); AddExecutor(ExecutorType.SpSummon, CardId.JuggernautLiebe, JuggernautLiebeSummon); - AddExecutor(ExecutorType.Activate, CardId.JuggernautLiebe); + AddExecutor(ExecutorType.Activate, CardId.JuggernautLiebe, JuggernautLiebeActivate); AddExecutor(ExecutorType.SpSummon, CardId.SlackerdMagician, SlackerdMagicianSpSummon); + AddExecutor(ExecutorType.Activate, CardId.SlackerdMagician, SlackerdMagicianActivate); AddExecutor(ExecutorType.SpSummon, CardId.DowneredMagician, DowneredMagicianSpSummon); AddExecutor(ExecutorType.SpSummon, CardId.Zeus, ZeusSpSummon); AddExecutor(ExecutorType.Activate, CardId.Zeus, ZeusEffect); @@ -116,6 +123,7 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Summon, CardId.Empen, EmpenSummon); AddExecutor(ExecutorType.Summon, CardId.RaizaMegaMonarch, RaizaMegaMonarchSummon); + AddExecutor(ExecutorType.Activate, CardId.RaizaMegaMonarch, RaizaMegaMonarchActivate); AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, MagnificentMapActivate); AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, Active_MagnificentMapActivate); AddExecutor(ExecutorType.Activate, CardId.AdventOfAdventure, AdventOfAdventureEffect); @@ -140,6 +148,7 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) // Chain block for strongest effect monster AddExecutor(ExecutorType.Activate, CardId.Empen, EmpenEffect); + AddExecutor(ExecutorType.Activate, CardId.Empen, EmpenBattleEffect); AddExecutor(ExecutorType.Activate, CardId.Robina, RobinaBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenBanishedEffect); @@ -147,6 +156,98 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.Stri, StriBanishedEffect); } + private bool SlackerdMagicianActivate() + { + return Util.IsChainTarget(Card); + } + + private bool EmpenBattleEffect() + { + if (!(Duel.Phase == DuelPhase.Main1 || Duel.Phase == DuelPhase.Main2)) + { + if (ActivateDescription == Util.GetStringId(CardId.Empen, 1)) + { + ClientCard BestMonster = Util.GetBestEnemyMonster(); + + if (BestMonster != null) + { + // prioritize theres cards as cost (Do not discard Unexplored Winds and Dreaming Town if you can) + List cost = new List(); + + if (Bot.Hand.Count() > 2) + { + cost = Bot.Hand.GetMatchingCards(card => !(card.IsCode(CardId.UnexploredWinds)) || card.IsCode(CardId.DreamingTown)) + .Select(c => c.Id) + .ToList(); + } + else cost = Bot.Hand.Select(c => c.Id).ToList(); + + if (cost.Count() > 0 && ActivateEmpenBattleEffect) + { + AI.SelectCard(cost); + return true; + } + } + } + } + + return false; + } + + private bool RaizaMegaMonarchActivate() + { + if (ActivateDescription == Util.GetStringId(CardId.RaizaMegaMonarch, 0)) + { + if (Enemy.GetFieldCount() > 1) + { + AI.SelectYesNo(true); + AI.SelectCard(Util.GetBestEnemyCard()); + } + else AI.SelectYesNo(false); + } + + return true; + } + + private bool JuggernautLiebeActivate() + { + return !Card.IsDisabled(); + } + + public int SelectSTPlace(ClientCard card = null, bool avoid_Impermanence = false) + { + List list = new List { 0, 1, 2, 3, 4 }; + 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; + } + foreach (int seq in list) + { + int zone = (int)System.Math.Pow(2, seq); + if (Bot.SpellZone[seq] == null) + { + if (card != null && card.Location == CardLocation.Hand && avoid_Impermanence && Impermanence_list.Contains(seq)) continue; + return zone; + }; + } + + return 0; + } + + public override void OnSelectChain(IList cards) + { + foreach (var imperm in cards.GetMatchingCards(card => card.IsCode(10045474))) + { + Impermanence_list.Add(10045474); // Imperm ID + } + + base.OnSelectChain(cards); + } + private bool GustavMaxActivate() { return !Card.IsDisabled(); @@ -176,12 +277,19 @@ public override CardPosition OnSelectPosition(int CardID, IList po private bool HarpiesFeatherStormSet() { + AI.SelectPlace(SelectSTPlace(Card, true)); return !Bot.HasInSpellZone(CardId.HarpiesFeatherStorm); } private bool EmpenSummon() { - return UnexploredWindsTribute(); + if (Bot.MonsterZone.GetMatchingCards(card => card.Level == 1 && card.HasRace(CardRace.WindBeast)).Count() > 0) + { + AI.SelectPlace(SelectSTPlace(Card, true)); + return UnexploredWindsTribute(); + } + + return false; } // Prefer always first if RPS is won @@ -192,6 +300,7 @@ public override bool OnSelectHand() private bool NormalSummonRobina() { + AI.SelectPlace(SelectSTPlace(Card)); return (!robina_NormalSummonEffectActivated || Snowl_Activated) && !PrioritizeBossMonstersViaUnexploredWindsTribute(); } @@ -245,9 +354,12 @@ public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender if (attacker.IsCode(CardId.Empen) && realDefenderPower > realAttackerPower) { - int empenPower = attacker.Attack + defender.RealPower; + int empenPower = attacker.Attack + attacker.RealPower; int target_preEffectPower = (defender.Attack + defender.RealPower) / 2; + if (target_preEffectPower < empenPower) + ActivateEmpenBattleEffect = true; + return (target_preEffectPower < empenPower) && Bot.Hand.Count() > 0; } @@ -264,9 +376,7 @@ public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender private bool ZeusSpSummon() { if (Bot.HasInMonstersZone(CardId.Zeus)) return false; - AI.SelectPosition(CardPosition.Attack); - AI.SelectPlace(Zones.ExtraMonsterZones); return true; } @@ -285,8 +395,6 @@ private bool DreamingTownActivate() private bool DowneredMagicianSpSummon() { AI.SelectPosition(CardPosition.Attack); - AI.SelectPlace(Zones.ExtraMonsterZones); - return SlackerMagicianAttacks; } @@ -366,7 +474,7 @@ private bool TrippleTacticsTalentActivate() AI.SelectOption(3); AI.SelectNextCard(Enemy.Hand.GetDangerousMonster()); } - + AI.SelectPlace(SelectSTPlace(Card, true)); return true; } @@ -380,6 +488,8 @@ private bool TrippleTacticsThrustActivate() } else AI.SelectCard(new List { CardId.HarpiesFeatherDuster }); + AI.SelectPlace(SelectSTPlace(Card, true)); + return true; } @@ -387,7 +497,9 @@ private bool SlackerdMagicianSpSummon() { if (Bot.MonsterZone.GetMatchingCardsCount(card => card.HasType(CardType.Xyz)) > 0) return false; - AI.SelectPlace(Zones.ExtraMonsterZones); + if (Bot.HasInExtra(CardId.UnderworldGoddess)) AI.SelectPlace(SelectSTPlace(Card, true)); + else AI.SelectPlace(Zones.ExtraMonsterZones); + AI.SelectPosition(CardPosition.Attack); if (Duel.Player == 0 && Duel.Phase == DuelPhase.BattleStart) @@ -401,10 +513,13 @@ private bool SlackerdMagicianSpSummon() private bool RaizaMegaMonarchSummon() { - if (ActivateDescription == Util.GetStringId(CardId.RaizaMegaMonarch,0) && Util.IsAllEnemyBetter() && Enemy.GetFieldCount() > 1) + if (Util.IsAllEnemyBetter() && Enemy.GetFieldCount() > 1) { if (Bot.MonsterZone.GetMatchingCards(card => card.Level == 1 && card.HasRace(CardRace.WindBeast)).Count() > 0) + { + AI.SelectPlace(SelectSTPlace(Card, true)); return UnexploredWindsTribute(); + } } return false; @@ -412,8 +527,11 @@ private bool RaizaMegaMonarchSummon() private bool AvianSummon() { - if(Bot.MonsterZone.GetMatchingCards(card => card.Level == 1 && card.HasRace(CardRace.WindBeast)).Count() > 0) + if (Bot.MonsterZone.GetMatchingCards(card => card.Level == 1 && card.HasRace(CardRace.WindBeast)).Count() > 0) + { + AI.SelectPlace(SelectSTPlace(Card, true)); return UnexploredWindsTribute(); + } return false; } @@ -421,8 +539,10 @@ private bool AvianSummon() private bool SnowlSummon() { if (Bot.MonsterZone.GetMatchingCards(card => card.Level == 1 && card.HasRace(CardRace.WindBeast)).Count() > 0) + { + AI.SelectPlace(Zones.ExtraMonsterZones); return UnexploredWindsTribute(); - + } return false; } @@ -454,13 +574,16 @@ private bool UnexploredWindsTribute() private bool UnexploredWindsActivate() { + AI.SelectPlace(SelectSTPlace(Card, true)); if (Card.Location == CardLocation.Hand) return true; else if (Card.Location == CardLocation.SpellZone) { List reveal = Bot.Hand.GetMatchingCards(card => card.Level > 5 && card.HasRace(CardRace.WindBeast)).Select(c => c.Id).ToList(); - if (!Bot.Hand.ContainsMonsterWithLevel(1) && reveal.Count() > 0) + if (!(Bot.Hand.ContainsMonsterWithLevel(1) && Bot.MonsterZone.ContainsMonsterWithLevel(1)) + && reveal.Count() > 0 + ) { AI.SelectCard(reveal); return true; @@ -476,7 +599,10 @@ private bool NormalSummonEglen() else { if ((!Bot.HasInHandOrHasInMonstersZone(CardId.Robina) && !robina_NormalSummonEffectActivated) && !PrioritizeBossMonstersViaUnexploredWindsTribute()) + { + AI.SelectPlace(SelectSTPlace(Card, true)); return true; + } } return false; @@ -610,7 +736,10 @@ private bool AvianActivate() private bool TerraformingActivate() { if (!Bot.HasInHandOrInSpellZone(CardId.MagnificentMap)) + { + AI.SelectPlace(SelectSTPlace(Card, true)); return true; + } return false; } @@ -619,7 +748,7 @@ private bool ZeusEffect() { if (Util.GetLastChainCard() == Card) return false; - if (Util.IsAllEnemyBetter() || Util.IsChainTarget(Card) && (Duel.Player == 0 || Duel.Player == 1)) + if ((Util.IsAllEnemyBetter() || Util.IsChainTarget(Card) || Enemy.GetFieldCount() >= 3) && (Duel.Player == 0 || Duel.Player == 1) && !Card.IsDisabled()) return true; return false; @@ -627,9 +756,7 @@ private bool ZeusEffect() private bool JuggernautLiebeSummon() { - AI.SelectPlace(Zones.ExtraMonsterZones); return true; - } private bool BookOfMoonActivate() @@ -641,7 +768,10 @@ private bool BookOfMoonActivate() if (enemy_bestCard != null && Enemy.MonsterZone.GetMatchingCardsCount(card => card.HasPosition(CardPosition.FaceUp)) > 0) { AI.SelectCard(enemy_bestCard); + AI.SelectPlace(SelectSTPlace(Card, true)); return true; + + BookOfMoonActivated = true; } return false; @@ -658,7 +788,8 @@ private bool FuchoSpSummon() private bool JuggernautGustavMaxOverlay() { - AI.SelectPlace(Zones.ExtraMonsterZones); + if (Bot.HasInExtra(CardId.UnderworldGoddess)) AI.SelectPlace(SelectSTPlace(Card, true)); + else AI.SelectPlace(Zones.ExtraMonsterZones); return true; } @@ -673,7 +804,7 @@ public override void OnNewTurn() toccan_NormalSummonEffectActivated = false; //Battle monsters - ActivateempenBattleEffect = false; + ActivateEmpenBattleEffect = false; // Battle phase actions SlackerMagicianAttacks = false; @@ -681,6 +812,11 @@ public override void OnNewTurn() // XYZ Activation ZeusActivated = false; Snowl_Activated = false; + ActivateLiebe = false; + + Impermanence_list.Clear(); + + BookOfMoonActivated = false; base.OnNewTurn(); } @@ -807,16 +943,20 @@ private bool AdventOfAdventureEffect() return true; } + AI.SelectPlace(SelectSTPlace(Card, true)); + return false; } private bool DreamingTownSet() { + AI.SelectPlace(SelectSTPlace(Card, true)); return Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina) || Bot.HasInHandOrHasInMonstersZone(CardId.Eglen) || Bot.HasInBanished(CardId.Eglen); } private bool PotOfDualityActivate() { + AI.SelectPlace(SelectSTPlace(Card, true)); if (!Bot.HasInHand(CardId.Robina)) { AI.SelectCard(CardId.Robina); @@ -887,16 +1027,25 @@ private bool RobinaEffect() { AI.SelectYesNo(true); AI.SelectNextCard(CardId.Eglen); + AI.SelectPlace(SelectSTPlace( + Bot.Hand.GetFirstMatchingCard(card => card.IsCode(CardId.Eglen)) + )); } else if (!toccan_NormalSummonEffectActivated && BanishedRecycleCards().Count() > 0) { AI.SelectYesNo(true); AI.SelectNextCard(CardId.Toccan); + AI.SelectPlace(SelectSTPlace( + Bot.Hand.GetFirstMatchingCard(card => card.IsCode(CardId.Toccan)) + )); } else if (!stri_NormalSummonEffectActivated && BanishedRecycleCards().Count() > 0) { AI.SelectYesNo(true); AI.SelectNextCard(CardId.Stri); + AI.SelectPlace(SelectSTPlace( + Bot.Hand.GetFirstMatchingCard(card => card.IsCode(CardId.Stri)) + )); } robina_NormalSummonEffectActivated = true; @@ -952,10 +1101,34 @@ public void NormalSummonBossMonsters() { AI.SelectYesNo(true); - if (Bot.HasInHand(CardId.Empen)) AI.SelectCard(CardId.Empen); - else if (Bot.HasInHand(CardId.Avian)) AI.SelectCard(CardId.Avian); - else if (Bot.HasInHand(CardId.Snowl)) AI.SelectCard(CardId.Snowl); - else AI.SelectCard(CardId.RaizaMegaMonarch); + if (Bot.HasInHand(CardId.Empen)) + { + AI.SelectCard(CardId.Empen); + AI.SelectPlace(SelectSTPlace( + Bot.Hand.GetFirstMatchingCard(card => card.IsCode(CardId.Empen)) + )); + } + else if (Bot.HasInHand(CardId.Avian)) + { + AI.SelectCard(CardId.Avian); + AI.SelectPlace(SelectSTPlace( + Bot.Hand.GetFirstMatchingCard(card => card.IsCode(CardId.Avian)) + )); + } + else if (Bot.HasInHand(CardId.Snowl)) + { + AI.SelectCard(CardId.Snowl); + AI.SelectPlace(SelectSTPlace( + Bot.Hand.GetFirstMatchingCard(card => card.IsCode(CardId.Snowl)) + )); + } + else + { + AI.SelectCard(CardId.RaizaMegaMonarch); + AI.SelectPlace(SelectSTPlace( + Bot.Hand.GetFirstMatchingCard(card => card.IsCode(CardId.RaizaMegaMonarch)) + )); + } AI.SelectMaterials(materials); } @@ -1000,36 +1173,6 @@ private bool EmpenEffect() return true; } - else - { - if (ActivateDescription == Util.GetStringId(CardId.Empen, 1)) - { - ClientCard BestMonster = Util.GetBestEnemyMonster(); - - if (BestMonster != null) - { - // prioritize theres cards as cost (Do not discard Unexplored Winds and Dreaming Town if you can) - List cost = new List(); - - if (Bot.Hand.Count() > 2) - { - cost = Bot.Hand.GetMatchingCards(card => !(card.IsCode(CardId.UnexploredWinds)) || card.IsCode(CardId.DreamingTown)) - .Select(c => c.Id) - .ToList(); - } - else cost = Bot.Hand.Select(c => c.Id).ToList(); - - int strongestMonsterAttack = BestMonster.Attack + BestMonster.RealPower; - int empenPower = Card.Attack + Card.RealPower; - - if (cost.Count() > 0 && strongestMonsterAttack >= empenPower) - { - AI.SelectCard(cost); - return true; - } - } - } - } return false; } @@ -1053,7 +1196,8 @@ private bool EglenEffect() .ToList(); if (!Bot.HasInHandOrHasInMonstersZone(CardId.Empen) - || Bot.MonsterZone.GetCardCount(CardId.Empen) > 0 && Duel.Player == 1) + || Bot.MonsterZone.GetCardCount(CardId.Empen) > 0 + && Duel.Player == 1) { // Fetch empen from deck AI.SelectCard(CardId.Empen); From a6bd599f1f2ec898591bb0e598e7c819c4b9f784 Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Sat, 27 Jan 2024 18:43:49 +0800 Subject: [PATCH 16/21] Fixes on executor consistency. WIP: - Underworld goddess Link Summon - Raiza Monarch summoning mechanics fix --- Game/AI/Decks/FloowandereezeExecutor.cs | 121 ++++++++++++------------ 1 file changed, 58 insertions(+), 63 deletions(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index a6bd4d69..fb761ecb 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -90,16 +90,6 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.TrippleTacticsThrust, TrippleTacticsThrustActivate); AddExecutor(ExecutorType.Activate, CardId.TrippleTacticsTalent, TrippleTacticsTalentActivate); - // Reposition Monsters - AddExecutor(ExecutorType.Repos, CardId.Empen, BossMonsterRepos); - AddExecutor(ExecutorType.Repos, CardId.Snowl, BossMonsterRepos); - AddExecutor(ExecutorType.Repos, CardId.RaizaMegaMonarch, BossMonsterRepos); - AddExecutor(ExecutorType.Repos, CardId.Avian, BossMonsterRepos); - AddExecutor(ExecutorType.Repos, CardId.DowneredMagician, BossMonsterRepos); - AddExecutor(ExecutorType.Repos, CardId.GustavMax, BossMonsterRepos); - AddExecutor(ExecutorType.Repos, CardId.JuggernautLiebe, BossMonsterRepos); - AddExecutor(ExecutorType.Repos, CardId.Zeus, BossMonsterRepos); - AddExecutor(ExecutorType.Repos, CardId.Robina, Level1MonsterRepos); AddExecutor(ExecutorType.Repos, CardId.Eglen, Level1MonsterRepos); AddExecutor(ExecutorType.Repos, CardId.Stri, Level1MonsterRepos); @@ -154,6 +144,16 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Toccan, ToccanBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Stri, StriBanishedEffect); + + // Reposition Monsters + AddExecutor(ExecutorType.Repos, CardId.Empen, BossMonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.Snowl, BossMonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.RaizaMegaMonarch, BossMonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.Avian, BossMonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.DowneredMagician, BossMonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.GustavMax, BossMonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.JuggernautLiebe, BossMonsterRepos); + AddExecutor(ExecutorType.Repos, CardId.Zeus, BossMonsterRepos); } private bool SlackerdMagicianActivate() @@ -165,28 +165,26 @@ private bool EmpenBattleEffect() { if (!(Duel.Phase == DuelPhase.Main1 || Duel.Phase == DuelPhase.Main2)) { - if (ActivateDescription == Util.GetStringId(CardId.Empen, 1)) + ClientCard BestMonster = Util.GetBestEnemyMonster(); + + if (BestMonster != null) { - ClientCard BestMonster = Util.GetBestEnemyMonster(); - if (BestMonster != null) - { - // prioritize theres cards as cost (Do not discard Unexplored Winds and Dreaming Town if you can) - List cost = new List(); + // prioritize theres cards as cost (Do not discard Unexplored Winds and Dreaming Town if you can) + List cost = new List(); - if (Bot.Hand.Count() > 2) - { - cost = Bot.Hand.GetMatchingCards(card => !(card.IsCode(CardId.UnexploredWinds)) || card.IsCode(CardId.DreamingTown)) - .Select(c => c.Id) - .ToList(); - } - else cost = Bot.Hand.Select(c => c.Id).ToList(); + if (Bot.Hand.Count() > 2) + { + cost = Bot.Hand.GetMatchingCards(card => !(card.IsCode(CardId.UnexploredWinds)) || card.IsCode(CardId.DreamingTown)) + .Select(c => c.Id) + .ToList(); + } + else cost = Bot.Hand.Select(c => c.Id).ToList(); - if (cost.Count() > 0 && ActivateEmpenBattleEffect) - { - AI.SelectCard(cost); - return true; - } + if ((cost.Count() > 0 && ActivateEmpenBattleEffect) || Duel.Player != 0) + { + AI.SelectCard(cost); + return true; } } } @@ -349,13 +347,14 @@ public override BattlePhaseAction OnBattle(IList attackers, IList realAttackerPower) { - int empenPower = attacker.Attack + attacker.RealPower; - int target_preEffectPower = (defender.Attack + defender.RealPower) / 2; + int empenPower = attacker.Attack; + int target_preEffectPower = realDefenderPower / 2; if (target_preEffectPower < empenPower) ActivateEmpenBattleEffect = true; @@ -363,10 +362,10 @@ public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender return (target_preEffectPower < empenPower) && Bot.Hand.Count() > 0; } - + //Slacker Magician if (attacker.IsCode(CardId.SlackerdMagician) && realDefenderPower > realAttackerPower) { - int potentialSelfDamage = (defender.Attack + defender.RealPower) - (attacker.Attack + attacker.RealPower); + int potentialSelfDamage = realDefenderPower - realAttackerPower; return Bot.LifePoints > potentialSelfDamage; } @@ -376,15 +375,25 @@ public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender private bool ZeusSpSummon() { if (Bot.HasInMonstersZone(CardId.Zeus)) return false; + AI.SelectPosition(CardPosition.Attack); + if (Bot.MonsterZone.GetFirstMatchingCard(card => card.HasType(CardType.Xyz) && card.Rank == 10) != null) + { + int xyzPosition = Bot.MonsterZone.GetFirstMatchingCard(card => card.HasType(CardType.Xyz) && card.Rank == 10).Position; + AI.SelectPlace(xyzPosition); + } + return true; } private bool DreamingTownActivate() { if (Bot.HasInHand(CardId.Robina) && !robina_NormalSummonEffectActivated) + { AI.SelectCard(CardId.Robina); + AI.SelectPlace(SelectSTPlace(Bot.Hand.GetFirstMatchingCard(card => Card.IsCode(CardId.Robina)))); + } return Card.Location == CardLocation.SpellZone && Duel.Player == 1 @@ -680,6 +689,8 @@ private bool PotOfProsperityActivate() new ProsperityMaterials { id = CardId.DowneredMagician, preserveCopy = true } }; + AI.SelectPlace(SelectSTPlace(Card)); + return PotOfProsperityFunction(extraDeckMaterials, cardsId); } @@ -756,6 +767,12 @@ private bool ZeusEffect() private bool JuggernautLiebeSummon() { + if (Bot.MonsterZone.GetFirstMatchingCard(card => card.HasType(CardType.Xyz) && card.Rank == 10) != null) + { + int xyzPosition = Bot.MonsterZone.GetFirstMatchingCard(card => card.HasType(CardType.Xyz) && card.Rank == 10).Position; + AI.SelectPlace(xyzPosition); + } + return true; } @@ -763,15 +780,15 @@ private bool BookOfMoonActivate() { if (!(Duel.Player == 0)) return false; if(Duel.CurrentChain.Contains(Card)) return false; + if(BookOfMoonActivated) return false; ClientCard enemy_bestCard = Util.GetBestEnemyCard(true); if (enemy_bestCard != null && Enemy.MonsterZone.GetMatchingCardsCount(card => card.HasPosition(CardPosition.FaceUp)) > 0) { AI.SelectCard(enemy_bestCard); AI.SelectPlace(SelectSTPlace(Card, true)); - return true; - BookOfMoonActivated = true; + return true; } return false; @@ -1216,39 +1233,17 @@ private bool EglenEffect() AI.SelectNextCard(CardId.Empen); AI.SelectMaterials(materials); + AI.SelectPlace(SelectSTPlace( + Bot.Hand.GetFirstMatchingCard(card => card.IsCode(CardId.Empen)) + )); + eglen_NormalSummonEffectActivated = true; return true; } else { - if (!Bot.HasInHand(CardId.Avian) && Duel.Player == 1) - { - if (!Bot.HasInHand(CardId.Empen)) AI.SelectCard(CardId.Empen); - else AI.SelectCard(CardId.Avian); - - // Normal summon next monster - if (Bot.HasInHand(CardId.Empen)) AI.SelectNextCard(CardId.Empen); - else AI.SelectNextCard(CardId.Avian); - - if (Bot.HasInSpellZone(CardId.UnexploredWinds) && Util.GetBestEnemyCard() != null && Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 0) - { - AI.SelectOption(2); - materials.Clear(); - materials.Add(Bot.MonsterZone.GetFirstMatchingCard(card => card.Level == 1).Id); - materials.Add(Util.GetBestEnemyCard().Id); - } - - AI.SelectMaterials(materials); - } - else - { - if (Bot.HasInSpellZone(CardId.UnexploredWinds) && Util.GetBestEnemyCard() != null) - { - AI.SelectOption(2); - materials.Add(Util.GetBestEnemyCard().Id); - } - } + NormalSummonBossMonsters(); eglen_NormalSummonEffectActivated = true; From 786d94c60a2e520f5c1819b06b03ca3cab03fb32 Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Sat, 27 Jan 2024 20:33:01 +0800 Subject: [PATCH 17/21] -Added underworld goddess link summon; not tested -Fixes on summon positioning of XYZ -Fixes on Dreaming Town -Fixes on Thrust search -Added attachement effect on Zeus; not tested --- Game/AI/Decks/FloowandereezeExecutor.cs | 67 ++++++++++++++++++------- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index fb761ecb..0be13397 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -1,13 +1,6 @@ using YGOSharp.OCGWrapper.Enums; using System.Collections.Generic; using System.Linq; -using System; -using System.Threading; -using System.Configuration; -using YGOSharp.OCGWrapper; -using YGOSharp.Network.Enums; -using WindBot.Game.AI.Enums; -using System.Diagnostics.Eventing.Reader; namespace WindBot.Game.AI.Decks { @@ -108,6 +101,9 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.SpSummon, CardId.Zeus, ZeusSpSummon); AddExecutor(ExecutorType.Activate, CardId.Zeus, ZeusEffect); + // Link summons + AddExecutor(ExecutorType.SpSummon, CardId.UnderworldGoddess, LinkUnderworldGoddess); + AddExecutor(ExecutorType.Summon, CardId.Snowl, SnowlSummon); AddExecutor(ExecutorType.Summon, CardId.Avian, AvianSummon); AddExecutor(ExecutorType.Summon, CardId.Empen, EmpenSummon); @@ -156,6 +152,27 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Repos, CardId.Zeus, BossMonsterRepos); } + private bool LinkUnderworldGoddess() + { + if (Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() >= 4 && Enemy.MonsterZone.Count() > 0) + { + List materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).ToList(); + ClientCard enemyBestMonster = Util.GetBestEnemyMonster(); + + if (enemyBestMonster != null) + { + materials.Add(enemyBestMonster); + AI.SelectMaterials(materials); + + return true; + } + + return false; + } + + return false; + } + private bool SlackerdMagicianActivate() { return Util.IsChainTarget(Card); @@ -395,10 +412,12 @@ private bool DreamingTownActivate() AI.SelectPlace(SelectSTPlace(Bot.Hand.GetFirstMatchingCard(card => Card.IsCode(CardId.Robina)))); } - return Card.Location == CardLocation.SpellZone + return (Card.Location == CardLocation.SpellZone && Duel.Player == 1 && Bot.Hand.ContainsMonsterWithLevel(1) - && !MagnificentMapActivated; + && !MagnificentMapActivated + && Enemy.MonsterZone.Count() >= 1) + || Util.IsChainTarget(Card); } private bool DowneredMagicianSpSummon() @@ -489,7 +508,7 @@ private bool TrippleTacticsTalentActivate() private bool TrippleTacticsThrustActivate() { - if (Bot.Deck.GetCardCount(CardId.TrippleTacticsTalent) > 0) AI.SelectCard(CardId.TrippleTacticsTalent); + if (!Bot.HasInHand(CardId.TrippleTacticsTalent)) AI.SelectCard(CardId.TrippleTacticsTalent); else if (!(Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina))) { if (PotOfProsperityActivated) AI.SelectCard(CardId.PotOfDuality); @@ -759,6 +778,25 @@ private bool ZeusEffect() { if (Util.GetLastChainCard() == Card) return false; + // Material attachment effect + if (Duel.Player == 0 && ActivateDescription == Util.GetStringId(CardId.Zeus, 0)) + { + List prefferedAttachments = new List(); + + if (Bot.Deck.GetFirstMatchingCard(card => card.IsCode(CardId.TrippleTacticsTalent)) != null) + prefferedAttachments.Add(CardId.TrippleTacticsThrust); + else if (Bot.Deck.GetMatchingCards(card => card.IsCode(CardId.BookOfMoon)).Count() > 1) + prefferedAttachments.Add(CardId.BookOfMoon); + else + prefferedAttachments.AddRange(new List { + CardId.RaizaMegaMonarch, + CardId.DimensionShifter + }); + + if (prefferedAttachments.Count() > 0) + return true; + } + if ((Util.IsAllEnemyBetter() || Util.IsChainTarget(Card) || Enemy.GetFieldCount() >= 3) && (Duel.Player == 0 || Duel.Player == 1) && !Card.IsDisabled()) return true; @@ -767,12 +805,6 @@ private bool ZeusEffect() private bool JuggernautLiebeSummon() { - if (Bot.MonsterZone.GetFirstMatchingCard(card => card.HasType(CardType.Xyz) && card.Rank == 10) != null) - { - int xyzPosition = Bot.MonsterZone.GetFirstMatchingCard(card => card.HasType(CardType.Xyz) && card.Rank == 10).Position; - AI.SelectPlace(xyzPosition); - } - return true; } @@ -840,8 +872,7 @@ public override void OnNewTurn() private bool DreamingTownGraveyardActivate() { - return Card.Location == CardLocation.Grave - && Util.IsAllEnemyBetter(); + return Card.Location == CardLocation.Grave; } private bool ToccanBanishedEffect() From 7d73c64687aa5c089fe0f5ef0ab03474e569569d Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Sat, 27 Jan 2024 20:35:15 +0800 Subject: [PATCH 18/21] Reverted .sln version --- WindBot.sln | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WindBot.sln b/WindBot.sln index ab5ded86..20b5494c 100644 --- a/WindBot.sln +++ b/WindBot.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.8.34316.72 +# Visual Studio Version 15 +VisualStudioVersion = 15.0.28307.960 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindBot", "WindBot.csproj", "{3E7FAF67-A27D-4A61-B161-93AD4414183E}" EndProject From 6fc4f52231525bf8ab441d38dcebae00fadc7404 Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Sat, 27 Jan 2024 20:36:16 +0800 Subject: [PATCH 19/21] correction to the changes on .sln --- WindBot.sln | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WindBot.sln b/WindBot.sln index 20b5494c..721077a1 100644 --- a/WindBot.sln +++ b/WindBot.sln @@ -1,6 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 15 +# Visual Studio 15 VisualStudioVersion = 15.0.28307.960 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindBot", "WindBot.csproj", "{3E7FAF67-A27D-4A61-B161-93AD4414183E}" From 293abf24abd4b4df2985871450c1ff2cc85e3956 Mon Sep 17 00:00:00 2001 From: Edoardo Lolletti Date: Fri, 16 Feb 2024 21:08:29 +0100 Subject: [PATCH 20/21] Update android solution --- libWindbot.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/libWindbot.csproj b/libWindbot.csproj index 87a79a85..f42beb86 100644 --- a/libWindbot.csproj +++ b/libWindbot.csproj @@ -50,6 +50,7 @@ + From c75334cc88b5c0070ab2a6499869b3f7a6d6614b Mon Sep 17 00:00:00 2001 From: jdistro07 Date: Thu, 28 Mar 2024 21:12:39 +0800 Subject: [PATCH 21/21] - Fixed Book of Moon not setting - Prioritize Terraforming over Duality and Prosperity - Improvements on Avian negate conditions - Fixed Zeus not activating on Battle Phase - Optimized Dreaming Town activation conditions - Fixed normal summon using Map during opponent's turn. WIP: 1. Improvements on Prosperity and Duality search; for some reason AI.SelectCard just won't pick what it should prioritize. --- Game/AI/Decks/FloowandereezeExecutor.cs | 302 ++++++++++++++++++------ 1 file changed, 224 insertions(+), 78 deletions(-) diff --git a/Game/AI/Decks/FloowandereezeExecutor.cs b/Game/AI/Decks/FloowandereezeExecutor.cs index 0be13397..efce4932 100644 --- a/Game/AI/Decks/FloowandereezeExecutor.cs +++ b/Game/AI/Decks/FloowandereezeExecutor.cs @@ -1,6 +1,7 @@ using YGOSharp.OCGWrapper.Enums; using System.Collections.Generic; using System.Linq; +using YGOSharp.OCGWrapper; namespace WindBot.Game.AI.Decks { @@ -56,7 +57,10 @@ public class CardId ActivateEmpenBattleEffect = false, ActivateLiebe = false, MagnificentMapActivated = false, - Snowl_Activated = false; + MagnificentMapActivated_OpponentTurn = false, + Snowl_Activated = false, + DreamingTownActivated = false, + Battle_ZeusBoardWipeEffect = false; // spell actions private bool PotOfProsperityActivated = false; @@ -69,17 +73,30 @@ public class CardId private bool ZeusActivated = false; List Impermanence_list = new List(); + int[] PotentialSpellZoneWipes = new int[] + { + 18144506, // Harpie's Feather Duster + 14532163 // Lighting Storm + + }; + int[] PotentialMonsterWipes = new int[] + { + 53129443, // Dark Hole + 14532163 // Lighting Storm + }; public FloowandereezeExecutor(GameAI ai, Duel duel) : base(ai, duel) { - AddExecutor(ExecutorType.Activate, CardId.DimensionShifter); + AddExecutor(ExecutorType.Activate, CardId.DimensionShifter, DimensionShifterActivate); AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherDuster, DefaultHarpiesFeatherDusterFirst); - AddExecutor(ExecutorType.Activate, CardId.BookOfMoon, BookOfMoonActivate); + AddExecutor(ExecutorType.Activate, CardId.Terraforming, TerraformingActivate); AddExecutor(ExecutorType.Activate, CardId.PotOfDuality, PotOfDualityActivate); AddExecutor(ExecutorType.Activate, CardId.PotOfProsperity, PotOfProsperityActivate); - AddExecutor(ExecutorType.Activate, CardId.Terraforming, TerraformingActivate); + AddExecutor(ExecutorType.Activate, CardId.AdventOfAdventure, AdventOfAdventureEffect); + AddExecutor(ExecutorType.SpellSet, CardId.BookOfMoon, BookOfMoonSet); + AddExecutor(ExecutorType.Activate, CardId.BookOfMoon, BookOfMoonActivate); AddExecutor(ExecutorType.Activate, CardId.TrippleTacticsThrust, TrippleTacticsThrustActivate); AddExecutor(ExecutorType.Activate, CardId.TrippleTacticsTalent, TrippleTacticsTalentActivate); @@ -99,7 +116,8 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Activate, CardId.SlackerdMagician, SlackerdMagicianActivate); AddExecutor(ExecutorType.SpSummon, CardId.DowneredMagician, DowneredMagicianSpSummon); AddExecutor(ExecutorType.SpSummon, CardId.Zeus, ZeusSpSummon); - AddExecutor(ExecutorType.Activate, CardId.Zeus, ZeusEffect); + AddExecutor(ExecutorType.Activate, CardId.Zeus, ZeusAttachEffect); + AddExecutor(ExecutorType.Activate, CardId.Zeus, ZeusBoardwipeEffect); // Link summons AddExecutor(ExecutorType.SpSummon, CardId.UnderworldGoddess, LinkUnderworldGoddess); @@ -109,14 +127,13 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Summon, CardId.Empen, EmpenSummon); AddExecutor(ExecutorType.Summon, CardId.RaizaMegaMonarch, RaizaMegaMonarchSummon); + AddExecutor(ExecutorType.SpellSet, CardId.DreamingTown, DreamingTownSet); + AddExecutor(ExecutorType.Activate, CardId.DreamingTown, DreamingTownActivate); + AddExecutor(ExecutorType.Activate, CardId.DreamingTown, DreamingTownGraveyardActivate); AddExecutor(ExecutorType.Activate, CardId.RaizaMegaMonarch, RaizaMegaMonarchActivate); AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, MagnificentMapActivate); AddExecutor(ExecutorType.Activate, CardId.MagnificentMap, Active_MagnificentMapActivate); - AddExecutor(ExecutorType.Activate, CardId.AdventOfAdventure, AdventOfAdventureEffect); AddExecutor(ExecutorType.Activate, CardId.UnexploredWinds, UnexploredWindsActivate); - AddExecutor(ExecutorType.SpellSet, CardId.DreamingTown, DreamingTownSet); - AddExecutor(ExecutorType.Activate, CardId.DreamingTown, DreamingTownActivate); - AddExecutor(ExecutorType.Activate, CardId.DreamingTown, DreamingTownGraveyardActivate); AddExecutor(ExecutorType.SpellSet, CardId.HarpiesFeatherStorm, HarpiesFeatherStormSet); AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherStorm, HarpiesFeatherStormActivate); @@ -135,7 +152,6 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) // Chain block for strongest effect monster AddExecutor(ExecutorType.Activate, CardId.Empen, EmpenEffect); AddExecutor(ExecutorType.Activate, CardId.Empen, EmpenBattleEffect); - AddExecutor(ExecutorType.Activate, CardId.Robina, RobinaBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Eglen, EglenBanishedEffect); AddExecutor(ExecutorType.Activate, CardId.Toccan, ToccanBanishedEffect); @@ -152,6 +168,31 @@ public FloowandereezeExecutor(GameAI ai, Duel duel) AddExecutor(ExecutorType.Repos, CardId.Zeus, BossMonsterRepos); } + private bool ZeusBoardwipeEffect() + { + if (Util.GetLastChainCard() == Card) return false; + + Battle_ZeusBoardWipeEffect = true; + + return (Util.IsAllEnemyBetter() && Enemy.GetFieldCount() > 2) + || Util.IsChainTarget(Card); + } + + private bool BookOfMoonSet() + { + return (Enemy.GetMonsterCount() != 0 || Util.GetBestEnemyMonster(true, true) != null) + && !Bot.HasInSpellZone(CardId.BookOfMoon) && Duel.Phase == DuelPhase.Main2; + } + + /// + /// Activate on opponent's turn + /// + /// + private bool DimensionShifterActivate() + { + return Duel.Player == 1 || !Duel.IsFirst; + } + private bool LinkUnderworldGoddess() { if (Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() >= 4 && Enemy.MonsterZone.Count() > 0) @@ -357,6 +398,16 @@ public override BattlePhaseAction OnBattle(IList attackers, IList potentialSelfDamage; } + //Zeus + if (attacker.IsCode(CardId.Zeus) && realDefenderPower > realAttackerPower) + { + int zeusPower = attacker.Attack; + + if (zeusPower < realDefenderPower) + ActivateEmpenBattleEffect = true; + + return zeusPower < realDefenderPower; + } + return base.OnPreBattleBetween(attacker, defender); } @@ -412,12 +474,21 @@ private bool DreamingTownActivate() AI.SelectPlace(SelectSTPlace(Bot.Hand.GetFirstMatchingCard(card => Card.IsCode(CardId.Robina)))); } + DreamingTownActivated = true; + + ClientCard lastActivatedCard = Util.GetLastChainCard(); + bool isSpellZoneWipe; + + if (lastActivatedCard != null) isSpellZoneWipe = PotentialSpellZoneWipes.Contains(lastActivatedCard.Id); + else isSpellZoneWipe = false; + return (Card.Location == CardLocation.SpellZone && Duel.Player == 1 - && Bot.Hand.ContainsMonsterWithLevel(1) - && !MagnificentMapActivated - && Enemy.MonsterZone.Count() >= 1) - || Util.IsChainTarget(Card); + && Bot.Hand.ContainsCardWithId(CardId.Robina) + && !MagnificentMapActivated_OpponentTurn + && (Enemy.GetFieldCount() >= 3 || Util.IsChainTarget(Card))) + || isSpellZoneWipe + || Duel.Phase == DuelPhase.Battle; } private bool DowneredMagicianSpSummon() @@ -644,13 +715,11 @@ private bool SnowlActivate() return true; } - // Quick effect - else if (ActivateDescription == Util.GetStringId(CardId.Snowl, 0)) + // Activate face down effect + else if (Duel.Player == 1 && (Duel.Phase == DuelPhase.BattleStart || Util.IsChainTarget(Card))) { - if (Duel.Player == 1 && !(Duel.Phase == DuelPhase.Main1 || Duel.Phase == DuelPhase.Main2)) - { - List prefferedCost = new List(); - prefferedCost.AddRange(new List { + List prefferedCost = new List(); + prefferedCost.AddRange(new List { CardId.Stri, CardId.Eglen, CardId.Toccan, @@ -659,10 +728,9 @@ private bool SnowlActivate() CardId.TrippleTacticsThrust }); - AI.SelectCard(prefferedCost); + AI.SelectCard(prefferedCost); - return true; - } + return true; } return false; @@ -752,13 +820,14 @@ private bool PotOfProsperityFunction(List extraDeckMonsters private bool AvianActivate() { - if (Duel.LastChainPlayer == 1) - { - if (Bot.HasInMonstersZone(CardId.Empen)) AI.SelectCard(Util.GetBestEnemySpell(true)); - else AI.SelectCard(Util.GetBestEnemyCard(true)); + ClientCard lastActivatedCard = Util.GetLastChainCard(); - return true; - } + if (lastActivatedCard != null) + return Duel.LastChainPlayer == 1 + && (lastActivatedCard.HasType(CardType.Counter) + || Util.IsChainTarget(Card) + || Util.IsChainTarget(Bot.MonsterZone.GetFirstMatchingCard(c => c.IsCode(CardId.Empen)))) + && (PotentialMonsterWipes.Contains(lastActivatedCard.Id) || PotentialMonsterWipes.Contains(lastActivatedCard.Id)); return false; } @@ -774,12 +843,12 @@ private bool TerraformingActivate() return false; } - private bool ZeusEffect() + private bool ZeusAttachEffect() { if (Util.GetLastChainCard() == Card) return false; // Material attachment effect - if (Duel.Player == 0 && ActivateDescription == Util.GetStringId(CardId.Zeus, 0)) + if (Duel.Player == 0 && ActivateDescription == Util.GetStringId(CardId.Zeus, 1)) { List prefferedAttachments = new List(); @@ -797,7 +866,7 @@ private bool ZeusEffect() return true; } - if ((Util.IsAllEnemyBetter() || Util.IsChainTarget(Card) || Enemy.GetFieldCount() >= 3) && (Duel.Player == 0 || Duel.Player == 1) && !Card.IsDisabled()) + if ((Util.IsAllEnemyBetter() || Util.IsChainTarget(Card) || Enemy.GetFieldCount() > 3) && (Duel.Player == 0 || Duel.Player == 1) && !Card.IsDisabled() && Bot.MonsterZone.GetMatchingCardsCount(c => c.IsCode(CardId.Empen) && c.HasPosition(CardPosition.FaceUp)) == 0) return true; return false; @@ -810,19 +879,18 @@ private bool JuggernautLiebeSummon() private bool BookOfMoonActivate() { - if (!(Duel.Player == 0)) return false; - if(Duel.CurrentChain.Contains(Card)) return false; - if(BookOfMoonActivated) return false; - - ClientCard enemy_bestCard = Util.GetBestEnemyCard(true); + if (Util.GetLastChainCard() != null) + if (Util.GetLastChainCard().Id == CardId.BookOfMoon) return false; // Do not chain to self - if (enemy_bestCard != null && Enemy.MonsterZone.GetMatchingCardsCount(card => card.HasPosition(CardPosition.FaceUp)) > 0) { - AI.SelectCard(enemy_bestCard); - AI.SelectPlace(SelectSTPlace(Card, true)); - BookOfMoonActivated = true; - return true; + if (Util.IsAllEnemyBetter(true)) + { + ClientCard monster = Enemy.GetMonsters().GetHighestAttackMonster(true); + if (monster != null && monster.HasType(CardType.Effect) && !monster.HasType(CardType.Link) && (monster.HasType(CardType.Xyz) || monster.Level > 4)) + { + AI.SelectCard(monster); + return true; + } } - return false; } @@ -867,6 +935,13 @@ public override void OnNewTurn() BookOfMoonActivated = false; + // Spells + MagnificentMapActivated = false; + MagnificentMapActivated_OpponentTurn = false; + DreamingTownActivated = false; + + Battle_ZeusBoardWipeEffect = false; + base.OnNewTurn(); } @@ -924,6 +999,8 @@ private bool Active_MagnificentMapActivate() AI.SelectNextCard(CardId.Robina); } + MagnificentMapActivated = true; + return true; } else if (Card.Location == CardLocation.SpellZone && Bot.HasInHandOrHasInMonstersZone(CardId.Robina) && Duel.Player == 0) @@ -935,28 +1012,28 @@ private bool Active_MagnificentMapActivate() else if (eglen_NormalSummonEffectActivated && !Bot.HasInHand(CardId.Eglen)) AI.SelectNextCard(CardId.Eglen); else AI.SelectNextCard(CardId.Stri); + MagnificentMapActivated = true; + return true; } - - if (ActivateDescription == Util.GetStringId(CardId.MagnificentMap, 0) && Duel.Player == 1) + else if (Duel.Player == 1 && Bot.Hand.GetMatchingCardsCount(c => c.Level == 1) > 0 && Duel.LastSummonPlayer == 1 && DreamingTownActivated == false) { - int levelOneMonsters = Bot.MonsterZone.GetMatchingCardsCount(card => card.Level == 1); - if (!robina_NormalSummonEffectActivated) AI.SelectCard(CardId.Robina); else NormalSummonBossMonsters(); - MagnificentMapActivated = true; + MagnificentMapActivated_OpponentTurn = true; return true; } - - return false; + return false; } private bool MagnificentMapActivate() { - return !Bot.HasInSpellZone(CardId.MagnificentMap) && Card.Location == CardLocation.Hand; + return !Bot.HasInSpellZone(CardId.MagnificentMap) + && Card.Location == CardLocation.Hand + && (Bot.GetMonsterCount() != 0 || Bot.Hand.GetMatchingCards(c => c.Level == 1).Count() > 0); } private bool AdventOfAdventureEffect() @@ -968,7 +1045,7 @@ private bool AdventOfAdventureEffect() int[] cost; if(!Bot.Hand.ContainsMonsterWithLevel(1)) cost = Bot.Hand.GetMatchingCards(card => (card.Level > 5 || card.Level == 1) && !card.IsCode(CardId.Robina) && !card.IsCode(CardId.Empen) || !card.IsCode(CardId.Avian) || !card.IsCode(CardId.Snowl)).Select(c => c.Id).ToArray(); - else cost = Bot.Hand.GetMatchingCards(card => card.Level == 1 && !(card.IsCode(CardId.Robina) || card.IsCode(CardId.Eglen))).Select(c => c.Id).ToArray(); + else cost = Bot.Hand.GetMatchingCards(card => card.Level == 1 && !card.IsCode(CardId.Robina)).Select(c => c.Id).ToArray(); if (!Bot.HasInHand(CardId.Robina) && cost.Count() > 0) { @@ -999,7 +1076,10 @@ private bool AdventOfAdventureEffect() private bool DreamingTownSet() { AI.SelectPlace(SelectSTPlace(Card, true)); - return Bot.HasInHandOrHasInMonstersZone(CardId.Robina) || Bot.HasInBanished(CardId.Robina) || Bot.HasInHandOrHasInMonstersZone(CardId.Eglen) || Bot.HasInBanished(CardId.Eglen); + return (Bot.HasInHandOrHasInMonstersZone(CardId.Robina) + || Bot.HasInBanished(CardId.Robina) + || Bot.HasInHandOrHasInMonstersZone(CardId.Eglen) + || Bot.HasInBanished(CardId.Eglen)); } private bool PotOfDualityActivate() @@ -1012,20 +1092,29 @@ private bool PotOfDualityActivate() } else if (!Bot.HasInHand(CardId.Eglen)) { - AI.SelectCard(CardId.Robina); + AI.SelectCard(CardId.Eglen); return true; } - else if (!Bot.HasInHandOrInSpellZone(CardId.MagnificentMap)) + else if (!Bot.HasInHand(CardId.Stri)) { - AI.SelectCard(CardId.MagnificentMap); + AI.SelectCard(CardId.Stri); + return true; + } + else if (!Bot.HasInHand(CardId.Toccan)) + { + AI.SelectCard(CardId.Toccan); return true; } else { int[] otherPrefferedCards = new int[] { - CardId.Stri, - CardId.Toccan + CardId.PotOfProsperity, + CardId.AdventOfAdventure, + CardId.AdventOfAdventure, + CardId.TrippleTacticsThrust, + CardId.TrippleTacticsTalent, + CardId.Terraforming }; AI.SelectCard(otherPrefferedCards); @@ -1060,15 +1149,14 @@ private bool RobinaEffect() { if (Snowl_Activated) return false; - // Search eglen - if (!(Bot.HasInHandOrHasInMonstersZone(CardId.Eglen) || Bot.HasInBanished(CardId.Eglen))) AI.SelectCard(CardId.Eglen); - else if (Bot.HasInHandOrHasInMonstersZone(CardId.Eglen) || Bot.HasInBanished(CardId.Eglen) && Bot.Graveyard.Count() > 0) AI.SelectCard(CardId.Stri); - else AI.SelectCard(CardId.Toccan); + // Search + if (!Bot.HasInHandOrHasInMonstersZone(CardId.Eglen) || !Bot.HasInBanished(CardId.Eglen)) AI.SelectCard(CardId.Eglen); + else if (!Bot.HasInHandOrHasInMonstersZone(CardId.Toccan) || !Bot.HasInBanished(CardId.Toccan)) AI.SelectCard(CardId.Toccan); + else AI.SelectCard(CardId.Stri); int materials = Bot.MonsterZone.GetMatchingCardsCount(card => card.Level == 1); - if(materials > 1) - NormalSummonBossMonsters(); + NormalSummonBossMonsters(); // Normal summon again if (!eglen_NormalSummonEffectActivated) @@ -1123,10 +1211,11 @@ public List BanishedRecycleCards() return recycleCards; } + /// + /// Global function for normal summoning monsters from level one monsters + /// public void NormalSummonBossMonsters() { - int[] hand_bossMonsters = Bot.Hand.GetMatchingCards(card => card.Level > 7).Select(c => c.Id).ToArray(); - List materials = new List(); materials = Bot.MonsterZone.GetMatchingCards(card => card.Level == 1) .Select(x => x.Id) @@ -1143,29 +1232,31 @@ public void NormalSummonBossMonsters() if(Enemy.SpellZone.Count() > 0 && Util.GetBestEnemySpell() != null) materials.Add(Util.GetBestEnemySpell().Id); else materials.Add(Util.GetBestEnemyCard().Id); } - - // summon boss monsters - if (hand_bossMonsters.Count() > 0 && materials.Count() > 1) + + if (materials.Count() >= 2) { AI.SelectYesNo(true); - if (Bot.HasInHand(CardId.Empen)) + if (Bot.HasInHand(CardId.Empen) && !Bot.HasInMonstersZone(CardId.Empen) && materials.Count >= 2) { AI.SelectCard(CardId.Empen); + AI.SelectMaterials(materials); AI.SelectPlace(SelectSTPlace( Bot.Hand.GetFirstMatchingCard(card => card.IsCode(CardId.Empen)) )); } - else if (Bot.HasInHand(CardId.Avian)) + else if (Bot.HasInHand(CardId.Avian) && Bot.HasInMonstersZone(CardId.Empen) || Bot.HasInMonstersZone(CardId.Snowl) && materials.Count >= 2) { AI.SelectCard(CardId.Avian); + AI.SelectMaterials(materials); AI.SelectPlace(SelectSTPlace( Bot.Hand.GetFirstMatchingCard(card => card.IsCode(CardId.Avian)) )); } - else if (Bot.HasInHand(CardId.Snowl)) + else if (Bot.HasInHand(CardId.Snowl) && (Bot.HasInMonstersZone(CardId.Empen) || Bot.GetMonsterCount() == 0) && materials.Count >= 2) { AI.SelectCard(CardId.Snowl); + AI.SelectMaterials(materials); AI.SelectPlace(SelectSTPlace( Bot.Hand.GetFirstMatchingCard(card => card.IsCode(CardId.Snowl)) )); @@ -1173,6 +1264,7 @@ public void NormalSummonBossMonsters() else { AI.SelectCard(CardId.RaizaMegaMonarch); + AI.SelectMaterials(materials); AI.SelectPlace(SelectSTPlace( Bot.Hand.GetFirstMatchingCard(card => card.IsCode(CardId.RaizaMegaMonarch)) )); @@ -1244,8 +1336,7 @@ private bool EglenEffect() .ToList(); if (!Bot.HasInHandOrHasInMonstersZone(CardId.Empen) - || Bot.MonsterZone.GetCardCount(CardId.Empen) > 0 - && Duel.Player == 1) + || Bot.MonsterZone.GetCardCount(CardId.Empen) > 0) { // Fetch empen from deck AI.SelectCard(CardId.Empen); @@ -1261,8 +1352,8 @@ private bool EglenEffect() } // Summon empen - AI.SelectNextCard(CardId.Empen); AI.SelectMaterials(materials); + AI.SelectNextCard(CardId.Empen); AI.SelectPlace(SelectSTPlace( Bot.Hand.GetFirstMatchingCard(card => card.IsCode(CardId.Empen)) @@ -1272,16 +1363,71 @@ private bool EglenEffect() return true; } - else + else if (!Bot.HasInHandOrHasInMonstersZone(CardId.Avian) + && Duel.Player == 1 + || Bot.MonsterZone.GetCardCount(CardId.Avian) > 0) { - NormalSummonBossMonsters(); + // Fetch Avian from deck + AI.SelectCard(CardId.Avian); + + // Tribute opponent's card using Unexplored winds + if (Bot.HasInSpellZone(CardId.UnexploredWinds) && Util.GetBestEnemyCard() != null && Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 0) + { + AI.SelectOption(1); + + materials.Clear(); + materials.Add(Bot.MonsterZone.GetFirstMatchingCard(card => card.Level == 1).Id); + materials.Add(Util.GetBestEnemyCard().Id); + } + + // Summon Avian + AI.SelectMaterials(materials); + AI.SelectNextCard(CardId.Avian); + + AI.SelectPlace(SelectSTPlace( + Bot.Hand.GetFirstMatchingCard(card => card.IsCode(CardId.Avian)) + )); eglen_NormalSummonEffectActivated = true; return true; } - } + else if (!Bot.HasInHandOrHasInMonstersZone(CardId.Snowl) + && Duel.Turn > 2 + || Bot.MonsterZone.GetCardCount(CardId.Snowl) > 0) + { + // Fetch Snowl from deck + AI.SelectCard(CardId.Avian); + + // Tribute opponent's card using Unexplored winds + if (Bot.HasInSpellZone(CardId.UnexploredWinds) && Util.GetBestEnemyCard() != null && Bot.MonsterZone.GetMatchingCards(card => card.Level == 1).Count() > 0) + { + AI.SelectOption(1); + + materials.Clear(); + materials.Add(Bot.MonsterZone.GetFirstMatchingCard(card => card.Level == 1).Id); + materials.Add(Util.GetBestEnemyCard().Id); + } + // Summon Snowl + AI.SelectMaterials(materials); + AI.SelectNextCard(CardId.Snowl); + + AI.SelectPlace(SelectSTPlace( + Bot.Hand.GetFirstMatchingCard(card => card.IsCode(CardId.Snowl)) + )); + + eglen_NormalSummonEffectActivated = true; + + return true; + } + else + { + NormalSummonBossMonsters(); + eglen_NormalSummonEffectActivated = true; + return true; + } + } return false; } }