diff --git a/libWindbot/Game/AI/AIUtil.cs b/libWindbot/Game/AI/AIUtil.cs index eeeb8bf..4a0718c 100644 --- a/libWindbot/Game/AI/AIUtil.cs +++ b/libWindbot/Game/AI/AIUtil.cs @@ -424,7 +424,7 @@ public IList SelectPreferredCards(IList preferred, IList public IList CheckSelectCount(IList _selected, IList cards, int min, int max) { - var selected = _selected.ToList(); + var selected = _selected.Distinct().ToList(); if (selected.Count < min) { foreach (ClientCard card in cards) @@ -442,5 +442,115 @@ public IList CheckSelectCount(IList _selected, IList + /// Get all xyz materials lists that xyz monster required level in the 'pre_materials' list + /// + /// Original materials + /// Xyz monster required level + /// SpSummon rule:number of xyz materials + /// More xyz materials + /// Filter xyz materials func + /// + public List> GetXyzMaterials(IList param_pre_materials, int level, int material_count, bool material_count_above = false, Func material_func = null) + { + List> result = new List>(); + List pre_materials = param_pre_materials?.Where(card => card != null && !(card.IsFacedown() & card.Location == CardLocation.MonsterZone) && card.Level == level && !card.IsMonsterNotBeXyzMaterial()).ToList(); + if (pre_materials?.Count() < material_count) return result; + Func default_func = card => true; + material_func = material_func ?? default_func; + for (int i = 1; i < Math.Pow(2, pre_materials.Count); i++) + { + List temp_materials = new List(); + string binaryString = Convert.ToString(i, 2).PadLeft(pre_materials.Count, '0'); + char[] reversedBinaryChars = binaryString.Reverse().ToArray(); + for (int j = 0; j < pre_materials.Count; j++) + { + if (reversedBinaryChars[j] == '1' && material_func(pre_materials[j])) + { + temp_materials.Add(pre_materials[j]); + } + } + if (material_count_above ? temp_materials.Count >= material_count : temp_materials.Count == material_count) + { + result.Add(temp_materials); + } + } + return result; + } + + /// + /// Get all synchro materials lists that synchro monster level == param 'level' in the 'pre_materials' list + /// + /// Original materials + /// Synchro monster level + /// SpSummon rule:number of tuner monsters + /// SpSummon rule:number of non-tuner monsters count + /// More tuner monsters + /// More non-tuner monsters + /// Filter tuner monsters func + /// Filter non-tuner monsters func + /// + public List> GetSynchroMaterials(IList param_pre_materials, int level, int tuner_count, int n_tuner_count, bool tuner_count_above = false, bool n_tuner_count_above = true, Func tuner_func = null, Func n_tuner_func = null) + { + List> t_result = new List>(); + List pre_materials = param_pre_materials?.Where(card => card != null && !(card.IsFacedown() & card.Location == CardLocation.MonsterZone) && card.Level > 0 && !card.IsMonsterNotBeSynchroMaterial()).ToList(); + if (pre_materials?.Count() < tuner_count + n_tuner_count) return t_result; + Func default_func = card => true; + tuner_func = tuner_func ?? default_func; + n_tuner_func = n_tuner_func ?? default_func; + pre_materials.Sort(CardContainer.CompareCardLevel); + Stack materials_stack = new Stack(); + for (var i = 0; i < pre_materials.Count; i++) + { + if (pre_materials[i].Level > level) break; + materials_stack.Push(new object[] { pre_materials[i].Level, i, pre_materials[i].Level, new List { pre_materials[i] } }); + } + while (materials_stack.Count > 0) + { + object[] data = materials_stack.Pop(); + int num = (int)data[0]; + int index = (int)data[1]; + int sum = (int)data[2]; + List temp_materials = (List)data[3]; + if (sum == level) + { + t_result.Add(temp_materials); + } + else if (sum < level) + { + for (var i = index + 1; i < pre_materials.Count; i++) + { + if (pre_materials[i].Level > level - sum) break; + if (i > index + 1 && pre_materials[i].Level == pre_materials[i - 1].Level) continue; + var new_temp_materials = new List(temp_materials); + new_temp_materials.Add(pre_materials[i]); + materials_stack.Push(new object[] { pre_materials[i].Level, i, sum + pre_materials[i].Level, new_temp_materials }); + } + } + } + List> result = new List>(); + for (int i = 0; i < t_result.Count; i++) + { + List materials = t_result[i]; + List tuner_materials = new List(); + List n_tuner_materials = new List(); + foreach (ClientCard material in materials) + { + if (material.HasType(CardType.Tuner) && tuner_func(material)) + { + tuner_materials.Add(material); + } + else if (material.Level > 0 && n_tuner_func(material)) + { + n_tuner_materials.Add(material); + } + } + if ((tuner_count_above ? tuner_materials.Count >= tuner_count : tuner_materials.Count == tuner_count) + && (n_tuner_count_above ? n_tuner_materials.Count >= n_tuner_count : n_tuner_materials.Count == n_tuner_count)) + result.Add(materials); + } + return result; + } } } \ No newline at end of file diff --git a/libWindbot/Game/AI/CardContainer.cs b/libWindbot/Game/AI/CardContainer.cs index 1b263e5..bc69190 100644 --- a/libWindbot/Game/AI/CardContainer.cs +++ b/libWindbot/Game/AI/CardContainer.cs @@ -25,6 +25,15 @@ public static int CompareCardLevel(ClientCard cardA, ClientCard cardB) return 1; } + public static int CompareCardLink(ClientCard cardA, ClientCard cardB) + { + if (cardA.LinkCount < cardB.LinkCount) + return -1; + if (cardA.LinkCount == cardB.LinkCount) + return 0; + return 1; + } + public static int CompareDefensePower(ClientCard cardA, ClientCard cardB) { if (cardA == null && cardB == null) diff --git a/libWindbot/Game/AI/CardExtension.cs b/libWindbot/Game/AI/CardExtension.cs index 1fcc453..684848a 100644 --- a/libWindbot/Game/AI/CardExtension.cs +++ b/libWindbot/Game/AI/CardExtension.cs @@ -78,5 +78,21 @@ public static bool IsFusionSpell(this ClientCard card) { return Enum.IsDefined(typeof(FusionSpell), card.Id); } + + /// + /// Is this monster not be synchro material? + /// + public static bool IsMonsterNotBeSynchroMaterial(this ClientCard card) + { + return Enum.IsDefined(typeof(NotBeSynchroMaterialMonster), card.Id); + } + + /// + /// Is this monster not be xyz material? + /// + public static bool IsMonsterNotBeXyzMaterial(this ClientCard card) + { + return Enum.IsDefined(typeof(NotBeXyzMaterialMonster), card.Id); + } } } \ No newline at end of file diff --git a/libWindbot/Game/AI/Decks/BraveExecutor.cs b/libWindbot/Game/AI/Decks/BraveExecutor.cs index c04b96a..f55c255 100644 --- a/libWindbot/Game/AI/Decks/BraveExecutor.cs +++ b/libWindbot/Game/AI/Decks/BraveExecutor.cs @@ -354,8 +354,8 @@ private bool DestinyHeroDestroyPhoenixEnforcerEffect() return true; else { - ClientCard target = Util.GetProblematicEnemyCard(); - if (target != null) + ClientCard target = Util.GetProblematicEnemyCard(2500); + if (target != null && !Util.ChainContainPlayer(0)) { AI.SelectCard(CardId.DestinyHeroDestroyPhoenixEnforcer); AI.SelectNextCard(target); diff --git a/libWindbot/Game/AI/Decks/ExosisterExecutor.cs b/libWindbot/Game/AI/Decks/ExosisterExecutor.cs new file mode 100644 index 0000000..03f1517 --- /dev/null +++ b/libWindbot/Game/AI/Decks/ExosisterExecutor.cs @@ -0,0 +1,2977 @@ +using YGOSharp.OCGWrapper; +using YGOSharp.OCGWrapper.Enums; +using System.Collections.Generic; +using WindBot; +using WindBot.Game; +using WindBot.Game.AI; +using System.Linq; +using System; + +namespace WindBot.Game.AI.Decks +{ + [Deck("Exosister", "AI_Exosister")] + + class ExosisterExecutor : DefaultExecutor + { + public class CardId + { + public const int ExosisterElis = 16474916; + public const int ExosisterStella = 43863925; + public const int ExosisterIrene = 79858629; + public const int ExosisterSophia = 5352328; + public const int ExosisterMartha = 37343995; + public const int Aratama = 16889337; + public const int Sakitama = 67972302; + // _CardId.MaxxC = 23434538; + // _CardId.AshBlossom = 14558127; + + public const int ExosisterPax = 77913594; + public const int ExosisterArment = 4408198; + public const int PotofExtravagance = 84211599; + // _CardId.CalledByTheGrave = 24224830; + + public const int ExosisterVadis = 77891946; + public const int ExosisterReturnia = 197042; + // _CardId.InfiniteImpermanence = 10045474; + + public const int ExosisterMikailis = 42741437; + public const int ExosisterKaspitell = 78135071; + public const int ExosisterGibrine = 5530780; + public const int ExosisterAsophiel = 41524885; + public const int ExosistersMagnifica = 59242457; + public const int TellarknightConstellarCaduceus = 58858807; + public const int StellarknightConstellarDiamond = 9272381; + public const int DivineArsenalAAZEUS_SkyThunder = 90448279; + public const int DonnerDaggerFurHire = 8728498; + // _CardId.EvilswarmExcitonKnight = 46772449; + + public const int NaturalExterio = 99916754; + public const int NaturalBeast = 33198837; + public const int ImperialOrder = 61740673; + public const int SwordsmanLV7 = 37267041; + public const int RoyalDecree = 51452091; + public const int Number41BagooskatheTerriblyTiredTapir = 90590303; + public const int InspectorBoarder = 15397015; + public const int DimensionShifter = 91800273; + } + + public ExosisterExecutor(GameAI ai, Duel duel) + : base(ai, duel) + { + // trigger + AddExecutor(ExecutorType.Activate, CardId.ExosistersMagnifica, ExosistersMagnificaActivateTrigger); + + // quick effect + AddExecutor(ExecutorType.Activate, CardId.ExosisterMikailis, ExosisterMikailisActivate); + AddExecutor(ExecutorType.Activate, CardId.ExosistersMagnifica, ExosistersMagnificaActivateBanish); + AddExecutor(ExecutorType.Activate, CardId.ExosisterReturnia, ExosisterReturniaActivate); + AddExecutor(ExecutorType.Activate, CardId.ExosisterVadis, ExosisterVadisActivate); + AddExecutor(ExecutorType.Activate, _CardId.InfiniteImpermanence, InfiniteImpermanenceActivate); + AddExecutor(ExecutorType.Activate, CardId.StellarknightConstellarDiamond); + AddExecutor(ExecutorType.Activate, _CardId.AshBlossom, AshBlossomActivate); + AddExecutor(ExecutorType.Activate, _CardId.CalledByTheGrave, CalledbytheGraveActivate); + AddExecutor(ExecutorType.Activate, DefaultExosisterTransform); + AddExecutor(ExecutorType.Activate, CardId.ExosisterArment, ExosisterArmentActivate); + + // free chain + AddExecutor(ExecutorType.Activate, _CardId.MaxxC, MaxxCActivate); + + // search + AddExecutor(ExecutorType.Activate, CardId.PotofExtravagance, PotofExtravaganceActivate); + + // field effect + AddExecutor(ExecutorType.Activate, CardId.Aratama); + AddExecutor(ExecutorType.Activate, CardId.DonnerDaggerFurHire, DonnerDaggerFurHireActivate); + AddExecutor(ExecutorType.Activate, CardId.ExosisterKaspitell, ExosisterKaspitellActivate); + AddExecutor(ExecutorType.Activate, CardId.ExosisterGibrine, ExosisterGibrineActivate); + AddExecutor(ExecutorType.Activate, CardId.ExosisterAsophiel, ExosisterAsophielActivate); + + AddExecutor(ExecutorType.Activate, CardId.ExosisterSophia, ExosisterSophiaActivate); + AddExecutor(ExecutorType.Activate, CardId.ExosisterIrene, ExosisterIreneActivate); + AddExecutor(ExecutorType.Activate, CardId.ExosisterStella, ExosisterStellaActivate); + + // addition monster summmon + AddExecutor(ExecutorType.Activate, CardId.ExosisterElis, ExosisterElisActivate); + AddExecutor(ExecutorType.Activate, CardId.Sakitama, SakitamaActivate); + AddExecutor(ExecutorType.Activate, CardId.ExosisterPax, ExosisterPaxActivate); + AddExecutor(ExecutorType.Activate, CardId.ExosisterStella, ExosisterStellaSecondActivate); + + // xyz summon + AddExecutor(ExecutorType.SpSummon, CardId.StellarknightConstellarDiamond); + AddExecutor(ExecutorType.SpSummon, CardId.DonnerDaggerFurHire, DonnerDaggerFurHireSpSummonCheck); + AddExecutor(ExecutorType.SpSummon, CardId.ExosisterMikailis, ExosisterMikailisAdvancedSpSummonCheck); + AddExecutor(ExecutorType.SpSummon, CardId.ExosisterKaspitell, ExosisterKaspitellAdvancedSpSummonCheck); + + AddExecutor(ExecutorType.SpSummon, CardId.ExosisterKaspitell, ExosisterKaspitellSpSummonCheck); + AddExecutor(ExecutorType.SpSummon, CardId.ExosisterMikailis, ExosisterMikailisSpSummonCheck); + AddExecutor(ExecutorType.SpSummon, CardId.TellarknightConstellarCaduceus, TellarknightConstellarCaduceusSpSummonCheck); + + AddExecutor(ExecutorType.SpSummon, CardId.ExosistersMagnifica, ExosistersMagnificaSpSummonCheck); + + AddExecutor(ExecutorType.SpSummon, _CardId.EvilswarmExcitonKnight, DefaultEvilswarmExcitonKnightSummon); + AddExecutor(ExecutorType.Activate, _CardId.EvilswarmExcitonKnight, DefaultEvilswarmExcitonKnightEffect); + + // normal summon for xyz(avoiding MaxxC) + AddExecutor(ExecutorType.Summon, CardId.ExosisterStella, ExosisterAvoidMaxxCSummonCheck); + AddExecutor(ExecutorType.Summon, CardId.ExosisterSophia, ExosisterAvoidMaxxCSummonCheck); + AddExecutor(ExecutorType.Summon, CardId.ExosisterIrene, ExosisterAvoidMaxxCSummonCheck); + AddExecutor(ExecutorType.Summon, CardId.ExosisterElis, ExosisterAvoidMaxxCSummonCheck); + + // activate martha + AddExecutor(ExecutorType.Activate, CardId.ExosisterMartha, ExosisterMarthaActivate); + + // normal summon for xyz + AddExecutor(ExecutorType.Summon, CardId.ExosisterStella, ExosisterStellaSummonCheck); + AddExecutor(ExecutorType.Summon, CardId.Aratama, AratamaSummonCheck); + AddExecutor(ExecutorType.Summon, ExosisterForElisSummonCheck); + AddExecutor(ExecutorType.Summon, ForSakitamaSummonCheck); + AddExecutor(ExecutorType.Summon, CardId.ExosisterIrene, ExosisterIreneSummonCheck); + AddExecutor(ExecutorType.Summon, Level4SummonCheck); + AddExecutor(ExecutorType.Summon, ExosisterForArmentSummonCheck); + AddExecutor(ExecutorType.Summon, ForDonnerSummonCheck); + + AddExecutor(ExecutorType.Activate, CardId.ExosisterPax, ExosisterPaxActivateForEndSearch); + + // other + AddExecutor(ExecutorType.Repos, DefaultMonsterRepos); + AddExecutor(ExecutorType.SpellSet, SpellSetCheck); + } + + const int SetcodeTimeLord = 0x4a; + const int SetcodeShadoll = 0x9d; + const int SetcodeInferoid = 0xbb; + const int SetcodeOrcust = 0x11b; + const int SetcodeExosister = 0x172; + const int SetcodeTearlaments = 0x181; + List SetcodeForDiamond = new List{SetcodeShadoll, SetcodeInferoid, SetcodeTearlaments}; + + List affectGraveCardIdList = new List{ + 71344451, 40975243, 87746184, 70534340, 45906428, 71490127, 3659803, 12071500, 6077601, 11827244, 95238394, 81223446, 40003819, + 72490637, 21011044, 59419719, 14735698, 45410988 + }; + + Dictionary> DeckCountTable = new Dictionary>{ + {3, new List { CardId.ExosisterElis, CardId.ExosisterStella, CardId.ExosisterMartha, CardId.Aratama, CardId.Sakitama, + _CardId.MaxxC, _CardId.AshBlossom, CardId.ExosisterPax, CardId.ExosisterVadis }}, + {2, new List { CardId.ExosisterIrene, CardId.ExosisterSophia, CardId.PotofExtravagance, _CardId.CalledByTheGrave, + CardId.ExosisterReturnia, _CardId.InfiniteImpermanence }}, + {1, new List { CardId.ExosisterArment }}, + }; + Dictionary ExosisterMentionTable = new Dictionary{ + {CardId.ExosisterElis, CardId.ExosisterStella}, {CardId.ExosisterStella, CardId.ExosisterElis}, + {CardId.ExosisterIrene, CardId.ExosisterSophia}, {CardId.ExosisterSophia, CardId.ExosisterIrene}, + {CardId.ExosisterMartha, CardId.ExosisterElis} + }; + List ExosisterSpellTrapList = new List{CardId.ExosisterPax, CardId.ExosisterArment, CardId.ExosisterVadis, CardId.ExosisterReturnia}; + + Dictionary calledbytheGraveCount = new Dictionary(); + bool enemyActivateMaxxC = false; + bool enemyActivateLockBird = false; + bool enemyMoveGrave = false; + bool paxCallToField = false; + List infiniteImpermanenceList = new List(); + + bool summoned = false; + bool elisEffect1Activated = false; + bool stellaEffect1Activated = false; + bool irenaEffect1Activated = false; + bool sophiaEffect1Activated = false; + bool marthaEffect1Activated = false; + bool mikailisEffect1Activated = false; + bool mikailisEffect3Activated = false; + bool kaspitellEffect1Activated = false; + bool kaspitellEffect3Activated = false; + bool gibrineEffect1Activated = false; + bool gibrineEffect3Activated = false; + bool asophielEffect1Activated = false; + bool asophielEffect3Activated = false; + bool sakitamaEffect1Activated = false; + List exosisterTransformEffectList = new List(); + List oncePerTurnEffectActivatedList = new List(); + List activatedMagnificaList = new List(); + List targetedMagnificaList = new List(); + List transformDestList = new List(); + List spSummonThisTurn = new List(); + bool potActivate = false; + List removeChosenList = new List(); + + /// + /// Shuffle List and return a random-order card list + /// + public List ShuffleCardList(List list) + { + List result = list; + int n = result.Count; + while (n-- > 1) + { + int index = Program.Rand.Next(n + 1); + ClientCard temp = result[index]; + result[index] = result[n]; + result[n] = temp; + } + return result; + } + + public ClientCard GetProblematicEnemyMonster(int attack = 0, bool canBeTarget = false) + { + List floodagateList = Enemy.GetMonsters().Where(c => c?.Data != null && + c.IsFloodgate() && c.IsFaceup() && (!canBeTarget || !c.IsShouldNotBeTarget())).ToList(); + if (floodagateList.Count > 0) + { + floodagateList.Sort(CardContainer.CompareCardAttack); + floodagateList.Reverse(); + return floodagateList[0]; + } + + List dangerList = Enemy.MonsterZone.Where(c => c?.Data != null && + c.IsMonsterDangerous() && c.IsFaceup() && (!canBeTarget || !c.IsShouldNotBeTarget())).ToList(); + if (dangerList.Count > 0) + { + dangerList.Sort(CardContainer.CompareCardAttack); + dangerList.Reverse(); + return dangerList[0]; + } + + List invincibleList = Enemy.MonsterZone.Where(c => c?.Data != null && + c.IsMonsterInvincible() && c.IsFaceup() && (!canBeTarget || !c.IsShouldNotBeTarget())).ToList(); + if (invincibleList.Count > 0) + { + invincibleList.Sort(CardContainer.CompareCardAttack); + invincibleList.Reverse(); + return invincibleList[0]; + } + + if (attack == 0) + attack = Util.GetBestAttack(Bot); + List betterList = Enemy.MonsterZone.GetMonsters() + .Where(card => card.GetDefensePower() >= attack && card.IsAttack() && (!canBeTarget || !card.IsShouldNotBeTarget())).ToList(); + if (betterList.Count > 0) + { + betterList.Sort(CardContainer.CompareCardAttack); + betterList.Reverse(); + return betterList[0]; + } + return null; + } + + public ClientCard GetProblematicEnemyCard(bool canBeTarget = false) + { + List floodagateList = Enemy.MonsterZone.Where(c => c?.Data != null && !removeChosenList.Contains(c) && + c.IsFloodgate() && c.IsFaceup() && (!canBeTarget || !c.IsShouldNotBeTarget())).ToList(); + if (floodagateList.Count > 0) + { + floodagateList.Sort(CardContainer.CompareCardAttack); + floodagateList.Reverse(); + return floodagateList[0]; + } + + List problemEnemySpellList = Enemy.SpellZone.Where(c => c?.Data != null && !removeChosenList.Contains(c) + && c.IsFloodgate() && c.IsFaceup() && (!canBeTarget || !c.IsShouldNotBeTarget())).ToList(); + if (problemEnemySpellList.Count > 0) + { + return ShuffleCardList(problemEnemySpellList)[0]; + } + + List dangerList = Enemy.MonsterZone.Where(c => c?.Data != null && !removeChosenList.Contains(c) + && c.IsMonsterDangerous() && c.IsFaceup() && (!canBeTarget || !c.IsShouldNotBeTarget())).ToList(); + if (dangerList.Count > 0 + && (Duel.Player == 0 || (Duel.Phase > DuelPhase.Main1 && Duel.Phase < DuelPhase.Main2))) + { + dangerList.Sort(CardContainer.CompareCardAttack); + dangerList.Reverse(); + return dangerList[0]; + } + + List invincibleList = Enemy.MonsterZone.Where(c => c?.Data != null && !removeChosenList.Contains(c) + && c.IsMonsterInvincible() && c.IsFaceup() && (!canBeTarget || !c.IsShouldNotBeTarget())).ToList(); + if (invincibleList.Count > 0) + { + invincibleList.Sort(CardContainer.CompareCardAttack); + invincibleList.Reverse(); + return invincibleList[0]; + } + + List enemyMonsters = Enemy.GetMonsters().Where(c => !removeChosenList.Contains(c)).ToList(); + if (enemyMonsters.Count > 0) + { + enemyMonsters.Sort(CardContainer.CompareCardAttack); + enemyMonsters.Reverse(); + foreach(ClientCard target in enemyMonsters) + { + if (target.HasType(CardType.Fusion) || target.HasType(CardType.Ritual) || target.HasType(CardType.Synchro) || target.HasType(CardType.Xyz) || (target.HasType(CardType.Link) && target.LinkCount >= 2) ) + { + if (!canBeTarget || !(target.IsShouldNotBeTarget() || target.IsShouldNotBeMonsterTarget())) return target; + } + } + } + + List spells = Enemy.GetSpells().Where(c => c.IsFaceup() && !removeChosenList.Contains(c) + && (c.HasType(CardType.Equip) || c.HasType(CardType.Pendulum) || c.HasType(CardType.Field) || c.HasType(CardType.Continuous))) + .ToList(); + if (spells.Count > 0) + { + return ShuffleCardList(spells)[0]; + } + + return null; + } + + public ClientCard GetBestEnemyMonster(bool onlyFaceup = false, bool canBeTarget = false) + { + ClientCard card = GetProblematicEnemyMonster(0, canBeTarget); + if (card != null) + return card; + + card = Enemy.MonsterZone.GetHighestAttackMonster(canBeTarget); + if (card != null) + return card; + + List monsters = Enemy.GetMonsters(); + + // after GetHighestAttackMonster, the left monsters must be face-down. + if (monsters.Count > 0 && !onlyFaceup) + return ShuffleCardList(monsters)[0]; + + return null; + } + + public ClientCard GetBestEnemySpell(bool onlyFaceup = false, bool canBeTarget = false) + { + List problemEnemySpellList = Enemy.SpellZone.Where(c => c?.Data != null + && c.IsFloodgate() && c.IsFaceup() && (!canBeTarget || !c.IsShouldNotBeTarget())).ToList(); + if (problemEnemySpellList.Count > 0) + { + return ShuffleCardList(problemEnemySpellList)[0]; + } + + List spells = Enemy.GetSpells().Where(card => !(card.IsFaceup() && card.IsCode(_CardId.EvenlyMatched))).ToList(); + + List faceUpList = spells.Where(ecard => ecard.IsFaceup() && + (ecard.HasType(CardType.Continuous) || ecard.HasType(CardType.Field) || ecard.HasType(CardType.Pendulum))).ToList(); + if (faceUpList.Count > 0) + { + return ShuffleCardList(faceUpList)[0]; + } + + if (spells.Count > 0 && !onlyFaceup) + { + return ShuffleCardList(spells)[0]; + } + + return null; + } + + public ClientCard GetBestEnemyCard(bool onlyFaceup = false, bool canBeTarget = false, bool checkGrave = false) + { + ClientCard card = GetBestEnemyMonster(onlyFaceup, canBeTarget); + if (card != null) + { + return card; + } + + card = GetBestEnemySpell(onlyFaceup, canBeTarget); + if (card != null) + { + return card; + } + + if (checkGrave && Enemy.Graveyard.Count > 0) + { + List graveMonsterList = Enemy.Graveyard.GetMatchingCards(c => c.IsMonster()).ToList(); + if (graveMonsterList.Count > 0) + { + graveMonsterList.Sort(CardContainer.CompareCardAttack); + graveMonsterList.Reverse(); + return graveMonsterList[0]; + } + return ShuffleCardList(Enemy.Graveyard.ToList())[0]; + } + + return null; + } + + /// + /// Check remain cards in deck + /// + /// Card's ID + public int CheckRemainInDeck(int id) + { + for (int count = 1; count < 4; ++count) + { + if (DeckCountTable[count].Contains(id)) { + return Bot.GetRemainingCount(id, count); + } + } + return 0; + } + + /// + /// Check negated turn count of id + /// + public int CheckCalledbytheGrave(int id) + { + if (!calledbytheGraveCount.ContainsKey(id)) + { + return 0; + } + return calledbytheGraveCount[id]; + } + + public void CheckEnemyMoveGrave() + { + if (Duel.LastChainPlayer == 1) + { + ClientCard card = Util.GetLastChainCard(); + if (Duel.LastChainLocation == CardLocation.Grave && card.Location == CardLocation.Grave) + { + Logger.DebugWriteLine("===Exosister: enemy activate effect from GY."); + enemyMoveGrave = true; + } + else if (affectGraveCardIdList.Contains(card.Id)) + { + Logger.DebugWriteLine("===Exosister: enemy activate effect that affect GY."); + enemyMoveGrave = true; + } + else + { + foreach (ClientCard targetCard in Duel.LastChainTargets) + { + if (targetCard.Location == CardLocation.Grave) + { + Logger.DebugWriteLine("===Exosister: enemy target cards of GY."); + enemyMoveGrave = true; + break; + } + } + } + } + } + + /// + /// Check exosister's relative card. 0 for error. + /// + public int CheckExosisterMentionCard(int id) + { + if (!ExosisterMentionTable.ContainsKey(id)) + { + return 0; + } + return ExosisterMentionTable[id]; + } + + /// + /// Check whether last chain card should be disabled. + /// + public bool CheckLastChainShouldNegated() + { + ClientCard lastcard = Util.GetLastChainCard(); + if (lastcard == null || lastcard.Controller != 1) return false; + if (lastcard.IsMonster() && lastcard.HasSetcode(SetcodeTimeLord) && Duel.Phase == DuelPhase.Standby) return false; + return true; + } + + /// + /// Check whether negate opposite's effect and clear flag + /// + public void CheckDeactiveFlag() + { + if (Util.GetLastChainCard() != null && Duel.LastChainPlayer == 1) + { + if (Util.GetLastChainCard().IsCode(_CardId.MaxxC)) + { + enemyActivateMaxxC = false; + } + if (Util.GetLastChainCard().IsCode(_CardId.LockBird)) + { + enemyActivateLockBird = false; + } + } + } + + /// + /// Check whether opposite use Maxx-C, and thus make less operation. + /// + public bool CheckLessOperation() + { + if (!enemyActivateMaxxC) + { + return false; + } + return CheckAtAdvantage(); + } + + /// + /// Check whether bot is at advantage. + /// + public bool CheckAtAdvantage() + { + if (GetProblematicEnemyMonster() == null && Bot.GetMonsters().Any(card => card.IsFaceup())) + { + return true; + } + return false; + } + + /// + /// Check whether bot is in danger and need to summon monster to defense. + /// + public bool CheckInDanger() + { + if (Duel.Phase > DuelPhase.Main1 && Duel.Phase < DuelPhase.Main2) + { + int totalAtk = 0; + foreach (ClientCard m in Enemy.GetMonsters()) + { + if (m.IsAttack() && !m.Attacked) totalAtk += m.Attack; + } + if (totalAtk >= Bot.LifePoints) return true; + } + return false; + } + + /// + /// Check whether can be used for xyz summon. + /// + public bool CheckAbleForXyz(ClientCard card) + { + return card.IsFaceup() && !card.HasType(CardType.Xyz) && !card.HasType(CardType.Link) && !card.HasType(CardType.Token) && card.Level == 4; + } + + /// + /// Check whether bot can activate martha. + /// + public bool CheckMarthaActivatable() + { + return !marthaEffect1Activated && CheckCalledbytheGrave(CardId.ExosisterMartha) == 0 && CheckRemainInDeck(CardId.ExosisterElis) > 0 + && !Bot.GetMonsters().Any(card => card.IsFacedown() || !card.HasType(CardType.Xyz)); + } + + /// + /// check enemy's dangerous card in grave + /// + public List CheckDangerousCardinEnemyGrave(bool onlyMonster = false) + { + List result = Enemy.Graveyard.GetMatchingCards(card => + (!onlyMonster || card.IsMonster()) && card.HasSetcode(SetcodeOrcust)).ToList(); + return result; + } + + /// + /// Whether spell or trap will be negate. If so, return true. + /// + /// is counter trap + /// check target + /// + public bool SpellNegatable(bool isCounter = false, ClientCard target = null) + { + // target default set + if (target == null) target = Card; + // won't negate if not on field + if (target.Location != CardLocation.SpellZone && target.Location != CardLocation.Hand) return false; + + // negate judge + if (Enemy.HasInMonstersZone(CardId.NaturalExterio, true) && !isCounter) return true; + if (target.IsSpell()) + { + if (Enemy.HasInMonstersZone(CardId.NaturalBeast, true)) return true; + if (Enemy.HasInSpellZone(CardId.ImperialOrder, true) || Bot.HasInSpellZone(CardId.ImperialOrder, true)) return true; + if (Enemy.HasInMonstersZone(CardId.SwordsmanLV7, true) || Bot.HasInMonstersZone(CardId.SwordsmanLV7, true)) return true; + } + if (target.IsTrap()) + { + if (Enemy.HasInSpellZone(CardId.RoyalDecree, true) || Bot.HasInSpellZone(CardId.RoyalDecree, true)) return true; + } + if (target.Location == CardLocation.SpellZone && (target.IsSpell() || target.IsTrap())) + { + int selfSeq = -1; + for (int i = 0; i < 5; ++i) + { + if (Bot.SpellZone[i] == Card) selfSeq = i; + } + if (infiniteImpermanenceList.Contains(selfSeq)) { + return true; + } + } + // how to get here? + return false; + } + + /// + /// Check whether'll be negated + /// + /// check whether card itself is disabled. + public bool CheckWhetherNegated(bool disablecheck = true){ + if (Card.IsSpell() || Card.IsTrap()){ + if (SpellNegatable()) return true; + } + if (CheckCalledbytheGrave(Card.Id) > 0){ + return true; + } + if (Card.IsMonster() && Card.Location == CardLocation.MonsterZone && Card.IsDefense()) + { + if (Enemy.MonsterZone.GetFirstMatchingFaceupCard(card => card.IsCode(CardId.Number41BagooskatheTerriblyTiredTapir) && card.IsDefense() && !card.IsDisabled()) != null + || Bot.MonsterZone.GetFirstMatchingFaceupCard(card => card.IsCode(CardId.Number41BagooskatheTerriblyTiredTapir) && card.IsDefense() && !card.IsDisabled()) != null) + { + return true; + } + } + if (disablecheck){ + return Card.IsDisabled(); + } + return false; + } + + /// + /// Select spell/trap's place randomly to avoid InfiniteImpermanence and so on. + /// + /// Card to set(default current card) + /// Whether need to avoid InfiniteImpermanence + /// Whether need to avoid set in this place + public void SelectSTPlace(ClientCard card = null, bool avoidImpermanence = false, List avoidList = null) + { + 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 && avoidImpermanence && infiniteImpermanenceList.Contains(seq)) continue; + if (avoidList != null && avoidList.Contains(seq)) continue; + AI.SelectPlace(zone); + return; + }; + } + AI.SelectPlace(0); + } + + public void SelectXyzMaterial(int num = 2, bool needExosister = false) + { + List materialList = Bot.GetMonsters().Where(card => CheckAbleForXyz(card)).ToList(); + if (materialList?.Count() < num) + { + return; + } + if (needExosister && !materialList.Any(card => card.HasSetcode(SetcodeExosister))) + { + return; + } + List selectedList = new List(); + + // if needed, select exosister with less atk first + if (needExosister) + { + List exosisterList = materialList.Where(card => card.HasSetcode(SetcodeExosister)).ToList(); + exosisterList.Sort(CardContainer.CompareCardAttack); + ClientCard firstSelect = exosisterList[0]; + selectedList.Add(firstSelect); + materialList.Remove(firstSelect); + } + + // select non-exosister or effecte used's exosister first + // never use martha first + List sortMaterialList = materialList.Where(card => + (card?.Data != null && !card.HasSetcode(SetcodeExosister)) || (exosisterTransformEffectList.Contains(card.Id) && card.Id != CardId.ExosisterMartha)).ToList(); + sortMaterialList.Sort(CardContainer.CompareCardAttack); + foreach (ClientCard card in sortMaterialList) + { + selectedList.Add(card); + if (selectedList.Count() >= num) + { + AI.SelectMaterials(selectedList); + return; + } + } + + List valuableMaterialList = materialList.Where(card => card.Id == CardId.ExosisterMartha || !exosisterTransformEffectList.Contains(card.Id)).ToList(); + valuableMaterialList.Sort(CardContainer.CompareCardAttack); + foreach (ClientCard card in valuableMaterialList) + { + selectedList.Add(card); + if (selectedList.Count() >= num) + { + AI.SelectMaterials(selectedList); + return; + } + } + } + + public void SelectDetachMaterial(ClientCard activateCard) + { + // TODO + AI.SelectCard(0); + } + + /// + /// go first + /// + public override bool OnSelectHand() + { + return true; + } + + /// + /// check whether enemy activate important card + /// + public override void OnChaining(int player, ClientCard card) + { + if (card == null) return; + + if (player == 1) + { + if (card.IsCode(_CardId.MaxxC) && CheckCalledbytheGrave(_CardId.MaxxC) == 0) + { + enemyActivateMaxxC = true; + } + if (card.IsCode(_CardId.LockBird) && CheckCalledbytheGrave(_CardId.LockBird) == 0) + { + enemyActivateLockBird = true; + } + if (card.IsCode(_CardId.InfiniteImpermanence)) + { + for (int i = 0; i < 5; ++i) + { + if (Enemy.SpellZone[i] == card) + { + infiniteImpermanenceList.Add(4-i); + break; + } + } + } + if (Duel.LastChainLocation == CardLocation.Grave && card.Location == CardLocation.Grave) + { + Logger.DebugWriteLine("===Exosister: enemy activate effect from GY."); + enemyMoveGrave = true; + } + } + base.OnChaining(player, card); + } + + public override void OnSelectChain(IList cards) + { + int player = Duel.LastChainPlayer; + ClientCard card = Util.GetLastChainCard(); + if (player == 1) + { + if (card != null && card.IsCode(_CardId.CalledByTheGrave)) + { + foreach (ClientCard targetCard in Duel.LastChainTargets) { + Logger.DebugWriteLine("===Exosister: " + targetCard?.Name + " is targeted by called by the grave."); + calledbytheGraveCount[targetCard.Id] = 2; + } + } + foreach (ClientCard targetCard in Duel.LastChainTargets) { + if (targetCard.Location == CardLocation.Grave) + { + Logger.DebugWriteLine("===Exosister: enemy target cards of GY."); + enemyMoveGrave = true; + break; + } + } + } + base.OnSelectChain(cards); + } + + /// + /// clear chain information + /// + public override void OnChainEnd() + { + enemyMoveGrave = false; + paxCallToField = false; + potActivate = false; + transformDestList.Clear(); + targetedMagnificaList.Clear(); + if (activatedMagnificaList.Count() > 0) + { + for (int idx = activatedMagnificaList.Count() - 1; idx >= 0; -- idx) + { + ClientCard checkTarget = activatedMagnificaList[idx]; + if (checkTarget == null || checkTarget.IsFacedown() || checkTarget.Location != CardLocation.MonsterZone) + { + activatedMagnificaList.RemoveAt(idx); + } + } + } + if (spSummonThisTurn.Count() > 0) + { + for (int idx = spSummonThisTurn.Count() - 1; idx >= 0; -- idx) + { + ClientCard checkTarget = spSummonThisTurn[idx]; + if (checkTarget == null || checkTarget.IsFacedown() || checkTarget.Location != CardLocation.MonsterZone) + { + spSummonThisTurn.RemoveAt(idx); + } + } + } + base.OnChainEnd(); + } + + public override void OnNewTurn() + { + enemyActivateMaxxC = false; + enemyActivateLockBird = false; + infiniteImpermanenceList.Clear(); + // CalledbytheGrave refresh + List key_list = calledbytheGraveCount.Keys.ToList(); + foreach (int dic in key_list) + { + if (calledbytheGraveCount[dic] > 1) + { + calledbytheGraveCount[dic] -= 1; + } + } + + summoned = false; + elisEffect1Activated = false; + stellaEffect1Activated = false; + irenaEffect1Activated = false; + sophiaEffect1Activated = false; + marthaEffect1Activated = false; + mikailisEffect1Activated = false; + mikailisEffect3Activated = false; + kaspitellEffect1Activated = false; + kaspitellEffect3Activated = false; + gibrineEffect1Activated = false; + gibrineEffect3Activated = false; + asophielEffect1Activated = false; + asophielEffect3Activated = false; + sakitamaEffect1Activated = false; + exosisterTransformEffectList.Clear(); + oncePerTurnEffectActivatedList.Clear(); + activatedMagnificaList.Clear(); + spSummonThisTurn.Clear(); + } + + /// + /// override for exosister's transform + /// + public override IList OnSelectCard(IList cards, int min, int max, int hint, bool cancelable) + { + bool beginTransformCheck = false; + // transform for main monster + if (hint == HintMsg.SpSummon && min == 1 && max == 1 && transformDestList.Count() > 0) + { + // check whether for transform + if (cards.All(card => card.Location == CardLocation.Extra && card.Rank == 4 && card.HasSetcode(SetcodeExosister))) + { + beginTransformCheck = true; + } + } + // transform for magnifica + if (hint == HintMsg.ToDeck && min == 1 && max == 1 && transformDestList.Count() > 0) + { + if (cards.All(card => card.Location == CardLocation.Overlay)) + { + beginTransformCheck = true; + } + } + if (beginTransformCheck) + { + for (int idx = 0; idx < transformDestList.Count(); ++ idx) + { + int targetId = transformDestList[idx]; + ClientCard targetCard = cards.FirstOrDefault(card => card.IsCode(targetId)); + if (targetCard != null) + { + List result = new List(); + result.Add(targetCard); + transformDestList.RemoveAt(idx); + spSummonThisTurn.AddRange(result); + return Util.CheckSelectCount(result, cards, min, max); + } + } + } + + if (Util.ChainContainsCard(_CardId.EvenlyMatched) && Util.ChainContainPlayer(1) && hint == HintMsg.Remove) + { + int botCount = Bot.GetMonsterCount() + Bot.GetSpellCount(); + int oppositeCount = Enemy.GetMonsterCount() + Enemy.GetSpellCount(); + if (botCount - oppositeCount == min && min == max) + { + Logger.DebugWriteLine("===Exosister: Evenly Matched activated."); + List allBotCards = new List(); + allBotCards.AddRange(Bot.GetMonsters()); + allBotCards.AddRange(Bot.GetSpells()); + List importantList = new List(); + + List magnificaList = allBotCards.Where(card => card.IsCode(CardId.ExosistersMagnifica)).ToList(); + if (magnificaList.Count > 0) + { + allBotCards.RemoveAll(c => magnificaList.Contains(c)); + importantList.AddRange(magnificaList); + } + if (!mikailisEffect1Activated) + { + List mikailisList = allBotCards.Where(card => spSummonThisTurn.Contains(card) + && card.IsCode(CardId.ExosisterMikailis) && card.IsFaceup()).ToList(); + if (mikailisList.Count > 0) + { + allBotCards.RemoveAll(c => mikailisList.Contains(c)); + importantList.AddRange(mikailisList); + } + } + if (!gibrineEffect1Activated) + { + List gibrineList = allBotCards.Where(card => spSummonThisTurn.Contains(card) + && card.IsCode(CardId.ExosisterGibrine) && card.IsFaceup()).ToList(); + if (gibrineList.Count > 0) + { + allBotCards.RemoveAll(c => gibrineList.Contains(c)); + importantList.AddRange(gibrineList); + } + } + if (!oncePerTurnEffectActivatedList.Contains(CardId.ExosisterVadis)) + { + List vadisList = allBotCards.Where(card => card.IsCode(CardId.ExosisterVadis) && card.IsFacedown()).ToList(); + if (vadisList.Count > 0) + { + allBotCards.RemoveAll(c => vadisList.Contains(c)); + importantList.AddRange(vadisList); + } + } + List xyzList = allBotCards.Where(card => card.IsMonster() && card.HasType(CardType.Xyz)).ToList(); + if (xyzList.Count > 0) + { + xyzList.Sort(CardContainer.CompareCardAttack); + xyzList.Reverse(); + allBotCards.RemoveAll(c => xyzList.Contains(c)); + importantList.AddRange(xyzList); + } + List monsterList = allBotCards.Where(card => card.IsMonster()).ToList(); + if (monsterList.Count > 0) + { + monsterList.Sort(CardContainer.CompareCardAttack); + monsterList.Reverse(); + allBotCards.RemoveAll(c => monsterList.Contains(c)); + importantList.AddRange(monsterList); + } + List faceDownList = allBotCards.Where(card => card.IsFacedown()).ToList(); + if (faceDownList.Count > 0) + { + allBotCards.RemoveAll(c => faceDownList.Contains(c)); + importantList.AddRange(ShuffleCardList(faceDownList)); + } + + importantList.Reverse(); + return Util.CheckSelectCount(importantList, cards, min, max); + } + } + + return base.OnSelectCard(cards, min, max, hint, cancelable); + } + + public override CardPosition OnSelectPosition(int cardId, IList positions) + { + YGOSharp.OCGWrapper.NamedCard cardData = YGOSharp.OCGWrapper.NamedCard.Get(cardId); + if (cardData != null) + { + if (Util.IsTurn1OrMain2()) + { + bool turnDefense = false; + if (cardId == CardId.DivineArsenalAAZEUS_SkyThunder || cardId == CardId.ExosistersMagnifica) + { + turnDefense = true; + } + if (!cardData.HasType(CardType.Xyz)) + { + turnDefense = true; + } + if (turnDefense) + { + return CardPosition.FaceUpDefence; + } + } + if (Duel.Player == 1) + { + if (!cardData.HasType(CardType.Xyz) || cardData.Defense >= cardData.Attack || Util.IsOneEnemyBetterThanValue(cardData.Attack, true)) + { + return CardPosition.FaceUpDefence; + } + } + int bestBotAttack = Math.Max(Util.GetBestAttack(Bot), cardData.Attack); + if (Util.IsAllEnemyBetterThanValue(bestBotAttack, true)) + { + return CardPosition.FaceUpDefence; + } + } + return base.OnSelectPosition(cardId, positions); + } + + /// + /// override for magnifica's spsummon + /// + public override bool OnSelectYesNo(int desc) + { + // magnifica spsummon + if (desc == Util.GetStringId(CardId.ExosistersMagnifica, 2)) + { + return true; + } + // pax spsummon + if (desc == Util.GetStringId(CardId.ExosisterPax, 1)) + { + return paxCallToField; + } + + return base.OnSelectYesNo(desc); + } + + /// + /// override for returnia's option + /// + public override int OnSelectOption(IList options) + { + // check retunia + int spSummonOption = -1; + int banishOption = -1; + int doNothingOption = -1; + for (int idx = 0; idx < options.Count(); ++ idx) + { + int option = options[idx]; + if (option == Util.GetStringId(CardId.ExosisterReturnia, 0)) + { + spSummonOption = idx; + } else if (option == Util.GetStringId(CardId.ExosisterReturnia, 1)) + { + banishOption = idx; + } else if (option == Util.GetStringId(CardId.ExosisterReturnia, 2)) + { + doNothingOption = idx; + } + } + + if (spSummonOption >= 0 || banishOption >= 0 || doNothingOption >= 0) + { + if (spSummonOption < 0 && banishOption < 0) + { + return doNothingOption; + } + if (banishOption >= 0) + { + // banish problem card + ClientCard target = GetProblematicEnemyCard(true); + if (target != null) + { + AI.SelectCard(target); + return banishOption; + } + + // dump banish + target = GetBestEnemyCard(false, false); + if (target != null) + { + AI.SelectCard(target); + return banishOption; + } + } + if (spSummonOption >= 0) + { + // TODO + } + } + + // check pot + int potBanish6Option = -1; + int potBanish3Option = -1; + for (int idx = 0; idx < options.Count(); ++idx) + { + int option = options[idx]; + if (option == Util.GetStringId(CardId.PotofExtravagance, 0)) + { + potBanish3Option = idx; + } + else if (option == Util.GetStringId(CardId.PotofExtravagance, 1)) + { + potBanish6Option = idx; + } + } + if (potBanish3Option >= 0 || potBanish6Option >= 0) + { + if (Bot.ExtraDeck.Count() > 9 && potBanish6Option >= 0) + { + return potBanish6Option; + } + return potBanish3Option; + } + + return base.OnSelectOption(options); + } + + public bool AshBlossomActivate() + { + if (CheckWhetherNegated(true) || !CheckLastChainShouldNegated()) return false; + if (Duel.LastChainPlayer == 1 && Util.GetLastChainCard().IsCode(_CardId.MaxxC)) + { + if (CheckAtAdvantage()) + { + return false; + } + } + CheckDeactiveFlag(); + return DefaultAshBlossomAndJoyousSpring(); + } + + public bool MaxxCActivate() + { + if (CheckWhetherNegated(true) || Duel.LastChainPlayer == 0) return false; + return DefaultMaxxC(); + } + + public bool InfiniteImpermanenceActivate() + { + if (CheckWhetherNegated()) return false; + // negate before effect used + foreach(ClientCard m in Enemy.GetMonsters()) + { + if (m.IsMonsterShouldBeDisabledBeforeItUseEffect() && !m.IsDisabled() && Duel.LastChainPlayer != 0) + { + if (Card.Location == CardLocation.SpellZone) + { + for (int i = 0; i < 5; ++ i) + { + if (Bot.SpellZone[i] == Card) + { + infiniteImpermanenceList.Add(i); + break; + } + } + } + if (Card.Location == CardLocation.Hand) + { + SelectSTPlace(Card, true); + } + AI.SelectCard(m); + return true; + } + } + + ClientCard LastChainCard = Util.GetLastChainCard(); + + // negate spells + if (Card.Location == CardLocation.SpellZone) + { + int this_seq = -1; + int that_seq = -1; + for (int i = 0; i < 5; ++i) + { + if (Bot.SpellZone[i] == Card) this_seq = i; + if (LastChainCard != null + && LastChainCard.Controller == 1 && LastChainCard.Location == CardLocation.SpellZone && Enemy.SpellZone[i] == LastChainCard) that_seq = i; + else if (Duel.Player == 0 && Util.GetProblematicEnemySpell() != null + && Enemy.SpellZone[i] != null && Enemy.SpellZone[i].IsFloodgate()) that_seq = i; + } + if ( (this_seq * that_seq >= 0 && this_seq + that_seq == 4) + || (Util.IsChainTarget(Card)) + || (LastChainCard != null && LastChainCard.Controller == 1 && LastChainCard.IsCode(_CardId.HarpiesFeatherDuster))) + { + ClientCard target = GetProblematicEnemyMonster(canBeTarget: true); + List enemyMonsters = Enemy.GetMonsters(); + CheckDeactiveFlag(); + AI.SelectCard(target); + infiniteImpermanenceList.Add(this_seq); + return true; + } + } + if ( (LastChainCard == null || LastChainCard.Controller != 1 || LastChainCard.Location != CardLocation.MonsterZone + || LastChainCard.IsDisabled() || LastChainCard.IsShouldNotBeTarget() || LastChainCard.IsShouldNotBeSpellTrapTarget()) ) + return false; + // negate monsters + if (Card.Location == CardLocation.SpellZone) + { + for (int i = 0; i < 5; ++i) + { + if (Bot.SpellZone[i] == Card) + { + infiniteImpermanenceList.Add(i); + break; + } + } + } + if (Card.Location == CardLocation.Hand) + { + SelectSTPlace(Card, true); + } + if (LastChainCard != null) AI.SelectCard(LastChainCard); + else + { + List enemyMonsters = Enemy.GetMonsters(); + enemyMonsters.Sort(CardContainer.CompareCardAttack); + enemyMonsters.Reverse(); + foreach (ClientCard card in enemyMonsters) + { + if (card.IsFaceup() && !card.IsShouldNotBeTarget() && !card.IsShouldNotBeSpellTrapTarget()) + { + CheckDeactiveFlag(); + AI.SelectCard(card); + return true; + } + } + } + return true; + } + + public bool CalledbytheGraveActivate() + { + if (CheckWhetherNegated(true)) return false; + if (Duel.LastChainPlayer == 1) + { + // negate + if (Util.GetLastChainCard().IsMonster()) + { + int code = Util.GetLastChainCard().Id; + if (code == 0) return false; + if (CheckCalledbytheGrave(code) > 0) return false; + if (Util.GetLastChainCard().IsCode(_CardId.MaxxC) && CheckAtAdvantage()) + { + return false; + } + if (code == CardId.DimensionShifter) + { + return false; + } + if (Enemy.Graveyard.GetFirstMatchingCard(card => card.IsMonster() && card.IsOriginalCode(code)) != null) + { + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + AI.SelectCard(code); + calledbytheGraveCount[code] = 2; + CheckDeactiveFlag(); + return true; + } + } + + // banish target + foreach (ClientCard cards in Enemy.Graveyard) + { + if (Duel.ChainTargets.Contains(cards)) + { + int code = cards.Id; + AI.SelectCard(cards); + calledbytheGraveCount[code] = 2; + return true; + } + } + + // become targets + if (Duel.ChainTargets.Contains(Card)) + { + List enemyMonsters = Enemy.Graveyard.GetMatchingCards(card => card.IsMonster()).ToList(); + if (enemyMonsters.Count > 0) + { + enemyMonsters.Sort(CardContainer.CompareCardAttack); + enemyMonsters.Reverse(); + int code = enemyMonsters[0].Id; + AI.SelectCard(code); + calledbytheGraveCount[code] = 2; + return true; + } + } + } + + // avoid danger monster in grave + if (Duel.LastChainPlayer == 1) return false; + List targets = CheckDangerousCardinEnemyGrave(true); + if (targets.Count() > 0) { + int code = targets[0].Id; + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + AI.SelectCard(code); + calledbytheGraveCount[code] = 2; + return true; + } + + return false; + } + + public List GetPotofExtravaganceBanish() + { + List banishList = new List(); + ClientCard aaZeus = Bot.ExtraDeck.FirstOrDefault(card => card.IsCode(CardId.DivineArsenalAAZEUS_SkyThunder)); + if (aaZeus != null) + { + banishList.Add(aaZeus); + } + + ClientCard diamond = Bot.ExtraDeck.FirstOrDefault(card => card.IsCode(CardId.StellarknightConstellarDiamond)); + if (diamond != null) + { + banishList.Add(diamond); + } + + ClientCard caduceus = Bot.ExtraDeck.FirstOrDefault(card => card.IsCode(CardId.TellarknightConstellarCaduceus)); + if (caduceus != null) + { + banishList.Add(caduceus); + } + + ClientCard evilswarm = Bot.ExtraDeck.FirstOrDefault(card => card.IsCode(_CardId.EvilswarmExcitonKnight)); + if (evilswarm != null) + { + banishList.Add(evilswarm); + } + + // second asophiel + if (Bot.ExtraDeck.Count(card => card.IsCode(CardId.ExosisterAsophiel)) > 1) + { + ClientCard asophiel2 = Bot.ExtraDeck.FirstOrDefault(card => card.IsCode(CardId.ExosisterAsophiel)); + banishList.Add(asophiel2); + } + + ClientCard gibrine = Bot.ExtraDeck.FirstOrDefault(card => card.IsCode(CardId.ExosisterGibrine)); + if (gibrine != null) + { + banishList.Add(gibrine); + } + + // 6 done + + // third mikailis + if (Bot.ExtraDeck.Count(card => card.IsCode(CardId.ExosisterMikailis)) > 2) + { + ClientCard mikailis3 = Bot.ExtraDeck.FirstOrDefault(card => card.IsCode(CardId.ExosisterMikailis)); + banishList.Add(mikailis3); + } + + // first asophiel + ClientCard asophiel1 = Bot.ExtraDeck.FirstOrDefault(card => card.IsCode(CardId.ExosisterAsophiel) && !banishList.Contains(card)); + if (asophiel1 != null) + { + banishList.Add(asophiel1); + } + + ClientCard donner = Bot.ExtraDeck.FirstOrDefault(card => card.IsCode(CardId.DonnerDaggerFurHire)); + if (donner != null) + { + banishList.Add(donner); + } + + // 9 done + + // second kaspitell + if (Bot.ExtraDeck.Count(card => card.IsCode(CardId.ExosisterKaspitell)) > 1) + { + ClientCard kaspitell = Bot.ExtraDeck.FirstOrDefault(card => card.IsCode(CardId.ExosisterKaspitell)); + banishList.Add(kaspitell); + } + + // second magnifica + if (Bot.ExtraDeck.Count(card => card.IsCode(CardId.ExosistersMagnifica)) > 1) + { + ClientCard magnifica2 = Bot.ExtraDeck.FirstOrDefault(card => card.IsCode(CardId.ExosistersMagnifica)); + banishList.Add(magnifica2); + } + + // second mikailis + if (Bot.ExtraDeck.Count(card => card.IsCode(CardId.ExosisterMikailis)) > 1) + { + ClientCard mikailis2 = Bot.ExtraDeck.FirstOrDefault(card => card.IsCode(CardId.ExosisterMikailis) && !banishList.Contains(card)); + banishList.Add(mikailis2); + } + + // first magnifica + ClientCard magnifica1 = Bot.ExtraDeck.FirstOrDefault(card => card.IsCode(CardId.ExosistersMagnifica) && !banishList.Contains(card)); + if (magnifica1 != null) + { + banishList.Add(magnifica1); + } + + // first kaspitell + ClientCard kaspitell1 = Bot.ExtraDeck.FirstOrDefault(card => card.IsCode(CardId.ExosisterKaspitell) && !banishList.Contains(card)); + if (kaspitell1 != null) + { + banishList.Add(kaspitell1); + } + + // first mikailis1 + ClientCard mikailis1 = Bot.ExtraDeck.FirstOrDefault(card => card.IsCode(CardId.ExosisterMikailis) && !banishList.Contains(card)); + if (mikailis1 != null) + { + banishList.Add(mikailis1); + } + + return banishList; + } + + public bool PotofExtravaganceActivate() + { + if (CheckWhetherNegated()) + { + return false; + } + List banishList = GetPotofExtravaganceBanish(); + + List addToHandOrderList = new List(); + + bool marthaActivatable = CheckMarthaActivatable(); + if (marthaActivatable) + { + if (!Bot.HasInHand(CardId.ExosisterMartha)) + { + addToHandOrderList.Add(CardId.ExosisterMartha); + } + if (Bot.HasInHand(CardId.ExosisterMartha) && !Bot.HasInHandOrInSpellZone(_CardId.CalledByTheGrave)) + { + addToHandOrderList.Add(_CardId.CalledByTheGrave); + } + } + int exosisterCount = Bot.Hand.Count(card => card?.Data != null && card.HasSetcode(SetcodeExosister)); + if (!stellaEffect1Activated && CheckCalledbytheGrave(CardId.ExosisterStella) == 0) + { + if (!Bot.HasInHand(CardId.ExosisterStella) && exosisterCount > 0) + { + addToHandOrderList.Add(CardId.ExosisterStella); + } + if (Bot.HasInHand(CardId.ExosisterStella) && exosisterCount == 0) + { + addToHandOrderList.AddRange(new List{ + CardId.ExosisterSophia, CardId.ExosisterIrene, CardId.ExosisterStella, CardId.ExosisterMartha, CardId.ExosisterElis}); + } + } + if (exosisterCount >= 0 && !Bot.HasInHandOrInSpellZone(CardId.ExosisterReturnia)) + { + addToHandOrderList.Add(CardId.ExosisterReturnia); + } + List remainOrderList = new List{ + CardId.Aratama, CardId.Sakitama, _CardId.MaxxC, _CardId.AshBlossom, _CardId.InfiniteImpermanence, + _CardId.CalledByTheGrave, CardId.ExosisterVadis, CardId.ExosisterReturnia, CardId.ExosisterPax + }; + addToHandOrderList.AddRange(remainOrderList); + + AI.SelectCard(banishList); + AI.SelectNextCard(addToHandOrderList); + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + + potActivate = true; + return true; + } + + public bool SakitamaActivate() + { + // summon + if (Card.Location == CardLocation.Hand) + { + // summon for xyz + if (Bot.GetMonsters().Count(card => CheckAbleForXyz(card)) == 1) + { + AI.SelectCard(CardId.Aratama, CardId.Sakitama); + sakitamaEffect1Activated = true; + return true; + } + + // summon for summon donner + if (!CheckLessOperation() && Bot.HasInExtra(CardId.DonnerDaggerFurHire) && + !Bot.HasInHand(CardId.ExosisterMartha) || Bot.HasInHandOrInSpellZone(CardId.ExosisterReturnia)) + { + List illegalList = Bot.GetMonsters().Where(card => card.IsFaceup() && !card.HasType(CardType.Xyz) && card.Level != 4 + && (card.Data == null || !card.HasSetcode(SetcodeExosister))).ToList(); + if (illegalList.Count() > 0) + { + if (illegalList.Count() == 1) + { + List otherMaterialList = Bot.GetMonsters().Where(card => card.IsFaceup() && !card.HasType(CardType.Xyz)).ToList(); + otherMaterialList.Sort(CardContainer.CompareCardAttack); + illegalList.AddRange(otherMaterialList); + } + if (illegalList.Count() == 1) + { + Logger.DebugWriteLine("===Exosister: activate sakitama for donner"); + AI.SelectCard(CardId.Aratama, CardId.Sakitama); + sakitamaEffect1Activated = true; + return true; + } + } + } + return false; + } + // add to hand + if (Card.Location == CardLocation.Grave) + { + AI.SelectCard(CardId.Sakitama, CardId.Aratama); + return true; + } + return true; + } + + public bool DonnerDaggerFurHireActivate() + { + if (CheckAtAdvantage() && !Bot.HasInHand(CardId.ExosisterMartha) && !Bot.HasInHandOrInSpellZone(CardId.ExosisterReturnia)) + { + return false; + } + + ClientCard targetCard = Util.GetProblematicEnemyMonster(canBeTarget: true); + if (targetCard == null) + { + List enemyMonsters = Enemy.GetMonsters(); + if (enemyMonsters.Count() > 0) + { + enemyMonsters.Sort(CardContainer.CompareCardAttack); + enemyMonsters.Reverse(); + targetCard = enemyMonsters[0]; + } + } + + if (targetCard != null) + { + AI.SelectCard(Card); + AI.SelectNextCard(targetCard); + return true; + } + + return false; + } + + public bool ExosisterElisActivate() + { + if (ActivateDescription != Util.GetStringId(CardId.ExosisterElis, 0)) + { + return false; + } + + if (Bot.GetMonsters().Count(card => CheckAbleForXyz(card)) == 1) + { + elisEffect1Activated = true; + return true; + } + + return false; + } + + public bool ExosisterStellaActivate() + { + return ExosisterStellaActivateInner(true); + } + + public bool ExosisterStellaSecondActivate() + { + return ExosisterStellaActivateInner(false); + } + + public bool ExosisterStellaActivateInner(bool checkMartha = false) + { + if (ActivateDescription != Util.GetStringId(CardId.ExosisterStella, 0) || CheckWhetherNegated(true)) + { + return false; + } + + bool ableToXyz = Bot.GetMonsters().Count(card => CheckAbleForXyz(card)) >= 2; + + if (CheckLessOperation() && ableToXyz) + { + return false; + } + if (checkMartha && Bot.HasInHand(CardId.ExosisterMartha) && ableToXyz + && Bot.Hand.Count(card => card.IsMonster() && card.HasSetcode(CardId.ExosisterMartha)) == 1) + { + return false; + } + + AI.SelectCard(CardId.ExosisterSophia, CardId.ExosisterIrene, CardId.ExosisterStella, CardId.ExosisterElis); + stellaEffect1Activated = true; + return true; + } + + public bool ExosisterIreneActivate() + { + if (ActivateDescription != Util.GetStringId(CardId.ExosisterIrene, 0) || CheckWhetherNegated(true)) + { + return false; + } + + List shuffleList = new List(); + foreach (int cardId in new List{CardId.ExosisterIrene, CardId.ExosisterSophia, CardId.ExosisterArment}) + { + if (Bot.HasInHand(cardId)) + { + shuffleList.Add(cardId); + } + } + if (elisEffect1Activated || Bot.Hand.Count(card => card.IsCode(CardId.ExosisterElis)) > 1) + { + shuffleList.Add(CardId.ExosisterElis); + } + foreach (int cardId in new List{CardId.ExosisterPax, CardId.ExosisterReturnia, CardId.ExosisterVadis}) + { + if ((oncePerTurnEffectActivatedList.Contains(cardId) && Bot.HasInHand(cardId)) || Bot.Hand.Count(card => card.IsCode(cardId)) > 1) + { + shuffleList.Add(cardId); + } + } + + if (shuffleList.Count() > 0) + { + Logger.DebugWriteLine("===Exosister: irene return " + shuffleList[0]); + AI.SelectCard(shuffleList); + return true; + } + return false; + } + + public bool ExosisterSophiaActivate() + { + if (ActivateDescription == Util.GetStringId(CardId.ExosisterSophia, 0) && !CheckWhetherNegated(true)) + { + sophiaEffect1Activated = true; + return true; + } + return false; + } + + public bool ExosisterMarthaActivate() + { + if (ActivateDescription != Util.GetStringId(CardId.ExosisterMartha, 0)) { + return false; + } + if (CheckLessOperation() && Bot.GetMonsterCount() > 0) + { + return false; + } + + marthaEffect1Activated = true; + return true; + } + + public bool DefaultExosisterTransform() + { + List canTransformList = new List + { + CardId.ExosisterElis, CardId.ExosisterStella, CardId.ExosisterIrene, CardId.ExosisterSophia, CardId.ExosisterMartha + }; + if (Card.IsDisabled() || !canTransformList.Contains(Card.Id)) + { + return false; + } + List checkTransformCode = new List{ + Util.GetStringId(CardId.ExosisterElis, 1), + Util.GetStringId(CardId.ExosisterStella, 1), + Util.GetStringId(CardId.ExosisterIrene, 1), + Util.GetStringId(CardId.ExosisterSophia, 1), + Util.GetStringId(CardId.ExosisterMartha, 1) + }; + if (!checkTransformCode.Contains(ActivateDescription) && ActivateDescription != -1) + { + return false; + } + + // mikailis + if (!Bot.HasInMonstersZone(CardId.ExosisterMikailis) && !mikailisEffect1Activated && (Duel.Player == 1 || !mikailisEffect3Activated) + && !transformDestList.Contains(CardId.ExosisterMikailis) && Bot.HasInExtra(CardId.ExosisterMikailis)) + { + exosisterTransformEffectList.Add(Card.Id); + transformDestList.Add(CardId.ExosisterMikailis); + return true; + } + + // kaspitell on bot's turn + if (!Bot.HasInMonstersZone(CardId.ExosisterKaspitell) && !kaspitellEffect3Activated && Duel.Player == 0 + && !transformDestList.Contains(CardId.ExosisterKaspitell) && Bot.HasInExtra(CardId.ExosisterKaspitell)) + { + exosisterTransformEffectList.Add(Card.Id); + transformDestList.Add(CardId.ExosisterKaspitell); + return true; + } + + // gibrine + if (!Bot.HasInMonstersZone(CardId.ExosisterGibrine) && !gibrineEffect1Activated + && !transformDestList.Contains(CardId.ExosisterGibrine) && Bot.HasInExtra(CardId.ExosisterGibrine)) + { + exosisterTransformEffectList.Add(Card.Id); + transformDestList.Add(CardId.ExosisterGibrine); + return true; + } + + // asophiel + if (!Bot.HasInMonstersZone(CardId.ExosisterAsophiel) && !asophielEffect1Activated + && !transformDestList.Contains(CardId.ExosisterAsophiel) && Bot.HasInExtra(CardId.ExosisterAsophiel)) + { + exosisterTransformEffectList.Add(Card.Id); + transformDestList.Add(CardId.ExosisterAsophiel); + return true; + } + + // kaspitell on bot's turn + if (!Bot.HasInMonstersZone(CardId.ExosisterKaspitell) && !kaspitellEffect1Activated + && !transformDestList.Contains(CardId.ExosisterKaspitell) && Bot.HasInExtra(CardId.ExosisterKaspitell)) + { + exosisterTransformEffectList.Add(Card.Id); + transformDestList.Add(CardId.ExosisterKaspitell); + return true; + } + + return false; + } + + public bool ExosisterMikailisActivate() + { + // banish + if (ActivateDescription == Util.GetStringId(CardId.ExosisterMikailis, 0)) + { + // activate after search + if (Duel.Player == 0 && !mikailisEffect3Activated && Duel.Phase < DuelPhase.End && !DefaultOnBecomeTarget()) + { + return false; + } + + // banish problem card + ClientCard target = GetProblematicEnemyCard(true); + if (target != null && Duel.LastChainPlayer != 0) + { + removeChosenList.Add(target); + mikailisEffect1Activated = true; + AI.SelectCard(target); + return true; + } + + // banish target + if (Duel.LastChainPlayer == 1) + { + List targetList = Duel.LastChainTargets.Where(card => card.Controller == 1 && + (card.Location == CardLocation.Grave || card.Location == CardLocation.MonsterZone || card.Location == CardLocation.SpellZone || card.Location == CardLocation.FieldZone)).ToList(); + if (targetList.Count() > 0) + { + mikailisEffect1Activated = true; + AI.SelectCard(ShuffleCardList(targetList)); + return true; + } + } + + // dump banish + target = GetBestEnemyCard(false, true, true); + if ((DefaultOnBecomeTarget() && !Util.ChainContainsCard(_CardId.EvenlyMatched)) || Bot.UnderAttack || (Duel.Phase == DuelPhase.End && Duel.LastChainPlayer != 0) + || (Duel.Player == 0 && Bot.GetMonsters().Count(card => card.HasType(CardType.Xyz) && card.Rank == 4 && card.HasSetcode(SetcodeExosister)) == 2 && Duel.LastChainPlayer != 0) + || (Duel.Player == 1 && Enemy.GetMonsterCount() >= 2)) + { + mikailisEffect1Activated = true; + AI.SelectCard(target); + return true; + } + return false; + } + + // search + if (CheckWhetherNegated(true)) + { + return false; + } + + List searchTarget = new List{ + CardId.ExosisterReturnia, + CardId.ExosisterVadis, + CardId.ExosisterPax, + CardId.ExosisterArment + }; + List firstSearchList = new List(); + List lastSearchList = new List(); + foreach (int cardId in searchTarget) + { + if (Bot.HasInHandOrInSpellZone(cardId) || CheckRemainInDeck(cardId) == 0) + { + lastSearchList.Add(cardId); + continue; + } + if (cardId == CardId.ExosisterReturnia && Bot.GetMonsters().Any(card => card.IsFacedown() || !card.HasSetcode(SetcodeExosister))) + { + lastSearchList.Add(cardId); + continue; + } + firstSearchList.Add(cardId); + } + firstSearchList.AddRange(lastSearchList); + + mikailisEffect3Activated = true; + SelectDetachMaterial(Card); + AI.SelectNextCard(firstSearchList); + return true; + } + + public bool ExosisterKaspitellActivate() + { + // block spsummon from GY + if (ActivateDescription == Util.GetStringId(CardId.ExosisterKaspitell, 0) || ActivateDescription == -1) + { + if (Enemy.HasInMonstersZone(CardId.InspectorBoarder, true)) + { + return false; + } + kaspitellEffect1Activated = true; + return true; + } + + // search + if (CheckWhetherNegated(true)) + { + return false; + } + + // search martha for activate + if (CheckMarthaActivatable() && CheckRemainInDeck(CardId.ExosisterMartha) > 0 && !Bot.HasInHand(CardId.ExosisterMartha)) + { + kaspitellEffect3Activated = true; + SelectDetachMaterial(Card); + AI.SelectNextCard(CardId.ExosisterMartha); + return true; + } + // search sophia for draw + if (!summoned && !sophiaEffect1Activated && CheckCalledbytheGrave(CardId.ExosisterSophia) == 0 && !Bot.HasInHand(CardId.ExosisterSophia) + && (Bot.GetMonsters().Count(card => CheckAbleForXyz(card)) == 1 || (Bot.HasInHand(CardId.ExosisterElis) && !elisEffect1Activated))) + { + kaspitellEffect3Activated = true; + SelectDetachMaterial(Card); + AI.SelectNextCard(CardId.ExosisterSophia); + return true; + } + // search stella for next xyz + if (!summoned && !Bot.HasInHand(CardId.ExosisterStella) && !stellaEffect1Activated && CheckCalledbytheGrave(CardId.ExosisterStella) == 0 + && CheckRemainInDeck(CardId.ExosisterStella) > 0 && Bot.Hand.Any(card => card?.Data != null && card.IsMonster() && card.HasSetcode(SetcodeExosister))) + { + kaspitellEffect3Activated = true; + SelectDetachMaterial(Card); + AI.SelectNextCard(CardId.ExosisterStella); + return true; + } + kaspitellEffect3Activated = true; + SelectDetachMaterial(Card); + AI.SelectNextCard(CardId.ExosisterMartha, CardId.ExosisterStella, CardId.ExosisterElis, CardId.ExosisterSophia, CardId.ExosisterIrene); + return true; + } + + public bool ExosisterGibrineActivate() + { + // negate + if (ActivateDescription == Util.GetStringId(CardId.ExosisterGibrine, 0)) + { + if (Duel.Player == 1) + { + ClientCard target = Enemy.MonsterZone.GetShouldBeDisabledBeforeItUseEffectMonster(); + if (target != null) + { + gibrineEffect1Activated = true; + AI.SelectCard(target); + return true; + } + } + + ClientCard LastChainCard = Util.GetLastChainCard(); + if (LastChainCard != null && LastChainCard.Controller == 1 && LastChainCard.Location == CardLocation.MonsterZone && + !LastChainCard.IsDisabled() && !LastChainCard.IsShouldNotBeTarget() && !LastChainCard.IsShouldNotBeMonsterTarget()) + { + gibrineEffect1Activated = true; + AI.SelectCard(LastChainCard); + return true; + } + + return false; + } + + // gain atk + if (CheckWhetherNegated(true)) + { + return false; + } + gibrineEffect3Activated = true; + SelectDetachMaterial(Card); + return true; + } + + public bool ExosisterAsophielActivate() + { + // block activate from GY + if (ActivateDescription == Util.GetStringId(CardId.ExosisterAsophiel, 0) || ActivateDescription == -1) + { + if (Enemy.HasInMonstersZone(CardId.InspectorBoarder, true)) + { + return false; + } + asophielEffect1Activated = true; + return true; + } + + // return hand + if (CheckWhetherNegated(true)) + { + return false; + } + ClientCard targetCard = Util.GetProblematicEnemyMonster(0, true); + if (targetCard != null) + { + asophielEffect3Activated = true; + SelectDetachMaterial(Card); + AI.SelectNextCard(targetCard); + return true; + } + + return false; + } + + public bool ExosistersMagnificaActivateTrigger() + { + // sp summon + if (ActivateDescription == Util.GetStringId(CardId.ExosistersMagnifica, 1)) + { + // return after effect used + if (activatedMagnificaList.Contains(Card)) + { + // return to Mikailis for danger card + if (Card.Overlays.Contains(CardId.ExosisterMikailis) && !mikailisEffect1Activated) + { + ClientCard target = GetProblematicEnemyCard(true); + if (target != null && !Duel.CurrentChain.Any(card => card == Card)) + { + transformDestList.Add(CardId.ExosisterMikailis); + return true; + } + } + + // negate important card + if (Card.Overlays.Contains(CardId.ExosisterGibrine) && !gibrineEffect1Activated) + { + ClientCard target = Enemy.MonsterZone.GetShouldBeDisabledBeforeItUseEffectMonster(); + if (target != null) + { + transformDestList.Add(CardId.ExosisterGibrine); + return true; + } + } + } + + // become target + if ((DefaultOnBecomeTarget() && !Util.ChainContainsCard(_CardId.EvenlyMatched)) || (Duel.CurrentChain.Any(c => c == Card) && Duel.LastChainPlayer != 0)) + { + targetedMagnificaList.Add(Card); + transformDestList.AddRange(new List{CardId.ExosistersMagnifica, CardId.ExosisterMikailis, CardId.ExosisterGibrine, CardId.ExosisterKaspitell, CardId.ExosisterAsophiel}); + return true; + } + } + return false; + } + public bool ExosistersMagnificaActivateBanish() + { + // banish + if (ActivateDescription == Util.GetStringId(CardId.ExosistersMagnifica, 0)) + { + if (CheckWhetherNegated()) + { + return false; + } + // banish problem card + ClientCard target = GetProblematicEnemyCard(); + bool isProblemCard = false; + if (target != null) + { + isProblemCard = true; + Logger.DebugWriteLine("===Exosister: magnifica target 1: " + target?.Name); + } + + // banish target + if (Duel.LastChainPlayer == 1 && target == null) + { + List currentTargetList = Duel.LastChainTargets.Where(card => card.Controller == 1 && + (card.Location == CardLocation.MonsterZone || card.Location == CardLocation.SpellZone || card.Location == CardLocation.FieldZone)).ToList(); + if (currentTargetList.Count() > 0) + { + target = ShuffleCardList(currentTargetList)[0]; + Logger.DebugWriteLine("===Exosister: magnifica target 2: " + target?.Name); + } + } + + // dump banish + if (target == null) + { + target = GetBestEnemyCard(false, false); + bool check1 = !DefaultOnBecomeTarget() || Util.ChainContainsCard(_CardId.EvenlyMatched); + bool check2 = !targetedMagnificaList.Contains(Card); + bool check3 = !Bot.UnderAttack; + bool check4 = Duel.Phase != DuelPhase.End; + bool check5 = Duel.Player == 0 || Enemy.GetMonsterCount() < 2; + Logger.DebugWriteLine("===Exosister: magnifica check flag: " + check1 + " " + check2 + " " + check3 + " " + check4 + " " + check5); + if (check1 && check2 && check3 && check4 && check5) + { + target = null; + } + } + + if (target != null && (Duel.LastChainPlayer != 0 || Util.GetLastChainCard() == Card)) + { + if (isProblemCard) + { + removeChosenList.Add(target); + } + Logger.DebugWriteLine("===Exosister: magnifica target final: " + target?.Name); + activatedMagnificaList.Add(Card); + AI.SelectCard(CardId.ExosisterGibrine, CardId.ExosisterAsophiel, CardId.ExosisterKaspitell, CardId.ExosisterMikailis); + AI.SelectNextCard(target); + return true; + } + + return false; + } + return false; + } + + public bool ExosisterPaxActivate() + { + if (potActivate || Bot.LifePoints <= 800) + { + return false; + } + + List checkListForSpSummon = new List{ + CardId.ExosisterSophia, CardId.ExosisterIrene, CardId.ExosisterStella, CardId.ExosisterMartha, CardId.ExosisterElis + }; + List checkListForSearch = new List{ + CardId.ExosisterMartha, CardId.ExosisterStella, CardId.ExosisterVadis, CardId.ExosisterReturnia, CardId.ExosisterSophia, + CardId.ExosisterIrene, CardId.ExosisterArment, CardId.ExosisterElis + }; + if (Duel.Player == 0 && Duel.LastChainPlayer != 0) + { + // search returnia for banish + if (CheckAtAdvantage() && GetProblematicEnemyCard(true) != null && CheckRemainInDeck(CardId.ExosisterReturnia) > 0 && !Bot.HasInHandOrInSpellZone(CardId.ExosisterReturnia)) + { + if (Bot.GetMonsterCount() > 0 && Bot.GetMonsters().All(card => card.IsFaceup() && card.HasSetcode(SetcodeExosister))) + { + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + oncePerTurnEffectActivatedList.Add(Card.Id); + AI.SelectCard(CardId.ExosisterReturnia); + paxCallToField = false; + return true; + } + } + + // search martha for activate + if (CheckMarthaActivatable() && CheckRemainInDeck(CardId.ExosisterMartha) > 0 && !Bot.HasInHand(CardId.ExosisterMartha)) + { + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + oncePerTurnEffectActivatedList.Add(Card.Id); + AI.SelectCard(CardId.ExosisterMartha); + paxCallToField = false; + return true; + } + + // stella relative + if (!stellaEffect1Activated && CheckCalledbytheGrave(CardId.ExosisterStella) == 0) + { + // try to search stella + if (Bot.Hand.Count(card => card.IsCode(CardId.ExosisterStella)) == 0 && CheckRemainInDeck(CardId.ExosisterStella) > 0) + { + bool shouldSpSummon = !CheckLessOperation() && summoned && Bot.HasInMonstersZoneOrInGraveyard(CardId.ExosisterElis); + if (Bot.Hand.Any(card => card?.Data != null && card.IsMonster() && card.HasSetcode(SetcodeExosister))) + { + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + oncePerTurnEffectActivatedList.Add(Card.Id); + AI.SelectCard(CardId.ExosisterStella); + paxCallToField = shouldSpSummon; + return true; + } + } + + // search monster for stella to summon + bool searchExosisterMonster = false; + if (Bot.HasInHand(CardId.ExosisterStella) && Bot.Hand.Count(card => card?.Data != null && card.IsMonster() && card.HasSetcode(SetcodeExosister)) == 1) + { + searchExosisterMonster = true; + } + if (Bot.HasInMonstersZone(CardId.ExosisterStella) && Bot.Hand.Count(card => card?.Data != null && card.IsMonster() && card.HasSetcode(SetcodeExosister)) == 0) + { + searchExosisterMonster = true; + } + if (searchExosisterMonster) + { + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + oncePerTurnEffectActivatedList.Add(Card.Id); + AI.SelectCard(CardId.ExosisterSophia, CardId.ExosisterIrene, CardId.ExosisterMartha, CardId.ExosisterStella, CardId.ExosisterElis); + paxCallToField = false; + return true; + } + } + + // addition summon + if (Bot.GetMonsters().Count(card => CheckAbleForXyz(card)) == 1 && summoned && !CheckLessOperation()) + { + if ( (sakitamaEffect1Activated || !Bot.HasInHand(CardId.Sakitama)) + && (stellaEffect1Activated || !Bot.HasInMonstersZone(CardId.ExosisterStella)) + && (elisEffect1Activated || !Bot.HasInHand(CardId.ExosisterElis)) + ) + { + foreach (int checkId in checkListForSpSummon) + { + int checkTarget = CheckExosisterMentionCard(checkId); + if (checkTarget > 0 && Bot.HasInMonstersZoneOrInGraveyard(checkId) && CheckRemainInDeck(checkTarget) > 0) + { + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + oncePerTurnEffectActivatedList.Add(Card.Id); + AI.SelectCard(checkId); + paxCallToField = true; + return true; + } + } + } + } + } + + // in danger + bool inDanger = CheckInDanger(); + + // trigger transform + CheckEnemyMoveGrave(); + + bool forReturnia = false; + if (!oncePerTurnEffectActivatedList.Contains(CardId.ExosisterReturnia) && Bot.HasInSpellZone(CardId.ExosisterReturnia) && Bot.GetMonsters().Count() == 0) + { + forReturnia = true; + } + + // become target + if (enemyMoveGrave || DefaultOnBecomeTarget() || inDanger || forReturnia) + { + List checkList = checkListForSpSummon; + bool shouldSpSummon = enemyMoveGrave || inDanger || forReturnia; + if (!shouldSpSummon && !Bot.HasInMonstersZone(new List{ + CardId.ExosisterElis, CardId.ExosisterStella, CardId.ExosisterIrene, CardId.ExosisterSophia, CardId.ExosisterMartha})) + { + shouldSpSummon = true; + } + if (CheckAtAdvantage() && !enemyMoveGrave) + { + shouldSpSummon = false; + checkList = checkListForSearch; + } + foreach (int checkId in checkList) + { + bool checkSuccessFlag = false; + + if (shouldSpSummon) + { + int checkTarget = CheckExosisterMentionCard(checkId); + checkSuccessFlag = checkTarget > 0 && Bot.HasInMonstersZoneOrInGraveyard(checkTarget) && CheckRemainInDeck(checkId) > 0 + && !exosisterTransformEffectList.Contains(checkId) && !Bot.HasInMonstersZone(checkId); + } else + { + checkSuccessFlag = !Bot.HasInHandOrHasInMonstersZone(checkId) && !Bot.HasInSpellZone(checkId) && CheckRemainInDeck(checkId) > 0; + } + + if (checkSuccessFlag) + { + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + oncePerTurnEffectActivatedList.Add(Card.Id); + AI.SelectCard(checkId); + paxCallToField = shouldSpSummon; + return true; + } + } + } + + return false; + } + + public bool ExosisterPaxActivateForEndSearch() + { + if (potActivate || Bot.LifePoints <= 800) + { + return false; + } + + if (Duel.Player == 0 || Duel.Phase >= DuelPhase.End) + { + // search spell/trap + List checkSpellTrapListForSearch = new List{ + CardId.ExosisterVadis, CardId.ExosisterMartha, CardId.ExosisterReturnia, CardId.ExosisterStella, CardId.ExosisterSophia, + CardId.ExosisterIrene, CardId.ExosisterArment, CardId.ExosisterElis + }; + foreach (int checkId in checkSpellTrapListForSearch) + { + if (!Bot.HasInHandOrHasInMonstersZone(checkId) && !Bot.HasInSpellZone(checkId) && CheckRemainInDeck(checkId) > 0) + { + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + oncePerTurnEffectActivatedList.Add(Card.Id); + AI.SelectCard(CardId.ExosisterSophia, CardId.ExosisterIrene, CardId.ExosisterMartha, CardId.ExosisterStella, CardId.ExosisterElis); + paxCallToField = false; + return true; + } + } + } + return false; + } + + public bool ExosisterArmentActivate() + { + if (Bot.LifePoints <= 800) + { + return false; + } + ClientCard activateTarget = null; + + if (Duel.Player == 0) + { + bool decided = false; + + // addition summon + if (Bot.GetMonsters().Count(card => CheckAbleForXyz(card)) == 1 && summoned && !CheckLessOperation()) + { + if ( (sakitamaEffect1Activated || !Bot.HasInHand(CardId.Sakitama)) + && (stellaEffect1Activated || !Bot.HasInMonstersZone(CardId.ExosisterStella)) + && (elisEffect1Activated || !Bot.HasInHand(CardId.ExosisterElis)) + ) + { + decided = true; + } + } + + if (Duel.LastChainPlayer == 1) + { + foreach (ClientCard target in Duel.LastChainTargets) + { + if (target.Controller == 0 && target.Location == CardLocation.MonsterZone && target.IsFaceup() && target.HasSetcode(SetcodeExosister)) + { + activateTarget = target; + decided = true; + break; + } + } + } + + if (!decided) + { + return false; + } + } + + if (activateTarget == null && Duel.LastChainPlayer == 1) + { + { + foreach (ClientCard target in Duel.LastChainTargets) + { + if (target.Controller == 0 && target.Location == CardLocation.MonsterZone && target.IsFaceup() && target.HasSetcode(SetcodeExosister)) + { + activateTarget = target; + break; + } + } + } + } + + if (activateTarget == null) + { + List targetList = Bot.GetMonsters().Where(card => card.IsFaceup() && card.HasSetcode(SetcodeExosister) && !card.HasType(CardType.Xyz)).ToList(); + if (targetList.Count() > 0) + { + targetList.Sort(CardContainer.CompareCardAttack); + activateTarget = targetList[0]; + } + } + + if (activateTarget == null) + { + return false; + } + + // mikailis + if (!Bot.HasInMonstersZone(CardId.ExosisterMikailis) && !mikailisEffect1Activated && (Duel.Player == 1 || !mikailisEffect3Activated) + && !transformDestList.Contains(CardId.ExosisterMikailis) && Bot.HasInExtra(CardId.ExosisterMikailis)) + { + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + AI.SelectCard(activateTarget); + transformDestList.Add(CardId.ExosisterMikailis); + return true; + } + + // kaspitell on bot's turn + if (!Bot.HasInMonstersZone(CardId.ExosisterKaspitell) && !kaspitellEffect3Activated && Duel.Player == 0 + && !transformDestList.Contains(CardId.ExosisterKaspitell) && Bot.HasInExtra(CardId.ExosisterKaspitell)) + { + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + AI.SelectCard(activateTarget); + transformDestList.Add(CardId.ExosisterKaspitell); + return true; + } + + // gibrine + if (!Bot.HasInMonstersZone(CardId.ExosisterGibrine) && !gibrineEffect1Activated + && !transformDestList.Contains(CardId.ExosisterGibrine) && Bot.HasInExtra(CardId.ExosisterGibrine)) + { + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + AI.SelectCard(activateTarget); + transformDestList.Add(CardId.ExosisterGibrine); + return true; + } + + // asophiel + if (!Bot.HasInMonstersZone(CardId.ExosisterAsophiel) && !asophielEffect1Activated + && !transformDestList.Contains(CardId.ExosisterAsophiel) && Bot.HasInExtra(CardId.ExosisterAsophiel)) + { + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + AI.SelectCard(activateTarget); + transformDestList.Add(CardId.ExosisterAsophiel); + return true; + } + + // kaspitell on bot's turn + if (!Bot.HasInMonstersZone(CardId.ExosisterKaspitell) && !kaspitellEffect1Activated + && !transformDestList.Contains(CardId.ExosisterKaspitell) && Bot.HasInExtra(CardId.ExosisterKaspitell)) + { + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + AI.SelectCard(activateTarget); + transformDestList.Add(CardId.ExosisterKaspitell); + return true; + } + + return false; + } + + public bool ExosisterVadisActivate() + { + if (Bot.LifePoints <= 800) + { + return false; + } + + List checkListForSpSummon = new List{ + CardId.ExosisterSophia, CardId.ExosisterIrene, CardId.ExosisterStella, CardId.ExosisterMartha, CardId.ExosisterElis + }; + + bool decideToActivate = false; + bool checkTransform = false; + + // special summon for xyz + if (Duel.Player == 0 && Duel.Phase > DuelPhase.Draw && !CheckLessOperation()) + { + decideToActivate = true; + } + + // move grave + CheckEnemyMoveGrave(); + if (enemyMoveGrave) + { + decideToActivate = true; + checkTransform = true; + } + + // for returia + if (!oncePerTurnEffectActivatedList.Contains(CardId.ExosisterReturnia) && Bot.HasInSpellZone(CardId.ExosisterReturnia) && Bot.GetMonsters().Count() == 0) + { + decideToActivate = true; + } + + if (CheckInDanger() || (DefaultOnBecomeTarget() && !Util.ChainContainsCard(_CardId.EvenlyMatched))) + { + decideToActivate = true; + } + + if (decideToActivate) + { + foreach (int checkId in checkListForSpSummon) + { + int checkTarget = CheckExosisterMentionCard(checkId); + if (checkTarget > 0 && CheckRemainInDeck(checkId) > 0 && CheckRemainInDeck(checkTarget) > 0) + { + if (checkTransform) + { + int canTransformCount = 0; + foreach (int transformCheckId in new List{checkId, checkTarget}) + { + if (!Bot.HasInMonstersZone(checkId) && !exosisterTransformEffectList.Contains(checkId)) + { + canTransformCount ++; + } + } + + if (canTransformCount == 0) + { + continue; + } + } + oncePerTurnEffectActivatedList.Add(Card.Id); + Logger.DebugWriteLine("Exosiseter Vadis decide: " + checkId); + AI.SelectCard(checkId); + AI.SelectNextCard(checkTarget); + return true; + } + } + } + + return false; + } + + public bool ExosisterReturniaActivate() + { + if (Bot.LifePoints <= 800) + { + return false; + } + + // banish problem card + ClientCard target = GetProblematicEnemyCard(true); + if (target != null && Duel.LastChainPlayer != 0) + { + Logger.DebugWriteLine("===Exosister: returnia target 1: " + target?.Name); + removeChosenList.Add(target); + oncePerTurnEffectActivatedList.Add(Card.Id); + AI.SelectCard(target); + return true; + } + + // banish target + if (Duel.LastChainPlayer == 1) + { + List targetList = Duel.LastChainTargets.Where(card => card.Controller == 1 && + (card.Location == CardLocation.Grave || card.Location == CardLocation.MonsterZone || card.Location == CardLocation.SpellZone || card.Location == CardLocation.FieldZone)).ToList(); + if (targetList.Count() > 0) + { + oncePerTurnEffectActivatedList.Add(Card.Id); + List shuffleTargetList = ShuffleCardList(targetList); + Logger.DebugWriteLine("===Exosister: returnia target 2: " + shuffleTargetList[0]?.Name); + AI.SelectCard(shuffleTargetList); + return true; + } + } + + // dump banish + target = GetBestEnemyCard(false, true, true); + bool check1 = DefaultOnBecomeTarget() && target != null && (target.Location != CardLocation.Onfield || target.Id != _CardId.EvenlyMatched); + bool check2 = Bot.UnderAttack; + bool check3 = (Duel.Player == 1 && Duel.Phase == DuelPhase.End && Duel.LastChainPlayer != 0 && target != null && target.Location != CardLocation.Grave); + bool check4 = (Duel.Player == 1 && Enemy.GetMonsterCount() >= 2 && Duel.LastChainPlayer != 0); + Logger.DebugWriteLine("===Exosister: returnia check flag: " + check1 + " " + check2 + " " + check3 + " " + check4); + if (check1 || check2 || check3 || check4) + { + oncePerTurnEffectActivatedList.Add(Card.Id); + Logger.DebugWriteLine("===Exosister: returnia target 3: " + target?.Name); + AI.SelectCard(target); + return true; + } + + return false; + } + + /// + /// Check hand like exosister + elis + martha + /// + public bool ExosisterAvoidMaxxCSummonCheck() + { + if (!Bot.HasInHand(CardId.ExosisterMartha) || !Bot.HasInHand(CardId.ExosisterElis) || elisEffect1Activated || marthaEffect1Activated) + { + return false; + } + if (enemyActivateLockBird && CheckAtAdvantage()) + { + return false; + } + // normal summon non-elis exosister + if (Card.Id != CardId.ExosisterElis && Card.Id != CardId.ExosisterMartha) + { + summoned = true; + return true; + } + // normal summon elis + if (Card.IsCode(CardId.ExosisterElis)) + { + int otherExosisterCount = Bot.Hand.Count(card => card?.Data != null && !card.IsCode(CardId.ExosisterElis) && !card.IsCode(CardId.ExosisterMartha) + && card.IsMonster() && card.HasSetcode(SetcodeExosister)); + if (otherExosisterCount > 0) + { + return false; + } + if (Bot.Hand.Count(card => card?.Data != null && card.IsCode(CardId.ExosisterElis)) > 1) + { + summoned = true; + return true; + } + } + + return false; + } + + /// + /// Check hand like exosister + stella + /// + public bool ExosisterStellaSummonCheck() + { + if (stellaEffect1Activated || Bot.HasInMonstersZone(CardId.ExosisterStella, true) || CheckWhetherNegated(true) || CheckLessOperation()) + { + return false; + } + if (enemyActivateLockBird && CheckAtAdvantage()) + { + return false; + } + + int summonableCount = Bot.Hand.Count(card => card != Card && card?.Data != null && card.IsMonster() + && card.HasSetcode(SetcodeExosister)); + + if (summonableCount > 0) + { + summoned = true; + return true; + } + return false; + } + + /// + /// Check whether need Irene's redraw effect to search elis for xyz + /// + public bool ExosisterIreneSummonCheck() + { + if (irenaEffect1Activated || CheckLessOperation() + || CheckWhetherNegated(true) || CheckCalledbytheGrave(CardId.ExosisterElis) > 0 || CheckCalledbytheGrave(CardId.ExosisterIrene) > 0) + { + return false; + } + if (enemyActivateLockBird && CheckAtAdvantage()) + { + return false; + } + + if (CheckRemainInDeck(CardId.ExosisterElis) > 0) + { + summoned = true; + return true; + } + return false; + } + + /// + /// Check hand like exosister + elis + /// + public bool ExosisterForElisSummonCheck() + { + if (elisEffect1Activated || CheckCalledbytheGrave(CardId.ExosisterElis) > 0 || CheckLessOperation()) + { + return false; + } + if (Card?.Data == null) + { + return false; + } + if (!Card.HasSetcode(SetcodeExosister) || (Card.IsCode(CardId.ExosisterMartha) && CheckRemainInDeck(CardId.ExosisterElis) > 0)) + { + return false; + } + if (enemyActivateLockBird && CheckAtAdvantage()) + { + return false; + } + + if (Bot.Hand.Count(card => card != Card && card?.Data != null && card.IsCode(CardId.ExosisterElis)) > 0) + { + summoned = true; + return true; + } + + return false; + } + + public bool AratamaSummonCheck() + { + if (sakitamaEffect1Activated || CheckCalledbytheGrave(CardId.Aratama) > 0 || CheckCalledbytheGrave(CardId.Sakitama) > 0) + { + return false; + } + if (enemyActivateLockBird && CheckAtAdvantage()) + { + return false; + } + if (CheckRemainInDeck(CardId.Sakitama) > 0) + { + summoned = true; + return true; + } + return false; + } + + public bool ForSakitamaSummonCheck() + { + if (sakitamaEffect1Activated || CheckCalledbytheGrave(CardId.Sakitama) > 0 || CheckLessOperation()) + { + return false; + } + if (Bot.Hand.Count(card => card?.Data != null && Card != card && card.IsCode(CardId.Sakitama)) == 0) + { + return false; + } + if (enemyActivateLockBird && CheckAtAdvantage()) + { + return false; + } + if (Card?.Data != null && !Card.IsCode(CardId.ExosisterMartha) && Card.Level == 4) + { + summoned = true; + return true; + } + + return false; + } + + public bool Level4SummonCheck() + { + if (Card.Id == CardId.ExosisterMartha) + { + return false; + } + if (Bot.GetMonsters().Count(card => CheckAbleForXyz(card)) == 1) + { + summoned = true; + return true; + } + return false; + } + + public bool ForDonnerSummonCheck() + { + if (!Bot.HasInExtra(CardId.DonnerDaggerFurHire) || (!Bot.HasInHand(CardId.ExosisterMartha) && !Bot.HasInHandOrInSpellZone(CardId.ExosisterReturnia))) + { + return false; + } + if (CheckLessOperation()) + { + return false; + } + + List illegalList = Bot.GetMonsters().Where(card => card.IsFaceup() && !card.HasType(CardType.Xyz) && card.Level != 4 + && (card.Data == null || !card.HasSetcode(SetcodeExosister))).ToList(); + if (illegalList.Count() == 0) + { + return false; + } + + if (illegalList.Count() == 1) + { + List otherMaterialList = Bot.GetMonsters().Where(card => card.IsFaceup() && !card.HasType(CardType.Xyz)).ToList(); + otherMaterialList.Sort(CardContainer.CompareCardAttack); + illegalList.AddRange(otherMaterialList); + } + if (illegalList.Count() == 1) + { + List hands = Bot.Hand.Where(card => card?.Data != null && card.IsMonster()).ToList(); + if (hands.Count() > 0) + { + hands.Sort(CardContainer.CompareCardAttack); + if (Card != hands[0]) + { + return false; + } + } + Logger.DebugWriteLine("===Exosister: summon for donner"); + summoned = true; + return true; + } + + return false; + } + + public bool ExosisterForArmentSummonCheck() + { + if (!Bot.HasInHandOrInSpellZone(CardId.ExosisterArment)) + { + return false; + } + if (Card?.Data == null) + { + return false; + } + if (!Card.HasSetcode(SetcodeExosister)) + { + return false; + } + + if (!Bot.GetMonsters().Any(card => card?.Data != null && card.IsFaceup() && card.HasSetcode(SetcodeExosister))) + { + summoned = true; + return true; + } + + return false; + } + + public bool ExosisterMikailisSpSummonCheck() + { + return ExosisterMikailisSpSummonCheckInner(true); + } + + public bool ExosisterMikailisAdvancedSpSummonCheck() + { + if (!CheckLessOperation() || enemyActivateLockBird) + { + return false; + } + + return ExosisterMikailisSpSummonCheckInner(false); + } + + public bool ExosisterMikailisSpSummonCheckInner(bool shouldCheckLessOperation = true) + { + if (Bot.HasInMonstersZone(CardId.ExosisterMikailis) || mikailisEffect3Activated || (CheckLessOperation() && shouldCheckLessOperation)) + { + return false; + } + + // check searched spell/trap + if (!enemyActivateLockBird) + { + foreach (int cardId in ExosisterSpellTrapList) + { + if (!Bot.HasInHandOrInSpellZone(cardId)) + { + SelectXyzMaterial(2); + return true; + } + } + } + + // clear enemy card + if (!mikailisEffect1Activated && !Bot.HasInMonstersZone(CardId.ExosisterMikailis)) + { + ClientCard target = GetProblematicEnemyCard(true); + if (target != null) + { + List exosisterMaterialList = Bot.GetMonsters().Where(card => CheckAbleForXyz(card) && card.HasSetcode(SetcodeExosister)).ToList(); + if (exosisterMaterialList?.Count() > 0) + { + SelectXyzMaterial(2, true); + return true; + } + } + } + + return false; + } + + public bool ExosisterKaspitellSpSummonCheck() + { + return ExosisterKaspitellSpSummonCheckInner(true); + } + + public bool ExosisterKaspitellAdvancedSpSummonCheck() + { + if (!CheckLessOperation() || enemyActivateLockBird) + { + return false; + } + return ExosisterKaspitellSpSummonCheckInner(false); + } + + public bool ExosisterKaspitellSpSummonCheckInner(bool shouldCheckLessOperation = true) + { + if (Bot.HasInMonstersZone(CardId.ExosisterKaspitell) || kaspitellEffect3Activated || (shouldCheckLessOperation && CheckLessOperation())) + { + return false; + } + + bool searchMartha = true; + bool searchStella = true; + bool forMagnifica = false; + if (marthaEffect1Activated || CheckCalledbytheGrave(CardId.ExosisterMartha) > 0 + || CheckRemainInDeck(CardId.ExosisterMartha) == 0 || CheckRemainInDeck(CardId.ExosisterElis) == 0) + { + searchMartha = false; + } + if (Bot.GetMonsters().Any(card => card.HasType(CardType.Link) || card.HasType(CardType.Token))) + { + searchMartha = false; + } + if (stellaEffect1Activated || CheckCalledbytheGrave(CardId.ExosisterStella) > 0 || CheckRemainInDeck(CardId.ExosisterStella) == 0 + || !Bot.Hand.Any(card => card?.Data != null && card.IsMonster() && card.HasSetcode(SetcodeExosister))) + { + searchStella = false; + } + if (Bot.GetMonsters().Count(card => card?.Data != null + && card.HasType(CardType.Xyz) && card.HasType(CardType.Xyz) && !card.IsCode(CardId.ExosistersMagnifica)) == 1) + { + forMagnifica = true; + } + if (enemyActivateLockBird) + { + searchMartha = false; + searchStella = false; + } + + if (!searchMartha && !searchStella && !forMagnifica) + { + return false; + } + + List materialCheckList = Bot.GetMonsters().Where(card => + !card.HasType(CardType.Xyz) && !card.HasType(CardType.Token) && !card.HasType(CardType.Link)).ToList(); + if (materialCheckList.Count() == 2 && materialCheckList.All(card => card.Level == 4)) + { + SelectXyzMaterial(2); + return true; + } + + return false; + } + + public bool ExosistersMagnificaSpSummonCheck() + { + if (CheckLessOperation()) + { + return false; + } + + List materialList = Bot.GetMonsters().Where(card => card.IsFaceup() && card.HasType(CardType.Xyz) + && card.Rank == 4 && card.HasSetcode(SetcodeExosister)).ToList(); + materialList.Sort(CardContainer.CompareCardAttack); + + AI.SelectMaterials(materialList); + return true; + } + + public bool CheckCaduceusInner(ClientCard card) + { + if (card?.Data == null) + { + return false; + } + foreach (int setcode in SetcodeForDiamond) + { + if (card.HasSetcode(setcode)) + { + return true; + } + } + return false; + } + + public bool TellarknightConstellarCaduceusSpSummonCheck() + { + if (Duel.Turn == 1 || !Bot.HasInExtra(CardId.StellarknightConstellarDiamond)) + { + return false; + } + + // check whether need to call Diamond + if (Enemy.Graveyard.Any(card => CheckCaduceusInner(card))) + { + SelectXyzMaterial(2); + return true; + } + + return false; + } + + public bool DonnerDaggerFurHireSpSummonCheck() + { + if (!Bot.HasInHand(CardId.ExosisterMartha) && !Bot.HasInHandOrInSpellZone(CardId.ExosisterReturnia)) + { + return false; + } + + if (CheckLessOperation()) + { + return false; + } + + List illegalList = Bot.GetMonsters().Where(card => card.IsFaceup() && !card.HasType(CardType.Xyz) && card.Level != 4 + && (card.Data == null || !card.HasSetcode(SetcodeExosister))).ToList(); + + if (illegalList.Count() == 1) + { + + List otherMaterialList = Bot.GetMonsters().Where(card => card.IsFaceup() && !card.HasType(CardType.Xyz)).ToList(); + otherMaterialList.Sort(CardContainer.CompareCardAttack); + illegalList.AddRange(otherMaterialList); + } + if (illegalList.Count() > 1) + { + AI.SelectMaterials(illegalList); + return true; + } + + return false; + } + + public bool SpellSetCheck() + { + if (Duel.Phase == DuelPhase.Main1 && Bot.HasAttackingMonster() && Duel.Turn > 1) return false; + List onlyOneSetList = new List{ + CardId.ExosisterPax, CardId.ExosisterArment, CardId.ExosisterVadis, CardId.ExosisterReturnia + }; + if (onlyOneSetList.Contains(Card.Id) && Bot.HasInSpellZone(Card.Id)) + { + return false; + } + + // select place + if ((Card.IsTrap() || Card.HasType(CardType.QuickPlay))) + { + List avoid_list = new List(); + int setFornfiniteImpermanence = 0; + for (int i = 0; i < 5; ++i) + { + if (Enemy.SpellZone[i] != null && Enemy.SpellZone[i].IsFaceup() && Bot.SpellZone[4 - i] == null) + { + avoid_list.Add(4 - i); + setFornfiniteImpermanence += (int)System.Math.Pow(2, 4 - i); + } + } + if (Bot.HasInHand(_CardId.InfiniteImpermanence)) + { + if (Card.IsCode(_CardId.InfiniteImpermanence)) + { + AI.SelectPlace(setFornfiniteImpermanence); + return true; + } else + { + SelectSTPlace(Card, false, avoid_list); + return true; + } + } else + { + SelectSTPlace(); + } + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/libWindbot/Game/AI/Decks/KashtiraExecutor.cs b/libWindbot/Game/AI/Decks/KashtiraExecutor.cs new file mode 100644 index 0000000..3b82311 --- /dev/null +++ b/libWindbot/Game/AI/Decks/KashtiraExecutor.cs @@ -0,0 +1,1377 @@ +using YGOSharp.OCGWrapper.Enums; +using System.Collections.Generic; +using System.Linq; +using WindBot; +using WindBot.Game; +using WindBot.Game.AI; +namespace WindBot.Game.AI.Decks +{ + [Deck("Kashtira", "AI_Kashtira")] + class KashtiraExecutor : DefaultExecutor + { + public class CardId + { + public const int Nibiru = 27204311; + public const int KashtiraUnicorn = 68304193; + public const int KashtiraFenrir = 32909498; + public const int KashtiraTearlaments = 4928565; + public const int KashtiraScareclaw = 78534861; + public const int DimensionShifter = 91800273; + public const int NemesesCorridor = 72090076; + public const int KashtiraRiseheart = 31149212; + public const int G = 23434538; + public const int AshBlossom = 14558127; + public const int MechaPhantom = 31480215; + public const int Terraforming = 73628505; + public const int PotofProsperity = 84211599; + public const int KashtiraPapiyas = 34447918; + public const int CalledbytheGrave = 24224830; + public const int CrossoutDesignator = 65681983; + public const int KashtiraBirth = 69540484; + public const int PrimePlanetParaisos = 71832012; + public const int KashtiraBigBang = 33925864; + public const int InfiniteImpermanence = 10045474; + + public const int ThunderDragonColossus = 15291624; + public const int BorreloadSavageDragon = 27548199; + public const int CupidPitch = 21915012; + public const int KashtiraAriseHeart = 48626373; + public const int DiablosistheMindHacker = 95474755; + public const int KashtiraShangriIra = 73542331; + public const int GalaxyTomahawk = 10389142; + public const int BagooskatheTerriblyTiredTapir = 90590303; + public const int MekkKnightCrusadiaAvramax = 21887175; + public const int MechaPhantomBeastAuroradon = 44097050; + public const int QliphortGenius = 22423493; + public const int IP = 65741786; + + public const int Token = 10389143; + public const int Token_2 = 44097051; + } + bool isSummoned = false; + bool onlyXyzSummon = false; + bool activate_KashtiraUnicorn_1 = false; + bool activate_KashtiraFenrir_1 = false; + bool activate_KashtiraRiseheart_1 = false; + bool activate_KashtiraRiseheart_2 = false; + bool activate_PrimePlanetParaisos = false; + bool activate_KashtiraScareclaw_1 = false; + bool activate_KashtiraShangriIra = false; + bool activate_KashtiraTearlaments_1 = false; + bool activate_DimensionShifter = false; + bool activate_pre_PrimePlanetParaisos = false; + bool activate_pre_PrimePlanetParaisos_2 = false; + bool active_KashtiraPapiyas_1 = false; + bool active_KashtiraPapiyas_2 = false; + bool active_KashtiraBirth = false; + bool active_NemesesCorridor = false; + bool select_CalledbytheGrave = false; + bool summon_KashtiraUnicorn = false; + bool summon_KashtiraFenrir = false; + bool link_mode = false; + bool opt_0 = false; + bool opt_1 = false; + bool opt_2 = false; + + int flag = -1; + int pre_link_mode = -1; + List select_Cards = new List(); + List Impermanence_list = new List(); + List should_not_negate = new List + { + 81275020, 28985331 + }; + public KashtiraExecutor(GameAI ai, Duel duel) + : base(ai, duel) + { + AddExecutor(ExecutorType.Activate, CardId.ThunderDragonColossus); + AddExecutor(ExecutorType.SpSummon, CardId.ThunderDragonColossus); + AddExecutor(ExecutorType.Activate, CardId.Nibiru, NibiruEffect); + AddExecutor(ExecutorType.Activate, CardId.InfiniteImpermanence, Impermanence_activate); + AddExecutor(ExecutorType.Activate, CardId.DimensionShifter, DimensionShifterEffect); + AddExecutor(ExecutorType.Activate, CardId.G, DefaultMaxxC); + AddExecutor(ExecutorType.Activate, CardId.AshBlossom, DefaultAshBlossomAndJoyousSpring); + AddExecutor(ExecutorType.Activate, CardId.CalledbytheGrave, CalledbytheGraveEffect); + AddExecutor(ExecutorType.Activate, CardId.BorreloadSavageDragon, BorreloadSavageDragonEffect); + AddExecutor(ExecutorType.Activate, CardId.CrossoutDesignator, CrossoutDesignatorEffect); + AddExecutor(ExecutorType.Activate, CardId.Terraforming, TerraformingEffect); + AddExecutor(ExecutorType.Activate, CardId.PotofProsperity, PotofProsperityEffect); + AddExecutor(ExecutorType.Activate, CardId.KashtiraUnicorn, KashtiraUnicornEffect); + AddExecutor(ExecutorType.Activate, CardId.KashtiraFenrir, KashtiraFenrirEffect); + AddExecutor(ExecutorType.Activate, CardId.PrimePlanetParaisos, PrimePlanetParaisosEffect); + AddExecutor(ExecutorType.Activate, CardId.KashtiraBirth, KashtiraBirthEffect); + AddExecutor(ExecutorType.Activate, CardId.DiablosistheMindHacker, DiablosistheMindHackerEffect); + AddExecutor(ExecutorType.SpSummon, CardId.KashtiraFenrir, KashtiraFenrirSummon); + AddExecutor(ExecutorType.SpSummon, CardId.KashtiraUnicorn,() => { summon_KashtiraUnicorn = true; return true; }); + AddExecutor(ExecutorType.SpSummon, CardId.KashtiraFenrir, () => { summon_KashtiraFenrir = true; return true; }); + AddExecutor(ExecutorType.Summon, CardId.KashtiraUnicorn, DefaultSummon); + AddExecutor(ExecutorType.Summon, CardId.KashtiraFenrir, DefaultSummon); + AddExecutor(ExecutorType.Activate, CardId.KashtiraPapiyas, KashtiraPapiyasEffect); + AddExecutor(ExecutorType.Activate, CardId.KashtiraTearlaments, KashtiraTearlamentsEffect); + AddExecutor(ExecutorType.Activate, CardId.KashtiraScareclaw, KashtiraScareclawEffect); + AddExecutor(ExecutorType.Activate, CardId.KashtiraBirth, KashtiraBirthEffect_2); + AddExecutor(ExecutorType.Activate, CardId.GalaxyTomahawk); + AddExecutor(ExecutorType.SpSummon, CardId.GalaxyTomahawk, GalaxyTomahawkSummon); + AddExecutor(ExecutorType.SpSummon, CardId.KashtiraShangriIra, KashtiraShangriIraSummon); + AddExecutor(ExecutorType.Activate, CardId.KashtiraShangriIra, KashtiraShangriIraEffect); + AddExecutor(ExecutorType.SpSummon, CardId.KashtiraAriseHeart, KashtiraAriseHeartSummon_2); + AddExecutor(ExecutorType.SpSummon, CardId.DiablosistheMindHacker, DiablosistheMindHackerSummon_2); + AddExecutor(ExecutorType.Activate, CardId.KashtiraAriseHeart, KashtiraAriseHeartEffect); + AddExecutor(ExecutorType.SpSummon, CardId.KashtiraAriseHeart, KashtiraAriseHeartSummon); + AddExecutor(ExecutorType.SpSummon, CardId.DiablosistheMindHacker, DiablosistheMindHackerSummon); + //link mode + AddExecutor(ExecutorType.SpSummon, CardId.QliphortGenius, QliphortGeniusSummon); + AddExecutor(ExecutorType.SpSummon, CardId.IP, IPSummon); + AddExecutor(ExecutorType.Activate, CardId.IP, IPEffect); + AddExecutor(ExecutorType.SpSummon, CardId.MechaPhantomBeastAuroradon, MechaPhantomBeastAuroradonSummon); + AddExecutor(ExecutorType.Activate, CardId.MechaPhantomBeastAuroradon, MechaPhantomBeastAuroradonEffect); + AddExecutor(ExecutorType.SpSummon, CardId.CupidPitch, CupidPitchSummon); + AddExecutor(ExecutorType.Activate, CardId.CupidPitch); + AddExecutor(ExecutorType.SpSummon, CardId.BorreloadSavageDragon, BorreloadSavageDragonSummon); + AddExecutor(ExecutorType.Activate, CardId.NemesesCorridor, NemesesCorridorEffect); + AddExecutor(ExecutorType.SpSummon, CardId.MekkKnightCrusadiaAvramax, MekkKnightCrusadiaAvramaxSummon); + AddExecutor(ExecutorType.Activate, CardId.MekkKnightCrusadiaAvramax, MekkKnightCrusadiaAvramaxEffect); + //link mode + AddExecutor(ExecutorType.Activate, CardId.KashtiraRiseheart, KashtiraRiseheartEffect_2); + AddExecutor(ExecutorType.Activate, CardId.KashtiraRiseheart, KashtiraRiseheartEffect); + AddExecutor(ExecutorType.Activate, CardId.KashtiraBigBang, KashtiraBigBangEffect); + AddExecutor(ExecutorType.Activate, CardId.KashtiraPapiyas, KashtiraPapiyasEffect_2); + AddExecutor(ExecutorType.Activate, CardId.KashtiraBirth, KashtiraBirthEffect_3); + AddExecutor(ExecutorType.Summon, CardId.KashtiraRiseheart, KashtiraRiseheartSummon); + AddExecutor(ExecutorType.Summon, CardId.KashtiraTearlaments, DefaultSummon); + AddExecutor(ExecutorType.SpellSet, SpellSet); + AddExecutor(ExecutorType.Repos, DefaultRepos); + } + + public override bool OnSelectHand() + { + // go first + return true; + } + + public override void OnNewTurn() + { + if (pre_link_mode < 0) pre_link_mode = Program.Rand.Next(2); + isSummoned = false; + onlyXyzSummon = false; + activate_KashtiraUnicorn_1 = false; + activate_KashtiraFenrir_1 = false; + activate_KashtiraRiseheart_1 = false; + activate_KashtiraRiseheart_2 = false; + activate_PrimePlanetParaisos = false; + activate_KashtiraScareclaw_1 = false; + activate_KashtiraTearlaments_1 = false; + activate_KashtiraShangriIra = false; + activate_pre_PrimePlanetParaisos_2 = false; + active_KashtiraPapiyas_1 = false; + active_KashtiraPapiyas_2 = false; + active_KashtiraBirth = false; + active_NemesesCorridor = false; + link_mode = false; + summon_KashtiraUnicorn = false; + summon_KashtiraFenrir = false; + opt_0 = false; + opt_1 = false; + opt_2 = false; + if (flag >= 0) ++flag; + if (flag >= 2) { flag = -1; activate_DimensionShifter = false; } + } + public override bool OnSelectYesNo(int desc) + { + if (desc == 1149312192) + { + activate_pre_PrimePlanetParaisos = true; + } + return base.OnSelectYesNo(desc); + } + public override CardPosition OnSelectPosition(int cardId, IList positions) + { + if (cardId == 27204312|| cardId==CardId.MechaPhantom) + { + return CardPosition.FaceUpDefence; + } + return base.OnSelectPosition(cardId, positions); + } + public override int OnSelectOption(IList options) + { + if (options.Count == 2 && options[1] == Util.GetStringId(CardId.KashtiraBirth, 0)) + return 1; + if (options.Count == 2 && options.Contains(Util.GetStringId(CardId.KashtiraTearlaments, 1))) + { + return (isEffectByRemove() || Enemy.Deck.Count <= 3) ? 1 : 0; + } + if (options.Contains(Util.GetStringId(CardId.MechaPhantomBeastAuroradon, 3))) + { + if (opt_1) return options.IndexOf(Util.GetStringId(CardId.MechaPhantomBeastAuroradon, 3)); + else if (opt_0) return 0; + return options[options.Count - 1]; + } + return base.OnSelectOption(options); + } + public override int OnSelectPlace(int cardId, int player, CardLocation location, int available) + { + if (cardId == 0 && player == 1) + { + int zone = 0; + for (int i = 4; i >= 0; --i) + { + zone = (int)System.Math.Pow(2, i); + if ((available & zone) > 0) return zone; + } + } + if (cardId == CardId.GalaxyTomahawk) + { + if ((available & Zones.z5) > 0) return Zones.z5; + if ((available & Zones.z6) > 0) return Zones.z6; + } + return base.OnSelectPlace(cardId, player, location, available); + } + public override IList OnSelectCard(IList cards, int min, int max, int hint, bool cancelable) + { + if (cards.Any(card => card != null && card.Location == CardLocation.Extra + && hint == HintMsg.Remove && min == 1 && max == 1)) + { + //Can't get card info in enemy extral. + int index = Program.Rand.Next(cards.Count()); + if (index < 0 || index >= cards.Count()) return null; + IList res = new List(); + res.Add(cards.ElementAtOrDefault(index)); + return Util.CheckSelectCount(res, cards, min, max); + } + if (cards.Any(card => card != null && card.Location == CardLocation.Grave && card.Controller == 1) + && hint == HintMsg.Remove && ((min == 1 && max == 1) || (min == 3 && max == 3))) + { + if (select_CalledbytheGrave) { select_CalledbytheGrave = false; return null; } + List copyCards = new List(cards); + List keyCardsId = new List() + { + 44097050,15291624,63288573,70369116,83152482,72329844, + 24094258,86066372,74997493,85289965,21887175,11738489, + 98127546,50588353,10389142,90590303,27548199, + }; + List preCards = new List(); + List resCards = new List(); + foreach (var card in copyCards) + { + if (card != null && (keyCardsId.Contains(card.Id) || (card.Alias != 0 && keyCardsId.Contains(card.Alias)))) + preCards.Add(card); + else resCards.Add(card); + } + if (preCards.Count > 0) return Util.CheckSelectCount(preCards, cards, min, max); + resCards = FilterdRepeatIdCards(resCards); + if (resCards != null) + { + resCards.Sort(CardContainer.CompareCardAttack); + resCards.Reverse(); + return Util.CheckSelectCount(resCards, cards, min, max); + } + copyCards.Sort(CardContainer.CompareCardAttack); + copyCards.Reverse(); + return Util.CheckSelectCount(copyCards, cards, min, max); + } + if (cards.Any(card => card != null && card.Location == CardLocation.Extra && card.Controller == 0) + && hint == HintMsg.Remove && min == 3 && max == 3) + { + //pre_link_mode == 0 xyz_mode + //pre_link_mode == 1 link_mode + List repeatIdCards = FilterdRepeatIdCards(cards); + if (repeatIdCards?.Count >= 3) + { + if (pre_link_mode == 1) return Util.CheckSelectCount(repeatIdCards, cards, min, max); + } + List resCards = new List(); + List cardsId = new List() + { + CardId.BagooskatheTerriblyTiredTapir,CardId.BorreloadSavageDragon,CardId.CupidPitch, + CardId.QliphortGenius,CardId.IP,CardId.MechaPhantomBeastAuroradon,CardId.MekkKnightCrusadiaAvramax, + CardId.ThunderDragonColossus + }; + List filterCards = CardsIdToClientCards(cardsId, cards).ToList(); + if (repeatIdCards?.Count > 0 && pre_link_mode == 0) resCards.AddRange(repeatIdCards); + if (filterCards?.Count > 0) resCards.AddRange(filterCards); + if (repeatIdCards?.Count > 0 && pre_link_mode == 1) resCards.AddRange(repeatIdCards); + if (resCards.Count > 0) + { + return Util.CheckSelectCount(resCards, cards, min, max); + } + return null; + } + if (hint == HintMsg.Remove && cards.Any(card => card != null && (card.Location == CardLocation.Hand || card.Location == CardLocation.Grave) && card.Controller == 0) && min == 1 && max == 1) + { + if (select_Cards.Count > 0) + { + return Util.CheckSelectCount(select_Cards, cards, min, max); + } + else + { + IList grave_cards = cards.GetMatchingCards(card => card != null && card.Location == CardLocation.Grave); + if (grave_cards.Count > 0) return Util.CheckSelectCount(grave_cards, cards, min, max); + return null; + } + + } + if (hint == HintMsg.XyzMaterial && cards.Any(card => card != null && card.Location == CardLocation.Removed) && min == 1 && max == 1) + { + List m_cards = new List(); + List e_cards_u = new List(); + List e_cards_d = new List(); + foreach (var card in cards) + { + if (card != null && card.Controller == 0) + m_cards.Add(card); + if (card != null && card.Controller == 1 && card.IsFaceup()) + e_cards_u.Add(card); + if (card != null && card.Controller == 1 && card.IsFacedown()) + e_cards_d.Add(card); + } + List res = new List(); + if (e_cards_u.Count >= 0) + { + e_cards_u.Sort(CardContainer.CompareCardAttack); + e_cards_u.Reverse(); + res.AddRange(e_cards_u); + } + IList cardsId = new List() { CardId.KashtiraBigBang, CardId.KashtiraPapiyas }; + IList m_pre_cards = CardsIdToClientCards(cardsId, m_cards, false); + if (m_pre_cards?.Count >= 0) res.AddRange(m_pre_cards); + else if (m_cards.Count >= 0) res.AddRange(m_cards); + if (e_cards_d.Count >= 0) res.AddRange(e_cards_d); + if (res.Count <= 0) return null; + return Util.CheckSelectCount(res, cards, min, max); + } + if (hint == HintMsg.Release && cards.Any(card => card != null && card.Location == CardLocation.MonsterZone)) + { + List tRelease = new List(); + List nRelease = new List(); + foreach (var card in cards) + { + if (card == null || (card.IsExtraCard() && card.Id != CardId.DiablosistheMindHacker) || card.IsFacedown()) continue; + if (card.Id == CardId.Token || card.Id == CardId.Token_2) + tRelease.Add(card); + else nRelease.Add(card); + } + if (opt_1) + { + IList cardsId = new List() { CardId.Token, CardId.Token_2 }; + tRelease = CardsIdToClientCards(cardsId, tRelease, false).ToList(); + if(tRelease?.Count > 0) nRelease.AddRange(tRelease); + if (nRelease.Count <= 0) return null; + return Util.CheckSelectCount(nRelease, cards, min, max); + } + else + { + tRelease.AddRange(nRelease); + if(tRelease.Count <= 0) return null; + return Util.CheckSelectCount(tRelease, cards, min, max); + } + } + if (hint == HintMsg.Destroy && cards.Any(card => card != null && card.Controller == 1 && (card.Location & CardLocation.Onfield) > 0) && min==1 && max==1) + { + ClientCard card = Util.GetBestEnemyCard(); + List res = new List(); + if (card != null && cards.Contains(card)) + { + res.Add(card); + return Util.CheckSelectCount(res, cards, min, max); + } + res = cards.Where(_card => _card != null && _card.Controller == 1).ToList(); + if (res.Count <= 0) return null; + res.Sort(CardContainer.CompareCardAttack); + res.Reverse(); + return Util.CheckSelectCount(res, cards, min, max); + } + if (activate_pre_PrimePlanetParaisos) + { + activate_pre_PrimePlanetParaisos = false; + IList cardsId = new List(); + if (!Bot.HasInHand(CardId.KashtiraUnicorn) && !activate_KashtiraUnicorn_1 && CheckRemainInDeck(CardId.KashtiraUnicorn) > 0) cardsId.Add(CardId.KashtiraUnicorn); + if (!Bot.HasInHand(CardId.KashtiraFenrir) && !activate_KashtiraFenrir_1 && CheckRemainInDeck(CardId.KashtiraFenrir) > 0) cardsId.Add(CardId.KashtiraFenrir); + if (!Bot.HasInHand(CardId.KashtiraScareclaw) && !activate_KashtiraScareclaw_1 && CheckRemainInDeck(CardId.KashtiraScareclaw) > 0) cardsId.Add(CardId.KashtiraScareclaw); + if (!Bot.HasInHand(CardId.KashtiraTearlaments) && !activate_KashtiraTearlaments_1 && CheckRemainInDeck(CardId.KashtiraTearlaments) > 0) cardsId.Add(CardId.KashtiraTearlaments); + if (!Bot.HasInHand(CardId.KashtiraRiseheart) && (!activate_KashtiraRiseheart_2 || !activate_KashtiraRiseheart_1) && CheckRemainInDeck(CardId.KashtiraRiseheart) > 0) cardsId.Add(CardId.KashtiraRiseheart); + IList copyCards = new List(cards); + IList res = CardsIdToClientCards(cardsId, copyCards); + if (res?.Count <= 0) return null; + return Util.CheckSelectCount(res, cards, min, max); + + } + return base.OnSelectCard(cards, min, max, hint, cancelable); + } + private int CheckRemainInDeck(int id) + { + switch (id) + { + case CardId.Nibiru: + return Bot.GetRemainingCount(CardId.Nibiru, 1); + case CardId.KashtiraUnicorn: + return Bot.GetRemainingCount(CardId.KashtiraUnicorn, 3); + case CardId.KashtiraFenrir: + return Bot.GetRemainingCount(CardId.KashtiraFenrir, 3); + case CardId.KashtiraTearlaments: + return Bot.GetRemainingCount(CardId.KashtiraTearlaments, 1); + case CardId.KashtiraScareclaw: + return Bot.GetRemainingCount(CardId.KashtiraScareclaw, 2); + case CardId.DimensionShifter: + return Bot.GetRemainingCount(CardId.DimensionShifter, 2); + case CardId.NemesesCorridor: + return Bot.GetRemainingCount(CardId.NemesesCorridor, 1); + case CardId.KashtiraRiseheart: + return Bot.GetRemainingCount(CardId.KashtiraRiseheart, 3); + case CardId.G: + return Bot.GetRemainingCount(CardId.G, 2); + case CardId.AshBlossom: + return Bot.GetRemainingCount(CardId.AshBlossom, 3); + case CardId.MechaPhantom: + return Bot.GetRemainingCount(CardId.MechaPhantom, 1); + case CardId.Terraforming: + return Bot.GetRemainingCount(CardId.Terraforming, 1); + case CardId.PotofProsperity: + return Bot.GetRemainingCount(CardId.PotofProsperity, 2); + case CardId.KashtiraPapiyas: + return Bot.GetRemainingCount(CardId.KashtiraPapiyas, 3); + case CardId.CalledbytheGrave: + return Bot.GetRemainingCount(CardId.CalledbytheGrave, 2); + case CardId.CrossoutDesignator: + return Bot.GetRemainingCount(CardId.CrossoutDesignator, 1); + case CardId.KashtiraBirth: + return Bot.GetRemainingCount(CardId.KashtiraBirth, 3); + case CardId.PrimePlanetParaisos: + return Bot.GetRemainingCount(CardId.PrimePlanetParaisos, 3); + case CardId.KashtiraBigBang: + return Bot.GetRemainingCount(CardId.KashtiraBigBang, 1); + case CardId.InfiniteImpermanence: + return Bot.GetRemainingCount(CardId.InfiniteImpermanence, 2); + default: + return 0; + } + } + #region CopyImpermanence + public bool Impermanence_activate() + { + // negate before effect used + foreach (ClientCard m in Enemy.GetMonsters()) + { + if (m.IsMonsterShouldBeDisabledBeforeItUseEffect() && !m.IsDisabled() && Duel.LastChainPlayer != 0) + { + if (Card.Location == CardLocation.SpellZone) + { + for (int i = 0; i < 5; ++i) + { + if (Bot.SpellZone[i] == Card) + { + Impermanence_list.Add(i); + break; + } + } + } + if (Card.Location == CardLocation.Hand) + { + AI.SelectPlace(SelectSTPlace(Card, true)); + } + AI.SelectCard(m); + return true; + } + } + + ClientCard LastChainCard = Util.GetLastChainCard(); + + // negate spells + if (Card.Location == CardLocation.SpellZone) + { + int this_seq = -1; + int that_seq = -1; + for (int i = 0; i < 5; ++i) + { + if (Bot.SpellZone[i] == Card) this_seq = i; + if (LastChainCard != null + && LastChainCard.Controller == 1 && LastChainCard.Location == CardLocation.SpellZone && Enemy.SpellZone[i] == LastChainCard) that_seq = i; + else if (Duel.Player == 0 && Util.GetProblematicEnemySpell() != null + && Enemy.SpellZone[i] != null && Enemy.SpellZone[i].IsFloodgate()) that_seq = i; + } + if ((this_seq * that_seq >= 0 && this_seq + that_seq == 4) + || (Util.IsChainTarget(Card)) + || (LastChainCard != null && LastChainCard.Controller == 1 && LastChainCard.IsCode(_CardId.HarpiesFeatherDuster))) + { + List enemy_monsters = Enemy.GetMonsters(); + enemy_monsters.Sort(CardContainer.CompareCardAttack); + enemy_monsters.Reverse(); + foreach (ClientCard card in enemy_monsters) + { + if (card.IsFaceup() && !card.IsShouldNotBeTarget() && !card.IsShouldNotBeSpellTrapTarget()) + { + AI.SelectCard(card); + Impermanence_list.Add(this_seq); + return true; + } + } + } + } + if ((LastChainCard == null || LastChainCard.Controller != 1 || LastChainCard.Location != CardLocation.MonsterZone + || LastChainCard.IsDisabled() || LastChainCard.IsShouldNotBeTarget() || LastChainCard.IsShouldNotBeSpellTrapTarget())) + return false; + // negate monsters + if (is_should_not_negate() && LastChainCard.Location == CardLocation.MonsterZone) return false; + if (Card.Location == CardLocation.SpellZone) + { + for (int i = 0; i < 5; ++i) + { + if (Bot.SpellZone[i] == Card) + { + Impermanence_list.Add(i); + break; + } + } + } + if (Card.Location == CardLocation.Hand) + { + AI.SelectPlace(SelectSTPlace(Card, true)); + } + if (LastChainCard != null) AI.SelectCard(LastChainCard); + else + { + List enemy_monsters = Enemy.GetMonsters(); + enemy_monsters.Sort(CardContainer.CompareCardAttack); + enemy_monsters.Reverse(); + foreach (ClientCard card in enemy_monsters) + { + if (card.IsFaceup() && !card.IsShouldNotBeTarget() && !card.IsShouldNotBeSpellTrapTarget()) + { + AI.SelectCard(card); + return true; + } + } + } + return true; + } + 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 bool is_should_not_negate() + { + ClientCard last_card = Util.GetLastChainCard(); + if (last_card != null + && last_card.Controller == 1 && last_card.IsCode(should_not_negate)) + return true; + return false; + } + #endregion + private List FilterdRepeatIdCards(IList cards) + { + IList temp = new List(); + List res = new List(); + foreach (var card in cards) + { + if (card == null) continue; + if (temp.Count(_card => _card != null && _card.Id == card.Id) > 0 && res.Count(_card=>_card != null && _card.Id == card.Id) <= 0) + res.Add(card); + else + temp.Add(card); + } + return res.Count < 0 ? null : res; + } + private IList CardsIdToClientCards(IList cardsId, IList cardsList, bool uniqueId = true, bool alias = true) + { + if (cardsList?.Count() <= 0 || cardsId?.Count() <= 0) return new List(); + List res = new List(); + foreach (var cardid in cardsId) + { + List cards = cardsList.Where(card => card != null && (card.Id == cardid || ((card.Alias != 0 && cardid == card.Alias) & alias))).ToList(); + if (cards?.Count <= 0) continue; + cards.Sort(CardContainer.CompareCardAttack); + if (uniqueId) res.Add(cards.First()); + else res.AddRange(cards); + } + return res; + } + private IList ClientCardsToCardsId(IList cardsList, bool uniqueId = false, bool alias = false) + { + if (cardsList == null) return null; + if (cardsList.Count <= 0) return new List(); + IList res = new List(); + foreach (var card in cardsList) + { + if (card == null) continue; + if (card.Alias != 0 && alias && !(res.Contains(card.Alias) & uniqueId)) res.Add(card.Alias); + else if (card.Id != 0 && !(res.Contains(card.Id) & uniqueId)) res.Add(card.Id); + } + return res.Count < 0 ? null : res; + } + private bool DefaultRepos() + { + if (Card.Id == CardId.KashtiraScareclaw || (Card.Id == CardId.KashtiraShangriIra && Card.Attack<2000)) return false; + return DefaultMonsterRepos(); + } + private bool CrossoutDesignatorCheck(ClientCard LastChainCard, int id) + { + if (LastChainCard.IsCode(id) && CheckRemainInDeck(id) > 0) + { + AI.SelectAnnounceID(id); + return true; + } + return false; + } + private bool CrossoutDesignatorEffect() + { + ClientCard LastChainCard = Util.GetLastChainCard(); + if (LastChainCard == null || Duel.LastChainPlayer != 1) return false; + if (CrossoutDesignatorCheck(LastChainCard, CardId.Nibiru) + || CrossoutDesignatorCheck(LastChainCard, CardId.AshBlossom) + || CrossoutDesignatorCheck(LastChainCard, CardId.G) + || CrossoutDesignatorCheck(LastChainCard, CardId.NemesesCorridor) + || CrossoutDesignatorCheck(LastChainCard, CardId.InfiniteImpermanence) + || CrossoutDesignatorCheck(LastChainCard, CardId.CalledbytheGrave) + || CrossoutDesignatorCheck(LastChainCard, CardId.Terraforming) + || CrossoutDesignatorCheck(LastChainCard, CardId.PotofProsperity) + || CrossoutDesignatorCheck(LastChainCard, CardId.KashtiraPapiyas) + || CrossoutDesignatorCheck(LastChainCard, CardId.KashtiraUnicorn) + || CrossoutDesignatorCheck(LastChainCard, CardId.KashtiraFenrir) + || CrossoutDesignatorCheck(LastChainCard, CardId.KashtiraBirth)) + { + if (Card.Location == CardLocation.Hand) + { + AI.SelectPlace(SelectSTPlace(Card, true)); + } + return true; + } + return false; + } + private bool MekkKnightCrusadiaAvramaxEffect() + { + if (Card.Location == CardLocation.Grave) + { + List cards = Enemy.GetMonsters(); + cards.Sort(CardContainer.CompareCardAttack); + cards.Reverse(); + cards.AddRange(Enemy.GetSpells()); + if (cards.Count <= 0) return false; + AI.SelectCard(cards); + return true; + } + else return true; + } + private bool SpellSet() + { + return Card.HasType(CardType.QuickPlay) || Card.HasType(CardType.Trap); + } + private bool NibiruEffect() + { + if (Bot.HasInMonstersZone(CardId.KashtiraAriseHeart, true, false, true) && Util.GetBestAttack(Bot) > Util.GetBestAttack(Enemy)) return false; + return Bot.GetMonsterCount() <= 0 || Bot.GetMonsterCount() < Enemy.GetMonsterCount(); + } + private bool CalledbytheGraveEffect() + { + ClientCard card = Util.GetLastChainCard(); + if (card == null) return false; + int id = card.Id; + List g_cards = Enemy.GetGraveyardMonsters().Where(g_card => g_card != null && g_card.Id == id).ToList(); + if (Duel.LastChainPlayer != 0 && card != null) + { + if (Card.Location == CardLocation.Hand) + { + AI.SelectPlace(SelectSTPlace(Card, true)); + } + if (card.Location == CardLocation.Grave && card.HasType(CardType.Monster)) + { + AI.SelectCard(card); + } + else if (g_cards.Count() > 0 && card.HasType(CardType.Monster)) + { + AI.SelectCard(g_cards); + } + else return false; + select_CalledbytheGrave = true; + return true; + } + return false; + } + private bool CupidPitchSummon() + { + if (!Bot.HasInMonstersZone(CardId.Token_2) && !Bot.HasInMonstersZone(CardId.MechaPhantom)) return false; + IList cardsId = new List() { CardId.MechaPhantom, CardId.Token_2 }; + IList cards = CardsIdToClientCards(cardsId, Bot.GetMonsters(), false); + if (cards?.Count <= 0) return false; + AI.SelectMaterials(cards); + return true; + + } + private bool BorreloadSavageDragonSummon() + { + if (!Bot.HasInMonstersZone(CardId.Token_2) && !Bot.HasInMonstersZone(CardId.CupidPitch)) return false; + IList cardsId = new List() { CardId.CupidPitch, CardId.Token_2 }; + IList cards = CardsIdToClientCards(cardsId, Bot.GetMonsters(), false); + if (cards?.Count <= 0) return false; + AI.SelectMaterials(cards); + link_mode = false; + return true; + } + private bool BorreloadSavageDragonEffect() + { + if (ActivateDescription == -1) + { + AI.SelectCard(new[] { CardId.MekkKnightCrusadiaAvramax, CardId.MechaPhantomBeastAuroradon, CardId.IP, CardId.QliphortGenius}); + return true; + } + return true; + + } + private bool IPSummon() + { + if (!Bot.HasInMonstersZone(CardId.Token) && !Bot.HasInMonstersZone(CardId.Token_2)) return false; + if (!Bot.HasInExtra(CardId.MechaPhantomBeastAuroradon) || !(Bot.HasInExtra(CardId.MekkKnightCrusadiaAvramax) && (Bot.HasInExtra(CardId.QliphortGenius) || Bot.HasInMonstersZone(CardId.QliphortGenius, false, false, true)))) return false; + List cards = Bot.GetMonsters().Where(card => card != null && !card.HasType(CardType.Link) && card.IsFaceup() && card.HasType(CardType.Monster) && !card.HasType(CardType.Xyz)).ToList(); + if (cards?.Count < 2 && !link_mode) return false; + IList cardsId = new List { CardId.GalaxyTomahawk, CardId.Token }; + IList pre_cards = CardsIdToClientCards(cardsId, cards, false); + if (pre_cards?.Count >= 2) { AI.SelectMaterials(pre_cards); return true; } + cards.Sort(CardContainer.CompareCardAttack); + AI.SelectMaterials(cards); + return true; + } + private bool IPEffect() + { + if (!Bot.HasInExtra(CardId.MekkKnightCrusadiaAvramax) && !(Bot.HasInMonstersZone(CardId.QliphortGenius,false,false,true) || + Bot.HasInMonstersZone(CardId.MechaPhantomBeastAuroradon, false, false, true))) return false; + AI.SelectCard(CardId.MekkKnightCrusadiaAvramax); + IList cardsId = new List {CardId.MechaPhantomBeastAuroradon,CardId.IP,CardId.QliphortGenius}; + List m = new List(); + IList pre_m = CardsIdToClientCards(cardsId,Bot.GetMonsters()); + if (pre_m?.Count <= 0) return false; + int link_count = 0; + foreach (var card in pre_m) + { + m.Add(card); + link_count += (card.HasType(CardType.Link)) ? card.LinkCount : 1; + if (link_count >= 4) break; + } + if (link_count < 4) return false; + AI.SelectMaterials(m); + return true; + + } + private bool MechaPhantomBeastAuroradonEffect() + { + if (ActivateDescription == -1) return true; + else + { + if (CheckRemainInDeck(CardId.MechaPhantom) <= 0 + && GetEnemyOnFields().Count <= 0 && Bot.Graveyard.Count(card => card != null && card.HasType(CardType.Trap))<=0) return false; + List tRelease = new List(); + List nRelease = new List(); + foreach (var card in Bot.GetMonsters()) + { + if (card == null || (card.IsExtraCard() && card.Id != CardId.DiablosistheMindHacker) || card.IsFacedown()) continue; + if (card.Id == CardId.Token || card.Id == CardId.Token_2) + tRelease.Add(card); + else nRelease.Add(card); + } + int count = tRelease.Count() + nRelease.Count(); + opt_0 = false; + opt_1 = false; + opt_2 = false; + if (count >= 3 && Bot.Graveyard.Count(card => card != null && card.HasType(CardType.Trap)) >0 ) opt_2 = true; + if (count >= 2 && CheckRemainInDeck(CardId.MechaPhantom) > 0) opt_1 = true; + if (count >= 1 && GetEnemyOnFields().Count > 0) opt_0 = true; + if (!opt_0 && !opt_1 && !opt_2) return false; + return true; + } + + } + private bool QliphortGeniusSummon() + { + List cards = Bot.GetMonsters().Where(card => card != null && card.Id==CardId.Token).ToList(); + if (cards.Count <= 2) return false; + AI.SelectMaterials(cards); + return true; + } + private bool MekkKnightCrusadiaAvramaxSummon() + { + IList cardsId = new List() {CardId.MechaPhantomBeastAuroradon,CardId.IP,CardId.QliphortGenius}; + List cards = CardsIdToClientCards(cardsId,Bot.GetMonsters()).ToList(); + if (cards.Count <= 0) return false; + List m = new List(); + int link_count = 0; + foreach (var card in cards) + { + m.Add(card); + link_count += (card.HasType(CardType.Link)) ? card.LinkCount : 1; + if (link_count >= 4) break; + } + if (link_count < 4 || m.Count<2) return false; + AI.SelectMaterials(m); + return true; + } + private bool MechaPhantomBeastAuroradonSummon() + { + if (!Bot.HasInMonstersZone(CardId.QliphortGenius,false,false,true) && !Bot.HasInMonstersZone(CardId.Token, false, false, true)) return false; + List m = new List(); + List m1 = Bot.GetMonsters().Where(card => card != null && card.Id == CardId.QliphortGenius).ToList(); + List m2 = Bot.GetMonsters().Where(card => card != null && card.Id == CardId.Token).ToList(); + if (m1.Count > 0) m.AddRange(m1); + if (m2.Count > 0) m.AddRange(m2); + m1.Clear(); + int link_count = 0; + foreach (var card in m) + { + m1.Add(card); + link_count += (card.HasType(CardType.Link)) ? card.LinkCount : 1; + if (link_count >= 3) break; + } + if (link_count < 3) return false; + AI.SelectMaterials(m1); + return true; + } + private bool KashtiraFenrirSummon() + { + if (Bot.HasInHandOrInSpellZone(CardId.KashtiraBirth) && Bot.HasInHandOrInSpellZone(CardId.KashtiraPapiyas)) { summon_KashtiraFenrir = true; return true; } + return false; + } + private bool DiablosistheMindHackerEffect() + { + AI.SelectCard(CardId.KashtiraFenrir, CardId.KashtiraUnicorn, CardId.KashtiraScareclaw, CardId.KashtiraTearlaments); + return true; + } + private bool KashtiraRiseheartSummon() + { + isSummoned = true; + return !activate_KashtiraRiseheart_2; + } + private bool DimensionShifterEffect() + { + if (activate_DimensionShifter) return false; + flag = -1; + ++flag; + activate_DimensionShifter = true; + return true; + } + private bool KashtiraBigBangEffect() + { + if (Card.Location == CardLocation.Removed) + { + AI.SelectCard(CardId.KashtiraShangriIra); + AI.SelectNextCard(CardId.KashtiraUnicorn,CardId.KashtiraFenrir,CardId.KashtiraTearlaments,CardId.KashtiraScareclaw); + return true; + } + else if(Card.Location==CardLocation.SpellZone) + { + if (Enemy.GetMonsterCount() <= 0) return false; + if (Bot.GetMonsterCount() <= 1) return true; + return Bot.GetMonsterCount()< Enemy.GetMonsterCount(); + } + return false; + } + private bool SpellActivate() + { + return Card.Location == CardLocation.Hand || (Card.IsFacedown() && (Card.Location == CardLocation.SpellZone || Card.Location == CardLocation.FieldZone)); + } + private bool PrimePlanetParaisosEffect() + { + if (SpellActivate()) { activate_pre_PrimePlanetParaisos_2 = true; return true; } + if (activate_pre_PrimePlanetParaisos_2 || activate_pre_PrimePlanetParaisos) return false; + List cards = GetEnemyOnFields().Where(card => card != null && !card.IsShouldNotBeTarget()).ToList(); + if (cards == null || cards.Count <= 0) return false; + return true; + } + private bool DiablosistheMindHackerSummon() + { + List cards = Bot.GetMonsters(); + cards.Sort(CardContainer.CompareCardAttack); + AI.SelectMaterials(cards); + return true; + } + private bool XyzCheck() + { + if (Bot.GetMonsters().Count(card => card != null && card.IsFaceup() && card.Level == 7) >= 4 && Bot.HasInExtra(CardId.KashtiraShangriIra)) return false; + if ((active_KashtiraPapiyas_1 || !Bot.HasInHandOrInSpellZone(CardId.KashtiraPapiyas)) + && (activate_KashtiraUnicorn_1 || !Bot.HasInHand(CardId.KashtiraUnicorn) || isSummoned || !Bot.HasInSpellZone(CardId.KashtiraBirth, true, true)) + && (activate_KashtiraFenrir_1 || !Bot.HasInHand(CardId.KashtiraFenrir) || isSummoned || !Bot.HasInSpellZone(CardId.KashtiraBirth, true, true)) + && (activate_KashtiraScareclaw_1 || !Bot.HasInHand(CardId.KashtiraScareclaw) || isSummoned || !Bot.HasInSpellZone(CardId.KashtiraBirth, true, true)) + && (activate_KashtiraTearlaments_1 || !Bot.HasInHand(CardId.KashtiraTearlaments) || isSummoned || !Bot.HasInSpellZone(CardId.KashtiraBirth, true, true)) + && (activate_KashtiraRiseheart_2 || !Bot.HasInHand(CardId.KashtiraRiseheart) || activate_KashtiraRiseheart_1 || isSummoned)) return true; + return false; + + } + private bool GalaxyTomahawkSummon() + { + if (CheckRemainInDeck(CardId.MechaPhantom) <= 0) return false; + if (Bot.GetMonsterCount() >= 4) return false; + if (onlyXyzSummon || activate_DimensionShifter || Bot.HasInMonstersZone(CardId.KashtiraAriseHeart,true,false,true)) return false; + if (!Bot.HasInExtra(CardId.MekkKnightCrusadiaAvramax) && !(Bot.HasInExtra(CardId.CupidPitch) || Bot.HasInExtra(CardId.BorreloadSavageDragon))) return false; + //if (!XyzCheck()) return false; + link_mode = true; + return DiablosistheMindHackerSummon(); + } + private bool DiablosistheMindHackerSummon_2() + { + if (Bot.HasInMonstersZone(CardId.DiablosistheMindHacker)) return false; + return DiablosistheMindHackerSummon(); + } + private bool isEffectByRemove() + { + return activate_DimensionShifter || Bot.HasInMonstersZone(CardId.KashtiraAriseHeart, true, false, true) || Enemy.HasInMonstersZone(CardId.KashtiraAriseHeart, true, false, true); + } + private bool NemesesCorridorEffect() + { + if (Card.Location == CardLocation.Hand) + { + if(Bot.GetMonsterCount()<=0) return true; + if (onlyXyzSummon || !Bot.HasInExtra(CardId.ThunderDragonColossus)) return false; + else return true; + } + return false; + } + private bool KashtiraTearlamentsEffect() + { + if (Card.Location == CardLocation.Hand) + { + if (Duel.Player != 0) return false; + if (Duel.CurrentChain.Count > 0) return false; + if (!ActivateLimit(Card.Id)) return false; + activate_KashtiraTearlaments_1 = true; + return true; + } + if (Card.Location == CardLocation.MonsterZone) + { + if (isEffectByRemove() && Enemy.Deck.Count >= 3) return true; + if (!isEffectByRemove() && Bot.Deck.Count > 10) return true; + return false; + } + if (Card.Location == CardLocation.Grave) + { + if (isEffectByRemove()) return false; + return Bot.Deck.Count > 10; + } + return false; + } + private bool ActivateLimit(int cardId) + { + if (Bot.MonsterZone.Count() <= 0 + && ((Bot.HasInHand(CardId.KashtiraFenrir) && !activate_KashtiraFenrir_1) + || (Bot.HasInHand(CardId.KashtiraUnicorn) && !activate_KashtiraUnicorn_1))) return false; + if (Bot.HasInHand(CardId.PrimePlanetParaisos) && !activate_pre_PrimePlanetParaisos_2) return false; + List cards = new List(); + List hand_cards = Bot.Hand.GetMatchingCards(card=>card!=null && card.HasSetcode(0x189)).ToList(); + List grave_cards = Bot.Graveyard.GetMatchingCards(card => card != null && card.HasSetcode(0x189)).ToList(); + List cardsid = new List(); + if (grave_cards.Count <= 0) + { + if ((Bot.HasInSpellZone(CardId.KashtiraBirth, true, true) && hand_cards.Count(card=>card!=null && card.Id == CardId.KashtiraBirth)>0) + || hand_cards.Count(card => card != null && card.Id == CardId.KashtiraBirth) > 1) + cardsid.Add(CardId.KashtiraBirth); + if ((active_KashtiraPapiyas_1 && hand_cards.Count(card => card != null && card.Id == CardId.KashtiraPapiyas) > 0) + || hand_cards.Count(card => card != null && card.Id == CardId.KashtiraPapiyas) > 1) + cardsid.Add(CardId.KashtiraPapiyas); + if (((activate_KashtiraFenrir_1 || summon_KashtiraFenrir) && hand_cards.Count(card => card != null && card.Id == CardId.KashtiraFenrir) > 0) + || hand_cards.Count(card => card != null && card.Id == CardId.KashtiraFenrir) > 1) + cardsid.Add(CardId.KashtiraFenrir); + if (((activate_KashtiraUnicorn_1 || summon_KashtiraUnicorn) && hand_cards.Count(card => card != null && card.Id == CardId.KashtiraUnicorn) > 0) + || hand_cards.Count(card => card != null && card.Id == CardId.KashtiraUnicorn) > 1) + cardsid.Add(CardId.KashtiraUnicorn); + if ((cardId != CardId.KashtiraScareclaw && hand_cards.Count(card => card != null && card.Id == CardId.KashtiraScareclaw) > 0) + || (hand_cards.Count(card => card != null && card.Id == CardId.KashtiraScareclaw) > 1)) + cardsid.Add(CardId.KashtiraScareclaw); + if ((activate_KashtiraRiseheart_2 && hand_cards.Count(card => card != null && card.Id == CardId.KashtiraRiseheart) > 0) + || hand_cards.Count(card => card != null && card.Id == CardId.KashtiraRiseheart) > 1) + cardsid.Add(CardId.KashtiraRiseheart); + if (cardId != CardId.KashtiraTearlaments && hand_cards.Count(card => card != null && card.Id == CardId.KashtiraTearlaments) > 0) + cardsid.Add(CardId.KashtiraTearlaments); + if(hand_cards.Count(card => card != null && card.Id == CardId.KashtiraBigBang) > 0) + cardsid.Add(CardId.KashtiraBigBang); + if (cardsid.Count <= 0) return false; + } + if (Bot.HasInHand(CardId.KashtiraFenrir) && !activate_KashtiraFenrir_1 && Bot.GetMonsterCount() <= 0) return false; + if (Bot.HasInHand(CardId.KashtiraUnicorn) && !activate_KashtiraUnicorn_1 && Bot.GetMonsterCount() <= 0) return false; + select_Cards.Clear(); + select_Cards.AddRange(grave_cards); + select_Cards.AddRange(CardsIdToClientCards(cardsid, hand_cards,false)); + return true; + } + private bool KashtiraScareclawEffect() + { + if (Card.Location == CardLocation.Hand) + { + if (Duel.Player != 0) return false; + if (Duel.CurrentChain.Count > 0) return false; + if (!ActivateLimit(Card.Id)) return false; + activate_KashtiraScareclaw_1 = true; + return true; + } + return false; + + } + private bool KashtiraAriseHeartEffect() + { + if (Card.IsDisabled()) return false; + if (ActivateDescription == Util.GetStringId(CardId.KashtiraAriseHeart, 1)) + { + return true; + } + else + { + return SelectEnemyCard(false,true); + } + } + private bool KashtiraAriseHeartSummon_2() + { + int xcount = 0; + int xcount_2 = 0; + int xcount_3 = 0; + foreach (var card in Bot.GetMonsters()) + { + if (card == null || card.IsFacedown()) continue; + if (card.Level == 7) ++xcount; + if (card.Level == 7 && card.HasSetcode(0x189))++xcount_2; + if (card.Level != 7 && card.HasSetcode(0x189) && !card.HasType(CardType.Xyz)) ++xcount_3; + } + if (xcount >= 2 && (xcount_3 > 0 || xcount - xcount_2 > 0)) return KashtiraAriseHeartSummon(); + return false; + } + private bool KashtiraAriseHeartSummon() + { + if (Bot.HasInMonstersZone(CardId.KashtiraShangriIra,false,false,true) && !activate_KashtiraShangriIra) return false; + if (activate_KashtiraShangriIra) + { + List materials = Bot.GetMonsters().GetMatchingCards(card => !card.IsExtraCard() && card.IsFaceup() && Card.HasSetcode(0x189)).ToList(); + if (materials.Count() <= 0) return false; + materials.Sort(CardContainer.CompareCardAttack); + materials.Sort(CardContainer.CompareCardLevel); + AI.SelectMaterials(materials); + return true; + } + else + { + return DiablosistheMindHackerSummon(); + } + } + private bool DefaultSummon() + { + if (Bot.HasInSpellZone(CardId.KashtiraBirth, true, true) && Bot.GetMonstersInMainZone().Count<5) + { + isSummoned = true; + if (Card.Id == CardId.KashtiraUnicorn) summon_KashtiraUnicorn = true; + else if(Card.Id == CardId.KashtiraFenrir) summon_KashtiraFenrir = true; + return true; + } + return false; + } + private bool KashtiraShangriIraSummon() + { + if (Bot.HasInMonstersZone(CardId.KashtiraShangriIra, true, false, true)) return false; + List materials = new List(); + foreach (var card in Bot.GetMonsters()) + { + if (materials.Count() >= 2) break; + if (card != null && card.IsFaceup() && card.Level == 7) + { + materials.Add(card); + } + } + if (materials.Count() < 2) return false; + materials.Sort(CardContainer.CompareCardAttack); + AI.SelectMaterials(materials); + return true; + } + private List GetEnemyOnFields() + { + List res = new List(); + List m_cards = Enemy.GetMonsters(); + List s_cards = Enemy.GetSpells(); + if (m_cards.Count > 0) res.AddRange(m_cards); + if(s_cards.Count > 0) res.AddRange(s_cards); + return res; + } + private bool KashtiraShangriIraEffect() + { + if (!Bot.HasInMonstersZone(CardId.KashtiraUnicorn, true, false, true) && Enemy.ExtraDeck.Count > 0 && CheckRemainInDeck(CardId.KashtiraUnicorn) > 0) + { + AI.SelectCard(CardId.KashtiraUnicorn); + } + else if (!Bot.HasInMonstersZone(CardId.KashtiraFenrir, true, false, true) && CheckRemainInDeck(CardId.KashtiraFenrir) > 0) + { + AI.SelectCard(CardId.KashtiraFenrir); + } + else if (!Bot.HasInMonstersZone(CardId.KashtiraScareclaw, true, false, true) && CheckRemainInDeck(CardId.KashtiraScareclaw) > 0) + { + AI.SelectCard(CardId.KashtiraScareclaw); + } + else + { + AI.SelectCard(CardId.KashtiraTearlaments, CardId.KashtiraUnicorn, CardId.KashtiraFenrir, CardId.KashtiraScareclaw); + } + activate_KashtiraShangriIra = true; + return true; + + } + private void DefaultAddCardId(List cardsid) + { + if (!Bot.HasInHand(CardId.KashtiraUnicorn) && !activate_KashtiraUnicorn_1) cardsid.Add(CardId.KashtiraUnicorn); + if (!Bot.HasInHand(CardId.KashtiraFenrir) && !activate_KashtiraFenrir_1) cardsid.Add(CardId.KashtiraFenrir); + if (!Bot.HasInHand(CardId.KashtiraRiseheart) && !activate_KashtiraRiseheart_2) cardsid.Add(CardId.KashtiraRiseheart); + if (!Bot.HasInHand(CardId.KashtiraTearlaments) && !activate_KashtiraTearlaments_1) cardsid.Add(CardId.KashtiraTearlaments); + if (!Bot.HasInHand(CardId.KashtiraScareclaw) && !activate_KashtiraScareclaw_1) cardsid.Add(CardId.KashtiraScareclaw); + } + private bool KashtiraPapiyasEffect_2() + { + if (Card.Location == CardLocation.Removed) + { + List cardsid = new List(); + DefaultAddCardId(cardsid); + if (!Bot.HasInExtra(CardId.KashtiraAriseHeart)) cardsid.Add(CardId.KashtiraAriseHeart); + if (!Bot.HasInExtra(CardId.KashtiraShangriIra)) cardsid.Add(CardId.KashtiraShangriIra); + cardsid.AddRange(new List() { CardId.KashtiraBigBang, CardId.KashtiraUnicorn, CardId.KashtiraFenrir, CardId.KashtiraRiseheart, CardId.KashtiraScareclaw, CardId.KashtiraTearlaments }); + AI.SelectCard(cardsid); + active_KashtiraPapiyas_2 = true; + return true; + } + else + { + AI.SelectCard(CardId.KashtiraFenrir); + List cardsid = new List(); + DefaultAddCardId(cardsid); + cardsid.AddRange(new List() { CardId.KashtiraUnicorn, CardId.KashtiraFenrir, CardId.KashtiraRiseheart, CardId.KashtiraScareclaw, CardId.KashtiraTearlaments }); + AI.SelectNextCard(cardsid); + if (Card.Location == CardLocation.Hand) + { + AI.SelectPlace(SelectSTPlace(Card, true)); + } + active_KashtiraPapiyas_1 = true; + onlyXyzSummon = true; + return true; + } + } + private bool KashtiraPapiyasEffect() + { + if (link_mode) return false; + return KashtiraPapiyasEffect_2(); + } + private bool SelectEnemyCard(bool faceUp = true, bool isXyz= false) + { + ClientCard card = Util.GetLastChainCard(); + if (card != null && card.Controller == 1 && card.IsFaceup() && (card.HasType(CardType.Monster) + || card.HasType(CardType.Continuous) || card.HasType(CardType.Equip) || card.HasType(CardType.Field)) + && (card.Location & CardLocation.Onfield)>0 && !card.IsShouldNotBeTarget()) + { AI.SelectCard(card);if (isXyz)AI.SelectNextCard(card); return true; } + if (GetEnemyOnFields().Count(_card => _card != null && !_card.IsShouldNotBeTarget() && !(faceUp & !_card.IsFaceup()) && !_card.HasType(CardType.Token)) <= 0) return false; + ClientCard dcard = GetEnemyOnFields().GetDangerousMonster(true); + if (Duel.Phase >= DuelPhase.BattleStart || Util.GetBestAttack(Enemy) >= Util.GetBestAttack(Bot) || dcard != null) + { + if (dcard != null) { AI.SelectCard(dcard); if(isXyz)AI.SelectNextCard(dcard) ; return true; } + List cards = GetEnemyOnFields().Where(_card => _card != null && !_card.IsShouldNotBeTarget() && !(!_card.IsFaceup() & faceUp)).ToList(); + cards.Sort(CardContainer.CompareCardAttack); + cards.Reverse(); + if (cards.Count <= 0) return false; + AI.SelectCard(cards); + if (isXyz) AI.SelectNextCard(cards); + return true; + } + return false; + } + private bool KashtiraFenrirEffect() + { + if (Card.IsDisabled()) return false; + if (ActivateDescription == Util.GetStringId(CardId.KashtiraFenrir, 1)) + { + IList cardsId = new List(); + if ((!Bot.HasInHandOrInSpellZone(CardId.KashtiraBirth) || isSummoned) + && !Bot.HasInHand(CardId.KashtiraRiseheart) && (!activate_KashtiraRiseheart_2 && (!activate_KashtiraRiseheart_1 || !isSummoned)) && CheckRemainInDeck(CardId.KashtiraRiseheart) > 0) + cardsId.Add(CardId.KashtiraRiseheart); + if (Bot.HasInHandOrInSpellZone(CardId.KashtiraBirth) && !isSummoned && !Bot.HasInHand(CardId.KashtiraUnicorn) && !activate_KashtiraUnicorn_1 && CheckRemainInDeck(CardId.KashtiraUnicorn) > 0) + cardsId.Add(CardId.KashtiraUnicorn); + if (!Bot.HasInHand(CardId.KashtiraTearlaments) && !activate_KashtiraTearlaments_1 && CheckRemainInDeck(CardId.KashtiraTearlaments) > 0) + cardsId.Add(CardId.KashtiraTearlaments); + if (!Bot.HasInHand(CardId.KashtiraScareclaw) && !activate_KashtiraScareclaw_1 && CheckRemainInDeck(CardId.KashtiraScareclaw) > 0) + cardsId.Add(CardId.KashtiraScareclaw); + cardsId.Add(CardId.KashtiraUnicorn); + cardsId.Add(CardId.KashtiraRiseheart); + activate_KashtiraFenrir_1 = true; + AI.SelectCard(cardsId); + return true; + } + else + { + if (Duel.LastChainPlayer == 0 && Util.GetLastChainCard() != null && + Util.GetLastChainCard().Id == CardId.PrimePlanetParaisos) return false; + List cards = GetEnemyOnFields().Where(card => card != null && card.IsFaceup()).ToList(); + if (cards.Count > 0) + { + cards.Sort(CardContainer.CompareCardAttack); + cards.Reverse(); + AI.SelectCard(cards); + } + return true; + } + } + + private bool TerraformingEffect() + { + if (Card.Location == CardLocation.Hand) + { + AI.SelectPlace(SelectSTPlace(Card, true)); + } + return true; + } + + private bool PotofProsperityEffect() + { + if (Bot.ExtraDeck.Count <= 3) return false; + List cardsId = new List(); + if (!Bot.HasInHandOrInSpellZone(CardId.PrimePlanetParaisos) && !activate_PrimePlanetParaisos) + cardsId.Add(CardId.PrimePlanetParaisos); + if (!Bot.HasInHandOrInSpellZone(CardId.PrimePlanetParaisos) && !activate_PrimePlanetParaisos && CheckRemainInDeck(CardId.PrimePlanetParaisos) > 0) + cardsId.Add(CardId.Terraforming); + if (!Bot.HasInHand(CardId.KashtiraUnicorn) && !activate_KashtiraUnicorn_1) + cardsId.Add(CardId.KashtiraUnicorn); + if(!Bot.HasInHand(CardId.KashtiraFenrir) && !activate_KashtiraFenrir_1) + cardsId.Add(CardId.KashtiraFenrir); + if (!Bot.HasInHand(CardId.KashtiraPapiyas) && !active_KashtiraPapiyas_1) + cardsId.Add(CardId.KashtiraPapiyas); + if (!Bot.HasInHand(CardId.KashtiraRiseheart) && !activate_KashtiraRiseheart_2) + cardsId.Add(CardId.KashtiraRiseheart); + if(!Bot.HasInHandOrInSpellZone(CardId.KashtiraBirth)) + cardsId.Add(CardId.KashtiraBirth); + if(!Bot.HasInHand(CardId.KashtiraScareclaw) && !activate_KashtiraScareclaw_1) + cardsId.Add(CardId.KashtiraScareclaw); + if(!Bot.HasInHand(CardId.KashtiraTearlaments) && !activate_KashtiraTearlaments_1) + cardsId.Add(CardId.KashtiraTearlaments); + if (Bot.HasInExtra(CardId.ThunderDragonColossus) && Bot.Banished.Count(card=>card!=null && card.IsFaceup() && card.HasType(CardType.Monster))>0) + cardsId.Add(CardId.NemesesCorridor); + if (!Bot.HasInHand(CardId.G)) + cardsId.Add(CardId.G); + if (!Bot.HasInHand(CardId.AshBlossom)) + cardsId.Add(CardId.AshBlossom); + cardsId.AddRange(new List() { CardId.CrossoutDesignator, CardId.CalledbytheGrave, CardId.Nibiru, CardId.InfiniteImpermanence }); + if (Card.Location == CardLocation.Hand) + { + AI.SelectPlace(SelectSTPlace(Card, true)); + } + AI.SelectCard(cardsId); + return true; + } + private bool KashtiraRiseheartEffect_2() + { + if (Card.Location != CardLocation.Hand) + { + if (CheckRemainInDeck(CardId.KashtiraBigBang) > 0 && Bot.GetMonsters().GetMatchingCards(card => card != null && card.HasType(CardType.Xyz) + && card.HasSetcode(0x189) && card.IsFaceup() && card.Overlays.Count > 0).Count > 0) + { + AI.SelectCard(CardId.KashtiraBigBang); + } + else if (Bot.HasInHandOrInSpellZone(CardId.KashtiraBirth) && !active_KashtiraBirth) + { + if (!Bot.HasInGraveyardOrInBanished(CardId.KashtiraUnicorn) && !activate_KashtiraUnicorn_1 + && CheckRemainInDeck(CardId.KashtiraUnicorn) > 0 && !active_KashtiraPapiyas_1 + && !Bot.HasInHand(CardId.KashtiraPapiyas) && CheckRemainInDeck(CardId.KashtiraPapiyas) > 0) + AI.SelectCard(CardId.KashtiraUnicorn); + else if (!Bot.HasInGraveyardOrInBanished(CardId.KashtiraFenrir) && !activate_KashtiraFenrir_1 + && CheckRemainInDeck(CardId.KashtiraFenrir) > 0) + AI.SelectCard(CardId.KashtiraFenrir); + else if (!Bot.HasInGraveyardOrInBanished(CardId.KashtiraUnicorn) && !activate_KashtiraUnicorn_1 + && CheckRemainInDeck(CardId.KashtiraUnicorn) > 0) + AI.SelectCard(CardId.KashtiraFenrir); + else if (Bot.Graveyard.Count(card => card != null && card.HasType(CardType.Monster) && card.HasSetcode(0x189) && !card.HasType(CardType.Xyz)) + + Bot.Banished.Count(card_2 => card_2 != null && card_2.HasType(CardType.Monster) && card_2.HasSetcode(0x189) && !card_2.HasType(CardType.Xyz)) <= 0) + AI.SelectCard(CardId.KashtiraFenrir, CardId.KashtiraUnicorn, CardId.KashtiraScareclaw, CardId.KashtiraTearlaments, CardId.KashtiraRiseheart); + else + AI.SelectCard(CardId.KashtiraFenrir, CardId.KashtiraUnicorn, CardId.KashtiraScareclaw, CardId.KashtiraTearlaments, CardId.KashtiraRiseheart); + } + else if (Bot.HasInHand(CardId.NemesesCorridor) && !active_NemesesCorridor && + Bot.Banished.Count(card_2 => card_2 != null && card_2.HasType(CardType.Monster)) <= 0 && Bot.HasInExtra(CardId.ThunderDragonColossus)) + { + AI.SelectCard(CardId.KashtiraFenrir, CardId.KashtiraUnicorn, CardId.KashtiraScareclaw, CardId.KashtiraTearlaments, CardId.KashtiraRiseheart); + } + else if (!active_KashtiraPapiyas_2 && CheckRemainInDeck(CardId.KashtiraPapiyas) > 0 && Bot.Banished.GetMatchingCardsCount(card => card != null && card.IsFaceup() && card.HasSetcode(0x189) && card.Id != CardId.KashtiraPapiyas) > 0) + { + AI.SelectCard(CardId.KashtiraPapiyas, CardId.KashtiraFenrir, CardId.KashtiraUnicorn, CardId.KashtiraScareclaw, CardId.KashtiraTearlaments, CardId.KashtiraRiseheart); + } + else + { + AI.SelectCard(CardId.KashtiraFenrir, CardId.KashtiraUnicorn, CardId.KashtiraScareclaw, CardId.KashtiraTearlaments, CardId.KashtiraRiseheart); + } + activate_KashtiraRiseheart_2 = true; + return true; + } + return false; + } + private bool KashtiraRiseheartEffect() + { + if (Card.Location == CardLocation.Hand) + { + activate_KashtiraRiseheart_1 = true; + onlyXyzSummon = true; + return true; + } + return false; + } + private bool KashtiraBirthEffect() + { + if ((Card.Location == CardLocation.Hand || (Card.Location==CardLocation.SpellZone && Card.IsFacedown())) + && !Bot.HasInSpellZone(CardId.KashtiraBirth, true, true)) + { + if (Card.Location == CardLocation.Hand) + { + AI.SelectPlace(SelectSTPlace(Card, true)); + } + return true; + } + return false; + } + private bool KashtiraBirthEffect_2() + { + if (link_mode) return false; + return KashtiraBirthEffect_3(); + } + private bool KashtiraBirthEffect_3() + { + if (Card.Location == CardLocation.Hand || (Card.Location == CardLocation.SpellZone && Card.IsFacedown())) return false; + List cardsid = new List(); + if (!activate_KashtiraUnicorn_1 && !active_KashtiraPapiyas_1 && (Bot.HasInHand(CardId.KashtiraPapiyas) || CheckRemainInDeck(CardId.KashtiraPapiyas) > 0)) cardsid.Add(CardId.KashtiraPapiyas); + if (!activate_KashtiraFenrir_1) cardsid.Add(CardId.KashtiraFenrir); + if (!activate_KashtiraUnicorn_1) cardsid.Add(CardId.KashtiraUnicorn); + if (!activate_KashtiraRiseheart_2) cardsid.Add(CardId.KashtiraRiseheart); + cardsid.Add(CardId.KashtiraFenrir); + cardsid.Add(CardId.KashtiraUnicorn); + cardsid.Add(CardId.KashtiraTearlaments); + cardsid.Add(CardId.KashtiraScareclaw); + cardsid.Add(CardId.KashtiraRiseheart); + AI.SelectCard(cardsid); + return true; + } + private bool KashtiraUnicornEffect() + { + if (Card.IsDisabled()) return false; + if (ActivateDescription == Util.GetStringId(CardId.KashtiraUnicorn, 1)) + { + if ((!Bot.HasInHand(CardId.KashtiraPapiyas) && !active_KashtiraPapiyas_1) + ||(Bot.HasInHandOrInSpellZone(CardId.KashtiraBirth) && !Bot.HasInHand(CardId.KashtiraPapiyas))) + AI.SelectCard(CardId.KashtiraPapiyas, CardId.KashtiraBirth); + else + AI.SelectCard(CardId.KashtiraBirth, CardId.KashtiraPapiyas); + activate_KashtiraUnicorn_1 = true; + return true; + } + else + { + return true; + } + } + } + +} diff --git a/libWindbot/Game/AI/Decks/SwordsoulExecutor.cs b/libWindbot/Game/AI/Decks/SwordsoulExecutor.cs new file mode 100644 index 0000000..e9a967f --- /dev/null +++ b/libWindbot/Game/AI/Decks/SwordsoulExecutor.cs @@ -0,0 +1,3118 @@ +using YGOSharp.OCGWrapper.Enums; +using System.Collections.Generic; +using System.Linq; +using System; + +namespace WindBot.Game.AI.Decks +{ + [Deck("Swordsoul", "AI_Swordsoul")] + + public class SwordsoulExecutor : DefaultExecutor + { + public class CardId + { + public const int NibiruThePrimalBeing = 27204311; + public const int TenyiSpirit_Ashuna = 87052196; + public const int TenyiSpirit_Vishuda = 23431858; + public const int SwordsoulStrategistLongyuan = 93490856; + public const int SwordsoulOfTaia = 56495147; + public const int SwordsoulOfMoYe = 20001443; + public const int IncredibleEcclesiaTheVirtuous = 55273560; + // _CardId.AshBlossom = 14558127; + // _CardId.MaxxC = 23434538; + // _CardId.EffectVeiler = 97268402; + public const int TenyiSpirit_Adhara = 98159737; + + // _CardId.PotOfDesires = 35261759; + public const int SwordsoulEmergence = 56465981; + public const int SwordsoulSacredSummit = 93850690; + // _CardId.CalledByTheGrave = 24224830; + public const int CrossoutDesignator = 65681983; + + // _CardId.InfiniteImpermanence = 10045474; + public const int SwordsoulBlackout = 14821890; + + public const int GeomathmechFinalSigma = 42632209; + public const int PsychicEndPunisher = 60465049; + public const int SwordsoulSupremeSovereign_Chengying = 96633955; + public const int BaronneDeFleur = 84815190; + public const int SwordsoulSinisterSovereign_QixingLongyuan = 47710198; + public const int AdamancipatorRisen_Dragite = 9464441; + public const int DracoBerserkerOfTheTenyi = 5041348; + public const int SwordsoulGrandmaster_Chixiao = 69248256; + public const int BaxiaBrightnessOfTheYangZing = 83755611; + public const int YaziEvilOfTheYangZing = 43202238; + public const int ShamanOfTheTenyi = 78917791; + public const int MonkOfTheTenyi = 32519092; + + public const int SwordsoulToken = 20001444; + + public const int NaturalExterio = 99916754; + public const int NaturalBeast = 33198837; + public const int ImperialOrder = 61740673; + public const int SwordsmanLV7 = 37267041; + public const int RoyalDecree = 51452091; + public const int Number41BagooskatheTerriblyTiredTapir = 90590303; + public const int InspectorBoarder = 15397015; + } + + public SwordsoulExecutor(GameAI ai, Duel duel) + : base(ai, duel) + { + // startup effect + AddExecutor(ExecutorType.Activate, CardId.BaxiaBrightnessOfTheYangZing, BaxiaBrightnessOfTheYangZingActivate); + AddExecutor(ExecutorType.Activate, CardId.YaziEvilOfTheYangZing, YaziEvilOfTheYangZingActivate); + AddExecutor(ExecutorType.Activate, CardId.IncredibleEcclesiaTheVirtuous, IncredibleEcclesiaTheVirtuousActivate); + + // quick effect + AddExecutor(ExecutorType.Activate, _CardId.CalledByTheGrave, CalledbytheGraveActivate); + AddExecutor(ExecutorType.Activate, CardId.CrossoutDesignator, CrossoutDesignatorActivate); + AddExecutor(ExecutorType.Activate, _CardId.AshBlossom, AshBlossomActivate); + AddExecutor(ExecutorType.Activate, CardId.SwordsoulGrandmaster_Chixiao, SwordsoulGrandmaster_ChixiaoActivate); + AddExecutor(ExecutorType.Activate, _CardId.EffectVeiler, EffectVeilerActivate); + AddExecutor(ExecutorType.Activate, _CardId.InfiniteImpermanence, InfiniteImpermanenceActivate); + AddExecutor(ExecutorType.Activate, CardId.SwordsoulSinisterSovereign_QixingLongyuan, SwordsoulSinisterSovereign_QixingLongyuanActivate); + AddExecutor(ExecutorType.Activate, CardId.DracoBerserkerOfTheTenyi, DracoBerserkerOfTheTenyiActivate); + AddExecutor(ExecutorType.Activate, CardId.AdamancipatorRisen_Dragite, AdamancipatorRisen_DragiteActivate); + AddExecutor(ExecutorType.Activate, CardId.BaronneDeFleur, BaronneDeFleurActivate); + AddExecutor(ExecutorType.Activate, CardId.SwordsoulSupremeSovereign_Chengying, SwordsoulSupremeSovereign_ChengyingActivate); + + // free chain + AddExecutor(ExecutorType.Activate, _CardId.MaxxC, MaxxCActivate); + AddExecutor(ExecutorType.Activate, CardId.NibiruThePrimalBeing, NibiruThePrimalBeingActivate); + + // startup effect + AddExecutor(ExecutorType.Activate, CardId.SwordsoulEmergence, SwordsoulEmergenceActivate); + AddExecutor(ExecutorType.Activate, CardId.SwordsoulBlackout, SwordsoulBlackoutActivate); + + // synchro + AddExecutor(ExecutorType.SpSummon, CardId.YaziEvilOfTheYangZing, YaziEvilOfTheYangZingSpSummon); + AddExecutor(ExecutorType.SpSummon, CardId.BaxiaBrightnessOfTheYangZing, BaxiaBrightnessOfTheYangZingSpSummon); + AddExecutor(ExecutorType.SpSummon, CardId.SwordsoulGrandmaster_Chixiao, SwordsoulGrandmaster_ChixiaoSpSummon); + AddExecutor(ExecutorType.SpSummon, CardId.AdamancipatorRisen_Dragite, AdamancipatorRisen_DragiteSpSummon); + AddExecutor(ExecutorType.SpSummon, CardId.DracoBerserkerOfTheTenyi, DracoBerserkerOfTheTenyiSpSummon); + + AddExecutor(ExecutorType.SpSummon, Level10SpSummonCheckInit); + AddExecutor(ExecutorType.SpSummon, Level10SpSummonCheckCount); + AddExecutor(ExecutorType.SpSummon, Level10SpSummonCheckDecide); + AddExecutor(ExecutorType.SpSummon, Level10SpSummonCheckFinal); + + // startup effect + AddExecutor(ExecutorType.Activate, CardId.SwordsoulOfMoYe, SwordsoulOfMoYeActivate); + AddExecutor(ExecutorType.Activate, CardId.SwordsoulOfTaia, SwordsoulOfTaiaActivate); + + // summon + AddExecutor(ExecutorType.Activate, TenyiForShamanSpSummon); + AddExecutor(ExecutorType.SpSummon, CardId.IncredibleEcclesiaTheVirtuous, IncredibleEcclesiaTheVirtuousSpSummon); + AddExecutor(ExecutorType.Summon, CardId.SwordsoulOfMoYe, SwordsoulOfMoYeSummon); + AddExecutor(ExecutorType.Summon, CardId.IncredibleEcclesiaTheVirtuous, IncredibleEcclesiaTheVirtuousSummon); + AddExecutor(ExecutorType.Summon, CardId.SwordsoulOfTaia, SwordsoulOfTaiaSummon); + + // activate + AddExecutor(ExecutorType.Activate, CardId.SwordsoulStrategistLongyuan, SwordsoulStrategistLongyuanActivate); + AddExecutor(ExecutorType.Activate, _CardId.PotOfDesires, PotOfDesiresActivate); + AddExecutor(ExecutorType.Activate, CardId.ShamanOfTheTenyi, ShamanOfTheTenyiActivate); + AddExecutor(ExecutorType.Activate, CardId.SwordsoulSacredSummit, SwordsoulSacredSummitActivate); + AddExecutor(ExecutorType.Activate, CardId.TenyiSpirit_Vishuda, TenyiSpirit_VishudaActivate); + AddExecutor(ExecutorType.Activate, CardId.TenyiSpirit_Ashuna, TenyiSpirit_AshunaActivate); + AddExecutor(ExecutorType.Activate, CardId.TenyiSpirit_Adhara, TenyiSpirit_AdharaActivate); + AddExecutor(ExecutorType.Activate, TenyiForBlackoutSpSummon); + + // other + AddExecutor(ExecutorType.SpSummon, CardId.GeomathmechFinalSigma, GeomathmechFinalSigmaSpSummon); + AddExecutor(ExecutorType.SpSummon, CardId.PsychicEndPunisher, PsychicEndPunisherSpSummon); + AddExecutor(ExecutorType.Summon, TunerForSynchroSummon); + AddExecutor(ExecutorType.Summon, WyrmForBlackoutSummon); + AddExecutor(ExecutorType.SpSummon, CardId.ShamanOfTheTenyi, ShamanOfTheTenyiSpSummon); + AddExecutor(ExecutorType.SpSummon, CardId.MonkOfTheTenyi, MonkOfTheTenyiSpSummon); + AddExecutor(ExecutorType.Repos, DefaultMonsterRepos); + + AddExecutor(ExecutorType.Activate, CardId.PsychicEndPunisher, PsychicEndPunisherActivate); + AddExecutor(ExecutorType.SpellSet, SpellSetCheck); + } + + const int SetcodeTimeLord = 0x4a; + const int SetcodeYangZing = 0x9e; + const int SetcodePhantom = 0xdb; + const int SetcodeOrcust = 0x11b; + const int SetcodeTenyi = 0x12c; + const int SetcodeSwordsoul = 0x16b; + const int SetcodeFloowandereeze = 0x16d; + List normalCounterList = new List + { + _CardId.AshBlossom, CardId.BaronneDeFleur, 27548199, 4280258, 53262004 + }; + List notToNegateIdList = new List{ + 58699500 + }; + const int hintTimingMainEnd = 0x4; + const int hintReplaceDestroy = 96; + + Dictionary> DeckCountTable = new Dictionary>{ + {3, new List { CardId.SwordsoulStrategistLongyuan, CardId.SwordsoulOfTaia, CardId.SwordsoulOfMoYe, CardId.IncredibleEcclesiaTheVirtuous, + _CardId.AshBlossom, _CardId.MaxxC, _CardId.EffectVeiler, CardId.SwordsoulEmergence, _CardId.InfiniteImpermanence }}, + {2, new List { CardId.TenyiSpirit_Ashuna, _CardId.PotOfDesires, _CardId.CalledByTheGrave, CardId.SwordsoulBlackout }}, + {1, new List { CardId.NibiruThePrimalBeing, CardId.TenyiSpirit_Vishuda, CardId.TenyiSpirit_Adhara, CardId.SwordsoulSacredSummit, + CardId.CrossoutDesignator }}, + }; + + Dictionary calledbytheGraveCount = new Dictionary(); + List CrossoutDesignatorTargetList = new List(); + bool enemyActivateMaxxC = false; + bool enemyActivateLockBird = false; + List infiniteImpermanenceList = new List(); + + bool summoned = false; + bool onlyWyrmSpSummon = false; + List activatedCardIdList = new List(); + List canSpSummonLevel10IdList = new List(); + + List effectUsedBaronneDeFleurList = new List(); + List currentNegateMonsterList = new List(); + + /// + /// Shuffle List and return a random-order card list + /// + public List ShuffleCardList(List list) + { + List result = list; + int n = result.Count; + while (n-- > 1) + { + int index = Program.Rand.Next(result.Count); + int nextIndex = (index + Program.Rand.Next(result.Count - 1)) % result.Count; + ClientCard tempCard = result[index]; + result[index] = result[nextIndex]; + result[nextIndex] = tempCard; + } + return result; + } + + public ClientCard GetProblematicEnemyMonster(int attack = 0, bool canBeTarget = false) + { + List floodagateList = Enemy.GetMonsters().Where(c => c?.Data != null && + c.IsFloodgate() && c.IsFaceup() && (!canBeTarget || !c.IsShouldNotBeTarget())).ToList(); + if (floodagateList.Count() > 0) + { + floodagateList.Sort(CardContainer.CompareCardAttack); + floodagateList.Reverse(); + return floodagateList[0]; + } + + List dangerList = Enemy.MonsterZone.Where(c => c?.Data != null && + c.IsMonsterDangerous() && c.IsFaceup() && (!canBeTarget || !c.IsShouldNotBeTarget())).ToList(); + if (dangerList.Count() > 0) + { + dangerList.Sort(CardContainer.CompareCardAttack); + dangerList.Reverse(); + return dangerList[0]; + } + + List invincibleList = Enemy.MonsterZone.Where(c => c?.Data != null && + c.IsMonsterInvincible() && c.IsFaceup() && (!canBeTarget || !c.IsShouldNotBeTarget())).ToList(); + if (invincibleList.Count() > 0) + { + invincibleList.Sort(CardContainer.CompareCardAttack); + invincibleList.Reverse(); + return invincibleList[0]; + } + + if (attack == 0) + attack = Util.GetBestAttack(Bot); + List betterList = Enemy.MonsterZone.GetMonsters() + .Where(card => card.GetDefensePower() >= attack && card.IsAttack() && (!canBeTarget || !card.IsShouldNotBeTarget())).ToList(); + if (betterList.Count() > 0) + { + betterList.Sort(CardContainer.CompareCardAttack); + betterList.Reverse(); + return betterList[0]; + } + return null; + } + + public List GetProblematicEnemyCardList(bool canBeTarget = false, bool ignoreNormalSpell = false) + { + List resultList = new List(); + + List floodagateList = Enemy.MonsterZone.Where(c => c?.Data != null + && c.IsFloodgate() && c.IsFaceup() && (!canBeTarget || !c.IsShouldNotBeTarget())).ToList(); + if (floodagateList.Count() > 0) + { + floodagateList.Sort(CardContainer.CompareCardAttack); + floodagateList.Reverse(); + resultList.AddRange(floodagateList); + } + + List problemEnemySpellList = Enemy.SpellZone.Where(c => c?.Data != null && !resultList.Contains(c) + && c.IsFloodgate() && c.IsFaceup() && (!canBeTarget || !c.IsShouldNotBeTarget())).ToList(); + if (problemEnemySpellList.Count() > 0) + { + resultList.AddRange(ShuffleCardList(problemEnemySpellList)); + } + + List dangerList = Enemy.MonsterZone.Where(c => c?.Data != null && !resultList.Contains(c) + && c.IsMonsterDangerous() && c.IsFaceup() && (!canBeTarget || !c.IsShouldNotBeTarget())).ToList(); + if (dangerList.Count() > 0 + && (Duel.Player == 0 || (Duel.Phase > DuelPhase.Main1 && Duel.Phase < DuelPhase.Main2))) + { + dangerList.Sort(CardContainer.CompareCardAttack); + dangerList.Reverse(); + resultList.AddRange(dangerList); + } + + List invincibleList = Enemy.MonsterZone.Where(c => c?.Data != null && !resultList.Contains(c) + && c.IsMonsterInvincible() && c.IsFaceup() && (!canBeTarget || !c.IsShouldNotBeTarget())).ToList(); + if (invincibleList.Count() > 0) + { + invincibleList.Sort(CardContainer.CompareCardAttack); + invincibleList.Reverse(); + resultList.AddRange(invincibleList); + } + + List enemyMonsters = Enemy.GetMonsters().ToList(); + if (enemyMonsters.Count() > 0) + { + enemyMonsters.Sort(CardContainer.CompareCardAttack); + enemyMonsters.Reverse(); + foreach(ClientCard target in enemyMonsters) + { + if (target.HasType(CardType.Fusion | CardType.Ritual | CardType.Synchro | CardType.Xyz) + || (target.HasType(CardType.Link) && target.LinkCount >= 2) ) + { + if (!canBeTarget || !(target.IsShouldNotBeTarget() || target.IsShouldNotBeMonsterTarget())) + { + if (!resultList.Contains(target)) + { + resultList.Add(target); + } + } + } + } + } + + List spells = Enemy.GetSpells().Where(c => c.IsFaceup() + && c.HasType(CardType.Equip | CardType.Pendulum | CardType.Field | CardType.Continuous)).ToList(); + if (spells.Count() > 0 && !ignoreNormalSpell) + { + resultList.AddRange(ShuffleCardList(spells)); + } + + return resultList; + } + + public ClientCard GetBestEnemyMonster(bool onlyFaceup = false, bool canBeTarget = false) + { + ClientCard card = GetProblematicEnemyMonster(0, canBeTarget); + if (card != null) + return card; + + card = Enemy.MonsterZone.GetHighestAttackMonster(canBeTarget); + if (card != null) + return card; + + List monsters = Enemy.GetMonsters(); + + // after GetHighestAttackMonster, the left monsters must be face-down. + if (monsters.Count() > 0 && !onlyFaceup) + return ShuffleCardList(monsters)[0]; + + return null; + } + + public ClientCard GetBestEnemySpell(bool onlyFaceup = false, bool canBeTarget = false) + { + List problemEnemySpellList = Enemy.SpellZone.Where(c => c?.Data != null + && c.IsFloodgate() && c.IsFaceup() && (!canBeTarget || !c.IsShouldNotBeTarget())).ToList(); + if (problemEnemySpellList.Count() > 0) + { + return ShuffleCardList(problemEnemySpellList)[0]; + } + + List spells = Enemy.GetSpells().Where(card => !(card.IsFaceup() && card.IsCode(_CardId.EvenlyMatched))).ToList(); + + List faceUpList = spells.Where(ecard => ecard.IsFaceup() && + ecard.HasType(CardType.Equip | CardType.Pendulum | CardType.Field | CardType.Continuous)).ToList(); + if (faceUpList.Count() > 0) + { + return ShuffleCardList(faceUpList)[0]; + } + + if (spells.Count() > 0 && !onlyFaceup) + { + return ShuffleCardList(spells)[0]; + } + + return null; + } + + public ClientCard GetBestEnemyCard(bool onlyFaceup = false, bool canBeTarget = false, bool checkGrave = false) + { + ClientCard card = GetBestEnemyMonster(onlyFaceup, canBeTarget); + if (card != null) + { + return card; + } + + card = GetBestEnemySpell(onlyFaceup, canBeTarget); + if (card != null) + { + return card; + } + + if (checkGrave && Enemy.Graveyard.Count() > 0) + { + List graveMonsterList = Enemy.Graveyard.GetMatchingCards(c => c.IsMonster()).ToList(); + if (graveMonsterList.Count() > 0) + { + graveMonsterList.Sort(CardContainer.CompareCardAttack); + graveMonsterList.Reverse(); + return graveMonsterList[0]; + } + return ShuffleCardList(Enemy.Graveyard.ToList())[0]; + } + + return null; + } + + public List GetNormalEnemyTargetList(bool canBeTarget = true) + { + List targetList = GetProblematicEnemyCardList(canBeTarget); + List enemyMonster = Enemy.GetMonsters().Where(card => card.IsFaceup() && !targetList.Contains(card)).ToList(); + enemyMonster.Sort(CardContainer.CompareCardAttack); + enemyMonster.Reverse(); + targetList.AddRange(enemyMonster); + targetList.AddRange(ShuffleCardList(Enemy.GetSpells())); + targetList.AddRange(ShuffleCardList(Enemy.GetMonsters().Where(card => card.IsFacedown()).ToList())); + + return targetList; + } + + public List GetMonsterListForTargetNegate(bool canBeMonsterTarget = false, bool canBeTrapTarget = false) + { + List resultList = new List(); + if (CheckWhetherNegated(true)) + { + return resultList; + } + + // negate before used + ClientCard target = Enemy.MonsterZone.FirstOrDefault(card => card?.Data != null + && card.IsMonsterShouldBeDisabledBeforeItUseEffect() && card.IsFaceup() && !card.IsShouldNotBeTarget() + && (!canBeMonsterTarget || !card.IsShouldNotBeMonsterTarget()) && (!canBeTrapTarget || !card.IsShouldNotBeSpellTrapTarget()) + && !currentNegateMonsterList.Contains(card)); + if (target != null) + { + resultList.Add(target); + } + + // negate monster effect on the field + foreach (ClientCard chainingCard in Duel.CurrentChain) + { + if (chainingCard.Location == CardLocation.MonsterZone && chainingCard.Controller == 1 && !chainingCard.IsDisabled() + && (!canBeMonsterTarget || !chainingCard.IsShouldNotBeMonsterTarget()) && (!canBeTrapTarget || !chainingCard.IsShouldNotBeSpellTrapTarget()) + && !chainingCard.IsShouldNotBeTarget() && !currentNegateMonsterList.Contains(chainingCard)) + { + resultList.Add(chainingCard); + } + } + + return resultList; + } + + /// + /// Check whether negate opposite's effect and clear flag + /// + public void CheckDeactiveFlag() + { + ClientCard lastChainCard = Util.GetLastChainCard(); + if (lastChainCard != null && Duel.LastChainPlayer == 1) + { + if (lastChainCard.IsCode(_CardId.MaxxC)) + { + enemyActivateMaxxC = false; + } + if (lastChainCard.IsCode(_CardId.LockBird)) + { + enemyActivateLockBird = false; + } + if (lastChainCard.IsCode(_CardId.CalledByTheGrave) && !CrossoutDesignatorTargetList.Contains(_CardId.CalledByTheGrave)) + { + foreach (ClientCard target in Duel.LastChainTargets) + { + if (target.IsMonster() && target.Controller == 0 && target.Location == CardLocation.Grave) + { + calledbytheGraveCount[target.Id] = 0; + } + } + } + if (lastChainCard.Controller == 1 && lastChainCard.Location == CardLocation.MonsterZone) + { + currentNegateMonsterList.Add(lastChainCard); + } + } + } + + /// + /// Check negated turn count of id + /// + public int CheckCalledbytheGrave(int id) + { + if (!calledbytheGraveCount.ContainsKey(id)) + { + return 0; + } + return calledbytheGraveCount[id]; + } + + /// + /// Check remain cards in deck + /// + /// Card's ID + public int CheckRemainInDeck(int id) + { + for (int count = 1; count < 4; ++count) + { + if (DeckCountTable[count].Contains(id)) { + return Bot.GetRemainingCount(id, count); + } + } + return 0; + } + + /// + /// Whether spell or trap will be negate. If so, return true. + /// + /// is counter trap + /// check target + /// + public bool CheckSpellWillBeNegate(bool isCounter = false, ClientCard target = null) + { + // target default set + if (target == null) target = Card; + // won't negate if not on field + if (target.Location != CardLocation.SpellZone && target.Location != CardLocation.Hand) return false; + + // negate judge + if (Enemy.HasInMonstersZone(CardId.NaturalExterio, true) && !isCounter) return true; + if (target.IsSpell()) + { + if (Enemy.HasInMonstersZone(CardId.NaturalBeast, true)) return true; + if (Enemy.HasInSpellZone(CardId.ImperialOrder, true) || Bot.HasInSpellZone(CardId.ImperialOrder, true)) return true; + if (Enemy.HasInMonstersZone(CardId.SwordsmanLV7, true) || Bot.HasInMonstersZone(CardId.SwordsmanLV7, true)) return true; + } + if (target.IsTrap()) + { + if (Enemy.HasInSpellZone(CardId.RoyalDecree, true) || Bot.HasInSpellZone(CardId.RoyalDecree, true)) return true; + } + if (target.Location == CardLocation.SpellZone && (target.IsSpell() || target.IsTrap())) + { + int selfSeq = -1; + for (int i = 0; i < 5; ++i) + { + if (Bot.SpellZone[i] == Card) selfSeq = i; + } + if (infiniteImpermanenceList.Contains(selfSeq)) { + return true; + } + } + // how to get here? + return false; + } + + /// + /// Check whether'll be negated + /// + /// check whether card itself is disabled. + public bool CheckWhetherNegated(bool disablecheck = true) + { + if ((Card.IsSpell() || Card.IsTrap()) && CheckSpellWillBeNegate()){ + return true; + } + if (CheckCalledbytheGrave(Card.Id) > 0 || CrossoutDesignatorTargetList.Contains(Card.Id)){ + return true; + } + if (Card.IsMonster() && Card.Location == CardLocation.MonsterZone && Card.IsDefense()) + { + if (Enemy.MonsterZone.Any(card => CheckNumber41(card)) || Bot.MonsterZone.Any(card => CheckNumber41(card))) + { + return true; + } + } + if (disablecheck){ + return Card.IsDisabled(); + } + return false; + } + + public bool CheckNumber41(ClientCard card) + { + return card != null && card.IsFaceup() && card.IsCode(CardId.Number41BagooskatheTerriblyTiredTapir) && card.IsDefense() && !card.IsDisabled(); + } + + /// + /// Check whether bot is at advantage. + /// + public bool CheckAtAdvantage() + { + if (GetProblematicEnemyMonster() == null && + (Bot.GetMonsters().Any(card => card.IsFaceup()) || (Duel.Player == 0 && Duel.Turn == 1))) + { + return true; + } + return false; + } + + /// + /// Check whether last chain card should be disabled. + /// + public bool CheckLastChainShouldNegated() + { + ClientCard lastcard = Util.GetLastChainCard(); + if (lastcard == null || lastcard.Controller != 1) return false; + if (lastcard.IsMonster() && lastcard.HasSetcode(SetcodeTimeLord) && Duel.Phase == DuelPhase.Standby) return false; + if (notToNegateIdList.Contains(lastcard.Id)) return false; + if (Duel.CurrentChain.Count >= 2) + { + ClientCard lastlastChainCard = Duel.CurrentChain[Duel.CurrentChain.Count - 2]; + ClientCard lastChainCard = Duel.CurrentChain[Duel.CurrentChain.Count - 1]; + if (lastlastChainCard?.Controller == 0 && lastChainCard?.Controller == 1 && lastChainCard.IsCode(normalCounterList)) + { + bool notImportantFlag = lastlastChainCard.Location == CardLocation.Grave + && (lastlastChainCard.IsCode(CardId.SwordsoulOfTaia) || lastlastChainCard.IsCode(CardId.SwordsoulOfMoYe) || lastlastChainCard.IsCode(CardId.SwordsoulStrategistLongyuan)); + notImportantFlag |= lastlastChainCard.IsCode(CardId.PsychicEndPunisher) && Bot.LifePoints < Enemy.LifePoints; + if (notImportantFlag) + { + return false; + } + } + } + + return true; + } + + /// + /// check enemy's dangerous card in grave + /// + public List CheckDangerousCardinEnemyGrave(bool onlyMonster = false) + { + List result = Enemy.Graveyard.GetMatchingCards(card => + (!onlyMonster || card.IsMonster()) && (card.HasSetcode(SetcodeOrcust) || card.HasSetcode(SetcodePhantom))).ToList(); + List dangerMonsterIdList = new List{ + 99937011, 63542003, CardId.TenyiSpirit_Adhara, CardId.TenyiSpirit_Ashuna, CardId.TenyiSpirit_Vishuda, + 9411399, 28954097, 30680659 + }; + return result; + } + + /// + /// go first + /// + public override bool OnSelectHand() + { + return true; + } + + public override int OnSelectPlace(int cardId, int player, CardLocation location, int available) + { + // Geomathmech Final Sigma always place on extra monster zone + if (cardId == CardId.GeomathmechFinalSigma && location == CardLocation.MonsterZone) + { + if ((Zones.z5 & available) > 0) return Zones.z5; + if ((Zones.z6 & available) > 0) return Zones.z6; + } + return base.OnSelectPlace(cardId, player, location, available); + } + + public override CardPosition OnSelectPosition(int cardId, IList positions) + { + YGOSharp.OCGWrapper.NamedCard cardData = YGOSharp.OCGWrapper.NamedCard.Get(cardId); + if (cardData != null) + { + if (cardData.Id == CardId.PsychicEndPunisher) + { + return CardPosition.FaceUpAttack; + } + if (Util.IsTurn1OrMain2()) + { + bool turnDefense = false; + if (!cardData.HasType(CardType.Synchro) || cardData.Attack <= cardData.Defense) + { + turnDefense = true; + } + if (turnDefense) + { + return CardPosition.FaceUpDefence; + } + } + if (Duel.Player == 1) + { + if (!cardData.HasType(CardType.Synchro) || cardData.Defense >= cardData.Attack || Util.IsOneEnemyBetterThanValue(cardData.Attack, true)) + { + return CardPosition.FaceUpDefence; + } + } else if (cardData.HasType(CardType.Synchro)) + { + return CardPosition.FaceUpAttack; + } + int bestBotAttack = Math.Max(Util.GetBestAttack(Bot), cardData.Attack); + if (Util.IsAllEnemyBetterThanValue(bestBotAttack, true)) + { + return CardPosition.FaceUpDefence; + } + } + return base.OnSelectPosition(cardId, positions); + } + + public override IList OnSelectCard(IList cards, int min, int max, int hint, bool cancelable) + { + if (Util.ChainContainPlayer(1) && hint == HintMsg.Remove && Duel.Phase > DuelPhase.Main1 && Duel.Phase < DuelPhase.Main2) + { + int botCount = Bot.GetMonsterCount() + Bot.GetSpellCount(); + int oppositeCount = Enemy.GetMonsterCount() + Enemy.GetSpellCount(); + if (botCount - oppositeCount == min && min == max) + { + Logger.DebugWriteLine("=== Evenly Matched activated."); + List banishList = new List(); + List botMonsters = Bot.GetMonsters().Where(card => !card.HasType(CardType.Token)).ToList(); + + // non-synchro monster + List faceDownMonsters = botMonsters.Where(card => card.IsFacedown()).ToList(); + banishList.AddRange(faceDownMonsters); + List nonSynchroMonsters = botMonsters.Where(card => !card.HasType(CardType.Synchro) && !banishList.Contains(card)).ToList(); + nonSynchroMonsters.Sort(CardContainer.CompareCardAttack); + banishList.AddRange(nonSynchroMonsters); + + // spells + List spells = Bot.GetSpells(); + banishList.AddRange(ShuffleCardList(spells)); + + // synchro monster + List synchroMonsters = botMonsters.Where(card => card.HasType(CardType.Synchro) && !banishList.Contains(card)).ToList(); + synchroMonsters.Sort(CardContainer.CompareCardAttack); + banishList.AddRange(synchroMonsters); + + return Util.CheckSelectCount(banishList, cards, min, max); + } + } + + return base.OnSelectCard(cards, min, max, hint, cancelable); + } + + public override void OnNewTurn() + { + enemyActivateMaxxC = false; + enemyActivateLockBird = false; + + List keyList = calledbytheGraveCount.Keys.ToList(); + foreach (int dic in keyList) + { + if (calledbytheGraveCount[dic] > 1) + { + calledbytheGraveCount[dic] -= 1; + } + } + CrossoutDesignatorTargetList.Clear(); + infiniteImpermanenceList.Clear(); + + summoned = false; + onlyWyrmSpSummon = false; + activatedCardIdList.Clear(); + } + + public override void OnChaining(int player, ClientCard card) + { + if (card == null) return; + + if (player == 1) + { + if (card.IsCode(_CardId.MaxxC) && CheckCalledbytheGrave(_CardId.MaxxC) == 0 && !CrossoutDesignatorTargetList.Contains(_CardId.MaxxC)) + { + enemyActivateMaxxC = true; + } + if (card.IsCode(_CardId.LockBird) && CheckCalledbytheGrave(_CardId.LockBird) == 0 && !CrossoutDesignatorTargetList.Contains(_CardId.LockBird)) + { + enemyActivateLockBird = true; + } + if (card.IsCode(_CardId.InfiniteImpermanence) && !CrossoutDesignatorTargetList.Contains(_CardId.InfiniteImpermanence)) + { + for (int i = 0; i < 5; ++i) + { + if (Enemy.SpellZone[i] == card) + { + infiniteImpermanenceList.Add(4-i); + break; + } + } + } + if (card.IsCode(_CardId.CalledByTheGrave) && !CrossoutDesignatorTargetList.Contains(_CardId.CalledByTheGrave)) + { + foreach (ClientCard target in Duel.LastChainTargets) + { + if (target.IsMonster() && target.Controller == 0 && target.Location == CardLocation.Grave) + { + calledbytheGraveCount[target.Id] = 2; + } + } + } + } + base.OnChaining(player, card); + } + + public override void OnChainEnd() + { + currentNegateMonsterList.Clear(); + for (int idx = effectUsedBaronneDeFleurList.Count() - 1; idx >= 0; -- idx) + { + ClientCard checkTarget = effectUsedBaronneDeFleurList[idx]; + if (checkTarget == null || checkTarget.IsFacedown() || checkTarget.Location != CardLocation.MonsterZone) + { + effectUsedBaronneDeFleurList.RemoveAt(idx); + } + } + base.OnChainEnd(); + } + + /// + /// Select spell/trap's place randomly to avoid InfiniteImpermanence and so on. + /// + /// Card to set(default current card) + /// Whether need to avoid InfiniteImpermanence + /// Whether need to avoid set in this place + public void SelectSTPlace(ClientCard card = null, bool avoidImpermanence = false, List avoidList = null) + { + List list = new List { 0, 1, 2, 3, 4 }; + int n = list.Count; + while (n-- > 1) + { + int index = Program.Rand.Next(list.Count); + int nextIndex = (index + Program.Rand.Next(list.Count - 1)) % list.Count; + int tempInt = list[index]; + list[index] = list[nextIndex]; + list[nextIndex] = tempInt; + } + foreach (int seq in list) + { + int zone = (int)System.Math.Pow(2, seq); + if (Bot.SpellZone[seq] == null) + { + if (card != null && card.Location == CardLocation.Hand && avoidImpermanence && infiniteImpermanenceList.Contains(seq)) continue; + if (avoidList != null && avoidList.Contains(seq)) continue; + AI.SelectPlace(zone); + return; + }; + } + AI.SelectPlace(0); + } + + + public bool NibiruThePrimalBeingActivate() + { + if (Duel.Player == 0 || Bot.GetMonsters().Any(card => card.IsFaceup() && card.HasType(CardType.Synchro))) + { + return false; + } + + if (Util.GetBestAttack(Enemy) > Util.GetBestAttack(Bot)) + { + // end main phase + if ((CurrentTiming & hintTimingMainEnd) != 0) + { + SelectNibiruPosition(); + return true; + } + + // avoid Baronne de Fleur + List tunerList = Enemy.GetMonsters().Where(card => card.IsFaceup() && card.IsTuner() && !card.HasType(CardType.Xyz | CardType.Link)).ToList(); + List nonTunerList = Enemy.GetMonsters().Where(card => card.IsFaceup() && !card.IsTuner() && !card.HasType(CardType.Xyz | CardType.Link)).ToList(); + foreach (ClientCard tuner in tunerList) + { + foreach (ClientCard nonTuner in nonTunerList) + { + if (tuner.Level + nonTuner.Level == 10) + { + SelectNibiruPosition(); + return true; + } + } + } + } + + return false; + } + + public void SelectNibiruPosition() + { + int totalAttack = Bot.GetMonsters().Where(card => card.IsFaceup()).Sum(m => (int?)m.Attack) ?? 0; + totalAttack += Enemy.GetMonsters().Where(card => card.IsFaceup()).Sum(m => (int?)m.Attack) ?? 0; + Logger.DebugWriteLine("Nibiru token attack: " + totalAttack.ToString()); + if (totalAttack >= 3000) + { + AI.SelectPosition(CardPosition.FaceUpDefence); + AI.SelectPosition(CardPosition.FaceUpDefence); + } else { + AI.SelectPosition(CardPosition.FaceUpAttack); + AI.SelectPosition(CardPosition.FaceUpAttack); + } + } + + public bool TenyiSpirit_AshunaActivate() + { + if (ActivateDescription == Util.GetStringId(CardId.TenyiSpirit_Ashuna, 0)) + { + // special summon + if (TenyiSpSummonForTaiaCheck() || Level7TenyiSpSummonCheck()) + { + return true; + } + + } else if (ActivateDescription == Util.GetStringId(CardId.TenyiSpirit_Ashuna, 1) && Card.Location == CardLocation.Grave && CheckCalledbytheGrave(Card.Id) == 0) + { + // deck summon + + // trigger blackout + if (Bot.HasInHandOrInSpellZone(CardId.SwordsoulBlackout)) + { + List blackoutTarget = Bot.GetMonsters().Where(card => card.IsFaceup() + && !card.HasType(CardType.Synchro) && card.HasRace(CardRace.Wyrm)).ToList(); + if (blackoutTarget.Count() == 0) + { + AI.SelectCard(CardId.TenyiSpirit_Adhara, CardId.TenyiSpirit_Vishuda); + onlyWyrmSpSummon = true; + activatedCardIdList.Add(Card.Id); + return true; + } + } + + // for level8/10 synchro + List tunerIdList = new List{_CardId.AshBlossom, _CardId.EffectVeiler, CardId.TenyiSpirit_Adhara}; + bool hasTuner = Bot.GetMonsters().Any(card => card.IsFaceup() && card.IsCode(tunerIdList)); + hasTuner |= !summoned && Bot.HasInHand(tunerIdList); + if (hasTuner && CheckRemainInDeck(CardId.TenyiSpirit_Vishuda) > 0) + { + AI.SelectCard(CardId.TenyiSpirit_Ashuna); + onlyWyrmSpSummon = true; + activatedCardIdList.Add(Card.Id); + return true; + } + if (Bot.HasInMonstersZone(CardId.TenyiSpirit_Ashuna, false, false, true) && CheckRemainInDeck(CardId.TenyiSpirit_Adhara) > 0) + { + AI.SelectCard(CardId.TenyiSpirit_Adhara); + onlyWyrmSpSummon = true; + activatedCardIdList.Add(Card.Id); + return true; + } + } + return false; + } + + public bool TenyiSpirit_VishudaActivate() + { + if (ActivateDescription == Util.GetStringId(CardId.TenyiSpirit_Vishuda, 0)) + { + // special summon + if (TenyiSpSummonForTaiaCheck() || Level7TenyiSpSummonCheck()) + { + return true; + } + + } else if (ActivateDescription == Util.GetStringId(CardId.TenyiSpirit_Vishuda, 1) && Card.Location == CardLocation.Grave && CheckCalledbytheGrave(Card.Id) == 0) + { + // bounce + List dangerList = GetProblematicEnemyCardList(true, true); + if (dangerList.Count() > 0) + { + AI.SelectCard(dangerList); + return true; + } + } + return false; + } + + public bool Level7TenyiSpSummonCheck() + { + List advanceSummonCheckList = new List{CardId.SwordsoulOfMoYe, CardId.SwordsoulOfTaia, CardId.IncredibleEcclesiaTheVirtuous}; + List tunerList = new List{CardId.TenyiSpirit_Adhara, _CardId.EffectVeiler, _CardId.AshBlossom}; + if (!summoned && !Bot.HasInHand(advanceSummonCheckList) && Bot.HasInHand(tunerList)) + { + return true; + } + if (Bot.HasInExtra(CardId.PsychicEndPunisher) && Bot.HasInMonstersZone(CardId.SwordsoulToken) && !onlyWyrmSpSummon) + { + return true; + } + + return false; + } + + public bool SwordsoulStrategistLongyuanActivate() + { + // damage effect + if (Card.Location != CardLocation.Hand) + { + return true; + } + + // special summon token + if (CheckWhetherNegated() || (CheckAtAdvantage() && enemyActivateMaxxC && Util.IsTurn1OrMain2())) + { + return false; + } + List discardIdList = new List(); + + // discard Taia to SS + if (CheckAtAdvantage()) + { + if (Bot.HasInHand(CardId.SwordsoulSacredSummit) && Bot.HasInHand(CardId.SwordsoulOfTaia) + && !activatedCardIdList.Contains(CardId.SwordsoulOfTaia) && !activatedCardIdList.Contains(CardId.SwordsoulSacredSummit)) + { + discardIdList.Add(CardId.SwordsoulOfTaia); + } + } + + // discard tenyi + if (discardIdList.Count() == 0) + { + List tenyiList = new List{CardId.TenyiSpirit_Vishuda, CardId.TenyiSpirit_Ashuna, CardId.TenyiSpirit_Adhara}; + foreach (int tenyiId in tenyiList) + { + if (Bot.HasInHand(tenyiId)) + { + discardIdList.Add(tenyiId); + } + } + } + + // discard dump card + if (discardIdList.Count() == 0) + { + List checkIdList = new List{ + CardId.SwordsoulOfTaia, CardId.SwordsoulOfMoYe, CardId.SwordsoulBlackout, CardId.SwordsoulStrategistLongyuan, CardId.SwordsoulEmergence + }; + foreach (int checkId in checkIdList) + { + if (Bot.Hand.Count(card => card != Card && card.IsCode(checkIdList)) > 1) + { + discardIdList.Add(checkId); + } + } + } + + // discard card + if (discardIdList.Count() == 0) + { + List checkIdList = new List{ + CardId.SwordsoulOfTaia, CardId.SwordsoulOfMoYe, CardId.SwordsoulBlackout, CardId.SwordsoulStrategistLongyuan, + CardId.SwordsoulSacredSummit, CardId.SwordsoulEmergence + }; + foreach (int checkId in checkIdList) + { + if (Bot.Hand.Count(card => card != Card && card.IsCode(checkIdList)) >= 1) + { + discardIdList.Add(checkId); + } + } + } + + if (discardIdList.Count() > 0) + { + AI.SelectCard(discardIdList); + AI.SelectPosition(CardPosition.FaceUpAttack); + AI.SelectPosition(CardPosition.FaceUpDefence); + activatedCardIdList.Add(Card.Id); + return true; + } + + return false; + } + + public bool SwordsoulOfTaiaActivate() + { + // send to GY effect + if (Card.Location != CardLocation.MonsterZone) + { + List sendToGYTarget = new List(); + + // send Mo Ye to SS + if (!Bot.HasInGraveyard(CardId.SwordsoulOfMoYe) && CheckRemainInDeck(CardId.SwordsoulOfMoYe) > 0) + { + bool sendMoYe = false; + // baxia + if (Bot.HasInMonstersZone(CardId.BaxiaBrightnessOfTheYangZing, true, false, true + && !activatedCardIdList.Contains(CardId.BaxiaBrightnessOfTheYangZing))) + { + sendMoYe = true; + + } + if (Bot.HasInHand(CardId.SwordsoulSacredSummit) && !activatedCardIdList.Contains(CardId.SwordsoulSacredSummit)) { + if (Bot.Hand.Any(card => card.Id != CardId.SwordsoulSacredSummit && (card.HasSetcode(SetcodeSwordsoul) || card.HasRace(CardRace.Wyrm)))) + { + sendMoYe = true; + } + } + + if (sendMoYe) + { + sendToGYTarget.Add(CardId.SwordsoulOfMoYe); + } + } + + // send Tenyi + List checkTenyiList = new List {CardId.TenyiSpirit_Adhara, CardId.TenyiSpirit_Vishuda, CardId.TenyiSpirit_Ashuna}; + foreach (int id in checkTenyiList) + { + if (CheckRemainInDeck(id) > 0) + { + sendToGYTarget.Add(id); + } + } + + if (sendToGYTarget.Count() > 0) + { + AI.SelectCard(sendToGYTarget); + return true; + } + return false; + } + + // special summon token + // ignore negate check if blackout in GY + if (Bot.HasInGraveyard(CardId.SwordsoulBlackout) && !activatedCardIdList.Contains(CardId.SwordsoulBlackout)) + { + AI.SelectCard(CardId.SwordsoulBlackout); + AI.SelectPosition(CardPosition.FaceUpDefence); + activatedCardIdList.Add(Card.Id); + return true; + } + + if (CheckWhetherNegated()) + { + return false; + } + List banishIdList = new List(); + + List checkIdList = new List{ + CardId.SwordsoulStrategistLongyuan, CardId.SwordsoulEmergence, CardId.SwordsoulOfTaia, CardId.SwordsoulOfMoYe, CardId.MonkOfTheTenyi, + CardId.ShamanOfTheTenyi, CardId.SwordsoulSacredSummit, CardId.SwordsoulGrandmaster_Chixiao, CardId.TenyiSpirit_Ashuna, CardId.TenyiSpirit_Vishuda, + CardId.SwordsoulSinisterSovereign_QixingLongyuan, CardId.SwordsoulSupremeSovereign_Chengying, CardId.DracoBerserkerOfTheTenyi, + CardId.TenyiSpirit_Adhara + }; + + // dump check + foreach (int checkId in checkIdList) + { + if (Bot.Graveyard.Count(card => card.IsCode(checkId)) > 1) + { + banishIdList.Add(checkId); + } + } + + // priority check + if (banishIdList.Count() == 0) + { + foreach (int checkId in checkIdList) + { + if (Bot.HasInGraveyard(checkId)) + { + banishIdList.Add(checkId); + } + } + } + + if (banishIdList.Count() > 0) + { + AI.SelectCard(banishIdList); + AI.SelectPosition(CardPosition.FaceUpDefence); + activatedCardIdList.Add(Card.Id); + return true; + } + + return false; + } + + public bool SwordsoulOfTaiaSummon() + { + if (Bot.HasInGraveyard(CardId.SwordsoulBlackout)) + { + if (!activatedCardIdList.Contains(CardId.SwordsoulOfTaia) && !activatedCardIdList.Contains(CardId.SwordsoulBlackout)) + { + summoned = true; + return true; + } + } + if (SummonLevel4ForSynchro()) + { + summoned = true; + return true; + } + if (CheckWhetherNegated()) + { + return false; + } + if (SwordsoulOfTaiaEffectCheck() && !activatedCardIdList.Contains(CardId.SwordsoulOfTaia)) + { + summoned = true; + return true; + } + + return false; + } + + public bool SwordsoulOfTaiaEffectCheck(ClientCard exceptTarget = null) + { + if (exceptTarget == null) + { + exceptTarget = Card; + } + return Bot.Graveyard.Count(card => card != exceptTarget && (card.HasSetcode(SetcodeSwordsoul) || card.HasRace(CardRace.Wyrm))) > 0; + } + + public bool SwordsoulOfMoYeActivate() + { + // draw effect + if (Card.Location != CardLocation.MonsterZone) + { + return true; + } + + // special summon token + if (CheckWhetherNegated()) + { + return false; + } + List revealList = Bot.Hand.Where(card => card.HasSetcode(SetcodeSwordsoul) || card.HasRace(CardRace.Wyrm)).ToList(); + if (revealList.Count() > 0) + { + revealList = ShuffleCardList(revealList); + AI.SelectCard(revealList); + AI.SelectPosition(CardPosition.FaceUpDefence); + activatedCardIdList.Add(Card.Id); + return true; + } + return false; + } + + public bool SwordsoulOfMoYeSummon() + { + if (SummonLevel4ForSynchro()) + { + summoned = true; + return true; + } + if (CheckWhetherNegated()) + { + return false; + } + if (SwordsoulOfMoYeEffectCheck() && !activatedCardIdList.Contains(CardId.SwordsoulOfMoYe)) + { + summoned = true; + return true; + } + + return false; + } + + public bool SwordsoulOfMoYeEffectCheck(List exceptList = null) + { + if (exceptList == null) + { + exceptList = new List{Card}; + } + return Bot.Hand.Count(card => !exceptList.Contains(card) && (card.HasSetcode(SetcodeSwordsoul) || card.HasRace(CardRace.Wyrm))) > 0; + } + + public bool SummonLevel4ForSynchro() + { + bool hasNonTuner = Bot.GetMonsters().Any(card => card.IsFaceup() && !card.HasType(CardType.Xyz | CardType.Link) && !card.IsTuner()); + if (hasNonTuner) + { + return false; + } + List tunerList = Bot.GetMonsters().Where(card => + card.IsFaceup() && !card.HasType(CardType.Xyz | CardType.Link) && card.IsTuner()).ToList(); + if (tunerList.Count() > 0) + { + foreach (ClientCard tuner in tunerList) + { + int checkLevel = tuner.Level + 4; + if (Bot.ExtraDeck.Any(card => card.HasType(CardType.Synchro) && card.Level == checkLevel)) + { + return true; + } + } + } + + return false; + } + + public bool IncredibleEcclesiaTheVirtuousActivate() + { + if (Card.Location == CardLocation.Grave) + { + return true; + } + if (Duel.Player == 0 && !CheckWhetherNegated()) + { + bool canActivateMoye = !activatedCardIdList.Contains(CardId.SwordsoulOfMoYe) && CheckRemainInDeck(CardId.SwordsoulOfMoYe) > 0 + && CheckCalledbytheGrave(CardId.SwordsoulOfMoYe) == 0 && SwordsoulOfMoYeEffectCheck(); + bool canActivateTaia = !activatedCardIdList.Contains(CardId.SwordsoulOfTaia) && CheckRemainInDeck(CardId.SwordsoulOfTaia) > 0 + && CheckCalledbytheGrave(CardId.SwordsoulOfTaia) == 0 && SwordsoulOfTaiaEffectCheck(); + if (canActivateMoye && !summoned && !Bot.HasInHand(CardId.SwordsoulOfMoYe)) + { + AI.SelectCard(CardId.SwordsoulOfMoYe); + activatedCardIdList.Add(Card.Id); + return true; + } + if (canActivateTaia && !summoned && !Bot.HasInHand(CardId.SwordsoulOfTaia)) + { + AI.SelectCard(CardId.SwordsoulOfTaia); + activatedCardIdList.Add(Card.Id); + return true; + } + if (canActivateMoye) + { + AI.SelectCard(CardId.SwordsoulOfMoYe); + activatedCardIdList.Add(Card.Id); + return true; + } + if (canActivateTaia) + { + AI.SelectCard(CardId.SwordsoulOfTaia); + activatedCardIdList.Add(Card.Id); + return true; + } + } + + return false; + } + + public bool IncredibleEcclesiaTheVirtuousSummon() + { + if (CheckWhetherNegated()) + { + return false; + } + if (SwordsoulOfMoYeSummon() && CheckRemainInDeck(CardId.SwordsoulOfMoYe) > 0) + { + summoned = true; + return true; + } + if (SwordsoulOfTaiaSummon() && CheckRemainInDeck(CardId.SwordsoulOfTaia) > 0) + { + summoned = true; + return true; + } + + return false; + } + + public bool IncredibleEcclesiaTheVirtuousSpSummon() + { + if (CheckWhetherNegated()) + { + return false; + } + if (CheckAtAdvantage() && enemyActivateMaxxC && Util.IsTurn1OrMain2()) + { + return false; + } + + return true; + } + + public bool AshBlossomActivate() + { + if (CheckWhetherNegated(true) || !CheckLastChainShouldNegated()) return false; + if (CheckAtAdvantage() && Duel.LastChainPlayer == 1 && Util.GetLastChainCard().IsCode(_CardId.MaxxC)) + { + return false; + } + if (DefaultAshBlossomAndJoyousSpring()) + { + CheckDeactiveFlag(); + return true; + } + return false; + } + + public bool MaxxCActivate() + { + if (CheckWhetherNegated(true) || Duel.LastChainPlayer == 0) return false; + return DefaultMaxxC(); + } + + public bool EffectVeilerActivate() + { + if (CheckWhetherNegated(true)) return false; + + List shouldNegateList = GetMonsterListForTargetNegate(true); + if (shouldNegateList.Count() > 0) + { + ClientCard target = shouldNegateList[0]; + currentNegateMonsterList.Add(target); + AI.SelectCard(target); + return true; + } + + return false; + } + + public bool TunerForSynchroSummon() + { + if (!Card.IsCode(_CardId.AshBlossom) && !Card.IsCode(CardId.TenyiSpirit_Adhara) && !Card.IsCode(_CardId.EffectVeiler)) + { + return false; + } + // taia check + if (Bot.HasInExtra(CardId.MonkOfTheTenyi) && Bot.HasInHand(CardId.SwordsoulOfTaia) + && !activatedCardIdList.Contains(CardId.SwordsoulOfTaia) && CheckCalledbytheGrave(CardId.SwordsoulOfTaia) == 0) + { + return false; + } + + // already has tuner, skip (maybe affected by Dimensional Barrier) + if (Bot.GetMonsters().Any(card => card.IsFaceup() && card.IsTuner())) + { + return false; + } + + // level10 check + List checkOnField = new List{CardId.TenyiSpirit_Vishuda, CardId.TenyiSpirit_Ashuna}; + bool hasLevel7NonTuner = Bot.GetMonsters().Any(card => card.IsFaceup() && checkOnField.Contains(card.Id) && !card.IsTuner()); + if (hasLevel7NonTuner) + { + int totalLevel = Card.Level + 7; + if (Bot.ExtraDeck.Any(card => card.HasType(CardType.Synchro) && card.Level == totalLevel && (!onlyWyrmSpSummon || card.HasRace(CardRace.Wyrm)))) + { + summoned = true; + return true; + } + } + + List checkNonTuner = Bot.GetMonsters().Where(card => card.IsFaceup() && !card.IsTuner()).ToList(); + checkNonTuner.Sort(CardContainer.CompareCardAttack); + // level7 check + if (Bot.HasInExtra(CardId.YaziEvilOfTheYangZing) && GetProblematicEnemyCardList(true, true).Count() > 0) + { + foreach (ClientCard checkCard in checkNonTuner) + { + if (Card.Level + checkCard.Level == 7) + { + summoned = true; + return true; + } + } + } + // level 11 check + if (Bot.HasInExtra(CardId.PsychicEndPunisher)) + { + foreach (ClientCard checkCard in checkNonTuner) + { + if ((checkCard.IsDisabled() || !checkCard.HasType(CardType.Synchro)) && (Card.Level + checkCard.Level == 11)) + { + summoned = true; + return true; + } + } + } + + return false; + } + + public bool WyrmForBlackoutSummon() + { + if (Card.Level > 4 || !Card.HasRace(CardRace.Wyrm)) + { + return false; + } + if (Bot.HasInHandOrInSpellZone(CardId.SwordsoulBlackout) && !Bot.GetMonsters().Any(card => card.IsFaceup() && card.HasRace(CardRace.Wyrm))) + { + summoned = true; + return true; + } + return false; + } + + public bool TenyiSpirit_AdharaActivate() + { + if (ActivateDescription == Util.GetStringId(CardId.TenyiSpirit_Adhara, 0)) + { + // special summon + if (TenyiSpSummonForTaiaCheck()) + { + return true; + } + + } + else if (ActivateDescription == Util.GetStringId(CardId.TenyiSpirit_Adhara, 1) && Card.Location == CardLocation.Grave && CheckCalledbytheGrave(Card.Id) == 0) + { + // recycle + if (!activatedCardIdList.Contains(CardId.SwordsoulStrategistLongyuan) && SwordsoulOfMoYeEffectCheck() + && Bot.HasInBanished(CardId.SwordsoulStrategistLongyuan)) + { + AI.SelectCard(CardId.SwordsoulStrategistLongyuan); + return true; + } + if (!summoned) + { + if (!activatedCardIdList.Contains(CardId.SwordsoulOfMoYe) && SwordsoulOfMoYeEffectCheck() + && Bot.HasInBanished(CardId.SwordsoulOfMoYe)) + { + AI.SelectCard(CardId.SwordsoulOfMoYe); + return true; + } + if (!activatedCardIdList.Contains(CardId.SwordsoulOfTaia) && SwordsoulOfTaiaEffectCheck() + && Bot.HasInBanished(CardId.SwordsoulOfTaia)) + { + AI.SelectCard(CardId.SwordsoulOfTaia); + return true; + } + } + List recycleList = new List{CardId.TenyiSpirit_Vishuda, CardId.TenyiSpirit_Ashuna}; + foreach (int recycle in recycleList) + { + if (Bot.HasInBanished(recycle)) + { + AI.SelectCard(recycle); + return true; + } + } + } + + return false; + } + + public bool TenyiSpSummonForTaiaCheck() + { + if (!activatedCardIdList.Contains(CardId.SwordsoulOfTaia) && CheckCalledbytheGrave(CardId.SwordsoulOfTaia) == 0) + { + bool hasTaia = (!summoned && Bot.HasInHand(CardId.SwordsoulOfTaia)) || Bot.HasInMonstersZone(CardId.SwordsoulOfTaia); + bool noTargetInGrave = !Bot.Graveyard.Any(card => card.HasRace(CardRace.Wyrm) || card.HasSetcode(SetcodeSwordsoul)); + bool hasInExtra = Bot.HasInExtra(CardId.MonkOfTheTenyi); + bool notLongyuan = activatedCardIdList.Contains(CardId.SwordsoulStrategistLongyuan) || !Bot.HasInHand(CardId.SwordsoulStrategistLongyuan); + + if (hasTaia && noTargetInGrave && hasInExtra && notLongyuan) + { + return true; + } + } + return false; + } + + public bool TenyiForShamanSpSummon() + { + List checkEffectDesc = new List{ + Util.GetStringId(CardId.TenyiSpirit_Adhara, 0), Util.GetStringId(CardId.TenyiSpirit_Vishuda, 0), + Util.GetStringId(CardId.TenyiSpirit_Ashuna, 0) + }; + if (!checkEffectDesc.Contains(ActivateDescription) || summoned || !Bot.HasInExtra(CardId.ShamanOfTheTenyi) + || (CheckAtAdvantage() && enemyActivateMaxxC)) + { + return false; + } + ClientCard toSummonMoye = Bot.Hand.FirstOrDefault(card => card.IsCode(CardId.SwordsoulOfMoYe)); + if (toSummonMoye == null) + { + return false; + } + List notRevealCheckList = new List{Card, toSummonMoye}; + if (!SwordsoulOfMoYeEffectCheck(notRevealCheckList) || activatedCardIdList.Contains(CardId.SwordsoulOfMoYe)) + { + return false; + } + if (activatedCardIdList.Contains(CardId.SwordsoulOfTaia) || !Bot.HasInHandOrInGraveyard(CardId.SwordsoulOfTaia)) + { + return false; + } + + return true; + } + + public bool TenyiForBlackoutSpSummon() + { + List checkEffectDesc = new List{ + Util.GetStringId(CardId.TenyiSpirit_Adhara, 0), Util.GetStringId(CardId.TenyiSpirit_Vishuda, 0), + Util.GetStringId(CardId.TenyiSpirit_Ashuna, 0) + }; + if (!checkEffectDesc.Contains(ActivateDescription)) + { + return false; + } + if (CheckAtAdvantage() && enemyActivateMaxxC) + { + return false; + } + if (Bot.HasInHandOrInSpellZone(CardId.SwordsoulBlackout) && !Bot.GetMonsters().Any(card => card.IsFaceup() && card.HasRace(CardRace.Wyrm))) + { + return true; + } + return false; + } + + public bool PotOfDesiresActivate() + { + if (CheckWhetherNegated()) + { + return false; + } + if (CheckAtAdvantage()) + { + bool result = Bot.Deck.Count() >= 15; + if (result) + { + SelectSTPlace(null, true); + } + return result; + } + SelectSTPlace(null, true); + return true; + } + + public bool SwordsoulEmergenceActivate() + { + if (Card.Location == CardLocation.Removed) + { + return SwordsoulSpellBanishedEffect(); + } + + // Mo Ye + if (!Bot.HasInHand(CardId.SwordsoulOfMoYe) && !activatedCardIdList.Contains(CardId.SwordsoulOfMoYe) + && CheckRemainInDeck(CardId.SwordsoulOfMoYe) > 0 && SwordsoulOfMoYeEffectCheck()) + { + AI.SelectCard(CardId.SwordsoulOfMoYe); + activatedCardIdList.Add(Card.Id); + SelectSTPlace(null, true); + return true; + } + + // Taia + if (!Bot.HasInHand(CardId.SwordsoulOfTaia) && !activatedCardIdList.Contains(CardId.SwordsoulOfTaia) + && CheckRemainInDeck(CardId.SwordsoulOfTaia) > 0 && SwordsoulOfTaiaEffectCheck()) + { + AI.SelectCard(CardId.SwordsoulOfTaia); + activatedCardIdList.Add(Card.Id); + SelectSTPlace(null, true); + return true; + } + + // Longyuan + if (!Bot.HasInHand(CardId.SwordsoulStrategistLongyuan) && !activatedCardIdList.Contains(CardId.SwordsoulStrategistLongyuan) + && CheckRemainInDeck(CardId.SwordsoulStrategistLongyuan) > 0 && SwordsoulOfMoYeEffectCheck()) + { + AI.SelectCard(CardId.SwordsoulStrategistLongyuan); + activatedCardIdList.Add(Card.Id); + SelectSTPlace(null, true); + return true; + } + + // dump check + if (!Bot.HasInHand(CardId.SwordsoulOfMoYe) && CheckRemainInDeck(CardId.SwordsoulOfMoYe) > 0 && SwordsoulOfMoYeEffectCheck()) + { + AI.SelectCard(CardId.SwordsoulOfMoYe); + activatedCardIdList.Add(Card.Id); + SelectSTPlace(null, true); + return true; + } + List checkIdList = new List{CardId.SwordsoulOfTaia, CardId.SwordsoulOfMoYe, CardId.SwordsoulStrategistLongyuan}; + foreach (int checkId in checkIdList) + { + if (CheckRemainInDeck(checkId) > 0) + { + AI.SelectCard(checkId); + activatedCardIdList.Add(Card.Id); + SelectSTPlace(null, true); + return true; + } + } + + return false; + } + + public bool SwordsoulSacredSummitActivate() + { + if (Card.Location == CardLocation.Removed) + { + return SwordsoulSpellBanishedEffect(); + } + if (CheckAtAdvantage()) + { + if (enemyActivateMaxxC && Util.IsTurn1OrMain2()) + { + return false; + } + if (!activatedCardIdList.Contains(CardId.SwordsoulOfMoYe) && Bot.HasInGraveyard(CardId.SwordsoulOfMoYe) + && CheckCalledbytheGrave(CardId.SwordsoulOfMoYe) == 0 && SwordsoulOfMoYeEffectCheck()) + { + AI.SelectCard(CardId.SwordsoulOfMoYe); + activatedCardIdList.Add(Card.Id); + SelectSTPlace(null, true); + return true; + } + if (!activatedCardIdList.Contains(CardId.SwordsoulOfTaia) && CheckCalledbytheGrave(CardId.SwordsoulOfTaia) == 0) + { + ClientCard taia = Bot.Graveyard.FirstOrDefault(card => card.IsCode(CardId.SwordsoulOfTaia)); + if (taia != null && SwordsoulOfTaiaEffectCheck(taia)) + { + AI.SelectCard(CardId.SwordsoulOfTaia); + activatedCardIdList.Add(Card.Id); + SelectSTPlace(null, true); + return true; + } + } + } + bool controlSynchro = Bot.GetMonsters().Any(card => card.IsFaceup() && card.HasType(CardType.Synchro)); + + List rebornTargetList = Bot.Graveyard.Where(card => + card.IsMonster() && (card.HasSetcode(SetcodeSwordsoul) || (controlSynchro && card.HasRace(CardRace.Wyrm)))).ToList(); + rebornTargetList.Sort(CardContainer.CompareCardAttack); + rebornTargetList.Reverse(); + + if (rebornTargetList.Count() > 0) + { + ClientCard rebornTarget = rebornTargetList[0]; + if (rebornTarget.IsCode(CardId.SwordsoulOfMoYe) && (activatedCardIdList.Contains(CardId.SwordsoulOfMoYe) || !SwordsoulOfMoYeEffectCheck())) + { + return false; + } + if (rebornTarget.IsCode(CardId.SwordsoulOfTaia) && activatedCardIdList.Contains(CardId.SwordsoulOfTaia)) + { + return false; + } + AI.SelectCard(rebornTargetList); + activatedCardIdList.Add(Card.Id); + SelectSTPlace(null, true); + return true; + } + + return false; + } + + public bool SwordsoulSpellBanishedEffect() + { + // TODO + return false; + } + + public bool CalledbytheGraveActivate() + { + if (CheckWhetherNegated(true) || !CheckLastChainShouldNegated()) return false; + if (CheckAtAdvantage() && Duel.LastChainPlayer == 1 && Util.GetLastChainCard().IsCode(_CardId.MaxxC)) + { + return false; + } + if (Duel.LastChainPlayer == 1) + { + // negate + if (Util.GetLastChainCard().IsMonster()) + { + int code = Util.GetLastChainCard().Id; + if (code == 0) return false; + if (CheckCalledbytheGrave(code) > 0 || CrossoutDesignatorTargetList.Contains(code)) return false; + if (Util.GetLastChainCard().IsCode(_CardId.MaxxC) && CheckAtAdvantage()) + { + return false; + } + if (Enemy.Graveyard.GetFirstMatchingCard(card => card.IsMonster() && card.IsOriginalCode(code)) != null) + { + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + AI.SelectCard(code); + calledbytheGraveCount[code] = 2; + CheckDeactiveFlag(); + return true; + } + } + + // banish target + foreach (ClientCard cards in Enemy.Graveyard) + { + if (Duel.ChainTargets.Contains(cards) && cards.IsMonster()) + { + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + int code = cards.Id; + AI.SelectCard(cards); + calledbytheGraveCount[code] = 2; + return true; + } + } + + // become targets + if (Duel.ChainTargets.Contains(Card)) + { + List enemyMonsters = Enemy.Graveyard.GetMatchingCards(card => card.IsMonster()).ToList(); + if (enemyMonsters.Count() > 0) + { + enemyMonsters.Sort(CardContainer.CompareCardAttack); + enemyMonsters.Reverse(); + int code = enemyMonsters[0].Id; + AI.SelectCard(code); + calledbytheGraveCount[code] = 2; + return true; + } + } + } + + // avoid danger monster in grave + if (Duel.LastChainPlayer == 1) return false; + List targets = CheckDangerousCardinEnemyGrave(true); + if (targets.Count() > 0) { + int code = targets[0].Id; + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + AI.SelectCard(code); + calledbytheGraveCount[code] = 2; + return true; + } + + return false; + } + + public bool CrossoutDesignatorActivate() + { + if (CheckWhetherNegated(true) || !CheckLastChainShouldNegated()) return false; + // negate + if (Duel.LastChainPlayer == 1 && Util.GetLastChainCard() != null) + { + int code = Util.GetLastChainCard().Id; + int alias = Util.GetLastChainCard().Alias; + if (alias != 0 && alias - code < 10) code = alias; + if (code == 0) return false; + if (CheckCalledbytheGrave(code) > 0 || CrossoutDesignatorTargetList.Contains(code)) return false; + if (CheckRemainInDeck(code) > 0) + { + if (!(Card.Location == CardLocation.SpellZone)) + { + SelectSTPlace(null, true); + } + AI.SelectAnnounceID(code); + CrossoutDesignatorTargetList.Add(code); + CheckDeactiveFlag(); + return true; + } + } + return false; + } + + public bool InfiniteImpermanenceActivate() + { + if (CheckWhetherNegated()) return false; + + ClientCard LastChainCard = Util.GetLastChainCard(); + + // negate spells + if (Card.Location == CardLocation.SpellZone) + { + int this_seq = -1; + int that_seq = -1; + for (int i = 0; i < 5; ++i) + { + if (Bot.SpellZone[i] == Card) this_seq = i; + if (LastChainCard != null + && LastChainCard.Controller == 1 && LastChainCard.Location == CardLocation.SpellZone && Enemy.SpellZone[i] == LastChainCard) that_seq = i; + else if (Duel.Player == 0 && Util.GetProblematicEnemySpell() != null + && Enemy.SpellZone[i] != null && Enemy.SpellZone[i].IsFloodgate()) that_seq = i; + } + if ( (this_seq * that_seq >= 0 && this_seq + that_seq == 4) + || Util.IsChainTarget(Card) + || (LastChainCard != null && LastChainCard.Controller == 1 && LastChainCard.IsCode(_CardId.HarpiesFeatherDuster))) + { + CheckDeactiveFlag(); + ClientCard target = GetProblematicEnemyMonster(canBeTarget: true); + if (target != null) + { + AI.SelectCard(target); + } else { + AI.SelectCard(Enemy.GetMonsters()); + } + infiniteImpermanenceList.Add(this_seq); + return true; + } + } + + // negate monster + List shouldNegateList = GetMonsterListForTargetNegate(false, true); + if (shouldNegateList.Count() > 0) + { + ClientCard negateTarget = shouldNegateList[0]; + currentNegateMonsterList.Add(negateTarget); + + if (Card.Location == CardLocation.SpellZone) + { + for (int i = 0; i < 5; ++ i) + { + if (Bot.SpellZone[i] == Card) + { + infiniteImpermanenceList.Add(i); + break; + } + } + } + if (Card.Location == CardLocation.Hand) + { + SelectSTPlace(Card, true); + } + AI.SelectCard(negateTarget); + return true; + } + + return false; + } + + public bool SwordsoulBlackoutActivate() + { + // sp summon token + if (Card.Location == CardLocation.Removed) + { + AI.SelectPosition(CardPosition.FaceUpDefence); + activatedCardIdList.Add(Card.Id); + return true; + } + + // self destroy targer + List selfDestroyList = Bot.GetMonsters().Where(card => card.IsFaceup() && card.HasRace(CardRace.Wyrm)).ToList(); + selfDestroyList.Sort(CardContainer.CompareCardAttack); + ClientCard selfDestroyTarget = selfDestroyList[0]; + bool selfTargetIsImportant = selfDestroyTarget.HasType(CardType.Synchro); + + // choose Chengying + List chengyingList = Bot.GetMonsters().Where(card => + card.IsCode(CardId.SwordsoulSupremeSovereign_Chengying) && card.IsFaceup() && !card.IsDisabled()).ToList(); + if (chengyingList.Count() > 0 && Bot.Graveyard.Count() > 0) + { + selfDestroyTarget = chengyingList[0]; + selfTargetIsImportant = false; + } + foreach (ClientCard selfCard in selfDestroyList) + { + if (Duel.LastChainTargets.Contains(selfCard)) + { + selfDestroyTarget = selfCard; + selfTargetIsImportant = false; + } + } + + // destroy problem card + List problemCardList = GetProblematicEnemyCardList(true); + if (problemCardList.Count() >= 2 && Duel.Player == 1) + { + AI.SelectCard(selfDestroyTarget); + AI.SelectNextCard(problemCardList); + return true; + } + + List faceUpEnemyMonsterList = Enemy.GetMonsters().Where(card => card.IsFaceup()).ToList(); + faceUpEnemyMonsterList.Sort(CardContainer.CompareCardAttack); + faceUpEnemyMonsterList.Reverse(); + if (!selfTargetIsImportant && Duel.Player == 1) + { + // destroy multi monster + if (faceUpEnemyMonsterList.Count() >= 2) + { + AI.SelectCard(selfDestroyTarget); + AI.SelectNextCard(GetNormalEnemyTargetList()); + return true; + } + + // destroy card in EP + if (Duel.Phase == DuelPhase.End) + { + AI.SelectCard(selfDestroyTarget); + AI.SelectNextCard(GetNormalEnemyTargetList()); + return true; + } + } + + // destroy attack monster + if (Duel.Phase > DuelPhase.Main1 && Duel.Phase < DuelPhase.Main2 && faceUpEnemyMonsterList.Count() > 0) + { + int botBestAttack = Util.GetBestAttack(Bot); + int enemyBestAttack = faceUpEnemyMonsterList[0].GetDefensePower(); + if (enemyBestAttack >= botBestAttack) + { + AI.SelectCard(selfDestroyTarget); + AI.SelectNextCard(GetNormalEnemyTargetList()); + return true; + } + } + + return false; + } + + + public bool GeomathmechFinalSigmaSpSummon() + { + if (Bot.GetMonstersExtraZoneCount() > 0) return false; + bool hasFloowandereeze = Enemy.GetMonsters().Any(card => card.HasSetcode(SetcodeFloowandereeze)); + hasFloowandereeze |= Enemy.GetSpells().Any(card => card.HasSetcode(SetcodeFloowandereeze)); + hasFloowandereeze |= Enemy.Graveyard.Any(card => card.HasSetcode(SetcodeFloowandereeze)); + hasFloowandereeze |= Enemy.Banished.Any(card => card.HasSetcode(SetcodeFloowandereeze)); + if (hasFloowandereeze) + { + AI.SelectMaterials(GetSynchroMaterial(12)); + AI.SelectPosition(CardPosition.FaceUpAttack); + return true; + } + + return false; + } + + public bool PsychicEndPunisherSpSummon() + { + List materialList = GetSynchroMaterial(11); + if (materialList.Count() > 1) + { + AI.SelectMaterials(materialList); + AI.SelectPosition(CardPosition.FaceUpAttack); + return true; + } + + return false; + } + + /// + /// remove level10 summon filter + /// + public bool Level10SpSummonCheckInit() + { + canSpSummonLevel10IdList.Clear(); + return false; + } + + /// + /// check which level10 monster can be summoned + /// + public bool Level10SpSummonCheckCount() + { + List checkIdList = new List{ + CardId.SwordsoulSupremeSovereign_Chengying, CardId.SwordsoulSinisterSovereign_QixingLongyuan, CardId.BaronneDeFleur + }; + foreach (int checkId in checkIdList) + { + if (Card.IsCode(checkId)) + { + canSpSummonLevel10IdList.Add(checkId); + } + } + return false; + } + + /// + /// decide which level10 monster to summon + /// + public bool Level10SpSummonCheckDecide() + { + if (canSpSummonLevel10IdList.Count <= 1) + { + return false; + } + List decideIdList = new List(); + + // BaronneDeFleur + if (canSpSummonLevel10IdList.Contains(CardId.BaronneDeFleur)) + { + // protect maxxc + if (Bot.HasInHand(_CardId.MaxxC)) + { + canSpSummonLevel10IdList.Clear(); + canSpSummonLevel10IdList.Add(CardId.BaronneDeFleur); + return false; + } + + // continue to use taia for synchro + ClientCard taia = Bot.Graveyard.FirstOrDefault(card => card.IsCode(CardId.SwordsoulOfTaia)); + if (taia != null && SwordsoulOfTaiaEffectCheck(taia) && Bot.HasInHand(CardId.SwordsoulSacredSummit)) + { + canSpSummonLevel10IdList.Clear(); + canSpSummonLevel10IdList.Add(CardId.BaronneDeFleur); + return false; + } + + decideIdList.Add(CardId.BaronneDeFleur); + } + + // QixingLongyuan + if (canSpSummonLevel10IdList.Contains(CardId.SwordsoulSinisterSovereign_QixingLongyuan)) + { + if (CheckAtAdvantage()) + { + decideIdList.Add(CardId.SwordsoulSinisterSovereign_QixingLongyuan); + } + } + + // Chengying + if (canSpSummonLevel10IdList.Contains(CardId.SwordsoulSupremeSovereign_Chengying)) + { + int banishCount = Bot.Banished.Count() + Enemy.Banished.Count(); + // use blackout or chixiao to trigger + bool decideFlag = Bot.HasInHandOrInSpellZone(CardId.SwordsoulBlackout) + || Bot.HasInMonstersZone(CardId.SwordsoulGrandmaster_Chixiao, true, false, true); + if (CheckAtAdvantage()) + { + // overkill + if (3000 + banishCount * 100 >= Enemy.LifePoints) + { + decideFlag = true; + } + } else { + ClientCard enemyMonster = GetBestEnemyMonster(true); + if (enemyMonster != null && decideIdList.Count() == 0) + { + // for high-power monster + if (3000 + banishCount * 200 >= enemyMonster.GetDefensePower()) + { + decideFlag = true; + } + } + } + + if (decideFlag) + { + decideIdList.Add(CardId.SwordsoulSupremeSovereign_Chengying); + } + } + + if (decideIdList.Count() > 0) + { + // if multi selections, select randomly + canSpSummonLevel10IdList.Clear(); + int index = Program.Rand.Next(decideIdList.Count()); + int lastDecide = decideIdList[index]; + canSpSummonLevel10IdList.Add(lastDecide); + } + return false; + } + + /// + /// perform level10 monster's synchro summon + /// + public bool Level10SpSummonCheckFinal() + { + if (canSpSummonLevel10IdList.Count() == 1) + { + int finalDecideId = canSpSummonLevel10IdList[0]; + if (Card.IsCode(finalDecideId)) + { + List materialList = GetSynchroMaterial(10, Card.IsCode(CardId.SwordsoulSinisterSovereign_QixingLongyuan)); + if (materialList.Count() > 1) + { + AI.SelectMaterials(materialList); + return true; + } + return true; + } + } + + return false; + } + + public bool AdamancipatorRisen_DragiteSpSummon() + { + if (!Bot.HasInMonstersZone(CardId.SwordsoulGrandmaster_Chixiao, true)) + { + return false; + } + bool containWaterMonsterInGY = Bot.Graveyard.Any(card => card.IsMonster() && card.HasAttribute(CardAttribute.Water)); + bool canContainWaterInGY = containWaterMonsterInGY; + canContainWaterInGY |= Bot.GetMonsters().Any(card => card.HasAttribute(CardAttribute.Water) && card.IsFaceup()); + if (!canContainWaterInGY) + { + return false; + } + + SelectLevel8SynchroMaterial(false, !containWaterMonsterInGY); + return true; + } + + public bool DracoBerserkerOfTheTenyiSpSummon() + { + if (CheckAtAdvantage() && enemyActivateMaxxC && Util.IsTurn1OrMain2()) + { + return false; + } + + SelectLevel8SynchroMaterial(true); + return true; + } + + public bool SwordsoulGrandmaster_ChixiaoSpSummon() + { + if (CheckAtAdvantage() && enemyActivateLockBird) + { + return false; + } + if (!activatedCardIdList.Contains(CardId.SwordsoulGrandmaster_Chixiao)) + { + SelectLevel8SynchroMaterial(true); + return true; + } + + return false; + } + + public bool BaxiaBrightnessOfTheYangZingSpSummon() + { + if (CheckAtAdvantage()) + { + return false; + } + + List problemList = GetProblematicEnemyCardList(true); + if (problemList.Count() > 1 && !activatedCardIdList.Contains(CardId.BaxiaBrightnessOfTheYangZing + 1)) + { + SelectLevel8SynchroMaterial(true); + return true; + } + if (problemList.Count() == 1 && Bot.GetSpellCount() > 0 && !activatedCardIdList.Contains(CardId.BaxiaBrightnessOfTheYangZing + 2)) + { + bool checkFlag = false; + if (!activatedCardIdList.Contains(CardId.SwordsoulOfMoYe) && SwordsoulOfMoYeEffectCheck() && Bot.HasInGraveyard(CardId.SwordsoulOfMoYe)) + { + checkFlag = true; + } + if (!activatedCardIdList.Contains(CardId.SwordsoulOfTaia) && Bot.HasInGraveyard(CardId.SwordsoulOfTaia)) + { + checkFlag = true; + } + if (checkFlag) + { + SelectLevel8SynchroMaterial(true); + return true; + } + } + + return false; + } + + public void SelectLevel8SynchroMaterial(bool needWyrmNonTuner = false, bool needWaterNonTuner = false) + { + List tunerList = Bot.GetMonsters().Where(card => card.IsFaceup() && card.IsTuner() && card.Level < 8).ToList(); + List nonTunerList = Bot.GetMonsters().Where(card => card.IsFaceup() && !card.IsTuner() && card.Level < 8 + && (!needWyrmNonTuner || card.HasRace(CardRace.Wyrm) && (!needWaterNonTuner || card.HasAttribute(CardAttribute.Water)))).ToList(); + tunerList.Sort(CardContainer.CompareCardAttack); + nonTunerList.Sort(CardContainer.CompareCardAttack); + + List materialList = new List(); + foreach (ClientCard tuner in tunerList) + { + materialList.Clear(); + materialList.Add(tuner); + if (tuner.Level == 4) + { + // use moye first + if (activatedCardIdList.Contains(CardId.SwordsoulOfMoYe)) + { + ClientCard moye = nonTunerList.GetFirstMatchingCard(card => card.IsCode(CardId.SwordsoulOfMoYe)); + if (moye != null) + { + materialList.Add(moye); + AI.SelectMaterials(materialList); + return; + } + } + + // use taia + if (activatedCardIdList.Contains(CardId.SwordsoulOfTaia) && !needWaterNonTuner) + { + ClientCard taia = nonTunerList.GetFirstMatchingCard(card => card.IsCode(CardId.SwordsoulOfTaia)); + if (taia != null) + { + materialList.Add(taia); + AI.SelectMaterials(materialList); + return; + } + } + } + + foreach (ClientCard nonTuner in nonTunerList) + { + if (tuner.Level + nonTuner.Level == 8) + { + materialList.Add(nonTuner); + AI.SelectMaterials(materialList); + return; + } + } + } + } + + public bool YaziEvilOfTheYangZingSpSummon() + { + if (Enemy.GetMonsterCount() + Enemy.GetSpellCount() == 0) + { + return false; + } + bool shouldSummon = GetProblematicEnemyCardList(true, true).Count() > 0; + shouldSummon |= !activatedCardIdList.Contains(CardId.SwordsoulOfMoYe) && CheckCalledbytheGrave(CardId.SwordsoulOfMoYe) == 0 + && CheckRemainInDeck(CardId.SwordsoulOfMoYe) > 0 && SwordsoulOfMoYeEffectCheck(); + shouldSummon |= !activatedCardIdList.Contains(CardId.SwordsoulOfTaia) && CheckCalledbytheGrave(CardId.SwordsoulOfTaia) == 0 + && CheckRemainInDeck(CardId.SwordsoulOfTaia) > 0; + + if (shouldSummon) + { + List materialList = GetSynchroMaterial(7); + if (materialList.Count() > 1) + { + AI.SelectMaterials(materialList); + return true; + } + } + + return false; + } + + public List GetSynchroMaterial(int level, bool needWyrmNonTuner = false) + { + List tunerList = Bot.GetMonsters().Where(card => + card.IsFaceup() && card.IsTuner() && !card.HasType(CardType.Xyz | CardType.Link)).ToList(); + List nonTunerList = Bot.GetMonsters().Where(card => + card.IsFaceup() && !card.IsTuner() && !card.HasType(CardType.Xyz | CardType.Link) && (!needWyrmNonTuner || card.HasRace(CardRace.Wyrm))).ToList(); + tunerList.Sort(CardContainer.CompareCardAttack); + nonTunerList.Sort(CardContainer.CompareCardAttack); + List selectList = new List(); + foreach (ClientCard tuner in tunerList) + { + selectList.Clear(); + selectList.Add(tuner); + foreach (ClientCard nonTuner in nonTunerList) + { + if (tuner.Level + nonTuner.Level == level && (nonTuner.IsDisabled() || !nonTuner.HasType(CardType.Synchro))) + { + selectList.Add(nonTuner); + return selectList; + } + } + } + selectList.Clear(); + return selectList; + } + + public bool ShamanOfTheTenyiSpSummon() + { + if (CheckAtAdvantage() && enemyActivateMaxxC && Util.IsTurn1OrMain2()) + { + Logger.DebugWriteLine("[Shaman] advantage & maxxc, skip"); + return false; + } + // check extra summon + List extraZoneMonsters = Bot.GetMonstersInExtraZone(); + if (extraZoneMonsters.Count() > 0 && extraZoneMonsters.Any(card => card.IsFacedown() || !card.HasType(CardType.Link) || !card.HasRace(CardRace.Wyrm))) + { + Logger.DebugWriteLine("[Shaman] extra zone occupied, skip"); + return false; + } + // check spsummon target + bool hasSpSummonTaret = !activatedCardIdList.Contains(CardId.SwordsoulOfTaia) && CheckCalledbytheGrave(CardId.SwordsoulOfTaia) == 0 + && Bot.HasInHandOrInGraveyard(CardId.SwordsoulOfTaia); + hasSpSummonTaret |= !activatedCardIdList.Contains(CardId.SwordsoulOfMoYe) && CheckCalledbytheGrave(CardId.SwordsoulOfMoYe) == 0 + && Bot.HasInGraveyard(CardId.SwordsoulOfMoYe) && SwordsoulOfMoYeEffectCheck(); + hasSpSummonTaret |= Bot.GetGraveyardMonsters().Any(card => card.HasType(CardType.Synchro) && card.IsCanRevive() && card.HasRace(CardRace.Wyrm)); + if (!hasSpSummonTaret) + { + Logger.DebugWriteLine("[Shaman] no target, skip"); + return false; + } + + // select material + List materialList = new List(extraZoneMonsters); + List mainMonsterZoneMonsters = Bot.GetMonstersInMainZone().Where(card => + card.IsFaceup() && !card.HasType(CardType.Synchro) && card.HasRace(CardRace.Wyrm)).ToList(); + mainMonsterZoneMonsters.Sort(CardContainer.CompareCardAttack); + materialList.AddRange(mainMonsterZoneMonsters); + if (materialList.Count() >= 2) + { + AI.SelectMaterials(materialList.GetRange(0, 2)); + return true; + } + + return false; + } + + public bool MonkOfTheTenyiSpSummon() + { + List materialList = Bot.GetMonsters().Where(card => + card.IsFaceup() && !card.HasType(CardType.Synchro | CardType.Link) && card.HasSetcode(SetcodeTenyi)).ToList(); + if (materialList.Count() > 0) + { + materialList.Sort(CardContainer.CompareCardAttack); + AI.SelectMaterials(materialList); + return true; + } + return false; + } + + + public bool PsychicEndPunisherActivate() + { + if (Duel.Phase > DuelPhase.Main1 && Duel.Phase < DuelPhase.Main2) + { + return true; + } + if (Bot.LifePoints <= 1500 || CheckWhetherNegated()) + { + return false; + } + List selfBanishTarget = Bot.GetMonsters().Where(card => card != Card && (card.IsFacedown() || card.GetDefensePower() <= 1000)).ToList(); + if (selfBanishTarget.Count() == 0) + { + return false; + } + selfBanishTarget.Sort(CardContainer.CompareCardAttack); + AI.SelectCard(selfBanishTarget); + AI.SelectNextCard(GetNormalEnemyTargetList(true)); + return true; + } + + public bool SwordsoulSupremeSovereign_ChengyingActivate() + { + if (ActivateDescription == Util.GetStringId(CardId.SwordsoulSupremeSovereign_Chengying, 0) || ActivateDescription == -1) + { + activatedCardIdList.Add(Card.Id); + List banishTargetList = Duel.CurrentChain.Where(card => card.Controller == 1 && card.Location == CardLocation.Grave).ToList(); + banishTargetList.AddRange(CheckDangerousCardinEnemyGrave(false)); + if (banishTargetList.Count() > 0) + { + ClientCard graveTarget = banishTargetList[0]; + Logger.DebugWriteLine("Chengying banish grave: " + graveTarget?.Name); + } + List fieldTargetList = GetNormalEnemyTargetList(); + if (fieldTargetList.Count() > 0) + { + ClientCard fieldTarget = fieldTargetList[0]; + Logger.DebugWriteLine("Chengying banish field: " + fieldTarget?.Name); + } + banishTargetList.AddRange(fieldTargetList); + AI.SelectCard(banishTargetList); + + } else if (ActivateDescription == hintReplaceDestroy) + { + List removeCardIdList = new List{ + _CardId.CalledByTheGrave, CardId.CrossoutDesignator, _CardId.InfiniteImpermanence, _CardId.AshBlossom, + _CardId.MaxxC, _CardId.EffectVeiler, CardId.MonkOfTheTenyi, CardId.ShamanOfTheTenyi, CardId.SwordsoulGrandmaster_Chixiao, + CardId.SwordsoulOfTaia, CardId.SwordsoulStrategistLongyuan, CardId.SwordsoulOfMoYe + }; + AI.SelectCard(removeCardIdList); + } else + { + Logger.DebugWriteLine("Chengying desc: " + ActivateDescription.ToString()); + } + + return true; + } + + public bool BaronneDeFleurActivate() + { + if (ActivateDescription == Util.GetStringId(CardId.BaronneDeFleur, 1)) + { + // negate + if (CheckWhetherNegated(true) || !CheckLastChainShouldNegated()) return false; + if (Duel.LastChainPlayer == 1) + { + ClientCard lastChainCard = Util.GetLastChainCard(); + if (CheckAtAdvantage() && lastChainCard.IsCode(_CardId.MaxxC)) + { + return false; + } + if (Duel.LastChainTargets.Contains(Card) && lastChainCard.IsCode(_CardId.EffectVeiler, _CardId.InfiniteImpermanence, _CardId.BreakthroughSkill)) + { + return false; + } + } + CheckDeactiveFlag(); + effectUsedBaronneDeFleurList.Add(Card); + return true; + } else if (Duel.Phase == DuelPhase.Standby) + { + // special summon after effect used + if (effectUsedBaronneDeFleurList.Contains(Card) && !CheckWhetherNegated(true)) + { + if (Duel.Player == 1) + { + if (!Bot.HasInMonstersZone(CardId.SwordsoulGrandmaster_Chixiao) && Bot.HasInGraveyard(CardId.SwordsoulGrandmaster_Chixiao)) + { + AI.SelectCard(CardId.SwordsoulGrandmaster_Chixiao); + return true; + } + } else if (GetProblematicEnemyCardList(true, true).Count() > 0) + { + return false; + } else if (CheckAtAdvantage()) { + if (Bot.ExtraDeck.Any(card => card.IsFacedown() && card.HasType(CardType.Synchro) && card.Level == 8)) + { + if (Bot.HasInGraveyard(CardId.SwordsoulOfMoYe) && SwordsoulOfMoYeEffectCheck() && CheckCalledbytheGrave(CardId.SwordsoulOfMoYe) == 0) + { + AI.SelectCard(CardId.SwordsoulOfMoYe); + return true; + } + if (CheckCalledbytheGrave(CardId.SwordsoulOfTaia) == 0) + { + ClientCard taia = Bot.Graveyard.FirstOrDefault(card => card.IsCode(CardId.SwordsoulOfTaia)); + if (taia != null && SwordsoulOfTaiaEffectCheck(taia)) + { + AI.SelectCard(CardId.SwordsoulOfTaia); + return true; + } + } + } + } + } + } else { + // destroy + List targetList = GetNormalEnemyTargetList(); + if (targetList.Count() > 0) + { + AI.SelectCard(targetList); + return true; + } + } + + return false; + } + + public bool SwordsoulSinisterSovereign_QixingLongyuanActivate() + { + if (ActivateDescription == Util.GetStringId(CardId.SwordsoulSinisterSovereign_QixingLongyuan, 0)) + { + // draw + return true; + } else if (ActivateDescription == -1 || ActivateDescription == Util.GetStringId(CardId.SwordsoulSinisterSovereign_QixingLongyuan, 1)) + { + // remove monster + return true; + } else if (ActivateDescription == Util.GetStringId(CardId.SwordsoulSinisterSovereign_QixingLongyuan, 2)) + { + // remove spell/trap + ClientCard lastChainCard = Util.GetLastChainCard(); + if (lastChainCard != null && lastChainCard.Controller == 1) + { + bool activateFlag = DefaultOnBecomeTarget(); + activateFlag |= Enemy.LifePoints <= 1200; + activateFlag |= lastChainCard.HasType(CardType.Continuous | CardType.Equip | CardType.Field | CardType.Pendulum); + if (activateFlag) + { + return true; + } + } + } else + { + Logger.DebugWriteLine("qixinglongyuan desc: " + ActivateDescription); + } + + return false; + } + + public bool AdamancipatorRisen_DragiteActivate() + { + // bounce + if (ActivateDescription == -1 || ActivateDescription == Util.GetStringId(CardId.AdamancipatorRisen_Dragite, 0)) + { + if (CheckWhetherNegated()) + { + return false; + } + if (CheckRemainInDeck(CardId.NibiruThePrimalBeing) > 0 && (Enemy.GetMonsterCount() + Enemy.GetSpellCount() > 0)) + { + AI.SelectCard(GetNormalEnemyTargetList(false)); + return true; + } + return false; + } + + // negate + if (CheckWhetherNegated()) + { + return false; + } + + return true; + } + + public bool DracoBerserkerOfTheTenyiActivate() + { + // do not banish Nibiru + ClientCard lastChainCard = Util.GetLastChainCard(); + if (lastChainCard != null && lastChainCard.IsCode(CardId.NibiruThePrimalBeing) && lastChainCard.Controller == 1) + { + return false; + } + return true; + } + + public bool SwordsoulGrandmaster_ChixiaoActivate() + { + if (ActivateDescription == Util.GetStringId(CardId.SwordsoulGrandmaster_Chixiao, 1)) + { + // negate + if (CheckWhetherNegated(true)) return false; + + List negateTargetList = new List(); + + List shouldNegateList = GetMonsterListForTargetNegate(true); + if (shouldNegateList.Count() > 0) + { + ClientCard target = shouldNegateList[0]; + currentNegateMonsterList.Add(target); + negateTargetList.AddRange(shouldNegateList); + } + + // negate unbreakable monster + if (Duel.Phase > DuelPhase.Main1 && Duel.Phase < DuelPhase.Main2) + { + bool botCanAttack = Bot.GetMonsters().Any(card => card.IsAttack()); + if (Duel.Player == 0 && botCanAttack) + { + negateTargetList.AddRange(Enemy.GetMonsters().Where(card => card.IsFaceup() && card.IsMonsterDangerous()).ToList()); + } + if (Duel.Player == 1) + { + ClientCard enemyMonster = Enemy.BattlingMonster; + if (enemyMonster != null && enemyMonster.IsMonsterInvincible()) + { + negateTargetList.Add(enemyMonster); + } + } + } + + // trigger Chengying + if (Bot.HasInMonstersZone(CardId.SwordsoulSupremeSovereign_Chengying, true, false, true) + && !activatedCardIdList.Contains(CardId.SwordsoulSupremeSovereign_Chengying) && Enemy.Graveyard.Count() > 0) + { + if (GetProblematicEnemyMonster() != null || (Duel.Phase == DuelPhase.End && Duel.Player == 1)) + { + bool triggerFlag = true; + List enemyTargetList = Enemy.GetMonsters().Where(card => + card.IsFaceup() && card.HasType(CardType.Effect) && !card.IsShouldNotBeMonsterTarget() && card.IsShouldNotBeTarget()).ToList(); + if (enemyTargetList.Count() == 0) + { + List botTargetList = Bot.GetMonsters().Where(card => card.IsFaceup() && card.HasType(CardType.Effect) + && !card.IsDisabled() && card != Card && !card.IsCode(CardId.SwordsoulSupremeSovereign_Chengying)).ToList(); + if (botTargetList.Count() == 0) + { + triggerFlag = false; + } else { + botTargetList.Sort(CardContainer.CompareCardAttack); + enemyTargetList.AddRange(botTargetList); + } + } else { + enemyTargetList.Sort(CardContainer.CompareCardAttack); + enemyTargetList.Reverse(); + } + if (triggerFlag) + { + negateTargetList.AddRange(enemyTargetList); + } + } + } + + if (negateTargetList.Count() > 0) + { + // select banish card + List graveBanishList = Bot.Graveyard.Where(card => card.HasSetcode(SetcodeSwordsoul) || card.HasRace(CardRace.Wyrm)).ToList(); + + if (graveBanishList.Count() > 0) + { + bool selectFlag = false; + // trigger blackout + ClientCard blackOut = graveBanishList.FirstOrDefault(card => card.IsCode(CardId.SwordsoulBlackout)); + if (Duel.Player == 0 && !activatedCardIdList.Contains(CardId.SwordsoulBlackout) && blackOut != null) + { + AI.SelectCard(blackOut); + selectFlag = true; + } + if (!selectFlag) + { + // banish dump card + List checkIdList = new List{ + CardId.SwordsoulEmergence, CardId.SwordsoulOfTaia, CardId.SwordsoulOfMoYe, CardId.SwordsoulStrategistLongyuan, CardId.MonkOfTheTenyi, + CardId.TenyiSpirit_Adhara, CardId.TenyiSpirit_Vishuda, CardId.TenyiSpirit_Ashuna + }; + foreach (int checkId in checkIdList) + { + List checkCardList = graveBanishList.Where(card => card.IsCode(checkId)).ToList(); + if (checkCardList.Count() > 1) + { + AI.SelectCard(checkCardList); + selectFlag = true; + break; + } + } + } + if (!selectFlag) + { + // banish exists card + List checkIdList = new List{ + CardId.SwordsoulEmergence, CardId.MonkOfTheTenyi, CardId.ShamanOfTheTenyi, CardId.SwordsoulOfTaia, + CardId.SwordsoulStrategistLongyuan, CardId.SwordsoulOfMoYe, CardId.TenyiSpirit_Adhara, CardId.TenyiSpirit_Vishuda, CardId.TenyiSpirit_Ashuna + }; + foreach (int checkId in checkIdList) + { + List checkCardList = graveBanishList.Where(card => card.IsCode(checkId)).ToList(); + if (checkCardList.Count() > 0) + { + AI.SelectCard(checkCardList); + selectFlag = true; + break; + } + } + } + if (!selectFlag) + { + AI.SelectCard(ShuffleCardList(graveBanishList)); + } + } + AI.SelectNextCard(negateTargetList); + activatedCardIdList.Add(Card.Id); + return true; + } + + } else { + // search + if (CheckAtAdvantage() && enemyActivateMaxxC && Util.IsTurn1OrMain2()) + { + if (CheckRemainInDeck(CardId.SwordsoulBlackout) > 0) + { + AI.SelectCard(CardId.SwordsoulBlackout); + activatedCardIdList.Add(Card.Id); + return true; + } + + List searchIdList = new List{ + CardId.SwordsoulBlackout, CardId.SwordsoulOfMoYe, CardId.SwordsoulOfTaia, CardId.SwordsoulEmergence, + CardId.SwordsoulStrategistLongyuan + }; + foreach (int checkId in searchIdList) + { + if (CheckRemainInDeck(checkId) > 0 && !Bot.HasInHand(checkId)) + { + AI.SelectCard(checkId); + activatedCardIdList.Add(Card.Id); + return true; + } + } + } + + if (CheckAtAdvantage()) + { + if (!activatedCardIdList.Contains(CardId.SwordsoulStrategistLongyuan) && !Bot.HasInHand(CardId.SwordsoulStrategistLongyuan) + && SwordsoulOfMoYeEffectCheck() && CheckRemainInDeck(CardId.SwordsoulStrategistLongyuan) > 0) + { + AI.SelectCard(CardId.SwordsoulStrategistLongyuan); + activatedCardIdList.Add(Card.Id); + return true; + } + + if (!activatedCardIdList.Contains(CardId.SwordsoulStrategistLongyuan) && Bot.HasInHand(CardId.SwordsoulStrategistLongyuan) + && !activatedCardIdList.Contains(CardId.SwordsoulOfTaia) && !activatedCardIdList.Contains(CardId.SwordsoulSacredSummit)) + { + // ready for another level 8 synchro + if (Bot.HasInHandOrInGraveyard(CardId.SwordsoulOfTaia) && !Bot.HasInHand(CardId.SwordsoulSacredSummit)) + { + if (CheckRemainInDeck(CardId.SwordsoulSacredSummit) > 0) + { + AI.SelectCard(CardId.SwordsoulSacredSummit); + activatedCardIdList.Add(Card.Id); + return true; + } + } + if (!Bot.HasInHandOrInGraveyard(CardId.SwordsoulOfTaia) && Bot.HasInHand(CardId.SwordsoulSacredSummit)) + { + if (CheckRemainInDeck(CardId.SwordsoulOfTaia) > 0) + { + AI.SelectCard(CardId.SwordsoulOfTaia); + activatedCardIdList.Add(Card.Id); + return true; + } + } + } + } + + if (!Bot.HasInMonstersZone(CardId.SwordsoulToken) && Bot.HasInMonstersZone(CardId.SwordsoulStrategistLongyuan) + && Bot.HasInMonstersZone(CardId.SwordsoulStrategistLongyuan) && CheckRemainInDeck(CardId.SwordsoulBlackout) > 0 + && !activatedCardIdList.Contains(CardId.SwordsoulBlackout)) + { + Logger.DebugWriteLine("Chixiao banish blackout"); + AI.SelectCard(CardId.SwordsoulBlackout); + AI.SelectOption(1); + activatedCardIdList.Add(Card.Id); + return true; + } + + if (CheckAtAdvantage()) + { + List searchIdList = new List{ + CardId.SwordsoulBlackout, CardId.SwordsoulOfMoYe, CardId.SwordsoulOfTaia, CardId.SwordsoulEmergence, + CardId.SwordsoulStrategistLongyuan + }; + foreach (int checkId in searchIdList) + { + if (CheckRemainInDeck(checkId) > 0 && !Bot.HasInHand(checkId)) + { + AI.SelectCard(checkId); + activatedCardIdList.Add(Card.Id); + return true; + } + } + } + + List checkIdList = new List{ + CardId.SwordsoulBlackout, CardId.SwordsoulOfMoYe, CardId.SwordsoulOfTaia, CardId.SwordsoulEmergence, + CardId.SwordsoulStrategistLongyuan + }; + foreach (int checkId in checkIdList) + { + if (CheckRemainInDeck(checkId) > 0 && !Bot.HasInHand(checkId)) + { + AI.SelectCard(checkId); + activatedCardIdList.Add(Card.Id); + return true; + } + } + } + + return false; + } + + public bool BaxiaBrightnessOfTheYangZingActivate() + { + Logger.DebugWriteLine("Baxia desc: " + ActivateDescription.ToString()); + + if (ActivateDescription == Util.GetStringId(CardId.BaxiaBrightnessOfTheYangZing, 0)) + { + List enemyTargetList = GetNormalEnemyTargetList(true); + if (enemyTargetList.Count() > 0) + { + AI.SelectCard(enemyTargetList); + activatedCardIdList.Add(Card.Id + 1); + return true; + } + } else + { + List destroyTarget = Bot.GetSpells(); + destroyTarget.AddRange(Bot.GetMonsters().Where(card => card.IsFacedown() || card.Attack <= 1000).ToList()); + if (destroyTarget.Count() == 0) + { + return false; + } + + bool canUseMoye = !activatedCardIdList.Contains(CardId.SwordsoulOfMoYe) + && CheckCalledbytheGrave(CardId.SwordsoulOfMoYe) == 0 && SwordsoulOfMoYeEffectCheck(); + bool canUseTaia = !activatedCardIdList.Contains(CardId.SwordsoulOfTaia) + && CheckCalledbytheGrave(CardId.SwordsoulOfTaia) == 0 && SwordsoulOfTaiaEffectCheck(); + + if (canUseMoye && Bot.HasInGraveyard(CardId.SwordsoulOfMoYe)) + { + AI.SelectCard(destroyTarget); + AI.SelectNextCard(CardId.SwordsoulOfMoYe); + activatedCardIdList.Add(Card.Id + 2); + return true; + } + if (canUseTaia && Bot.HasInGraveyard(CardId.SwordsoulOfTaia)) + { + AI.SelectCard(destroyTarget); + AI.SelectNextCard(CardId.SwordsoulOfTaia); + activatedCardIdList.Add(Card.Id + 2); + return true; + } + if (Bot.HasInGraveyard(CardId.IncredibleEcclesiaTheVirtuous)) + { + // sp summon ecclesia for moye/taia + if (!activatedCardIdList.Contains(CardId.IncredibleEcclesiaTheVirtuous)) + { + if ((canUseMoye && CheckRemainInDeck(CardId.SwordsoulOfMoYe) > 0) + || (canUseTaia && CheckRemainInDeck(CardId.SwordsoulOfTaia) > 0)) + { + AI.SelectCard(destroyTarget); + AI.SelectNextCard(CardId.IncredibleEcclesiaTheVirtuous); + activatedCardIdList.Add(Card.Id + 2); + return true; + } + } + // sp summon ecclesia as tuner + if (Bot.GetMonsters().Any(card => card.IsFaceup() && !card.IsTuner() && card.Level == 4)) + { + AI.SelectCard(destroyTarget); + AI.SelectNextCard(CardId.IncredibleEcclesiaTheVirtuous); + activatedCardIdList.Add(Card.Id + 2); + return true; + } + } + } + + return false; + } + + public bool YaziEvilOfTheYangZingActivate() + { + if (Card.Location == CardLocation.Grave) + { + // special summon + if (!activatedCardIdList.Contains(CardId.SwordsoulOfMoYe) && CheckRemainInDeck(CardId.SwordsoulOfMoYe) > 0 + && CheckCalledbytheGrave(CardId.SwordsoulOfMoYe) == 0 && SwordsoulOfMoYeEffectCheck()) + { + AI.SelectCard(CardId.SwordsoulOfMoYe); + return true; + } + if (!activatedCardIdList.Contains(CardId.SwordsoulOfTaia) && CheckRemainInDeck(CardId.SwordsoulOfTaia) > 0 + && CheckCalledbytheGrave(CardId.SwordsoulOfTaia) == 0) + { + AI.SelectCard(CardId.SwordsoulOfTaia); + return true; + } + if (Bot.HasInMonstersZone(CardId.SwordsoulToken)) + { + List specialSummonIdListForSynchro = new List{CardId.SwordsoulStrategistLongyuan, CardId.SwordsoulOfMoYe, CardId.SwordsoulOfTaia}; + foreach (int checkId in specialSummonIdListForSynchro) + { + if (CheckRemainInDeck(checkId) > 0) + { + AI.SelectCard(checkId); + return true; + } + } + } + List specialSummonIdList = new List{ + CardId.TenyiSpirit_Ashuna, CardId.TenyiSpirit_Vishuda, CardId.TenyiSpirit_Adhara, + CardId.SwordsoulStrategistLongyuan, CardId.SwordsoulOfMoYe, CardId.SwordsoulOfTaia + }; + foreach (int checkId in specialSummonIdList) + { + if (CheckRemainInDeck(checkId) > 0) + { + AI.SelectCard(checkId); + return true; + } + } + } else + { + // destroy + if (CheckWhetherNegated(true)) + { + return false; + } + bool selfDestroy = false; + if (!activatedCardIdList.Contains(CardId.SwordsoulOfMoYe) && CheckRemainInDeck(CardId.SwordsoulOfMoYe) > 0 + && CheckCalledbytheGrave(CardId.SwordsoulOfMoYe) == 0 && SwordsoulOfMoYeEffectCheck()) + { + selfDestroy = true; + } + if (!activatedCardIdList.Contains(CardId.SwordsoulOfTaia) && CheckRemainInDeck(CardId.SwordsoulOfTaia) > 0 + && CheckCalledbytheGrave(CardId.SwordsoulOfTaia) == 0) + { + selfDestroy = true; + } + if (selfDestroy) + { + AI.SelectCard(Card); + } else + { + List YangZingList = Bot.GetMonsters().Where(card => card.IsFaceup() && card.HasSetcode(SetcodeYangZing)).ToList(); + YangZingList.Sort(CardContainer.CompareCardAttack); + AI.SelectCard(YangZingList); + } + AI.SelectNextCard(GetNormalEnemyTargetList(true)); + return true; + } + + return false; + } + + public bool ShamanOfTheTenyiActivate() + { + if (Duel.Phase > DuelPhase.Main1 && Duel.Phase < DuelPhase.Main2) + { + // destroy + AI.SelectCard(GetNormalEnemyTargetList()); + return true; + } else + { + // special summon + if (CheckAtAdvantage() && enemyActivateMaxxC && Util.IsTurn1OrMain2()) + { + return false; + } + + bool canUseMoye = Bot.HasInGraveyard(CardId.SwordsoulOfMoYe) && CheckCalledbytheGrave(CardId.SwordsoulOfMoYe) == 0 + && !activatedCardIdList.Contains(CardId.SwordsoulOfMoYe); + bool canUseTaia = Bot.HasInHandOrInGraveyard(CardId.SwordsoulOfTaia) && CheckCalledbytheGrave(CardId.SwordsoulOfTaia) == 0 + && !activatedCardIdList.Contains(CardId.SwordsoulOfTaia); + bool shouldDiscardTaia = !Bot.HasInGraveyard(CardId.SwordsoulOfTaia) && Bot.HasInHand(CardId.SwordsoulOfTaia); + List sortedReviveTargetList = Bot.GetGraveyardMonsters().Where(card => + card.IsCanRevive() && card.HasRace(CardRace.Wyrm)).ToList(); + sortedReviveTargetList.Sort(CardContainer.CompareCardAttack); + sortedReviveTargetList.Reverse(); + + if (CheckAtAdvantage()) + { + // try to kill + if (Duel.Turn > 1 && Enemy.GetMonsterCount() == 0) + { + int currentAttack = Util.GetTotalAttackingMonsterAttack(0); + if (currentAttack < Enemy.LifePoints) + { + List overkillList = sortedReviveTargetList.Where(card => + card.Attack + currentAttack >= Enemy.LifePoints).ToList(); + if (overkillList.Count() > 0) + { + SelectDiscardForShamanOfTheTenyi(shouldDiscardTaia); + AI.SelectNextCard(overkillList); + return true; + } + } + } + + // for next synchro + if (canUseMoye) + { + SelectDiscardForShamanOfTheTenyi(); + AI.SelectNextCard(CardId.SwordsoulOfMoYe); + return true; + } + if (canUseTaia) + { + SelectDiscardForShamanOfTheTenyi(shouldDiscardTaia); + AI.SelectNextCard(CardId.SwordsoulOfTaia); + return true; + } + + // choose max attack + SelectDiscardForShamanOfTheTenyi(); + AI.SelectNextCard(sortedReviveTargetList); + return true; + + } else { + // reborn synchro monster + List synchroMonsterList = sortedReviveTargetList.Where(card => card.HasType(CardType.Synchro)).ToList(); + if (synchroMonsterList.Count() > 0) + { + SelectDiscardForShamanOfTheTenyi(); + AI.SelectNextCard(synchroMonsterList); + return true; + } + + // for next synchro + if (canUseMoye) + { + SelectDiscardForShamanOfTheTenyi(); + AI.SelectNextCard(CardId.SwordsoulOfMoYe); + return true; + } + if (canUseTaia) + { + SelectDiscardForShamanOfTheTenyi(shouldDiscardTaia); + AI.SelectNextCard(CardId.SwordsoulOfTaia); + return true; + } + } + } + + return false; + } + + public void SelectDiscardForShamanOfTheTenyi(bool useTaia = false) + { + if (useTaia) + { + AI.SelectCard(CardId.SwordsoulOfTaia); + } else { + // drop tenyi + List tenyiList = new List{CardId.TenyiSpirit_Vishuda, CardId.TenyiSpirit_Ashuna, CardId.TenyiSpirit_Adhara}; + foreach (int tenyiId in tenyiList) + { + if (Bot.HasInHand(tenyiId)) + { + AI.SelectCard(tenyiId); + return; + } + } + + // drop dump card + foreach (ClientCard hand in Bot.Hand) + { + if (Bot.Hand.Where(card => card.IsCode(hand.Id)).Count() > 1) + { + AI.SelectCard(hand); + return; + } + } + + // check discard list + List discardList = new List{ + CardId.CrossoutDesignator, _CardId.PotOfDesires, CardId.TenyiSpirit_Ashuna, CardId.TenyiSpirit_Vishuda, + CardId.TenyiSpirit_Adhara, CardId.NibiruThePrimalBeing, CardId.SwordsoulSacredSummit, CardId.IncredibleEcclesiaTheVirtuous, + _CardId.InfiniteImpermanence, _CardId.CalledByTheGrave, CardId.SwordsoulOfTaia, CardId.SwordsoulOfMoYe, + CardId.SwordsoulStrategistLongyuan, _CardId.AshBlossom, _CardId.MaxxC, _CardId.EffectVeiler, + CardId.SwordsoulEmergence, CardId.SwordsoulBlackout + }; + foreach (int discardCheck in discardList) + { + if (Bot.HasInHand(discardCheck)) + { + AI.SelectCard(discardCheck); + return; + } + } + + } + } + + public bool SpellSetCheck() + { + if (Duel.Phase == DuelPhase.Main1 && Bot.HasAttackingMonster() && Duel.Turn > 1) return false; + List onlyOneSetList = new List{ + CardId.SwordsoulBlackout + }; + if (onlyOneSetList.Contains(Card.Id) && Bot.HasInSpellZone(Card.Id)) + { + return false; + } + + // select place + if ((Card.IsTrap() || Card.HasType(CardType.QuickPlay))) + { + List avoid_list = new List(); + int setFornfiniteImpermanence = 0; + for (int i = 0; i < 5; ++i) + { + if (Enemy.SpellZone[i] != null && Enemy.SpellZone[i].IsFaceup() && Bot.SpellZone[4 - i] == null) + { + avoid_list.Add(4 - i); + setFornfiniteImpermanence += (int)System.Math.Pow(2, 4 - i); + } + } + if (Bot.HasInHand(_CardId.InfiniteImpermanence)) + { + if (Card.IsCode(_CardId.InfiniteImpermanence)) + { + AI.SelectPlace(setFornfiniteImpermanence); + return true; + } else + { + SelectSTPlace(Card, false, avoid_list); + return true; + } + } else + { + SelectSTPlace(); + } + return true; + } + + else if (Enemy.HasInSpellZone(_CardId.AntiSpellFragrance, true) || Bot.HasInSpellZone(_CardId.AntiSpellFragrance, true)) + { + if (Card.IsSpell() && !Bot.HasInSpellZone(Card.Id)) + { + SelectSTPlace(); + return true; + } + } + + return false; + } + + } +} \ No newline at end of file diff --git a/libWindbot/Game/AI/Decks/TearlamentsExecutor.cs b/libWindbot/Game/AI/Decks/TearlamentsExecutor.cs new file mode 100644 index 0000000..23c48a8 --- /dev/null +++ b/libWindbot/Game/AI/Decks/TearlamentsExecutor.cs @@ -0,0 +1,2655 @@ +using YGOSharp.OCGWrapper; +using YGOSharp.OCGWrapper.Enums; +using System.Collections.Generic; +using System.Linq; +using WindBot; +using WindBot.Game; +using WindBot.Game.AI; +using System; +namespace WindBot.Game.AI.Decks +{ + [Deck("Tearlaments", "AI_Tearlaments")] + class TearlamentsExecutor : DefaultExecutor + { + public class CardId + { + public const int ShaddollBeast = 3717252; + public const int ShaddollDragon = 77723643; + public const int TearlamentsScheiren = 572850; + public const int TearlamentsReinoheart = 73956664; + public const int KelbektheAncientVanguard = 25926710; + public const int MudoratheSwordOracle = 99937011; + public const int AgidotheAncientSentinel = 62320425; + public const int KeldotheSacredProtector = 63542003; + public const int NaelshaddollAriel = 97518132; + public const int TearlamentsHavnis = 37961969; + public const int TearlamentsMerrli = 74078255; + public const int DivineroftheHerald = 92919429; + public const int HeraldofOrangeLight = 17266660; + public const int HeraldofGreenLight = 21074344; + public const int Eva = 40177746; + public const int TearlamentsScream = 6767771; + public const int PrimevalPlanetPerlereino = 77103950; + public const int TearlamentsSulliek = 74920585; + + public const int TearlamentsKaleidoHeart = 28226490; + public const int TearlamentsRulkallos = 84330567; + public const int PredaplantDragostapelia = 69946549; + public const int TearlamentsKitkallos = 92731385; + public const int ElShaddollWinda = 94977269; + public const int ElderEntityNtss = 80532587; + public const int BaronnedeFleur = 84815190; + public const int FADawnDragster = 33158448; + public const int AbyssDweller = 21044178; + public const int UnderworldGoddessoftheClosedWorld = 98127546; + public const int MekkKnightCrusadiaAvramax = 21887175; + public const int KnightmareUnicorn = 38342335; + public const int SprightElf = 27381364; + public const int IP = 65741786; + } + // false: EDOPro + const bool IS_YGOPRO = true; + // YGOPro: 0x181 + // EDOPro: 0x182 + int SETCODE = 0x181; + + bool activate_TearlamentsScheiren_1 = false; + bool activate_TearlamentsScheiren_2 = false; + bool activate_TearlamentsReinoheart_1 = false; + bool activate_TearlamentsReinoheart_2 = false; + bool activate_TearlamentsHavnis_1 = false; + bool activate_TearlamentsHavnis_2 = false; + bool activate_TearlamentsMerrli_1 = false; + bool activate_TearlamentsMerrli_2 = false; + + bool activate_TearlamentsKitkallos_1 = false; + bool activate_TearlamentsKitkallos_2 = false; + bool activate_TearlamentsKitkallos_3 = false; + bool TearlamentsKitkallostohand = true; + + bool activate_TearlamentsScream_1 = false; + bool activate_TearlamentsScream_2 = false; + + bool activate_TearlamentsSulliek_1 = false; + bool activate_TearlamentsSulliek_2 = false; + + bool activate_AgidotheAncientSentinel_2 = false; + bool activate_KelbektheAncientVanguard_2 = false; + bool activate_TearlamentsRulkallos_1 = false; + bool activate_TearlamentsRulkallos_2 = false; + bool activate_MudoratheSwordOracle_2 = false; + bool activate_KeldotheSacredProtector_2 = false; + bool activate_PrimevalPlanetPerlereino_1 = false; + bool activate_PrimevalPlanetPerlereino_2 = false; + bool activate_TearlamentsKaleidoHeart_1 = false; + bool activate_TearlamentsKaleidoHeart_2 = false; + bool activate_Eva = false; + bool activate_DivineroftheHerald = false; + bool summoned = false; + bool spsummoned = false; + bool TearlamentsKitkallos_summoned = false; + + bool summon_SprightElf = false; + bool chainlist = false; + + bool pre_activate_PrimevalPlanetPerlereino = false; + + bool select_TearlamentsKitkallos = false; + private enum Flag + { + TearlamentsKitkallos = 0x1, + TearlamentsRulkallos = 0x2, + TearlamentsKaleidoHeart = 0x4, + PredaplantDragostapelia = 0x8, + ElShaddollWinda = 0x10 + } + + List remainCards = new List(); + List fusionExtra = new List(); + List fusionMaterial = new List(); + List on_chaining_cards = new List(); + List mcard_0 = new List() { null, null, null }; + List mcard_1 = new List() { null, null, null }; + List mcard_2 = new List() { null, null, null }; + List mcard_3 = new List() { null, null, null }; + List ran_fusion_mode_0 = new List() { false, false, false }; + List ran_fusion_mode_1 = new List() { false, false, false }; + List ran_fusion_mode_2 = new List() { false, false, false }; + List ran_fusion_mode_3 = new List() { false, false, false }; + + ClientCard _PredaplantDragostapelia = null; + ClientCard chain_PredaplantDragostapelia = null; + ClientCard chain_TearlamentsSulliek = null; + ClientCard tgcard = null; + ClientCard no_fusion_card = null; + List e_PredaplantDragostapelia_cards = new List(); + + ClientCard link_card = null; + List no_link_ids = new List() { CardId.TearlamentsRulkallos, CardId.BaronnedeFleur, CardId.MekkKnightCrusadiaAvramax, CardId.AbyssDweller, CardId.PredaplantDragostapelia, CardId.UnderworldGoddessoftheClosedWorld, CardId.FADawnDragster, CardId.TearlamentsKaleidoHeart }; + + List key_send_to_deck_ids = new List() + { + CardId.TearlamentsMerrli,CardId.TearlamentsScheiren,CardId.TearlamentsHavnis,CardId.TearlamentsReinoheart,8736823, + 98715423,17484499 + }; + List all_key_card_ids = new List() + { + 55623480,86682165,60461804,10000090,28651380,97565997,87074380,80208158,95440946,93880808,16261341, + 91749600,26866984,5141117,50383626,30576089,22586618,7445307,73478096,18558867, + 51617185,60880471,34172284,88774734,25451383,71197066,24226942,78077209,98787535, + 29601381,83203672,62383431,89552119,92418590,31042659,83303851,17502671,11366199, + 46668237,64382839,46290741,25607552,1295442,5560911,56174248,7407724,1855886,27198001, + 11074235,48372950,94142993,81866673,34966096,42006475,99733359,20799347,71985676, + 55787576,43266605,3422200,97962972,20773176,84976088,55151012,80208323,98881700,56677752, + 24506253,6180710,20056760,44928016,45702014,60316373,37683547,62962630,20065259,8571567, + 21351206,35998832,26077387,37351133,94730900,83682209,38695361,59707204,12469386,1833916, + 98806751,82496097,27182739,28762303,74578072,30303854,5370235,50546208,44818,67436768,29169993, + 10286023,19667590,47897376,74891384,66752837,43534808,56815977,81344070,59724555,93708824, + 43411796,7084129,51993760,87988305,23619206,86962245,48144778,30068120,9047460,25538345,69764158, + 70645913,55702233,10928224,79531196,23893227,57421866,94693857,78080961,9742784,59185998, + 93169863,46576366,2830693,68543408,50820852,2511,8972398,61488417,71734607,63180841,51447164, + 74586817,28403802,91575236,286392,97584719,60195675,24701066,20665527,73345237,23732205,146746, + 72218246,41999284,60303245 + }; + List key_no_send_to_deck_ids = new List() + { + CardId.TearlamentsRulkallos,50588353,44097050 + }; + List key_remove_ids = new List() + { + CardId.TearlamentsMerrli,CardId.TearlamentsScheiren,CardId.TearlamentsHavnis,CardId.TearlamentsReinoheart,15291624, + 11738489,44097050,15291624,63288573,70369116,83152482,72329844,24094258,86066372, + 74997493,85289965,21887175,11738489, 98127546,50588353,10389142,90590303,27548199, + }; + List key_no_remove_ids = new List() + { + 18743376,72355272,81555617,45960523,29596581,56713174,80280944,61103515,28297833, + 90020780,8736823 + }; + List bot_send_to_deck_ids = new List(); + public TearlamentsExecutor(GameAI ai, Duel duel) + : base(ai, duel) + { + AddExecutor(ExecutorType.Activate, CardId.TearlamentsScream, TearlamentsScreamEffect_1); + AddExecutor(ExecutorType.Activate, CardId.AbyssDweller, () => { return Duel.Player != 0; }); + AddExecutor(ExecutorType.Activate, CardId.TearlamentsKaleidoHeart, TearlamentsKaleidoHeartEffect); + AddExecutor(ExecutorType.Activate, CardId.UnderworldGoddessoftheClosedWorld); + AddExecutor(ExecutorType.SpSummon, CardId.FADawnDragster, FADawnDragsterSummon); + AddExecutor(ExecutorType.Activate, CardId.TearlamentsKitkallos, TearlamentsKitkallosEffect_2); + AddExecutor(ExecutorType.SpSummon, CardId.UnderworldGoddessoftheClosedWorld, UnderworldGoddessoftheClosedWorldSummon); + AddExecutor(ExecutorType.SpSummon, CardId.SprightElf, SprightElfSummon_2); + AddExecutor(ExecutorType.SpSummon, CardId.IP, IPSummon_2); + AddExecutor(ExecutorType.Activate, CardId.BaronnedeFleur, BaronnedeFleurEffect); + AddExecutor(ExecutorType.Activate, CardId.ElderEntityNtss, ElderEntityNtssEffect); + AddExecutor(ExecutorType.Activate, CardId.PredaplantDragostapelia, PredaplantDragostapeliaEffect); + AddExecutor(ExecutorType.Activate, CardId.HeraldofOrangeLight); + AddExecutor(ExecutorType.Activate, CardId.HeraldofGreenLight); + AddExecutor(ExecutorType.Activate, CardId.TearlamentsRulkallos, TearlamentsRulkallosEffect); + AddExecutor(ExecutorType.Activate, CardId.FADawnDragster); + AddExecutor(ExecutorType.Activate, CardId.PrimevalPlanetPerlereino, PrimevalPlanetPerlereinoEffect); + AddExecutor(ExecutorType.Activate, CardId.TearlamentsScheiren, TearlamentsScheirenEffect); + AddExecutor(ExecutorType.Activate, CardId.TearlamentsKitkallos, TearlamentsKitkallosEffect); + AddExecutor(ExecutorType.Activate, CardId.SprightElf, SprightElfEffect); + AddExecutor(ExecutorType.SpSummon, CardId.UnderworldGoddessoftheClosedWorld, UnderworldGoddessoftheClosedWorldSummon_3); + AddExecutor(ExecutorType.Activate, CardId.MudoratheSwordOracle, MudoratheSwordOracleEffect); + AddExecutor(ExecutorType.Activate, CardId.DivineroftheHerald, DivineroftheHeraldEffect); + AddExecutor(ExecutorType.Activate, CardId.TearlamentsMerrli, TearlamentsMerrliEffect); + AddExecutor(ExecutorType.Activate, CardId.TearlamentsHavnis, TearlamentsHavnisEffect); + AddExecutor(ExecutorType.Activate, CardId.TearlamentsReinoheart, TearlamentsReinoheartEffect); + AddExecutor(ExecutorType.Summon, CardId.DivineroftheHerald, DivineroftheHeraldSummon); + AddExecutor(ExecutorType.Summon, CardId.TearlamentsMerrli, () => { summoned = true; return true; }); + AddExecutor(ExecutorType.Summon, CardId.TearlamentsReinoheart, () => { summoned = true; return true; }); + AddExecutor(ExecutorType.Activate, CardId.AgidotheAncientSentinel, AgidotheAncientSentinelEffect); + AddExecutor(ExecutorType.Activate, CardId.KelbektheAncientVanguard, KelbektheAncientVanguardEffect); + AddExecutor(ExecutorType.Activate, CardId.NaelshaddollAriel, NaelshaddollArielEffect); + AddExecutor(ExecutorType.Activate, CardId.ShaddollDragon, ShaddollDragonEffect); + AddExecutor(ExecutorType.Activate, CardId.Eva, EvaEffect); + AddExecutor(ExecutorType.Activate, CardId.TearlamentsSulliek, TearlamentsSulliekEffect); + AddExecutor(ExecutorType.Activate, CardId.TearlamentsScream,()=> { return !AllActivated(); }); + AddExecutor(ExecutorType.Activate, CardId.KeldotheSacredProtector, MudoratheSwordOracleEffect); + AddExecutor(ExecutorType.Activate, CardId.ShaddollBeast, () => { return Bot.Deck.Count > 0; }); + AddExecutor(ExecutorType.Summon, CardId.DivineroftheHerald, ()=> { return !Bot.HasInHand(CardId.HeraldofGreenLight) && !Bot.HasInHand(CardId.HeraldofOrangeLight); }); + AddExecutor(ExecutorType.SpSummon, CardId.AbyssDweller, AbyssDwellerSummon_2); + AddExecutor(ExecutorType.SpSummon, CardId.SprightElf, SprightElfSummon); + AddExecutor(ExecutorType.SpSummon, CardId.BaronnedeFleur, BaronnedeFleurSummon); + AddExecutor(ExecutorType.SpSummon, CardId.FADawnDragster, () => { SetSpSummon(); return true; }); + AddExecutor(ExecutorType.SpSummon, CardId.AbyssDweller, AbyssDwellerSummon); + AddExecutor(ExecutorType.Activate, CardId.IP, IPEffect); + AddExecutor(ExecutorType.SpSummon, CardId.IP, IPSummon); + AddExecutor(ExecutorType.SpSummon, CardId.UnderworldGoddessoftheClosedWorld, UnderworldGoddessoftheClosedWorldSummon_2); + AddExecutor(ExecutorType.Activate, CardId.KnightmareUnicorn, KnightmareUnicornEffect); + AddExecutor(ExecutorType.SpSummon, CardId.KnightmareUnicorn, KnightmareUnicornSummon); + AddExecutor(ExecutorType.Activate, CardId.MekkKnightCrusadiaAvramax, MekkKnightCrusadiaAvramaxEffect); + AddExecutor(ExecutorType.SpSummon, CardId.MekkKnightCrusadiaAvramax, MekkKnightCrusadiaAvramaxSummon); + AddExecutor(ExecutorType.SpSummon, CardId.BaronnedeFleur, BaronnedeFleurSummon_2); + AddExecutor(ExecutorType.SpSummon, CardId.BaronnedeFleur, () => { return Bot.HasInMonstersZone(CardId.SprightElf, true, false, true); }); + AddExecutor(ExecutorType.Repos, DefaultMonsterRepos); + AddExecutor(ExecutorType.SpellSet, SpellSet); + } + + public override bool OnSelectHand() + { + // go first + return true; + } + + public override void OnNewTurn() + { + List cards = Bot.ExtraDeck.Where(card => card != null && card.Id == CardId.PredaplantDragostapelia).ToList(); + if (_PredaplantDragostapelia == null && cards.Count > 0) _PredaplantDragostapelia = cards.FirstOrDefault(); + if (!key_send_to_deck_ids.Contains(all_key_card_ids[0])) key_send_to_deck_ids.AddRange(all_key_card_ids); + if (!key_remove_ids.Contains(all_key_card_ids[0])) key_remove_ids.AddRange(all_key_card_ids); + if (_PredaplantDragostapelia != null && (_PredaplantDragostapelia.Location != CardLocation.MonsterZone || _PredaplantDragostapelia.IsFacedown())) + e_PredaplantDragostapelia_cards.Clear(); + List temp = new List(e_PredaplantDragostapelia_cards); + foreach (var card in temp) + { + if (card == null || card.Location != CardLocation.MonsterZone || card.IsFacedown()) e_PredaplantDragostapelia_cards.Remove(card); + } + activate_TearlamentsScheiren_1 = false; + activate_TearlamentsScheiren_2 = false; + activate_TearlamentsReinoheart_1 = false; + activate_TearlamentsReinoheart_2 = false; + activate_TearlamentsHavnis_1 = false; + activate_TearlamentsHavnis_2 = false; + activate_TearlamentsMerrli_1 = false; + activate_TearlamentsMerrli_2 = false; + activate_PrimevalPlanetPerlereino_1 = false; + activate_PrimevalPlanetPerlereino_2 = false; + + activate_TearlamentsKitkallos_1 = false; + activate_TearlamentsKitkallos_2 = false; + activate_TearlamentsKitkallos_3 = false; + activate_TearlamentsScream_1 = false; + activate_TearlamentsScream_2 = false; + activate_TearlamentsSulliek_1 = false; + activate_TearlamentsSulliek_2 = false; + activate_TearlamentsRulkallos_1 = false; + activate_TearlamentsKaleidoHeart_1 = false; + activate_TearlamentsKaleidoHeart_2 = false; + activate_AgidotheAncientSentinel_2 = false; + activate_KelbektheAncientVanguard_2 = false; + activate_Eva = false; + activate_DivineroftheHerald = false; + summoned = false; + spsummoned = false; + summon_SprightElf = false; + TearlamentsKitkallos_summoned = false; + } + private List GetZoneCards(CardLocation loc, ClientField player) + { + List res = new List(); + List temp = new List(); + if ((loc & CardLocation.Hand) > 0) { temp = player.Hand.Where(card => card != null).ToList(); if (temp.Count() > 0) res.AddRange(temp); } + if ((loc & CardLocation.MonsterZone) > 0) { temp = player.GetMonsters(); if (temp.Count() > 0) res.AddRange(temp); } + if ((loc & CardLocation.SpellZone) > 0) { temp = player.GetSpells(); if (temp.Count() > 0) res.AddRange(temp); } + if ((loc & CardLocation.Grave) > 0) { temp = player.Graveyard.Where(card => card != null).ToList(); if (temp.Count() > 0) res.AddRange(temp); } + if ((loc & CardLocation.Removed) > 0) { temp = player.Banished.Where(card => card != null).ToList(); if (temp.Count() > 0) res.AddRange(temp); } + if ((loc & CardLocation.Extra) > 0) { temp = player.ExtraDeck.Where(card => card != null).ToList(); if (temp.Count() > 0) res.AddRange(temp); } + return res; + } + private IList CardsIdToClientCards(IList cardsId, IList cardsList, bool uniqueId = true, bool alias = true) + { + if (cardsList?.Count() <= 0 || cardsId?.Count() <= 0) return new List(); + List res = new List(); + foreach (var cardid in cardsId) + { + List cards = cardsList.Where(card => card != null && (card.Id == cardid || ((card.Alias != 0 && cardid == card.Alias) & alias))).ToList(); + if (cards?.Count <= 0) continue; + cards.Sort(CardContainer.CompareCardAttack); + if (uniqueId) res.Add(cards.First()); + else res.AddRange(cards); + } + res = res.Distinct().ToList(); + return res; + } + private List GetKeyFusionCard(int key) + { + int id = 0; + if (Duel.Player == 0) + { + switch (key) + { + case 0: + case 2: id = CardId.TearlamentsKitkallos; break; + case 1: + case 6: id = CardId.TearlamentsRulkallos; break; + case 3: id = CardId.PredaplantDragostapelia; break; + case 4: id = CardId.TearlamentsKaleidoHeart; break; + case 5: id = CardId.PredaplantDragostapelia; break; + default: break; + } + } + else + { + switch (key) + { + case 0: + case 2: id = CardId.ElShaddollWinda; break; + case 1: + case 4: id = CardId.TearlamentsKitkallos; break; + case 3: id = CardId.TearlamentsRulkallos; break; + case 5: id = CardId.TearlamentsKaleidoHeart; break; + case 6: id = CardId.PredaplantDragostapelia; break; + default: break; + } + } + List res = new List(); + int index = -1; + for (int i = 0; i < fusionExtra.Count; ++i) + { + ClientCard card = fusionExtra[i]; + if (card == null) continue; + if (card.Id == id) + { + index = i; + res.Add(card); + break; + } + } + if (index > -1 && index < fusionExtra.Count) fusionExtra.RemoveAt(index); + return res; + } + private bool IsLastFusionCard() + { + int count = 0; + if (activate_TearlamentsScheiren_2) ++count; + if (activate_TearlamentsHavnis_2) ++count; + if (activate_TearlamentsMerrli_2) ++count; + return count >= 2; + } + private bool CheckFusion(int listindex, int id) + { + int key = -1; + if (Duel.Player == 0) + { + if (fusionExtra.Count > 0) + { + bool flag_4 = fusionExtra.Count(card => card != null && card.Id == CardId.PredaplantDragostapelia) > 0 && Bot.HasInMonstersZone(CardId.ElShaddollWinda, true, false, true); + bool flag_1 = ((Duel.Phase < DuelPhase.End && (!activate_TearlamentsKitkallos_1 || !activate_TearlamentsKitkallos_2)) || (Duel.Phase == DuelPhase.End && !activate_TearlamentsKitkallos_1 && !activate_TearlamentsKitkallos_2)) && fusionExtra.Count(card => card != null && card.Id == CardId.TearlamentsKitkallos) > 0; + bool flag_2 = fusionExtra.Count(card => card != null && card.Id == CardId.TearlamentsRulkallos) > 0 && (Bot.HasInGraveyard(CardId.TearlamentsKitkallos) || Bot.GetMonsters().Count(card => card != null && card.Id == CardId.TearlamentsKitkallos) > 1 || Duel.CurrentChain.Any(card=>card!=null && card.Controller==0 && card!=Card && (card.Id==CardId.TearlamentsScheiren || card.Id==CardId.TearlamentsHavnis || card.Id==CardId.TearlamentsMerrli))); + // && !activate_TearlamentsKaleidoHeart_1 && GetZoneCards(CardLocation.Onfield, Enemy).Count(card => card != null && !card.IsShouldNotBeTarget()) > 0 && IsShouldSummonFusion(-1, -1, false, (int)Flag.TearlamentsKaleidoHeart) + //&& (!Bot.HasInSpellZone(CardId.PrimevalPlanetPerlereino, true, true) || (Bot.HasInSpellZone(CardId.PrimevalPlanetPerlereino, true, true) && activate_PrimevalPlanetPerlereino_2) + bool flag_5 = fusionExtra.Count(card => card != null && card.Id == CardId.TearlamentsKaleidoHeart) > 0 && IsShouldSummonFusion(-1, -1, false, (int)Flag.TearlamentsKaleidoHeart); + //&& Enemy.GetMonsters().Any(card => card != null && card.HasType(CardType.Effect) && !card.IsDisabled() && card.IsFaceup() && !card.IsShouldNotBeTarget()) + bool flag_6 = fusionExtra.Count(card => card != null && card.Id == CardId.PredaplantDragostapelia) > 0 && IsShouldSummonFusion(-1, -1, false, (int)Flag.PredaplantDragostapelia); + bool flag_7 = fusionExtra.Count(card => card != null && card.Id == CardId.TearlamentsRulkallos) > 0 && IsShouldSummonFusion(-1, -1, false, (int)Flag.TearlamentsRulkallos) && IsLastFusionCard(); + bool flag_3 = fusionExtra.Count(card => card != null && card.Id == CardId.TearlamentsKitkallos) > 0; + if (flag_4) key = 3; + else if (flag_1) key = 0; + else if (flag_2) key = 1; + else if (flag_5) key = 4; + else if (flag_6) key = 5; + else if (flag_7) key = 6; + else if (flag_3) key = 2; + if (key > -1) + { + List fusionMaterialTemp = new List(fusionMaterial); + fusionMaterialTemp.Remove(Card); + switch (key) + { + case 0: + case 2: + fusionMaterialTemp = fusionMaterialTemp.Where(card => card != null && (card.HasRace(CardRace.Aqua) || (card.HasType(CardType.Monster) && card.HasSetcode(SETCODE)))).ToList(); + break; + case 1: + case 6: + fusionMaterialTemp = fusionMaterialTemp.Where(card => card != null && card.Id == CardId.TearlamentsKitkallos).ToList(); + break; + case 3: + fusionMaterialTemp = fusionMaterialTemp.Where(card => card != null && card.Id == CardId.ElShaddollWinda).ToList(); + break; + case 4: + fusionMaterialTemp = fusionMaterialTemp.Where(card => card != null && card.HasType(CardType.Monster) && card.HasSetcode(SETCODE)).ToList(); + break; + case 5: + fusionMaterialTemp = fusionMaterialTemp.Where(card => card != null && (card.Id != CardId.TearlamentsRulkallos || card.IsDisabled()) && card.HasType(CardType.Fusion)).ToList(); + break; + default: + return false; + } + fusionMaterialTemp = fusionMaterialTemp.Where(card => card != null && (card.HasRace(CardRace.Aqua) || (card.HasType(CardType.Monster) && card.HasSetcode(SETCODE)))).ToList(); + int chaining_key_count = on_chaining_cards.Count(card => card != null && (card.Id == CardId.AgidotheAncientSentinel || card.Id == CardId.KelbektheAncientVanguard)); + int chaining_key_count_2 = on_chaining_cards.Count(card => card != null && card.Id == CardId.TearlamentsSulliek); + List current_chain_cards = new List(Duel.CurrentChain); + IList current_chain_key_cards = new List(); + foreach (var card in current_chain_cards) + { + if (card == null || card.Controller == 1) continue; + if ((card.Id == CardId.TearlamentsMerrli && !HasInList(current_chain_key_cards, CardId.TearlamentsMerrli)) + || (card.Id == CardId.TearlamentsHavnis && !HasInList(current_chain_key_cards, CardId.TearlamentsHavnis) + || (card.Id == CardId.TearlamentsScheiren && !HasInList(current_chain_key_cards, CardId.TearlamentsScheiren)))) + current_chain_key_cards.Add(card); + } + if ((fusionMaterialTemp.Count <= 0 && chaining_key_count <= 0 && chaining_key_count_2 <= 0) || current_chain_key_cards.Count() >= 2) + { + if (!remainCards.Contains(Card)) remainCards.Add(Card); + return false; + } + switch (id) + { + case CardId.TearlamentsScheiren: activate_TearlamentsScheiren_2 = true; break; + case CardId.TearlamentsHavnis: activate_TearlamentsHavnis_2 = true; break; + case CardId.TearlamentsMerrli: activate_TearlamentsMerrli_2 = true; break; + default: break; + } + if (chaining_key_count > 0 || chaining_key_count_2 > 0) + { + ran_fusion_mode_0[listindex] = true; + ran_fusion_mode_1[listindex] = true; + ran_fusion_mode_2[listindex] = true; + return true; + } + fusionMaterialTemp.Sort(CardContainer.CompareCardAttack); + fusionMaterialTemp = GetDefaultMaterial(fusionMaterialTemp); + List res = GetKeyFusionCard(key); + mcard_0[listindex] = res.ElementAtOrDefault(0); + mcard_1[listindex] = Card; + mcard_2[listindex] = fusionMaterialTemp.ElementAtOrDefault(0); + if (res.Any(card => card != null && card.Id == CardId.TearlamentsKaleidoHeart)) + { + if (fusionMaterialTemp.Count <= 1) + { + mcard_0[listindex] = null; + mcard_1[listindex] = null; + mcard_2[listindex] = null; + ran_fusion_mode_0[listindex] = true; + ran_fusion_mode_1[listindex] = true; + ran_fusion_mode_2[listindex] = true; + return true; + } + if (mcard_2[listindex] != null && mcard_2[listindex].Id == CardId.TearlamentsReinoheart) + { + mcard_3[listindex] = fusionMaterialTemp.ElementAtOrDefault(1); + } + else + { + List temp = fusionMaterialTemp.Where(card => card != null && card.Id == CardId.TearlamentsReinoheart).ToList(); + if (temp.Count <= 0) + { + mcard_0[listindex] = null; + mcard_1[listindex] = null; + mcard_2[listindex] = null; + ran_fusion_mode_0[listindex] = true; + ran_fusion_mode_1[listindex] = true; + ran_fusion_mode_2[listindex] = true; + return true; + } + mcard_3[listindex] = temp.ElementAtOrDefault(0); + } + } + if (mcard_1[listindex] != null) fusionMaterial.Remove(mcard_1[listindex]); + if (mcard_2[listindex] != null) fusionMaterial.Remove(mcard_2[listindex]); + if (mcard_3[listindex] != null) fusionMaterial.Remove(mcard_3[listindex]); + //foreach (var card in fusionMaterial) + //{ + // if (card == null) continue; + // Logger.DebugWriteLine("remain" + card.Id); + //} + return true; + } + } + return false; + } + else + { + if (fusionExtra.Count > 0) + { + bool flag_1 = (fusionExtra.Count(card => card != null && card.Id == CardId.ElShaddollWinda) > 0 + && (fusionExtra.Count(card => card != null && card.Id == CardId.TearlamentsKitkallos) <= 0 || + activate_TearlamentsKitkallos_1 || Bot.GetMonstersInMainZone().Count >= 4 || TearlamentsKitkallos_summoned) && Bot.GetGraveyardMonsters().Any(card => card != null && card.HasSetcode(0x9d)) + && Card.HasAttribute(CardAttribute.Dark)); + bool flag_2 = fusionExtra.Count(card => card != null && card.Id == CardId.TearlamentsKitkallos) > 0 && !activate_TearlamentsKitkallos_1; + bool flag_3 = fusionExtra.Count(card => card != null && card.Id == CardId.ElShaddollWinda) > 0 && Bot.GetGraveyardMonsters().Any(card => card != null && card.HasSetcode(0x9d)) + && Card.HasAttribute(CardAttribute.Dark); + bool flag_4 = fusionExtra.Count(card => card != null && card.Id == CardId.TearlamentsRulkallos) > 0 && (Bot.HasInGraveyard(CardId.TearlamentsKitkallos) || Bot.HasInMonstersZone(CardId.TearlamentsKitkallos, false, false, true)); + bool flag_6 = fusionExtra.Count(card => card != null && card.Id == CardId.TearlamentsKaleidoHeart) > 0 && !activate_TearlamentsKaleidoHeart_1 && GetZoneCards(CardLocation.Onfield, Enemy).Count(card => card != null && !card.IsShouldNotBeTarget()) > 0 && IsShouldSummonFusion(-1, -1, false, (int)Flag.TearlamentsKaleidoHeart) + && (!Bot.HasInSpellZone(CardId.PrimevalPlanetPerlereino, true, true) || (Bot.HasInSpellZone(CardId.PrimevalPlanetPerlereino, true, true) && activate_PrimevalPlanetPerlereino_2)); + //&& Enemy.GetMonsters().Any(card => card != null && card.HasType(CardType.Effect) && !card.IsDisabled() && card.IsFaceup() && !card.IsShouldNotBeTarget()) + bool flag_7 = fusionExtra.Count(card => card != null && card.Id == CardId.PredaplantDragostapelia) > 0 && IsShouldSummonFusion(-1, -1, false, (int)Flag.PredaplantDragostapelia); + bool flag_5 = fusionExtra.Count(card => card != null && card.Id == CardId.TearlamentsKitkallos) > 0; + if (flag_1) key = 0; + else if (flag_2) key = 1; + else if (flag_3) key = 2; + else if (flag_4) key = 3; + else if (flag_6) key = 5; + else if (flag_7) key = 6; + else if (flag_5) key = 4; + if (key > -1) + { + List fusionMaterialTemp = new List(fusionMaterial); + fusionMaterialTemp.Remove(Card); + switch (key) + { + case 0: + case 2: + fusionMaterialTemp = fusionMaterialTemp.Where(card => card != null && (card.HasType(CardType.Monster) && card.HasSetcode(0x9d))).ToList(); + break; + case 1: + case 4: + fusionMaterialTemp = fusionMaterialTemp.Where(card => card != null && (card.HasRace(CardRace.Aqua) || (card.HasType(CardType.Monster) && card.HasSetcode(SETCODE)))).ToList(); + break; + case 3: + fusionMaterialTemp = fusionMaterialTemp.Where(card => card != null && card.Id == CardId.TearlamentsKitkallos).ToList(); + break; + case 5: + fusionMaterialTemp = fusionMaterialTemp.Where(card => card != null && card.HasType(CardType.Monster) && card.HasSetcode(SETCODE)).ToList(); + break; + case 6: + fusionMaterialTemp = fusionMaterialTemp.Where(card => card != null && (card.Id != CardId.TearlamentsRulkallos || card.IsDisabled()) && card.HasType(CardType.Fusion)).ToList(); + break; + default: + return false; + } + int chaining_key_count = on_chaining_cards.Count(card => card != null && (card.Id == CardId.AgidotheAncientSentinel || card.Id == CardId.KelbektheAncientVanguard)); + int chaining_key_count_2 = on_chaining_cards.Count(card => card != null && card.Id == CardId.TearlamentsSulliek); + if (fusionMaterialTemp.Count <= 0 && chaining_key_count <= 0 && chaining_key_count_2 <= 0) + { + if (!remainCards.Contains(Card)) remainCards.Add(Card); + return false; + } + switch (id) + { + case CardId.TearlamentsScheiren: activate_TearlamentsScheiren_2 = true; break; + case CardId.TearlamentsHavnis: activate_TearlamentsHavnis_2 = true; break; + case CardId.TearlamentsMerrli: activate_TearlamentsMerrli_2 = true; break; + default: break; + } + if (chaining_key_count > 0 || chaining_key_count_2 > 0) + { + ran_fusion_mode_0[listindex] = true; + ran_fusion_mode_1[listindex] = true; + ran_fusion_mode_2[listindex] = true; + return true; + } + fusionMaterialTemp.Sort(CardContainer.CompareCardAttack); + fusionMaterialTemp = GetDefaultMaterial(fusionMaterialTemp); + List res = GetKeyFusionCard(key); + mcard_0[listindex] = res.ElementAtOrDefault(0); + mcard_1[listindex] = Card; + mcard_2[listindex] = fusionMaterialTemp.ElementAtOrDefault(0); + if (res.Any(card => card != null && card.Id == CardId.TearlamentsKaleidoHeart)) + { + if (fusionMaterialTemp.Count <= 1) + { + mcard_0[listindex] = null; + mcard_1[listindex] = null; + mcard_2[listindex] = null; + ran_fusion_mode_0[listindex] = true; + ran_fusion_mode_1[listindex] = true; + ran_fusion_mode_2[listindex] = true; + return true; + } + if (mcard_2[listindex] != null && mcard_2[listindex].Id == CardId.TearlamentsReinoheart) + { + mcard_3[listindex] = fusionMaterialTemp.ElementAtOrDefault(1); + } + else + { + List temp = fusionMaterialTemp.Where(card => card != null && card.Id == CardId.TearlamentsReinoheart).ToList(); + if (temp.Count <= 0) + { + mcard_0[listindex] = null; + mcard_1[listindex] = null; + mcard_2[listindex] = null; + ran_fusion_mode_0[listindex] = true; + ran_fusion_mode_1[listindex] = true; + ran_fusion_mode_2[listindex] = true; + return true; + } + mcard_3[listindex] = temp.ElementAtOrDefault(0); + } + } + if (mcard_1[listindex] != null) fusionMaterial.Remove(mcard_1[listindex]); + if (mcard_2[listindex] != null) fusionMaterial.Remove(mcard_2[listindex]); + if (mcard_3[listindex] != null) fusionMaterial.Remove(mcard_3[listindex]); + if (listindex > 0 && mcard_0[0] != null && mcard_0[listindex] != null && mcard_0[listindex].Id == CardId.ElShaddollWinda) + { + ClientCard temp = mcard_0[0]; + mcard_0[0] = mcard_0[listindex]; + mcard_0[listindex] = temp; + + } + return true; + + } + } + return false; + } + } + private bool FusionEffect(int id) + { + if (!chainlist) + { + chainlist = true; + fusionExtra = Bot.ExtraDeck.Where(fcard => fcard != null).ToList(); + fusionMaterial = GetZoneCards(CardLocation.MonsterZone, Bot).Where(mcard => mcard != null && mcard.IsFaceup()).ToList(); + fusionMaterial.AddRange(GetZoneCards(CardLocation.Hand | CardLocation.Grave, Bot)); + + } + int index = 0; + if (id == CardId.TearlamentsScheiren) index = 0; + else if (id == CardId.TearlamentsHavnis) index = 1; + else if (id == CardId.TearlamentsMerrli) index = 2; + if (!CheckFusion(index, id)) return false; + SetSpSummon(); + return true; + } + public override CardPosition OnSelectPosition(int cardId, IList positions) + { + NamedCard card = NamedCard.Get(cardId); + if (Duel.Turn > 1 && Enemy.GetMonsterCount() <= 0 && (card.Attack > 0 || cardId == CardId.FADawnDragster) + && Duel.Player == 0) + { + return CardPosition.FaceUpAttack; + } + else if (Duel.Player == 1) + { + if (card.Attack < 2000) return CardPosition.FaceUpDefence; + int eatk = Util.GetBestAttack(Enemy); + if(eatk > card.Attack ) return CardPosition.FaceUpDefence; + return CardPosition.FaceUpAttack; + } + else + { + if (card.Attack <= 1000) return CardPosition.FaceUpDefence; + } + return base.OnSelectPosition(cardId, positions); + } + public override int OnSelectPlace(int cardId, int player, CardLocation location, int available) + { + if (player == 0 && location == CardLocation.MonsterZone) + { + if (cardId == CardId.SprightElf) + { + if ((Zones.z5 & available) > 0) return Zones.z5; + if ((Zones.z6 & available) > 0) return Zones.z6; + } + if (cardId == CardId.TearlamentsRulkallos && Bot.HasInExtra(CardId.SprightElf)) + { + if ((Zones.z2 & available) > 0) return Zones.z2; + if ((Zones.z0 & available) > 0) return Zones.z0; + } + ClientCard card = Bot.MonsterZone[5]; + if (card != null && card.Id == CardId.SprightElf) + { + if ((Zones.z0 & available) > 0) return Zones.z0; + if ((Zones.z2 & available) > 0) return Zones.z2; + } + card = Bot.MonsterZone[6]; + if (card != null && card.Id == CardId.SprightElf) + { + if ((Zones.z4 & available) > 0) return Zones.z4; + if ((Zones.z2 & available) > 0) return Zones.z2; + + } + + } + if (player == 0 && location == CardLocation.SpellZone && location != CardLocation.FieldZone) + { + List keys = new List() { 0, 1, 2, 3, 4 }; + while (keys.Count > 0) + { + int index = Program.Rand.Next(keys.Count); + int key = keys[index]; + int zone = 1 << key; + if ((zone & available) > 0) return zone; + keys.Remove(key); + } + + } + return base.OnSelectPlace(cardId, player, location, available); + } + public override int OnSelectOption(IList options) + { + if (options.Count == 2 && (IS_YGOPRO ? options.Contains(1190) : options.Contains(573))) + { + return TearlamentsKitkallostohand ? 0 : 1; + } + return base.OnSelectOption(options); + } + public override bool OnSelectYesNo(int desc) + { + if (desc == 1233663200) pre_activate_PrimevalPlanetPerlereino = true; + return base.OnSelectYesNo(desc); + } + public override void OnSelectChain(IList cards) + { + if (on_chaining_cards.Count <= 0 && cards.Count > 0) + { + on_chaining_cards = new List(cards); + } + base.OnSelectChain(cards); + } + public override void OnChaining(int player, ClientCard card) + { + if (!chainlist) + { + chainlist = true; + remainCards.Clear(); + fusionExtra = Bot.ExtraDeck.Where(fcard => fcard != null).ToList(); + fusionMaterial = GetZoneCards(CardLocation.MonsterZone, Bot).Where(mcard => mcard != null && mcard.IsFaceup()).ToList(); + fusionMaterial.AddRange(GetZoneCards(CardLocation.Hand | CardLocation.Grave, Bot)); + + } + base.OnChaining(player, card); + } + public override void OnChainEnd() + { + remainCards.Clear(); + fusionExtra.Clear(); + fusionMaterial.Clear(); + on_chaining_cards.Clear(); + tgcard = null; + no_fusion_card = null; + for (int i = 0; i < mcard_0.Count; ++i) mcard_0[i] = null; + for (int i = 0; i < mcard_1.Count; ++i) mcard_1[i] = null; + for (int i = 0; i < mcard_2.Count; ++i) mcard_2[i] = null; + for (int i = 0; i < mcard_3.Count; ++i) mcard_3[i] = null; + for (int i = 0; i < ran_fusion_mode_0.Count; ++i) ran_fusion_mode_0[i] = false; + for (int i = 0; i < ran_fusion_mode_1.Count; ++i) ran_fusion_mode_1[i] = false; + for (int i = 0; i < ran_fusion_mode_2.Count; ++i) ran_fusion_mode_2[i] = false; + chainlist = false; + base.OnChainEnd(); + } + private bool IsAvailableZone(int seq) + { + ClientCard card = Bot.MonsterZone[seq]; + if (seq == 5 || seq == 6) + { + ClientCard card1 = Bot.MonsterZone[5]; + ClientCard card2 = Bot.MonsterZone[6]; + if (card1 != null && card1.Controller == 0 && no_link_ids.Contains(card1.Id)) return false; + if (card2 != null && card2.Controller == 0 && no_link_ids.Contains(card2.Id)) return false; + } + if (card == null) return true; + if (card.Controller != 0) return false; + if (card.IsFacedown()) return false; + if (card.IsDisabled()) return true; + if (card.Id == CardId.SprightElf && summon_SprightElf) return false; + if (no_link_ids.Contains(card.Id)) return false; + return true; + } + private bool IsAvailableLinkZone() + { + int zones = 0; + List cards = Bot.GetMonstersInMainZone().Where(card => card != null && card.IsFaceup()).ToList(); + foreach (var card in cards) + { + zones |= card.GetLinkedZones(); + } + ClientCard e_card = Bot.MonsterZone[5]; + if (e_card != null && e_card.IsFaceup() && e_card.HasType(CardType.Link)) + { + if (e_card.Controller == 0) + { + if (e_card.HasLinkMarker(CardLinkMarker.BottomLeft)) + zones |= 1 << 0; + if (e_card.HasLinkMarker(CardLinkMarker.Bottom)) + zones |= 1 << 1; + if (e_card.HasLinkMarker(CardLinkMarker.BottomRight)) + zones |= 1 << 2; + } + if (e_card.Controller == 1) + { + if (e_card.HasLinkMarker(CardLinkMarker.TopLeft)) + zones |= 1 << 2; + if (e_card.HasLinkMarker(CardLinkMarker.Top)) + zones |= 1 << 1; + if (e_card.HasLinkMarker(CardLinkMarker.TopRight)) + zones |= 1 << 0; + } + } + e_card = Bot.MonsterZone[6]; + if (e_card != null && e_card.IsFaceup() && e_card.HasType(CardType.Link)) + { + if (e_card.Controller == 0) + { + if (e_card.HasLinkMarker(CardLinkMarker.BottomLeft)) + zones |= 1 << 2; + if (e_card.HasLinkMarker(CardLinkMarker.Bottom)) + zones |= 1 << 3; + if (e_card.HasLinkMarker(CardLinkMarker.BottomRight)) + zones |= 1 << 4; + } + if (e_card.Controller == 1) + { + if (e_card.HasLinkMarker(CardLinkMarker.TopLeft)) + zones |= 1 << 4; + if (e_card.HasLinkMarker(CardLinkMarker.Top)) + zones |= 1 << 3; + if (e_card.HasLinkMarker(CardLinkMarker.TopRight)) + zones |= 1 << 2; + } + } + zones &= 0x7f; + link_card = null; + if ((zones & Zones.z0) > 0 && IsAvailableZone(0)) return GetZoneLinkCards(0); + if ((zones & Zones.z1) > 0 && IsAvailableZone(1)) return GetZoneLinkCards(1); + if ((zones & Zones.z2) > 0 && IsAvailableZone(2)) return GetZoneLinkCards(2); + if ((zones & Zones.z3) > 0 && IsAvailableZone(3)) return GetZoneLinkCards(3); + if ((zones & Zones.z4) > 0 && IsAvailableZone(4)) return GetZoneLinkCards(4); + if (IsAvailableZone(5)) return GetZoneLinkCards(5); + if (IsAvailableZone(6)) return GetZoneLinkCards(6); + return false; + } + private bool GetZoneLinkCards(int index) + { + if (index >= Bot.MonsterZone.Count()) index = 0; + link_card = Bot.MonsterZone[index]; + return true; + } + + private List GetDefaultMaterial(IList cards) + { + List first_cards = new List(); + List first_mzone_cards = new List(); + List grave_cards = new List(); + List mzone_cards = new List(); + List hand_cards = new List(); + List last_cards = new List(); + List last_cards_2 = new List(); + foreach (var card in Duel.CurrentChain) + { + if (card == null) continue; + if (((card.Id == CardId.TearlamentsScheiren && !HasInList(last_cards, CardId.TearlamentsScheiren)) + || (card.Id == CardId.TearlamentsMerrli && !HasInList(last_cards, CardId.TearlamentsMerrli)) + || (card.Id == CardId.TearlamentsHavnis && !HasInList(last_cards, CardId.TearlamentsHavnis)) + ) && cards.Contains(card)) + { + last_cards.Add(card); + } + + } + foreach (var card in remainCards) + { + if (card == null) continue; + if (!cards.Contains(card)) first_cards.Add(card); + } + foreach (var card in cards) + { + if (card == null || first_mzone_cards.Contains(card) || first_cards.Contains(card) || last_cards.Contains(card) || + grave_cards.Contains(card) || mzone_cards.Contains(card) || hand_cards.Contains(card)) continue; + if (card.Id == CardId.ElShaddollWinda && card.IsFaceup() && card.Location == CardLocation.MonsterZone && !card.IsDisabled()) first_cards.Add(card); + else if (card.Id != CardId.TearlamentsRulkallos && first_mzone_cards.Count() <= 0 && card.Location == CardLocation.MonsterZone && Bot.GetMonstersInMainZone().Count > 4) + { + first_mzone_cards.Add(card); + } + else if (card.Location == CardLocation.Grave) + { + if ((((card.Id == CardId.TearlamentsScheiren && !activate_TearlamentsScheiren_2) + || (card.Id == CardId.TearlamentsMerrli && !activate_TearlamentsMerrli_2) + || (card.Id == CardId.TearlamentsHavnis && !activate_TearlamentsHavnis_2)) + && last_cards.Count(mcard => mcard != null && mcard.Id == card.Id) <= 0 + && on_chaining_cards.Count(mcard => mcard != null && mcard.Id == card.Id) > 0) + || (on_chaining_cards.Count(ccard => ccard != null && ccard == card) > 0 && on_chaining_cards.Count(cccard => cccard != null && cccard.Id == card.Id) <= 1 + && last_cards.Count(mcard => mcard != null && mcard.Id == card.Id) <= 0 && Duel.CurrentChain.Count(cccard => cccard != null && cccard.Id == card.Id) > 0)|| (no_fusion_card!=null && no_fusion_card==card)) + { + last_cards.Add(card); + } + else grave_cards.Add(card); + + } + else if (card.Location == CardLocation.Hand) + { + if (card.Id == CardId.TearlamentsReinoheart) hand_cards.Insert(0, card); + else if (Duel.Player == 1 && card.Id == CardId.TearlamentsHavnis && !activate_TearlamentsHavnis_1) last_cards.Add(card); + else hand_cards.Add(card); + } + else if (card.Location == CardLocation.MonsterZone) + { + if (card.Id == CardId.TearlamentsKitkallos && card.IsDisabled()) last_cards.Add(card); + else if (card.Id == CardId.TearlamentsKitkallos) last_cards_2.Insert(0, card); + else if (card.Id == CardId.TearlamentsRulkallos + || card.Id == CardId.TearlamentsKaleidoHeart || card.Id == CardId.PredaplantDragostapelia || + (Duel.Player == 1 && card.Id == CardId.ElShaddollWinda)) last_cards_2.Add(card); + else mzone_cards.Add(card); + } + else mzone_cards.Add(card); + } + first_cards.AddRange(first_mzone_cards); + first_cards.AddRange(grave_cards); + first_cards.AddRange(hand_cards); + first_cards.AddRange(mzone_cards); + first_cards.AddRange(last_cards); + first_cards.AddRange(last_cards_2); + return first_cards; + } + public override IList OnSelectFusionMaterial(IList cards, int min, int max) + { + if (AI.HaveSelectedCards()) return null; + for (int i = 2; i >= 0; --i) + { + List keys = cards.Where(card => card != null && card.Location != CardLocation.MonsterZone && card.Id == CardId.TearlamentsReinoheart).ToList(); + if (ran_fusion_mode_1[i] || ran_fusion_mode_2[i] || ran_fusion_mode_3[i]) + { + if (ran_fusion_mode_1[i]) ran_fusion_mode_1[i] = false; + else if (ran_fusion_mode_2[i]) ran_fusion_mode_2[i] = false; + else if (ran_fusion_mode_3[i]) ran_fusion_mode_3[i] = false; + cards.ToList().Sort(CardContainer.CompareCardAttack); + return keys.Count > 0 ? Util.CheckSelectCount(keys, cards, min, max) : Util.CheckSelectCount(GetDefaultMaterial(cards), cards, min, max); + } + List res = null; + ClientCard mcard = mcard_1[i]; + if (mcard != null) + { + if (keys.Count() > 0) + { + mcard_1[i] = null; + return Util.CheckSelectCount(keys, cards, min, max); + } + mcard_1[i] = null; + List temp = new List(cards); + temp.Sort(CardContainer.CompareCardAttack); + res = GetDefaultMaterial(temp); + return Util.CheckSelectCount(res, cards, min, max); + } + mcard = mcard_2[i]; + if (mcard != null) + { + mcard_2[i] = null; + List temp = new List(cards); + temp.Sort(CardContainer.CompareCardAttack); + res = GetDefaultMaterial(temp); + return Util.CheckSelectCount(res, cards, min, max); + } + mcard = mcard_3[i]; + if (mcard != null) + { + mcard_3[i] = null; + List temp = new List(cards); + temp.Sort(CardContainer.CompareCardAttack); + res = GetDefaultMaterial(temp); + return Util.CheckSelectCount(res, cards, min, max); + } + } + return base.OnSelectFusionMaterial(cards, min, max); + } + private bool HasInList(IList cards, int id) + { + if (cards == null || cards.Count <= 0) return false; + return cards.Any(card => card != null && card.Id == id); + } + private bool IsCanSpSummon() + { + if ((Bot.HasInMonstersZone(CardId.ElShaddollWinda, true, false, true) + || Enemy.HasInMonstersZone(CardId.ElShaddollWinda, true, false, true)) && spsummoned) return false; + return true; + } + private void SetSpSummon() + { + if (Bot.HasInMonstersZone(CardId.ElShaddollWinda, true, false, true) || + Enemy.HasInMonstersZone(CardId.ElShaddollWinda, true, false, true)) spsummoned = true; + } + public override IList OnSelectCard(IList cards, int min, int max, int hint, bool cancelable) + { + if ((AI.HaveSelectedCards() && mcard_0.All(card => card == null) && ran_fusion_mode_0.All(flag => !flag)) + || (hint == HintMsg.FusionMaterial)) return null; + if (pre_activate_PrimevalPlanetPerlereino) + { + pre_activate_PrimevalPlanetPerlereino = false; + List ids = GetCardsIdSendToHand(); + return Util.CheckSelectCount(CardsIdToClientCards(ids, cards, false, true), cards, min, max); + + } + //!IS_YGOPRO && select_TearlamentsKitkallos && hint == HintMsg.AddToHand + if ((IS_YGOPRO && hint == HintMsg.OperateCard) || (!IS_YGOPRO && select_TearlamentsKitkallos && hint == HintMsg.AddToHand)) + { + if (!IS_YGOPRO) select_TearlamentsKitkallos = false; + IList ids = new List(); + IList res = new List(); + if (Duel.Player == 0) + { + if (!activate_TearlamentsScheiren_1 && !Bot.HasInHand(CardId.TearlamentsScheiren) && HasInList(cards, CardId.TearlamentsScheiren) && !AllActivated()) ids.Add(CardId.TearlamentsScheiren); + if (!activate_TearlamentsMerrli_1 && !Bot.HasInHand(CardId.TearlamentsMerrli) && HasInList(cards, CardId.TearlamentsMerrli) && !AllActivated()) ids.Add(CardId.TearlamentsMerrli); + if(!Bot.HasInHand(CardId.TearlamentsHavnis) && HasInList(cards, CardId.TearlamentsHavnis)) ids.Add(CardId.TearlamentsHavnis); + if (!activate_TearlamentsReinoheart_1 && !Bot.HasInHand(CardId.TearlamentsReinoheart) && HasInList(cards, CardId.TearlamentsReinoheart)) ids.Add(CardId.TearlamentsReinoheart); + if (ids.Count() <= 0 && !activate_TearlamentsKitkallos_2) + { + List should_spsummon_cards = GetZoneCards(CardLocation.Grave | CardLocation.Hand, Bot); + should_spsummon_cards = should_spsummon_cards.Where(card => card != null && card.HasSetcode(SETCODE) && card.HasType(CardType.Monster)).ToList(); + if (should_spsummon_cards.Count() <= 0) + { + if (HasInList(cards, CardId.TearlamentsScheiren)) ids.Add(CardId.TearlamentsScheiren); + if (HasInList(cards, CardId.TearlamentsMerrli)) ids.Add(CardId.TearlamentsMerrli); + if (HasInList(cards, CardId.TearlamentsReinoheart)) ids.Add(CardId.TearlamentsReinoheart); + if (HasInList(cards, CardId.TearlamentsHavnis)) ids.Add(CardId.TearlamentsHavnis); + } + } + if (HasInList(cards, CardId.TearlamentsScream) && !activate_TearlamentsScream_1) ids.Add(CardId.TearlamentsScream); + if (HasInList(cards, CardId.TearlamentsSulliek) && on_chaining_cards.Count(card => card != null && card.Id == CardId.TearlamentsScream) <= 0) ids.Add(CardId.TearlamentsSulliek); + if (HasInList(cards, CardId.PrimevalPlanetPerlereino) && !activate_PrimevalPlanetPerlereino_1) ids.Add(CardId.PrimevalPlanetPerlereino); + if (ids.Count > 0) + { + TearlamentsKitkallostohand = true; + } + else + { + if (IsShouldSummonFusion(SETCODE, (int)CardRace.Aqua)) + { + if (!activate_TearlamentsHavnis_2 && HasInList(cards, CardId.TearlamentsHavnis)) ids.Add(CardId.TearlamentsHavnis); + if (!activate_TearlamentsScheiren_2 && HasInList(cards, CardId.TearlamentsScheiren)) ids.Add(CardId.TearlamentsScheiren); + if (!activate_TearlamentsMerrli_2 && HasInList(cards, CardId.TearlamentsMerrli)) ids.Add(CardId.TearlamentsMerrli); + if (ids.Count > 0) TearlamentsKitkallostohand = false; + } + } + + } + else + { + if (IsShouldSummonFusion(SETCODE, (int)CardRace.Aqua, true)) + { + if (!activate_TearlamentsHavnis_2 && HasInList(cards, CardId.TearlamentsHavnis) && !Bot.HasInHand(CardId.TearlamentsHavnis)) ids.Add(CardId.TearlamentsHavnis); + if (!activate_TearlamentsScheiren_2 && HasInList(cards, CardId.TearlamentsScheiren) && !Bot.HasInHand(CardId.TearlamentsScheiren)) ids.Add(CardId.TearlamentsScheiren); + if (!activate_TearlamentsMerrli_2 && HasInList(cards, CardId.TearlamentsMerrli) && !Bot.HasInHand(CardId.TearlamentsMerrli)) ids.Add(CardId.TearlamentsMerrli); + if (!activate_TearlamentsHavnis_2 && HasInList(cards, CardId.TearlamentsHavnis) && !ids.Contains(CardId.TearlamentsHavnis)) ids.Add(CardId.TearlamentsHavnis); + if (!activate_TearlamentsScheiren_2 && HasInList(cards, CardId.TearlamentsScheiren) && !ids.Contains(CardId.TearlamentsScheiren)) ids.Add(CardId.TearlamentsScheiren); + if (!activate_TearlamentsMerrli_2 && HasInList(cards, CardId.TearlamentsMerrli) && !ids.Contains(CardId.TearlamentsMerrli)) ids.Add(CardId.TearlamentsMerrli); + } + if (ids.Count > 0) TearlamentsKitkallostohand = false; + else + { + if (!Bot.HasInHand(CardId.TearlamentsHavnis) && !activate_TearlamentsHavnis_1 && HasInList(cards, CardId.TearlamentsHavnis)) + { + ids.Add(CardId.TearlamentsHavnis); + TearlamentsKitkallostohand = true; + } + else if (!activate_TearlamentsReinoheart_2 && HasInList(cards, CardId.TearlamentsReinoheart) && Bot.Hand.Any(card => card != null && card.HasSetcode(SETCODE))) + { + ids.Add(CardId.TearlamentsReinoheart); + TearlamentsKitkallostohand = false; + } + else if (!activate_TearlamentsSulliek_2 && HasInList(cards, CardId.TearlamentsSulliek)) + { + ids.Add(CardId.TearlamentsSulliek); + TearlamentsKitkallostohand = false; + } + else + { + if (!Bot.HasInHand(CardId.PrimevalPlanetPerlereino) && HasInList(cards, CardId.PrimevalPlanetPerlereino)) ids.Add(CardId.PrimevalPlanetPerlereino); + if (!Bot.HasInHand(CardId.TearlamentsScheiren) && HasInList(cards, CardId.TearlamentsScheiren)) ids.Add(CardId.TearlamentsScheiren); + if (!Bot.HasInHand(CardId.TearlamentsMerrli) && HasInList(cards, CardId.TearlamentsMerrli)) ids.Add(CardId.TearlamentsMerrli); + if (!Bot.HasInHand(CardId.TearlamentsReinoheart) && HasInList(cards, CardId.TearlamentsReinoheart)) ids.Add(CardId.TearlamentsReinoheart); + if (!Bot.HasInHand(CardId.TearlamentsScream) && HasInList(cards, CardId.TearlamentsScream)) ids.Add(CardId.TearlamentsScream); + if (!Bot.HasInHand(CardId.TearlamentsSulliek) && HasInList(cards, CardId.TearlamentsSulliek)) ids.Add(CardId.TearlamentsSulliek); + TearlamentsKitkallostohand = true; + } + } + + } + res = CardsIdToClientCards(ids, cards, false); + if (res.Count <= 0 || (Bot.HasInMonstersZone(CardId.ElShaddollWinda, true, false, true) && spsummoned)) TearlamentsKitkallostohand = true; + return res.Count > 0 ? Util.CheckSelectCount(res, cards, min, max) : null; + } + if (hint == HintMsg.Remove && cards.Any(card => card != null && ((card.HasAttribute(CardAttribute.Light) && card.HasRace(CardRace.Fairy)) || card.Controller == 1))) + { + IList res = CardsIdToClientCards(new List() { CardId.HeraldofGreenLight, CardId.HeraldofOrangeLight, CardId.DivineroftheHerald }, cards.Where(card => card != null && card.Location == CardLocation.Grave).ToList(), false); + List eres = cards.Where(card => card != null && card.Controller == 1 && !key_no_remove_ids.Contains(card.Id)).ToList(); + eres.Sort(CardContainer.CompareCardAttack); + eres.Reverse(); + int emax = eres.Count > max ? max : eres.Count <= 0 ? min : eres.Count; + int mmax = res.Count > max ? max : res.Count <= 0 ? min : res.Count; + return eres.Count > 0 ? Util.CheckSelectCount(eres, cards, emax, emax) : res.Count > 0 ? Util.CheckSelectCount(res, cards, mmax, mmax) : null; + } + if (hint == HintMsg.AddToHand && cards.Any(card => card != null && card.Location == CardLocation.Deck)) + { + List ids = new List() { CardId.HeraldofOrangeLight, CardId.HeraldofGreenLight, CardId.DivineroftheHerald }; + if (!Bot.HasInSpellZoneOrInGraveyard(CardId.DivineroftheHerald) && (Bot.HasInHand(CardId.HeraldofOrangeLight) || Bot.HasInHand(CardId.HeraldofGreenLight))) + { + ids.Clear(); + ids.AddRange(new List() { CardId.DivineroftheHerald, CardId.HeraldofOrangeLight, CardId.HeraldofGreenLight }); + } + ids.AddRange(GetCardsIdSendToHand().Distinct()); + IList res = CardsIdToClientCards(ids, cards, false); + return res.Count > 0 ? Util.CheckSelectCount(res, cards, max, max) : null; + } + if (hint == HintMsg.ToGrave && cards.Any(card => card != null && card.Location == CardLocation.MonsterZone) && min == 1 && max == 1) + { + List h_cards = new List(); + List m_cards = new List(); + List s_cards = new List(); + foreach (var card in cards) + { + if (card == null) continue; + if (card.Location == CardLocation.Hand) h_cards.Add(card); + else if (card.Location == CardLocation.SpellZone) s_cards.Add(card); + else m_cards.Add(card); + } + List mkeycards = new List(); + List hkeycards = new List(); + mkeycards = cards.Where(card => card != null && card.Id == CardId.TearlamentsKitkallos).ToList(); + if (!activate_TearlamentsKitkallos_3 && mkeycards.Count > 0 && !AllActivated() && IsShouldSummonFusion(SETCODE, (int)CardRace.Aqua) + && ((CheckRemainInDeck(CardId.TearlamentsHavnis) > 0 && !activate_TearlamentsHavnis_2) + || (CheckRemainInDeck(CardId.TearlamentsMerrli) > 0 && !activate_TearlamentsMerrli_2) + || (CheckRemainInDeck(CardId.TearlamentsScheiren) > 0 && !activate_TearlamentsScheiren_2))) + return Util.CheckSelectCount(mkeycards, cards, min, max); + if (IsShouldSummonFusion()) + { + if (!activate_TearlamentsScheiren_2 && HasInList(cards, CardId.TearlamentsScheiren)) + { + hkeycards = cards.Where(card => card != null && card.Id == CardId.TearlamentsScheiren && card.Location == CardLocation.Hand).ToList(); + mkeycards = cards.Where(card => card != null && card.Id == CardId.TearlamentsScheiren && card.Location == CardLocation.MonsterZone).ToList(); + } + else if (!activate_TearlamentsHavnis_2 && HasInList(cards, CardId.TearlamentsHavnis)) + { + hkeycards = cards.Where(card => card != null && card.Id == CardId.TearlamentsHavnis && card.Location == CardLocation.Hand).ToList(); + mkeycards = cards.Where(card => card != null && card.Id == CardId.TearlamentsHavnis && card.Location == CardLocation.MonsterZone).ToList(); + } + else if (!activate_TearlamentsMerrli_2 && HasInList(cards, CardId.TearlamentsMerrli)) + { + hkeycards = cards.Where(card => card != null && card.Id == CardId.TearlamentsMerrli && card.Location == CardLocation.Hand).ToList(); + mkeycards = cards.Where(card => card != null && card.Id == CardId.TearlamentsMerrli && card.Location == CardLocation.MonsterZone).ToList(); + } + else if (!activate_TearlamentsReinoheart_2 && (HasinZoneKeyCard(CardLocation.Hand) || (Bot.Hand.Count(ccard => ccard != null && ccard.HasSetcode(SETCODE) && ccard != cards.Where(card => card != null && card.Location == CardLocation.Hand && card.Id == CardId.TearlamentsReinoheart).FirstOrDefault()) > 0 && HasinZoneKeyCard(CardLocation.Deck)))) + { + hkeycards = cards.Where(card => card != null && card.Id == CardId.TearlamentsReinoheart && card.Location == CardLocation.Hand).ToList(); + mkeycards = cards.Where(card => card != null && card.Id == CardId.TearlamentsReinoheart && card.Location == CardLocation.MonsterZone).ToList(); + } + if (mkeycards.Count > 0 || hkeycards.Count > 0) + { + if (Bot.GetMonstersInMainZone().Count < 5) + { + hkeycards.AddRange(mkeycards); + return Util.CheckSelectCount(hkeycards, cards, min, max); + } + else + { + mkeycards.AddRange(hkeycards); + return Util.CheckSelectCount(mkeycards, cards, min, max); + } + } + } + mkeycards = cards.Where(card => card != null && card.Id == CardId.TearlamentsKaleidoHeart).ToList(); + if (!activate_TearlamentsKaleidoHeart_2 && IsCanSpSummon() && mkeycards.Count > 0) return Util.CheckSelectCount(mkeycards, cards, min, max); + mkeycards = cards.Where(card => card != null && card.Id == CardId.TearlamentsRulkallos).ToList(); + if (!activate_TearlamentsRulkallos_2 && IsCanSpSummon() && mkeycards.Count > 0) return Util.CheckSelectCount(mkeycards, cards, min, max); + s_cards.AddRange(h_cards); + m_cards.Sort(CardContainer.CompareCardAttack); + s_cards.AddRange(m_cards); + return Util.CheckSelectCount(s_cards, cards, min, max); + } + if (hint == HintMsg.ToGrave && cards.Any(card => card != null && card.Location == CardLocation.Hand) && min == 1 && max == 1) + { + IList ids = new List(); + if (!activate_AgidotheAncientSentinel_2) ids.Add(CardId.AgidotheAncientSentinel); + if (!activate_KelbektheAncientVanguard_2) ids.Add(CardId.KelbektheAncientVanguard); + if (IsShouldSummonFusion(SETCODE, (int)CardRace.Aqua)) + { + if (activate_TearlamentsScheiren_1 && !activate_TearlamentsScheiren_2) ids.Add(CardId.TearlamentsScheiren); + if (summoned && !activate_TearlamentsMerrli_2) ids.Add(CardId.TearlamentsMerrli); + if (!activate_TearlamentsHavnis_2) ids.Add(CardId.TearlamentsHavnis); + if (!activate_TearlamentsMerrli_2) ids.Add(CardId.TearlamentsMerrli); + if (!activate_TearlamentsScheiren_2) ids.Add(CardId.TearlamentsScheiren); + } + if (Enemy.GetSpellCount() > 0) ids.Add(CardId.ShaddollDragon); + if (Bot.Deck.Count > 0) ids.Add(CardId.ShaddollBeast); + if (Enemy.Graveyard.Count > 0) ids.Add(CardId.NaelshaddollAriel); + if (!activate_Eva && Bot.Graveyard.Count(card => card != null && card.HasAttribute(CardAttribute.Light) && card.HasRace(CardRace.Fairy)) > 0 + && (CheckRemainInDeck(CardId.HeraldofGreenLight) > 0 || CheckRemainInDeck(CardId.HeraldofOrangeLight) > 0)) ids.Add(CardId.Eva); + if (((Bot.HasInHand(CardId.HeraldofOrangeLight) || Bot.HasInHand(CardId.HeraldofGreenLight)) + && Bot.Hand.Count(card => card != null && card.HasRace(CardRace.Fairy)) > 2) + || (!Bot.HasInHand(CardId.HeraldofOrangeLight) && !Bot.HasInHand(CardId.HeraldofGreenLight))) + { + ids.Add(CardId.MudoratheSwordOracle); + ids.Add(CardId.KeldotheSacredProtector); + } + if (!activate_TearlamentsScream_2 && CheckRemainInDeck(CardId.TearlamentsSulliek) > 0) ids.Add(CardId.TearlamentsScream); + if (!activate_TearlamentsSulliek_2) ids.Add(CardId.TearlamentsSulliek); + if (!activate_TearlamentsReinoheart_2 && HasInList(cards, CardId.TearlamentsReinoheart)) ids.Add(CardId.TearlamentsReinoheart); + if (!cards.Any(card => card != null && !card.HasRace(CardRace.Fairy))) + { + ids.Add(CardId.HeraldofGreenLight); + ids.Add(CardId.HeraldofOrangeLight); + } + ids = ids.Distinct().ToList(); + IList res = CardsIdToClientCards(ids, cards, false); + List temp = new List(cards); + foreach (var card in cards) + { + if (temp.Count <= 1) break; + if ((!summoned && card.Id == CardId.DivineroftheHerald) + || card.Id == CardId.HeraldofOrangeLight || card.Id == CardId.HeraldofGreenLight + || (!summoned && card.Id == CardId.TearlamentsMerrli && !activate_TearlamentsHavnis_1)) + { + temp.Remove(card); + } + } + temp.Sort(CardContainer.CompareCardAttack); + return res.Count > 0 ? Util.CheckSelectCount(res, cards, min, max) : Util.CheckSelectCount(temp, cards, min, max); + + } + if (hint == HintMsg.ToGrave && cards.Any(card => card != null && (card.Location == CardLocation.Deck || card.Location == CardLocation.Extra)) && min == 1 && max == 1) + { + List cardsid = new List(); + if (HasInList(cards, CardId.AgidotheAncientSentinel) && !activate_AgidotheAncientSentinel_2 && !AllActivated()) + { + if (HasInList(cards, CardId.KelbektheAncientVanguard) && !activate_KelbektheAncientVanguard_2 && Bot.HasInHand(CardId.AgidotheAncientSentinel)) + { + cardsid.Add(CardId.KelbektheAncientVanguard); + } + else cardsid.Add(CardId.AgidotheAncientSentinel); + } + else if (HasInList(cards, CardId.KelbektheAncientVanguard) && !activate_KelbektheAncientVanguard_2 && !AllActivated()) + { + cardsid.Add(CardId.KelbektheAncientVanguard); + } + else if (HasInList(cards, CardId.ElderEntityNtss) && GetZoneCards(CardLocation.Onfield, Enemy).Count(card => card != null && !card.IsShouldNotBeTarget()) > 0) + { + cardsid.Add(CardId.ElderEntityNtss); + } + if (HasInList(cards, CardId.Eva) && !activate_Eva && + (CheckRemainInDeck(CardId.HeraldofOrangeLight) > 0 || CheckRemainInDeck(CardId.HeraldofGreenLight) > 0)) + cardsid.Add(CardId.Eva); + if (HasInList(cards, CardId.MudoratheSwordOracle)) cardsid.Add(CardId.MudoratheSwordOracle); + if (HasInList(cards, CardId.KeldotheSacredProtector)) cardsid.Add(CardId.KeldotheSacredProtector); + if (IsShouldSummonFusion()) + { + if (cards.Any(card => card != null && card.Id == CardId.TearlamentsHavnis) && !activate_TearlamentsHavnis_2) cardsid.Add(CardId.TearlamentsHavnis); + if (cards.Any(card => card != null && card.Id == CardId.TearlamentsMerrli) && !activate_TearlamentsMerrli_2) cardsid.Add(CardId.TearlamentsMerrli); + if (cards.Any(card => card != null && card.Id == CardId.TearlamentsScheiren) && !activate_TearlamentsScheiren_2) cardsid.Add(CardId.TearlamentsScheiren); + } + if (cards.Any(card => card != null && card.Id == CardId.TearlamentsSulliek) && !activate_TearlamentsSulliek_2) cardsid.Add(CardId.TearlamentsSulliek); + if (cards.Any(card => card != null && card.Id == CardId.TearlamentsScream) && !activate_TearlamentsScream_2 && CheckRemainInDeck(CardId.TearlamentsSulliek) > 0) cardsid.Add(CardId.TearlamentsScream); + IList res = CardsIdToClientCards(cardsid, cards, false); + if (res.Count > 0) no_fusion_card = res[0]; + return res.Count > 0 ? Util.CheckSelectCount(res, cards, min, max) : null; + } + if (hint == HintMsg.ToDeck && cards.Any(card => card != null && card.Location == CardLocation.Grave)) + { + List b_cards = new List(); + List e_cards = new List(); + List e_temp_1 = new List(); + List e_temp_2 = new List(); + List e_temp_3 = new List(); + List e_temp_4 = new List(); + foreach (var card in cards) + { + if (card == null) continue; + if (card.Controller == 0) b_cards.Add(card); + else e_cards.Add(card); + } + if (e_cards.Count <= 0 && Bot.Deck.Count > 2) + { + return null; + } + int imax = e_cards.Count > max ? max : e_cards.Count < 0 ? min : e_cards.Count; + if (Duel.CurrentChain == null || Duel.ChainTargets == null) return Util.CheckSelectCount(cards, cards, imax, imax); + foreach (var card in Duel.CurrentChain) + { + if (card == null || card.Controller == 0 || card.Location != CardLocation.Grave) continue; + if (cards.Contains(card)) + { + if (key_no_send_to_deck_ids.Contains(card.Id)) continue; + else if (key_send_to_deck_ids.Contains(card.Id) && !e_temp_1.Contains(card)) e_temp_1.Add(card); + else if (!e_temp_2.Contains(card)) e_temp_2.Add(card); + } + } + foreach (var card in Duel.ChainTargets) + { + if (card == null || card.Controller == 0 || card.Location != CardLocation.Grave) continue; + if (cards.Contains(card)) + { + if (key_no_send_to_deck_ids.Contains(card.Id)) continue; + else if (key_send_to_deck_ids.Contains(card.Id) && !e_temp_1.Contains(card)) e_temp_1.Add(card); + else if (!e_temp_2.Contains(card)) e_temp_2.Add(card); + } + } + foreach (var card in cards) + { + if (card == null || card.Controller == 0 || card.Location != CardLocation.Grave) continue; + if (key_send_to_deck_ids.Contains(card.Id) && !e_temp_1.Contains(card) && !e_temp_2.Contains(card)) e_temp_2.Add(card); + } + if (Bot.Deck.Count <= 0 && Duel.CurrentChain.Any(card => card != null && card.Controller == 0 && card.Id == CardId.ShaddollBeast)) + { + bot_send_to_deck_ids = new List { CardId.TearlamentsScheiren, CardId.TearlamentsMerrli, CardId.TearlamentsHavnis }; + IList temp = CardsIdToClientCards(bot_send_to_deck_ids, b_cards); + if (temp.Count <= 0) + { + for (int i = 0; i < b_cards.Count; i++) + { + if (i >= 2) break; + if (b_cards[i] == null || e_temp_1.Contains(b_cards[i])) continue; + e_temp_1.Insert(0, b_cards[i]); + } + } + else + { + for (int i = 0; i < temp.Count; i++) + { + if (i >= 2) break; + if (temp[i] == null || e_temp_1.Contains(temp[i])) continue; + e_temp_1.Insert(0, temp[i]); + } + } + } + if (Bot.Deck.Count < 3) + { + bot_send_to_deck_ids = new List(); + IList temp = new List(); + if (b_cards.Count > 0 && Bot.ExtraDeck.Any(card => card != null && card.HasType(CardType.Fusion) && card.Id != CardId.ElderEntityNtss)) + { + if (CheckRemainInDeck(CardId.TearlamentsScheiren) <= 0 && HasInList(cards, CardId.TearlamentsScheiren)) bot_send_to_deck_ids.Add(CardId.TearlamentsScheiren); + if (CheckRemainInDeck(CardId.TearlamentsMerrli) <= 0 && HasInList(cards, CardId.TearlamentsMerrli)) bot_send_to_deck_ids.Add(CardId.TearlamentsMerrli); + if (CheckRemainInDeck(CardId.TearlamentsHavnis) <= 0 && HasInList(cards, CardId.TearlamentsHavnis)) bot_send_to_deck_ids.Add(CardId.TearlamentsHavnis); + } + temp = CardsIdToClientCards(bot_send_to_deck_ids, b_cards); + if (temp.Count > 0) + { + for (int i = 0; i < temp.Count; i++) + { + if (temp[i] == null || e_temp_4.Contains(temp[i]) || e_temp_1.Contains(temp[i]) + || e_temp_2.Contains(temp[i])) continue; + e_temp_4.Add(temp[i]); + } + } + bot_send_to_deck_ids.Clear(); + if (HasInList(cards, CardId.NaelshaddollAriel)) bot_send_to_deck_ids.Add(CardId.NaelshaddollAriel); + if (CheckRemainInDeck(CardId.KelbektheAncientVanguard) <= 0 && HasInList(cards, CardId.KelbektheAncientVanguard)) bot_send_to_deck_ids.Add(CardId.KelbektheAncientVanguard); + if (CheckRemainInDeck(CardId.AgidotheAncientSentinel) <= 0 && HasInList(cards, CardId.AgidotheAncientSentinel)) bot_send_to_deck_ids.Add(CardId.AgidotheAncientSentinel); + if (CheckRemainInDeck(CardId.HeraldofOrangeLight) <= 0 && HasInList(cards, CardId.HeraldofOrangeLight)) bot_send_to_deck_ids.Add(CardId.HeraldofOrangeLight); + if (CheckRemainInDeck(CardId.HeraldofGreenLight) <= 0 && HasInList(cards, CardId.HeraldofGreenLight)) bot_send_to_deck_ids.Add(CardId.HeraldofGreenLight); + temp = CardsIdToClientCards(bot_send_to_deck_ids, b_cards); + if (temp.Count > 0) + { + for (int i = 0; i < temp.Count; i++) + { + if (temp[i] == null || e_temp_4.Contains(temp[i]) || e_temp_1.Contains(temp[i]) + || e_temp_2.Contains(temp[i])) continue; + e_temp_4.Add(temp[i]); + } + } + foreach (var card in b_cards) + { + if (card == null || e_temp_4.Contains(card) || e_temp_1.Contains(card) + || e_temp_2.Contains(card)) continue; + e_temp_4.Add(card); + } + } + e_temp_3 = e_cards.Where(card => card != null && !e_temp_1.Contains(card) && !e_temp_2.Contains(card) && !e_temp_4.Contains(card)).ToList(); + e_temp_1.AddRange(e_temp_2); + e_temp_1.AddRange(e_temp_4); + e_temp_1.AddRange(e_temp_3); + imax = e_temp_1.Count > max ? max : e_temp_1.Count < 0 ? min : e_temp_1.Count; + return e_temp_1.Count > 0 ? Util.CheckSelectCount(e_temp_1, cards, imax, imax) : Util.CheckSelectCount(e_cards, cards, max, max); + + } + if (hint == HintMsg.SpSummon && cards.Any(card => card != null && (card.Level == 2 || card.LinkCount == 2) && card.Location == CardLocation.Grave)) + { + IList res = new List(); + List ids = new List(); + if (Duel.Player == 0) + { + if (HasInList(cards, CardId.TearlamentsMerrli) && !activate_TearlamentsMerrli_1 && IsCanFusionSummon()) + { + ids.Add(CardId.TearlamentsMerrli); + } + else if (HasInList(cards, CardId.DivineroftheHerald) && !activate_DivineroftheHerald) + { + ids.Add(CardId.DivineroftheHerald); + } + else if (HasInList(cards, CardId.TearlamentsMerrli) && !activate_TearlamentsMerrli_1) + { + ids.Add(CardId.TearlamentsMerrli); + } + else if (HasInList(cards, CardId.IP) && Bot.ExtraDeck.Count(card => card != null && card.LinkCount > 2) > 0) + { + ids.Add(CardId.IP); + } + else + { + ids = new List() { CardId.DivineroftheHerald, CardId.TearlamentsMerrli, CardId.HeraldofOrangeLight, CardId.HeraldofGreenLight }; + } + } + else + { + if (HasInList(cards, CardId.DivineroftheHerald) && !activate_DivineroftheHerald && FusionDeckCheck() + && ((CheckRemainInDeck(CardId.AgidotheAncientSentinel) > 0 && !activate_AgidotheAncientSentinel_2) + || (CheckRemainInDeck(CardId.KelbektheAncientVanguard) > 0 && !activate_KelbektheAncientVanguard_2))) + { + ids.Add(CardId.DivineroftheHerald); + } + if (HasInList(cards, CardId.TearlamentsMerrli) && !activate_TearlamentsMerrli_1 && + IsShouldSummonFusion(-1, -1, true) && FusionDeckCheck()) + { + ids.Add(CardId.TearlamentsMerrli); + } + else if (HasInList(cards, CardId.DivineroftheHerald) && Bot.HasInExtra(CardId.ElderEntityNtss) && GetZoneCards(CardLocation.Onfield, Enemy).Any(card => card != null && !card.IsShouldNotBeTarget())) + { + ids.Add(CardId.DivineroftheHerald); + } + else if (HasInList(cards, CardId.IP) && Bot.ExtraDeck.Any(card => card != null && card.LinkCount > 2)) + { + ids.Add(CardId.IP); + } + else + { + ids = new List() { CardId.DivineroftheHerald, CardId.TearlamentsMerrli, CardId.HeraldofOrangeLight, CardId.HeraldofGreenLight }; + } + } + res = CardsIdToClientCards(ids, cards, false); + return res.Count > 0 ? Util.CheckSelectCount(res, cards, min, max) : null; + } + //(IS_YGOPRO && hint == HintMsg.Disable) || (!IS_YGOPRO && hint == HintMsg.Negate) + if (IS_YGOPRO && hint == HintMsg.Disable) + { + if (chain_TearlamentsSulliek != null && cards.Contains(chain_TearlamentsSulliek)) + { + List res = new List() { chain_TearlamentsSulliek }; + return Util.CheckSelectCount(res, cards, min, max); + } + return null; + } + if (hint == HintMsg.Faceup && cards.Any(card => card != null && card.Controller == 1)) + { + if (chain_PredaplantDragostapelia != null && cards.Contains(chain_PredaplantDragostapelia)) + { + List res = new List() { chain_PredaplantDragostapelia }; + e_PredaplantDragostapelia_cards.Add(chain_PredaplantDragostapelia); + return Util.CheckSelectCount(res, cards, min, max); + } + return null; + } + for (int i = 2; i >= 0; --i) + { + if (ran_fusion_mode_0[i]) + { + ran_fusion_mode_0[i] = false; + if (Duel.Player == 0) + { + List res0 = cards.Where(card => card != null && card.Id == CardId.PredaplantDragostapelia).ToList(); + if (res0.Count > 0 && Bot.HasInMonstersZone(CardId.ElShaddollWinda, true, false, true)) + { + return Util.CheckSelectCount(res0, cards, min, max); + } + res0 = cards.Where(card => card != null && card.Id == CardId.TearlamentsKitkallos).ToList(); + if (res0.Count > 0 && ((!activate_TearlamentsKitkallos_1 && + ((!activate_TearlamentsScheiren_2 && CheckRemainInDeck(CardId.TearlamentsScheiren) > 0) + || (!activate_TearlamentsHavnis_2 && CheckRemainInDeck(CardId.TearlamentsHavnis) > 0) + || (!activate_TearlamentsMerrli_2 && CheckRemainInDeck(CardId.TearlamentsMerrli) > 0))) || !activate_TearlamentsKitkallos_2)) + { + TearlamentsKitkallos_summoned = true; + return Util.CheckSelectCount(res0, cards, min, max); + } + res0 = cards.Where(card => card != null && card.Id == CardId.TearlamentsKaleidoHeart).ToList(); + //if (GetZoneCards(CardLocation.Onfield, Enemy).Count(card => card != null && !card.IsShouldNotBeTarget()) > 0 && IsShouldSummonFusion(-1, -1, false, (int)Flag.TearlamentsKaleidoHeart) + // && !activate_TearlamentsKaleidoHeart_1 && (!Bot.HasInSpellZone(CardId.PrimevalPlanetPerlereino, true, true) || (Bot.HasInSpellZone(CardId.PrimevalPlanetPerlereino, true, true) && activate_PrimevalPlanetPerlereino_2))) + if(res0.Count>0 && IsShouldSummonFusion(-1, -1, false, (int)Flag.TearlamentsKaleidoHeart)) + { + ran_fusion_mode_3[i] = true; + return Util.CheckSelectCount(res0, cards, min, max); + } + res0 = cards.Where(card => card != null && card.Id == CardId.TearlamentsRulkallos).ToList(); + if (Bot.Graveyard.Count(card => card != null && card.Id == CardId.TearlamentsKitkallos) > 0 || + Bot.MonsterZone.Count(card => card != null && card.Id == CardId.TearlamentsKitkallos && card.IsFaceup()) > 0 && res0.Count > 0) + { + activate_TearlamentsRulkallos_2 = false; + return Util.CheckSelectCount(res0, cards, min, max); + } + res0 = cards.Where(card => card != null && card.Id == CardId.PredaplantDragostapelia).ToList(); + //if (res0.Count > 0 && IsShouldSummonFusion(-1, -1, false, (int)Flag.PredaplantDragostapelia) && Enemy.GetMonsters().Any(card => card != null && card.HasType(CardType.Effect) && !card.IsDisabled() && card.IsFaceup() && !card.IsShouldNotBeTarget())) + if (res0.Count > 0 && IsShouldSummonFusion(-1, -1, false, (int)Flag.PredaplantDragostapelia)) + { + return Util.CheckSelectCount(res0, cards, min, max); + } + List res1 = cards.Where(card => card != null && card.Id == CardId.TearlamentsKitkallos).ToList(); + if (res1.Count > 0) + { + List material = GetDefaultMaterial(fusionMaterial); + if (((material.Count(mcard => mcard != null && mcard.Id == CardId.TearlamentsKitkallos && mcard.Location == CardLocation.MonsterZone) > 0 && + activate_TearlamentsKitkallos_1) || (material.Count(mcard => mcard != null && mcard.Id == CardId.TearlamentsKitkallos && mcard.Location == CardLocation.MonsterZone) > 1)) && + material.Count <= 2) + { + if (res0.Count > 0) + { + activate_TearlamentsRulkallos_2 = false; + return Util.CheckSelectCount(res0, cards, min, max); + } + TearlamentsKitkallos_summoned = true; + return Util.CheckSelectCount(res1, cards, min, max); + } + return Util.CheckSelectCount(res1, cards, min, max); + } + + } + else + { + List res = cards.Where(card => card != null && card.Id == CardId.TearlamentsKitkallos).ToList(); + if (res.Count > 0 && !activate_TearlamentsKitkallos_1 && + ((!activate_TearlamentsScheiren_2 && CheckRemainInDeck(CardId.TearlamentsScheiren) > 0) + || (!activate_TearlamentsHavnis_2 && CheckRemainInDeck(CardId.TearlamentsHavnis) > 0) + || (!activate_TearlamentsMerrli_2 && CheckRemainInDeck(CardId.TearlamentsMerrli) > 0)) && Bot.GetMonstersInMainZone().Count < 4) + { + TearlamentsKitkallos_summoned = true; + return Util.CheckSelectCount(res, cards, min, max); + } + res = cards.Where(card => card != null && card.Id == CardId.TearlamentsRulkallos).ToList(); + if (res.Count > 0) return Util.CheckSelectCount(res, cards, min, max); + res = cards.Where(card => card != null && card.Id == CardId.TearlamentsKaleidoHeart).ToList(); + if (res.Count>0 && GetZoneCards(CardLocation.Onfield, Enemy).Count(card => card != null && !card.IsShouldNotBeTarget()) > 0 && IsShouldSummonFusion(-1, -1, false, (int)Flag.TearlamentsKaleidoHeart) + && !activate_TearlamentsKaleidoHeart_1 && (!Bot.HasInSpellZone(CardId.PrimevalPlanetPerlereino, true, true) || (Bot.HasInSpellZone(CardId.PrimevalPlanetPerlereino, true, true) && activate_PrimevalPlanetPerlereino_2))) + { + ran_fusion_mode_3[i] = true; + return Util.CheckSelectCount(res, cards, min, max); + } + res = cards.Where(card => card != null && card.Id == CardId.ElShaddollWinda).ToList(); + if (res.Count > 0) return Util.CheckSelectCount(res, cards, min, max); + res = cards.Where(card => card != null && card.Id == CardId.PredaplantDragostapelia).ToList(); + if (res.Count > 0 && IsShouldSummonFusion(-1, -1, false, (int)Flag.PredaplantDragostapelia)) + { + return Util.CheckSelectCount(res, cards, min, max); + } + res = cards.Where(card => card != null && card.Id == CardId.TearlamentsKaleidoHeart).ToList(); + if (res.Count > 0 && IsShouldSummonFusion(-1, -1, false, (int)Flag.TearlamentsKaleidoHeart)) + { + return Util.CheckSelectCount(res, cards, min, max); + } + res = cards.Where(card => card != null && card.Id == CardId.TearlamentsKitkallos).ToList(); + if (res.Count > 0) + { + TearlamentsKitkallos_summoned = true; + return Util.CheckSelectCount(res, cards, min, max); + } + return null; + } + } + if (mcard_0[i] == null) continue; + if (cards.Contains(mcard_0[i])) + { + List res = new List() { mcard_0[i] }; + mcard_0[i] = null; + return Util.CheckSelectCount(res, cards, min, max); + } + else + { + return null; + } + } + return base.OnSelectCard(cards, min, max, hint, cancelable); + } + private bool IsCanFusionSummon() + { + if ((!activate_TearlamentsMerrli_2 && CheckRemainInDeck(CardId.TearlamentsMerrli) > 0) + || (!activate_TearlamentsHavnis_2 && CheckRemainInDeck(CardId.TearlamentsHavnis) > 0) + || (!activate_TearlamentsScheiren_2 && CheckRemainInDeck(CardId.TearlamentsScheiren) > 0)) + return Bot.ExtraDeck.Count(card => card != null && card.HasType(CardType.Fusion) && card.Id != CardId.ElderEntityNtss) > 0; + return false; + + } + private bool BaronnedeFleurSummon_2() + { + if (Duel.Turn > 1 && Duel.Phase < DuelPhase.Main2) return false; + List scards = Bot.GetMonsters().Where(card => card != null && card.Id == CardId.DivineroftheHerald && card.IsFaceup()).ToList(); + List mcards = Bot.GetMonsters().Where(card => card != null && !card.HasType(CardType.Tuner) && card.IsFaceup()).ToList(); + if (scards.Any(card => card != null && card.Level == 2) && mcards.Count(card => card != null && card.Level == 4) > 1) + { + List s = scards.Where(card => card != null && card.Level == 2 && card.Id == CardId.DivineroftheHerald && card.IsFaceup()).ToList(); + List res = new List() { s.FirstOrDefault() }; + res.AddRange(mcards.Where(card => card != null && card.Level == 4 && card.IsFaceup())); + AI.SelectMaterials(res); + SetSpSummon(); + return true; + } + return false; + } + private bool BaronnedeFleurSummon() + { + List scards = Bot.GetMonsters().Where(card => card != null && card.Id == CardId.DivineroftheHerald && card.IsFaceup()).ToList(); + List mcards = Bot.GetMonsters().Where(card => card != null && !card.HasType(CardType.Synchro) && card.IsFaceup()).ToList(); + if (scards.Any(card => card != null && card.Level == 2) && mcards.Any(card => card != null && card.Level == 8 && card.Id != CardId.TearlamentsRulkallos && card.Id != CardId.PredaplantDragostapelia)) { SetSpSummon(); return true; } + else if (scards.Any(card => card != null && card.Level == 5) && mcards.Any(card => card != null && card.Level == 5)) + { + List s = Bot.GetMonsters().Where(card => card != null && card.Level == 5 && card.Id == CardId.DivineroftheHerald && card.IsFaceup()).ToList(); + if (s.Count >= 0) + { + List res = new List() { s.FirstOrDefault() }; + res.AddRange(Bot.GetMonsters().Where(card => card != null && card.Level == 5 && card.Id == CardId.ElShaddollWinda && card.IsFaceup())); + res.AddRange(Bot.GetMonsters().Where(card => card != null && card.Level == 5 && card.IsFaceup())); + AI.SelectMaterials(res); + SetSpSummon(); + return true; + } + } + else if (scards.Any(card => card != null && card.Level == 6) && mcards.Any(card => card != null && card.Level == 4)) { SetSpSummon(); return true; } + return false; + + } + private bool SprightElfEffect() + { + ClientCard card = Util.GetLastChainCard(); + if (card != null && card.Controller == 0) return false; + SetSpSummon(); + return true; + } + private bool FusionDeckCheck() + { + return (CheckRemainInDeck(CardId.TearlamentsHavnis) > 0 && !activate_TearlamentsHavnis_2) + || (CheckRemainInDeck(CardId.TearlamentsMerrli) > 0 && !activate_TearlamentsMerrli_2) + || (CheckRemainInDeck(CardId.TearlamentsScheiren) > 0 && !activate_TearlamentsScheiren_2); + } + private List GetCardsIdSendToHand() + { + List ids = new List(); + if (!activate_TearlamentsScheiren_1 && !Bot.HasInHand(CardId.TearlamentsScheiren) && CheckRemainInDeck(CardId.TearlamentsScheiren) > 0 && Bot.Hand.Count(card => card != null && card.HasType(CardType.Monster)) > 0) ids.Add(CardId.TearlamentsScheiren); + if (!activate_TearlamentsMerrli_1 && !Bot.HasInHand(CardId.TearlamentsMerrli) && CheckRemainInDeck(CardId.TearlamentsMerrli) > 0 && (!summoned ||!activate_TearlamentsKitkallos_2) ) ids.Add(CardId.TearlamentsMerrli); + if (!activate_TearlamentsReinoheart_1 && !Bot.HasInHand(CardId.TearlamentsReinoheart) && CheckRemainInDeck(CardId.TearlamentsReinoheart) > 0) ids.Add(CardId.TearlamentsReinoheart); + if (!activate_TearlamentsScheiren_1 && !Bot.HasInHand(CardId.TearlamentsScheiren) && CheckRemainInDeck(CardId.TearlamentsScheiren) > 0) ids.Add(CardId.TearlamentsScheiren); + if (!activate_TearlamentsHavnis_1 && !Bot.HasInHand(CardId.TearlamentsHavnis) && CheckRemainInDeck(CardId.TearlamentsHavnis) > 0) + { + if (Duel.Player == 0 && (Duel.Phase != DuelPhase.End || AllActivated())) ids.Add(CardId.TearlamentsHavnis); + else ids.Insert(0, CardId.TearlamentsHavnis); + } + ids.AddRange(new List() { CardId.TearlamentsScheiren, CardId.TearlamentsMerrli, CardId.TearlamentsHavnis, CardId.TearlamentsReinoheart }); + return ids; + } + public int CheckRemainInDeck(int id) + { + switch (id) + { + case CardId.ShaddollBeast: + return Bot.GetRemainingCount(CardId.ShaddollBeast, 1); + case CardId.ShaddollDragon: + return Bot.GetRemainingCount(CardId.ShaddollDragon, 1); + case CardId.TearlamentsScheiren: + return Bot.GetRemainingCount(CardId.TearlamentsScheiren, 3); + case CardId.TearlamentsReinoheart: + return Bot.GetRemainingCount(CardId.TearlamentsReinoheart, 2); + case CardId.KelbektheAncientVanguard: + return Bot.GetRemainingCount(CardId.KelbektheAncientVanguard, 3); + case CardId.MudoratheSwordOracle: + return Bot.GetRemainingCount(CardId.MudoratheSwordOracle, 3); + case CardId.AgidotheAncientSentinel: + return Bot.GetRemainingCount(CardId.AgidotheAncientSentinel, 3); + case CardId.KeldotheSacredProtector: + return Bot.GetRemainingCount(CardId.KeldotheSacredProtector, 2); + case CardId.NaelshaddollAriel: + return Bot.GetRemainingCount(CardId.NaelshaddollAriel, 1); + case CardId.TearlamentsHavnis: + return Bot.GetRemainingCount(CardId.TearlamentsHavnis, 3); + case CardId.TearlamentsMerrli: + return Bot.GetRemainingCount(CardId.TearlamentsMerrli, 3); + case CardId.DivineroftheHerald: + return Bot.GetRemainingCount(CardId.DivineroftheHerald, 3); + case CardId.HeraldofOrangeLight: + return Bot.GetRemainingCount(CardId.HeraldofOrangeLight, 3); + case CardId.HeraldofGreenLight: + return Bot.GetRemainingCount(CardId.HeraldofGreenLight, 3); + case CardId.Eva: + return Bot.GetRemainingCount(CardId.Eva, 1); + case CardId.TearlamentsScream: + return Bot.GetRemainingCount(CardId.TearlamentsScream, 1); + case CardId.PrimevalPlanetPerlereino: + return Bot.GetRemainingCount(CardId.PrimevalPlanetPerlereino, 2); + case CardId.TearlamentsSulliek: + return Bot.GetRemainingCount(CardId.TearlamentsSulliek, 2); + default: + return 0; + } + } + private bool PredaplantDragostapeliaEffect() + { + ClientCard card = Util.GetLastChainCard(); + if (card != null && card.Controller != 0 && card.Location == CardLocation.MonsterZone && !card.IsShouldNotBeTarget() && !e_PredaplantDragostapelia_cards.Contains(card)) + { + chain_PredaplantDragostapelia = card; + return true; + } + return false; + } + private bool UnderworldGoddessoftheClosedWorldSummon_2() + { + return UnderworldGoddessoftheClosedWorldLinkSummon(false); + } + private bool UnderworldGoddessoftheClosedWorldLinkSummon(bool filter = true) + { + if (Duel.Turn == 1 || Enemy.GetMonsterCount() <= 0) return false; + List e_cards = Enemy.GetMonsters().Where(card => card != null && card.IsFaceup() && card.IsAttack()).ToList(); + List b_cards = Bot.GetMonsters().Where(card => card != null && card.IsFaceup() && card.IsAttack()).ToList(); + if ((e_cards.Count <= 0 || b_cards.Count <= 0) && Enemy.MonsterZone.GetDangerousMonster() == null) return false; + e_cards.Sort(CardContainer.CompareCardAttack); + e_cards.Reverse(); + b_cards.Sort(CardContainer.CompareCardAttack); + b_cards.Reverse(); + if ((e_cards[0].Attack > b_cards[0].Attack && (e_cards[0].IsShouldNotBeTarget() || e_cards[0].Attack >= 2500)) || Enemy.MonsterZone.GetDangerousMonster() != null) + { + List e_materials = new List(); + List m_materials = new List(); + List resMaterials = new List(); + foreach (var card in Enemy.GetMonsters()) + { + if (card != null && card.HasType(CardType.Effect) && card.IsFaceup()) + e_materials.Add(card); + } + if (e_materials.Count() <= 0) return false; + List mcards = Bot.GetMonsters(); + mcards.Sort(CardContainer.CompareCardAttack); + foreach (var card in mcards) + { + if (card == null || card.IsFacedown()) continue; + if (card.Id == CardId.SprightElf && summon_SprightElf) continue; + if (card.LinkCount < 3 && !(no_link_ids.Contains(card.Id) & filter) && card.IsFaceup() && card.HasType(CardType.Effect)) + { + if (card.Id == CardId.ElShaddollWinda) m_materials.Insert(0, card); + else m_materials.Add(card); + } + } + if (m_materials.Count() < 3) return false; + int link_count = 0; + int e_link_count = 0; + e_materials.Sort(CardContainer.CompareCardAttack); + e_materials.Reverse(); + foreach (var card in e_materials) + { + if (!resMaterials.Contains(card)) + resMaterials.Add(card); + e_link_count += (card.HasType(CardType.Link)) ? (card.LinkCount == 2 ? 2 : 1) : 1; + if (e_link_count >= 1) break; + } + if (e_link_count <= 0) return false; + link_count += e_link_count; + foreach (var card in m_materials) + { + if (e_link_count <= 1) + { + if (!resMaterials.Contains(card) && card.LinkCount < 3) + { + resMaterials.Add(card); + link_count += (card.HasType(CardType.Link)) ? card.LinkCount : 1; + if (link_count >= 5) break; + } + } + else + { + resMaterials.Add(card); + link_count += 1; + if (link_count >= 5) break; + } + } + if (link_count >= 5) { AI.SelectMaterials(resMaterials); SetSpSummon(); return true; } + } + return false; + } + private bool TearlamentsKaleidoHeartEffect() + { + if (Card.Location == CardLocation.MonsterZone) + { + activate_TearlamentsKaleidoHeart_1 = true; + return DestoryEnemyCard(); + } + else + { + activate_TearlamentsKaleidoHeart_2 = true; + return true; + } + } + private bool UnderworldGoddessoftheClosedWorldSummon() + { + if (Bot.HasInMonstersZone(CardId.ElShaddollWinda, true, false, true)) + { + return UnderworldGoddessoftheClosedWorldLinkSummon(); + } + return false; + } + private bool UnderworldGoddessoftheClosedWorldSummon_3() + { + return UnderworldGoddessoftheClosedWorldLinkSummon(); + } + private bool SpellActivate() + { + return Card.Location == CardLocation.Hand || (Card.Location == CardLocation.SpellZone && Card.IsFacedown()); + } + private bool SprightElfSummon_2() + { + List key_cards = Bot.GetMonsters().Where(card => card != null && card.Id == CardId.ElShaddollWinda && !card.IsDisabled() && card.IsFaceup()).ToList(); + if (key_cards.Count <= 0 || key_cards.Count > 1 || !IsAvailableLinkZone()) return false; + List cards = Bot.GetMonsters().Where(card => card != null && card.Level == 2 && card.Id != CardId.ElShaddollWinda && card.IsFaceup()).ToList(); + if (cards.Count <= 0) return false; + cards.Sort(CardContainer.CompareCardAttack); + cards.Insert(0, key_cards[0]); + AI.SelectMaterials(cards); + SetSpSummon(); + return true; + } + private bool FADawnDragsterSummon() + { + List key_cards = Bot.GetMonsters().Where(card => card != null && card.Id == CardId.ElShaddollWinda && !card.IsDisabled() && card.IsFaceup()).ToList(); + if (key_cards.Count <= 0 || key_cards.Count > 1 ) return false; + SetSpSummon(); + IList cards = CardsIdToClientCards(new List() { CardId.DivineroftheHerald }, Bot.GetMonsters().Where(card => card != null && card.IsFaceup()).ToList()); + if (cards.Count > 0) key_cards.Insert(0, cards[0]); + AI.SelectMaterials(key_cards); + return true; + } + private bool IPSummon_2() + { + if ((Bot.GetMonsterCount() <= 2 && Bot.Hand.Count<=2 && !Bot.HasInHand(CardId.TearlamentsScheiren) && !activate_TearlamentsScheiren_1&& !Bot.HasInHand(CardId.TearlamentsMerrli) && !activate_TearlamentsMerrli_1 ) || AllActivated() ) return false; + List key_cards = Bot.GetMonsters().Where(card => card != null && card.Id == CardId.ElShaddollWinda && !card.IsDisabled() && card.IsFaceup()).ToList(); + if (key_cards.Count <= 0 || key_cards.Count > 1 || !IsAvailableLinkZone()) return false; + List cards = Bot.GetMonsters().Where(card => card != null && !card.HasType(CardType.Link) && !no_link_ids.Contains(card.Id) && card.IsFaceup()).ToList(); + cards.Sort(CardContainer.CompareCardAttack); + cards.Insert(0, key_cards[0]); + AI.SelectMaterials(cards); + SetSpSummon(); + return true; + } + private bool SprightElfSummon() + { + if (!IsAvailableLinkZone()) return false; + List cards = GetZoneCards(CardLocation.MonsterZone, Bot).Where(card=>card != null && card.IsFaceup()).ToList(); + cards.Sort(CardContainer.CompareCardAttack); + List materials1 = new List(); + List materials2 = new List(); + List materials3 = new List(); + List materials4 = new List(); + foreach (var card in cards) + { + if (card == null) continue; + if (card.Level == 2 && materials1.Count <= 0) materials1.Add(card); + else if(link_card != null && card == link_card) materials2.Insert(0, link_card); + else if (!card.IsDisabled() && no_link_ids.Contains(card.Id)) materials4.Add(card); + else + { + if(card.Level <= 2) materials2.Add(card); + else materials3.Add(card); + } + + } + if (materials1.Count <= 0 || materials2.Count + materials3.Count <= 0) return false; + materials3.Sort(CardContainer.CompareCardLevel); + materials3.Reverse(); + materials1.AddRange(materials2); + materials1.AddRange(materials3); + summon_SprightElf = true; + AI.SelectMaterials(materials1); + SetSpSummon(); + return true; + } + private bool AbyssDwellerSummon() + { + if (Duel.Turn > 1 && Duel.Phase < DuelPhase.Main2) return false; + SetSpSummon(); + return true; + } + private bool AbyssDwellerSummon_2() + { + if (Bot.GetMonsters().Any(card => card != null && card.IsFaceup() && (card.Id == CardId.TearlamentsRulkallos || card.Id == CardId.TearlamentsKaleidoHeart))) return true; + return false; + } + private bool IPEffect() + { + if (Duel.LastChainPlayer == 0) return false; + if (!Bot.HasInExtra(CardId.KnightmareUnicorn) && !Bot.HasInExtra(CardId.MekkKnightCrusadiaAvramax) && !Bot.HasInExtra(CardId.UnderworldGoddessoftheClosedWorld)) return false; + List m = new List(); + List pre_m = new List(); + if (Bot.HasInExtra(CardId.UnderworldGoddessoftheClosedWorld)) + { + List e_cards = Enemy.GetMonsters().Where(card => card != null && card.IsFaceup() && card.IsAttack()).ToList(); + List b_cards = Bot.GetMonsters().Where(card => card != null && card.IsFaceup() && card.IsAttack()).ToList(); + if (e_cards.Count > 0 && b_cards.Count > 0) + { + e_cards.Sort(CardContainer.CompareCardAttack); + e_cards.Reverse(); + b_cards.Sort(CardContainer.CompareCardAttack); + b_cards.Reverse(); + if ((e_cards[0].Attack > b_cards[0].Attack && (e_cards[0].IsShouldNotBeTarget() || e_cards[0].Attack >= 2500)) || Enemy.MonsterZone.GetDangerousMonster() != null) + { + pre_m = Bot.GetMonsters().Where(card => card != null && card != Card && card.IsFaceup() && ((card.HasType(CardType.Link) && card.LinkCount < 3) || (card.HasType(CardType.Fusion | CardType.Xyz | CardType.Synchro))) && (!no_link_ids.Contains(card.Id) || card.IsDisabled())).ToList(); + List pre_m2 = new List(); + pre_m2.Add(Enemy.MonsterZone.GetDangerousMonster() == null ? e_cards[0] : Enemy.MonsterZone.GetDangerousMonster()); + pre_m2.AddRange(e_cards); + int link_count = 0; + foreach (var card in pre_m) + { + if (card == null || (card.Id == CardId.SprightElf && summon_SprightElf)) continue; + link_count += 1; + m.Add(card); + if (link_count >= 2) break; + } + if (link_count >= 2) + { + AI.SelectCard(CardId.UnderworldGoddessoftheClosedWorld); + m.Insert(0, Card); + m.Add(pre_m2.FirstOrDefault()); + AI.SelectMaterials(m); + return true; + } + } + } + } + if (Bot.HasInExtra(CardId.MekkKnightCrusadiaAvramax)) + { + m.Clear(); + pre_m = Bot.GetMonsters().Where(card => card != null && card != Card && card.IsFaceup() && ((card.HasType(CardType.Link) && card.LinkCount < 3) || (card.HasType(CardType.Fusion|CardType.Xyz|CardType.Synchro))) && (!no_link_ids.Contains(card.Id) || card.IsDisabled())).ToList(); + if (pre_m.Count > 0) + { + pre_m.Sort(CardContainer.CompareCardAttack); + int link_count = 0; + foreach (var card in pre_m) + { + if (card == null || (card.Id == CardId.SprightElf && summon_SprightElf)) continue; + link_count += (card.HasType(CardType.Link)) ? card.LinkCount : 1; + m.Add(card); + if (link_count >= 2) break; + } + if (link_count >= 2) + { + AI.SelectCard(CardId.MekkKnightCrusadiaAvramax); + m.Insert(0, Card); + AI.SelectMaterials(m); + return true; + } + } + } + if (Bot.HasInExtra(CardId.KnightmareUnicorn)) + { + List pre_cards = GetZoneCards(CardLocation.Onfield,Enemy); + if (Bot.Hand.Count > 0 && pre_cards.Count(card => card != null && !card.IsShouldNotBeTarget()) > 0) + { + m.Clear(); + pre_m = Bot.GetMonsters().Where(card => card != null && card != Card && card.IsFaceup() && !no_link_ids.Contains(card.Id) && card.Id != Card.Id).ToList(); + if (pre_m.Count > 0) + { + pre_m.Sort(CardContainer.CompareCardAttack); + int link_count = 0; + foreach (var card in pre_m) + { + if (card == null || (card.Id == CardId.SprightElf && summon_SprightElf)) continue; + link_count += (card.HasType(CardType.Link)) ? card.LinkCount : 1; + m.Add(card); + if (link_count >= 1) break; + } + if (link_count >= 1) + { + AI.SelectCard(CardId.KnightmareUnicorn); + m.Insert(0, Card); + AI.SelectMaterials(m); + return true; + } + } + } + } + return false; + } + private bool IPSummon() + { + if (Duel.Turn > 1 && Duel.Phase < DuelPhase.Main2) return false; + if (!Bot.HasInMonstersZone(CardId.SprightElf) || Bot.GetMonsterCount() <= 2) return false; + if (Bot.ExtraDeck.Count(card => card != null && card.LinkCount > 2) <= 0 || !IsAvailableLinkZone()) return false; + List cards = GetZoneCards(CardLocation.MonsterZone, Bot).Where(card => card != null && card.IsFaceup() && !card.HasType(CardType.Link)).ToList(); + List materials = new List(); + foreach (var card in cards) + { + if (card == null || (!card.IsDisabled() && no_link_ids.Contains(card.Id)) + || card.LinkCount >= 2) continue; + if (link_card != null && card == link_card) materials.Insert(0, link_card); + else materials.Add(card); + } + if (materials.Count <= 1) return false; + materials.Sort(CardContainer.CompareCardAttack); + AI.SelectMaterials(materials); + SetSpSummon(); + return true; + } + private bool KnightmareUnicornEffect() + { + List cards = GetZoneCards(CardLocation.Onfield,Enemy); + cards = cards.Where(card => card != null && !card.IsShouldNotBeTarget() && (tgcard == null || card != tgcard)).ToList(); + if (cards.Count <= 0) return false; + List ids = new List(); + if (!activate_KelbektheAncientVanguard_2) ids.Add(CardId.KelbektheAncientVanguard); + if (!activate_AgidotheAncientSentinel_2) ids.Add(CardId.AgidotheAncientSentinel); + ids.AddRange(new List() { CardId.MudoratheSwordOracle, CardId.KeldotheSacredProtector, CardId.ShaddollBeast, CardId.ShaddollDragon, CardId.TearlamentsSulliek, CardId.Eva, CardId.TearlamentsReinoheart }); + cards.Sort(CardContainer.CompareCardAttack); + cards.Reverse(); + AI.SelectCard(ids); + AI.SelectNextCard(cards); + return true; + + } + private bool MekkKnightCrusadiaAvramaxSummon() + { + if (!IsAvailableLinkZone() || (Duel.Turn > 1 && Duel.Phase < DuelPhase.Main2)) return false; + if (Bot.HasInMonstersZone(CardId.SprightElf, false, false, true) && !summon_SprightElf + && Bot.HasInMonstersZone(CardId.IP, false, false, true)) + { + List m1 = Bot.GetMonsters().Where(card => card != null && card.IsFaceup() && card.Id == CardId.SprightElf).ToList(); + List m2 = Bot.GetMonsters().Where(card => card != null && card.IsFaceup() && card.Id == CardId.IP).ToList(); + if (m1.Count <= 0 || m2.Count <= 0) return false; + List res = new List() { m1[0] }; + res.Add(m2[0]); + AI.SelectMaterials(res); + SetSpSummon(); + return true; + } + else + { + List cards = Bot.GetMonsters().Where(card => card != null && card.LinkCount != 2 &&card.IsFaceup() && (!no_link_ids.Contains(card.Id) || card.IsDisabled()) + && card.IsExtraCard() && card.Id != CardId.KnightmareUnicorn).ToList(); + List cards2 = Bot.GetMonsters().Where(card => card != null && card.IsFaceup() && card.Id == CardId.KnightmareUnicorn).ToList(); + if (cards.Count <= 0 || cards2.Count <= 0) return false; + cards.Sort(CardContainer.CompareCardAttack); + List res = new List(); + res.Add(cards.FirstOrDefault()); + res.Add(cards.FirstOrDefault()); + AI.SelectMaterials(res); + SetSpSummon(); + return true; + } + } + private bool MekkKnightCrusadiaAvramaxEffect() + { + if (Card.Location == CardLocation.MonsterZone) return true; + else return DestoryEnemyCard(); + } + private bool KnightmareUnicornSummon() + { + if (Bot.Hand.Count <= 0) return false; + if (!IsAvailableLinkZone()) return false; + List ecards = GetZoneCards(CardLocation.Onfield, Enemy); + if (ecards.Count(card => card != null && !card.IsShouldNotBeTarget()) <= 0) return false; + List tmepMaterials = new List(); + List resMaterials = new List(); + foreach (var card in Bot.GetMonsters()) + { + if (card == null || card.IsFacedown() || (card.Id == CardId.SprightElf && summon_SprightElf) + || (no_link_ids.Contains(card.Id)) || card.Id == CardId.TearlamentsKitkallos) continue; + if (tmepMaterials.Count(_card => _card != null && _card.Id == card.Id) <= 0) + tmepMaterials.Add(card); + } + int link_count = 0; + tmepMaterials.Sort(CardContainer.CompareCardAttack); + List materials = new List(); + List link_materials = tmepMaterials.Where(card => card != null && card.LinkCount == 2).ToList(); + List normal_materials = tmepMaterials.Where(card => card != null && card.LinkCount != 2).ToList(); + if (link_materials.Count() >= 1) + { + materials.Add(link_materials.FirstOrDefault()); + materials.AddRange(normal_materials); + } + else + { + materials.AddRange(normal_materials); + materials.AddRange(link_materials); + } + if (materials.Count(card => card != null && card.LinkCount >= 2) > 1 + && materials.Count(card => card != null && card.LinkCount < 2) < 1) return false; + foreach (var card in materials) + { + if (!resMaterials.Contains(card) && card.LinkCount < 3) + { + resMaterials.Add(card); + link_count += (card.HasType(CardType.Link)) ? card.LinkCount : 1; + if (link_count >= 3) break; + } + } + if (link_count >= 3) { AI.SelectMaterials(resMaterials);SetSpSummon(); return true; } + return false; + } + private bool BaronnedeFleurEffect() + { + if (ActivateDescription == Util.GetStringId(CardId.BaronnedeFleur, 0)) + { + return DestoryEnemyCard(); + } + if (ActivateDescription == Util.GetStringId(CardId.BaronnedeFleur, 1)) + { + return Duel.LastChainPlayer != 0; + } + return false; + + } + private bool PrimevalPlanetPerlereinoEffect() + { + if (SpellActivate()) return true; + else + { + ClientCard card = Util.GetLastChainCard(); + if (card != null && card.Controller == 0 && card.Id == CardId.TearlamentsKaleidoHeart) return false; + return DestoryEnemyCard(); + } + } + + private bool DestoryEnemyCard() + { + if (Duel.Player == 0 && Card.Id == CardId.PrimevalPlanetPerlereino && !on_chaining_cards.Any(ccard => ccard != null && !ccard.IsDisabled() && ccard.Controller == 0 && ccard.Id == CardId.TearlamentsKitkallos) + && Bot.HasInMonstersZone(CardId.TearlamentsKitkallos) && !activate_TearlamentsKitkallos_3 + && !AllActivated()) + { + List temp = new List(); + List temp2 = new List(); + foreach (var ccard in Bot.GetMonsters()) + { + if (ccard == null) continue; + if (ccard.Id == CardId.TearlamentsKitkallos && ccard.IsDisabled()) temp.Add(ccard); + else if(ccard.Id == CardId.TearlamentsKitkallos) temp2.Add(ccard); + } + temp.AddRange(temp2); + AI.SelectCard(temp); + activate_PrimevalPlanetPerlereino_2 = true; + return true; + } + ClientCard card = Util.GetProblematicEnemyMonster(0, true); + if (card != null && (tgcard == null || tgcard != card)) + { + AI.SelectCard(card); + tgcard = card; + return true; + } + card = Util.GetBestEnemySpell(true); + if (card != null && (tgcard == null || tgcard != card)) + { + AI.SelectCard(card); + tgcard = card; + return true; + } + List cards = GetZoneCards(CardLocation.Onfield, Enemy); + cards = cards.Where(tcard => tcard != null && !tcard.IsShouldNotBeTarget() && (tgcard == null || tcard != tgcard)).ToList(); + if (cards.Count <= 0) return false; + cards.Sort(CardContainer.CompareCardAttack); + cards.Reverse(); + tgcard = cards[0]; + AI.SelectCard(cards); + if (Card.Id == CardId.PrimevalPlanetPerlereino) activate_PrimevalPlanetPerlereino_2 = true; + return true; + } + private bool ElderEntityNtssEffect() + { + if (Card.Location == CardLocation.Grave) + { + return DestoryEnemyCard(); + } + else return true; + + } + private bool DivineroftheHeraldSummon() + { + if ((CheckRemainInDeck(CardId.KelbektheAncientVanguard) > 0 && !activate_KelbektheAncientVanguard_2) + || (CheckRemainInDeck(CardId.AgidotheAncientSentinel) > 0 && !activate_AgidotheAncientSentinel_2)) + { + summoned = true; + return true; + } + return false; + } + private bool EvaEffect() + { + List cards = Bot.GetGraveyardMonsters().Where(card => card != null && card.HasAttribute(CardAttribute.Light) && card.HasRace(CardRace.Fairy) && card != Card).ToList(); + if (cards.Count <= 0) return false; + activate_Eva = true; + return true; + } + private bool DivineroftheHeraldEffect() + { + if (Card.Location == CardLocation.MonsterZone) + { + if (Duel.Player == 0) + { + if (!IsCanSpSummon() && CheckRemainInDeck(CardId.MudoratheSwordOracle) <= 0 && CheckRemainInDeck(CardId.KeldotheSacredProtector) <= 0) return false; + if ((AllActivated() || Bot.ExtraDeck.Count(card=>card!=null && card.HasType(CardType.Fusion) && card.Id!=CardId.ElderEntityNtss)<=0) + && CheckRemainInDeck(CardId.MudoratheSwordOracle)<=0 && CheckRemainInDeck(CardId.KeldotheSacredProtector)<=0) return false; + if ((activate_KelbektheAncientVanguard_2 || CheckRemainInDeck(CardId.KelbektheAncientVanguard) <= 0) + && (activate_AgidotheAncientSentinel_2 || CheckRemainInDeck(CardId.AgidotheAncientSentinel) <= 0) && Bot.HasInExtra(CardId.SprightElf)) + { + List cards = Bot.GetMonsters().Where(card => card != null && card.IsFaceup() && !no_link_ids.Contains(card.Id) && card != Card).ToList(); + if (cards.Count() >= 1) return false; + } + } + activate_DivineroftheHerald = true; + return true; + } + else + { + return true; + } + } + private bool TearlamentsScreamEffect_1() + { + return SpellActivate(); + } + private bool MudoratheSwordOracleEffect() + { + if (Card.Location == CardLocation.Hand) + { + if ((Bot.Hand.Count(card => card != null && card.Id == CardId.AgidotheAncientSentinel) <= 0 || activate_AgidotheAncientSentinel_2) + && (Bot.Hand.Count(card => card != null && card.Id == CardId.KelbektheAncientVanguard) <= 0 || activate_KelbektheAncientVanguard_2) && + !summoned && !Bot.HasInHand(CardId.MudoratheSwordOracle) && !Bot.HasInHand(CardId.KeldotheSacredProtector)) return false; + IList cardsid = new List(); + if (!activate_AgidotheAncientSentinel_2) cardsid.Add(CardId.AgidotheAncientSentinel); + if (!activate_KelbektheAncientVanguard_2) cardsid.Add(CardId.KelbektheAncientVanguard); + cardsid.Add(CardId.KeldotheSacredProtector); + cardsid.Add(CardId.MudoratheSwordOracle); + if (Card.Id == CardId.MudoratheSwordOracle) activate_MudoratheSwordOracle_2 = true; + else if (Card.Id == CardId.KeldotheSacredProtector) activate_KeldotheSacredProtector_2 = true; + AI.SelectCard(cardsid); + SetSpSummon(); + return true; + } + else if (Card.Location == CardLocation.Grave) + { + ClientCard chain_card = Util.GetLastChainCard(); + if (chain_card != null && chain_card.Controller == 0) return false; + if (GetZoneCards(CardLocation.Grave, Enemy).Count() <= 0 && Bot.Deck.Count >= 3) return false; + if ((Duel.CurrentChain == null || Duel.CurrentChain.Count <= 0) && Bot.Deck.Count >= 3) return false; + if (Duel.CurrentChain.Any(card => card != null && card.Controller == 0 && (card.Id == CardId.MudoratheSwordOracle || card.Id == CardId.KeldotheSacredProtector) || card.Id == CardId.NaelshaddollAriel)) return false; + if (Duel.CurrentChain.Any(card => card != null && card.Controller == 0 && card.Id == CardId.ShaddollBeast) && Bot.Deck.Count <= 0) + { + if (Card.Id == CardId.MudoratheSwordOracle) activate_MudoratheSwordOracle_2 = true; + else if (Card.Id == CardId.KeldotheSacredProtector) activate_KeldotheSacredProtector_2 = true; + return true; + } + foreach (var card in Duel.ChainTargets) + { + if (card == null) continue; + if ((card == Card && (Bot.Deck.Count < 5 || Enemy.Graveyard.Count(ccard => ccard != null && !key_no_send_to_deck_ids.Contains(ccard.Id)) > 0)) + || (card.Controller == 1 && card.Location == CardLocation.Grave)) + { + if (Card.Id == CardId.MudoratheSwordOracle) activate_MudoratheSwordOracle_2 = true; + else if (Card.Id == CardId.KeldotheSacredProtector) activate_KeldotheSacredProtector_2 = true; + return true; + } + } + foreach (var card in Duel.CurrentChain) + { + if (card == null || card.Controller == 0 || card.Location != CardLocation.Grave) continue; + if (key_send_to_deck_ids.Contains(card.Id)) + { + if (Card.Id == CardId.MudoratheSwordOracle) activate_MudoratheSwordOracle_2 = true; + else if (Card.Id == CardId.KeldotheSacredProtector) activate_KeldotheSacredProtector_2 = true; + return true; + } + } + if (Duel.Phase == DuelPhase.End && Bot.Deck.Count < 3 && Bot.Graveyard.Count > 0) + { + if (Card.Id == CardId.MudoratheSwordOracle) activate_MudoratheSwordOracle_2 = true; + else if (Card.Id == CardId.KeldotheSacredProtector) activate_KeldotheSacredProtector_2 = true; + return true; + } + return false; + } + else + { + if (Duel.Phase == DuelPhase.End && Bot.Deck.Count < 3 && Bot.Graveyard.Count > 0) + { + if (Card.Id == CardId.MudoratheSwordOracle) activate_MudoratheSwordOracle_2 = true; + else if (Card.Id == CardId.KeldotheSacredProtector) activate_KeldotheSacredProtector_2 = true; + return true; + } + return false; + } + } + + private bool TearlamentsScheirenEffect() + { + if (Card.Location == CardLocation.Grave) + { + return FusionEffect(CardId.TearlamentsScheiren); + } + else + { + if (AllActivated() && (!Bot.GetMonsters().Any(card=>card!=null && card.IsFaceup() && card.Level==4) || !Bot.HasInExtra(CardId.AbyssDweller))) return false; + activate_TearlamentsScheiren_1 = true; + SetSpSummon(); + return true; + } + } + private bool NaelshaddollArielEffect() + { + if (Card.Location == CardLocation.Grave) + { + return Enemy.Graveyard.Count(card => card != null && !key_no_remove_ids.Contains(card.Id)) > 0; + } + else + { + SetSpSummon(); + return true; + } + } + private bool IsShouldSummonFusion(int setcode = -1,int race = -1,bool all = false,int flag = 0x1f) + { + List cards = GetZoneCards(CardLocation.MonsterZone, Bot).Where(card => card != null && card.IsFaceup()).ToList(); + cards.AddRange(GetZoneCards(CardLocation.Grave | CardLocation.Hand, Bot)); + int xcount_1 = 0; + int xcount_2 = 0; + int xcount_3 = 0; + if ((flag & (int)Flag.TearlamentsKitkallos)>0 && Bot.ExtraDeck.Count(card => card != null && card.Id == CardId.TearlamentsKitkallos) > 0) + { + foreach (var card in cards) + { + if (card == null) continue; + if (card.Id == CardId.TearlamentsRulkallos && card.Location == CardLocation.MonsterZone && !card.IsDisabled()) continue; + if (card.HasSetcode(SETCODE) && card.HasType(CardType.Monster)) + { + ++xcount_1; + if (card.HasRace(CardRace.Aqua)) { --xcount_1; ++xcount_3; } + } + else if (card.HasRace(CardRace.Aqua)) ++xcount_2; + } + if (setcode == SETCODE) + { + ++xcount_1; + if (race == (int)CardRace.Aqua) { --xcount_1; ++xcount_3; } + } + else if (race == (int)CardRace.Aqua) ++xcount_2; + if (xcount_3 > 1 || (xcount_1 > 0 && xcount_3 > 0) || (xcount_1 > 0 && xcount_2 > 0) || (xcount_2 > 0 && xcount_3 > 0)) return true; + } + if ((flag & (int)Flag.TearlamentsRulkallos) > 0 && Bot.ExtraDeck.Count(card => card != null && card.Id == CardId.TearlamentsRulkallos) > 0) + { + xcount_1 = 0; + xcount_2 = 0; + foreach (var card in cards) + { + if (card == null) continue; + if (card.Id == CardId.TearlamentsKitkallos && xcount_1 <= 0) ++xcount_1; + else if (card.HasSetcode(SETCODE) && card.HasType(CardType.Monster)) ++xcount_2; + } + if (setcode == SETCODE) ++xcount_2; + if (xcount_1 > 0 && xcount_2 > 0) return true; + } + if ((flag & (int)Flag.TearlamentsKaleidoHeart) > 0 && Bot.ExtraDeck.Count(card => card != null && card.Id == CardId.TearlamentsKaleidoHeart) > 0) + { + xcount_1 = 0; + xcount_2 = 0; + foreach (var card in cards) + { + if (card == null) continue; + if (card.Id == CardId.TearlamentsRulkallos && card.Location == CardLocation.MonsterZone && !card.IsDisabled()) continue; + if (card.Id == CardId.TearlamentsReinoheart && xcount_1 <= 0) ++xcount_1; + else if (card.HasRace(CardRace.Aqua)) ++xcount_2; + } + if (race == (int)CardRace.Aqua) ++xcount_2; + if (xcount_1 > 0 && xcount_2 > 0) return true; + } + if ((flag & (int)Flag.PredaplantDragostapelia) > 0 && Bot.ExtraDeck.Count(card => card != null && card.Id == CardId.PredaplantDragostapelia) > 0) + { + xcount_1 = 0; + foreach (var card in cards) + { + if (card == null) continue; + if (card.Id == CardId.TearlamentsRulkallos && card.Location == CardLocation.MonsterZone && !card.IsDisabled()) continue; + if (((Bot.GetMonstersInMainZone().Count > 4 && card.Location == CardLocation.MonsterZone)|| Bot.GetMonstersInMainZone().Count<=4) && card.HasType(CardType.Fusion)) ++xcount_1; + } + if (xcount_1 > 0) return true; + } + if (all) + { + if ((flag & (int)Flag.ElShaddollWinda) > 0 && Bot.ExtraDeck.Count(card => card != null && card.Id == CardId.ElShaddollWinda) > 0) + { + List materials_1 = new List(); + List materials_2 = new List(); + foreach (var card in cards) + { + if (card == null) continue; + if (card.HasSetcode(0x9d)) materials_1.Add(card); + else if ((card.Id == CardId.TearlamentsHavnis || card.Id == CardId.TearlamentsMerrli + || card.Id == CardId.TearlamentsScheiren) && card.HasAttribute(CardAttribute.Dark)) + materials_2.Add(card); + } + xcount_1 = materials_1.Count; + xcount_2 = materials_2.Count; + if ((setcode == SETCODE) && race == (int)CardRace.Aqua) + { + ++xcount_2; + } + if (xcount_1 > 0 && xcount_2 > 0) return true; + } + } + return false; + } + private bool TearlamentsRulkallosEffect() + { + if (Card.Location == CardLocation.Grave) + { + activate_TearlamentsRulkallos_2 = true; + SetSpSummon(); + return true; + } + else + { + if (Card.IsDisabled()) return false; + activate_TearlamentsRulkallos_1 = true; + return true; + } + } + private bool AgidotheAncientSentinelEffect() + { + if (Card.Location == CardLocation.Hand) + { + if (Duel.Player == 1) + { + //if (!activate_AgidotheAncientSentinel_2 && (Bot.HasInHand(CardId.HeraldofOrangeLight) || Bot.HasInHand(CardId.HeraldofGreenLight)) + // && Bot.Hand.Count(card => card != null && card.Id == CardId.AgidotheAncientSentinel) <= 1) return false; + return false; + } + else + { + if((!Bot.HasInGraveyard(CardId.KelbektheAncientVanguard) && !Bot.HasInGraveyard(CardId.MudoratheSwordOracle) + && !Bot.HasInGraveyard(CardId.KeldotheSacredProtector) && Bot.Hand.Count(card => card != null && card.Id == CardId.AgidotheAncientSentinel)<=1) + || Bot.GetMonstersInMainZone().Count>=4) return false; + } + if(!activate_AgidotheAncientSentinel_2 && (Bot.HasInHand(CardId.HeraldofOrangeLight) || Bot.HasInHand(CardId.HeraldofGreenLight)) + && Bot.Hand.Count(card => card != null && card.Id == CardId.AgidotheAncientSentinel) <= 1) return false; + SetSpSummon(); + return true; + } + else + { + if (AllActivated() && !Duel.CurrentChain.Any(card => card != null && card.Controller == 0 && (card.Id == CardId.TearlamentsHavnis || card.Id == CardId.TearlamentsMerrli || card.Id == CardId.TearlamentsScheiren))) return false; + activate_AgidotheAncientSentinel_2 = true; + return true; + } + } + private bool AllActivated() + { + return (activate_TearlamentsScheiren_2 || CheckRemainInDeck(CardId.TearlamentsScheiren) <= 0) + && (activate_TearlamentsHavnis_2 || CheckRemainInDeck(CardId.TearlamentsHavnis) <= 0) + && (activate_TearlamentsMerrli_2 || CheckRemainInDeck(CardId.TearlamentsMerrli) <= 0); + } + private bool KelbektheAncientVanguardEffect() + { + if (Card.Location == CardLocation.Hand) + { + if (Duel.LastChainPlayer == 0) return false; + if ((Bot.HasInHand(CardId.HeraldofOrangeLight) || Bot.HasInHand(CardId.HeraldofGreenLight)) + && !activate_KelbektheAncientVanguard_2) return false; + List cards = Enemy.GetMonsters(); + cards.Sort(CardContainer.CompareCardAttack); + cards.Reverse(); + AI.SelectCard(cards); + + SetSpSummon(); + return true; + } + else + { + if (AllActivated() && !Duel.CurrentChain.Any(card=>card!=null && card.Controller==0 && (card.Id==CardId.TearlamentsHavnis||card.Id==CardId.TearlamentsMerrli || card.Id==CardId.TearlamentsScheiren))) return false; + activate_KelbektheAncientVanguard_2 = true; + return true; + } + } + private bool TearlamentsMerrliEffect() + { + if (Card.Location == CardLocation.MonsterZone) + { + if (AllActivated()) return false; + activate_TearlamentsMerrli_1 = true; + return true; + } + else + { + return FusionEffect(CardId.TearlamentsMerrli); + } + } + private bool TearlamentsHavnisEffect() + { + if (Card.Location == CardLocation.Hand) + { + if (AllActivated()) return false; + activate_TearlamentsHavnis_1 = true; + return true; + } + else + { + return FusionEffect(CardId.TearlamentsHavnis); + } + } + private bool SpellSet() + { + if (Card.Id == CardId.TearlamentsSulliek) return !Bot.GetSpells().Any(card => card != null && card.Id == CardId.TearlamentsSulliek && (card.IsFacedown() || (card.IsFaceup() && !card.IsDisabled()))); + return Card.HasType(CardType.QuickPlay) || Card.HasType(CardType.Trap); + } + private bool TearlamentsReinoheartEffect() + { + if (Card.Location == CardLocation.Grave) + { + List cards = Bot.Hand.Where(card => card != null && card.HasSetcode(SETCODE)).ToList(); + List temp = new List(cards); + foreach (var card in temp) + { + if ((card.Id == CardId.TearlamentsScheiren && !activate_TearlamentsScheiren_1) + || (card.Id == CardId.TearlamentsMerrli && !summoned && !activate_TearlamentsMerrli_1) + ||(card.Id==CardId.TearlamentsHavnis && cards.Count(ccard=>ccard!=null && ccard.Id==CardId.TearlamentsHavnis) > 1)) + cards.Remove(card); + } + if (cards.Count() <= 0) return false; + activate_TearlamentsReinoheart_2 = true; + SetSpSummon(); + return true; + } + else + { + if (AllActivated()) return false; + activate_TearlamentsReinoheart_1 = true; + return true; + } + } + private bool ShaddollDragonEffect() + { + if (Card.Location == CardLocation.Grave) + { + ClientCard card = Util.GetBestEnemySpell(); + List cards = Enemy.GetSpells().Where(ccard=> tgcard == null || tgcard != ccard).ToList(); + if (card != null && (tgcard == null || tgcard != card)) { AI.SelectCard(card); return true; } + else if (cards.Count > 0) { AI.SelectCard(cards); return true; } + return false; + } + else return true; + } + private bool TearlamentsKitkallosEffect_2() + { + if (Bot.HasInMonstersZone(CardId.ElShaddollWinda, true, false, true)) return TearlamentsKitkallosEffect(); + return false; + } + private bool TearlamentsKitkallosEffect() + { + if (ActivateDescription == Util.GetStringId(CardId.TearlamentsKitkallos, 1)) + { + if (Card.IsDisabled()) return false; + if (AllActivated() && !Bot.HasInGraveyard(CardId.TearlamentsKaleidoHeart) && !Bot.HasInGraveyard(CardId.TearlamentsRulkallos) + && !Bot.HasInGraveyard(CardId.TearlamentsKitkallos)) return false; + if(Bot.HasInMonstersZone(CardId.ElShaddollWinda,true,false,true)) AI.SelectCard(CardId.ElShaddollWinda); + else if (Bot.HasInMonstersZone(CardId.TearlamentsKitkallos) && !activate_TearlamentsKitkallos_3 && !AllActivated()) AI.SelectCard(CardId.TearlamentsKitkallos); + else if (!activate_TearlamentsScheiren_2 && Bot.HasInMonstersZone(CardId.TearlamentsScheiren) && IsShouldSummonFusion()) AI.SelectCard(CardId.TearlamentsScheiren); + else if (!activate_TearlamentsMerrli_2 && Bot.HasInMonstersZone(CardId.TearlamentsMerrli) && IsShouldSummonFusion()) AI.SelectCard(CardId.TearlamentsMerrli); + else if (!activate_TearlamentsHavnis_2 && Bot.HasInMonstersZone(CardId.TearlamentsHavnis) && IsShouldSummonFusion()) AI.SelectCard(CardId.TearlamentsHavnis); + else if (Bot.HasInMonstersZone(CardId.TearlamentsReinoheart) && !activate_TearlamentsReinoheart_1 && !AllActivated()) AI.SelectCard(CardId.TearlamentsReinoheart); + else if (Bot.HasInMonstersZone(CardId.Eva) && Bot.Graveyard.Count(card => card != null && card.HasAttribute(CardAttribute.Light) && card.HasRace(CardRace.Fairy)) > 0 + && (CheckRemainInDeck(CardId.HeraldofGreenLight) > 0 || CheckRemainInDeck(CardId.HeraldofOrangeLight) > 0)) AI.SelectCard(CardId.Eva); + else if ((Bot.HasInExtra(CardId.TearlamentsRulkallos) && !Bot.HasInGraveyard(CardId.TearlamentsKitkallos)) + || (Bot.HasInExtra(CardId.PredaplantDragostapelia) && Bot.Graveyard.Count(card => card != null && card.HasType(CardType.Fusion)) <= 0)) AI.SelectCard(CardId.TearlamentsKitkallos); + else if (Bot.HasInMonstersZone(CardId.ShaddollDragon) && Enemy.GetSpellCount() > 0) AI.SelectCard(CardId.ShaddollDragon); + else + { + List mcards = GetZoneCards(CardLocation.MonsterZone, Bot); + mcards.Sort(CardContainer.CompareCardAttack); + AI.SelectCard(mcards); + } + if(!activate_TearlamentsKitkallos_1 && Bot.HasInGraveyard(CardId.TearlamentsKitkallos)) AI.SelectNextCard(Bot.Graveyard.Where(card => card != null && card.Id == CardId.TearlamentsKitkallos).ToList()); + if (!activate_TearlamentsMerrli_1 && Bot.HasInGraveyard(CardId.TearlamentsMerrli) && !AllActivated()) AI.SelectNextCard(Bot.Graveyard.Where(card => card != null && card.Id == CardId.TearlamentsMerrli).ToList()); + else if (!activate_TearlamentsMerrli_1 && Bot.HasInHand(CardId.TearlamentsMerrli) && !AllActivated()) AI.SelectNextCard(Bot.Hand.Where(card => card != null && card.Id == CardId.TearlamentsMerrli).ToList()); + else if (!activate_TearlamentsReinoheart_1 && Bot.HasInGraveyard(CardId.TearlamentsReinoheart) && !AllActivated()) AI.SelectNextCard(Bot.Graveyard.Where(card => card != null && card.Id == CardId.TearlamentsReinoheart).ToList()); + else if (!activate_TearlamentsReinoheart_1 && Bot.HasInHand(CardId.TearlamentsReinoheart) && !AllActivated()) AI.SelectNextCard(Bot.Hand.Where(card => card != null && card.Id == CardId.TearlamentsReinoheart).ToList()); + else AI.SelectNextCard(CardId.TearlamentsKaleidoHeart,CardId.TearlamentsRulkallos,CardId.TearlamentsKitkallos); + activate_TearlamentsKitkallos_2 = true; + SetSpSummon(); + return true; + } + else if (Card.Location == CardLocation.Grave) + { + if (AllActivated()) return false; + activate_TearlamentsKitkallos_3 = true; + return true; + } + else + { + if (Card.IsDisabled()) return false; + if (!IS_YGOPRO) select_TearlamentsKitkallos = true; + activate_TearlamentsKitkallos_1 = true; + return true; + } + } + private bool HasinZoneKeyCard(CardLocation loc) + { + if (loc == CardLocation.Hand) + { + if (!activate_TearlamentsScheiren_2 && Bot.HasInHand(CardId.TearlamentsScheiren)) return true; + if (!activate_TearlamentsHavnis_2 && Bot.HasInHand(CardId.TearlamentsHavnis)) return true; + if (!activate_TearlamentsMerrli_2 && Bot.HasInHand(CardId.TearlamentsMerrli)) return true; + } + if (loc == CardLocation.Deck) + { + if (!activate_TearlamentsScheiren_2 && CheckRemainInDeck(CardId.TearlamentsScheiren)>0) return true; + if (!activate_TearlamentsHavnis_2 && CheckRemainInDeck(CardId.TearlamentsHavnis)>0) return true; + if (!activate_TearlamentsMerrli_2 && CheckRemainInDeck(CardId.TearlamentsMerrli)>0) return true; + } + return false; + } + private bool TearlamentsSulliekEffect() + { + if (SpellActivate()) return true; + if (Card.Location == CardLocation.SpellZone) + { + ClientCard card = Util.GetLastChainCard(); + if (card != null && card.Controller == 1 && card.Location == CardLocation.MonsterZone + && !card.IsShouldNotBeTarget()) + { + if (_PredaplantDragostapelia != null && _PredaplantDragostapelia.Location == CardLocation.MonsterZone && _PredaplantDragostapelia.IsFaceup() + && e_PredaplantDragostapelia_cards.Contains(card)) return false; + chain_TearlamentsSulliek = card; + return true; + } + else + { + if (Duel.Player == 1 || Duel.Phase == DuelPhase.End) + { + if (Duel.LastChainPlayer == 0 || Duel.CurrentChain.Count(ccard=>ccard!=null &&ccard.Controller==0 + && (ccard.Id==CardId.TearlamentsHavnis || ccard.Id == CardId.TearlamentsMerrli || ccard.Id == CardId.TearlamentsScheiren))>0) return false; + if (((Bot.HasInMonstersZone(CardId.TearlamentsKitkallos,false,false,true) && !activate_TearlamentsKitkallos_3 && IsShouldSummonFusion(SETCODE, (int)CardRace.Aqua) + && ((CheckRemainInDeck(CardId.TearlamentsHavnis) > 0 && !activate_TearlamentsHavnis_2) + || (CheckRemainInDeck(CardId.TearlamentsMerrli) > 0 && !activate_TearlamentsMerrli_2) + || (CheckRemainInDeck(CardId.TearlamentsScheiren) > 0 && !activate_TearlamentsScheiren_2)) && Bot.GetMonsterCount()<3) + ||(IsCanFusionSummon() && (Bot.HasInMonstersZone(CardId.TearlamentsScheiren) || Bot.HasInMonstersZone(CardId.TearlamentsHavnis) + || Bot.HasInMonstersZone(CardId.TearlamentsMerrli))) || (!activate_TearlamentsReinoheart_2 && Bot.HasInMonstersZone(CardId.TearlamentsReinoheart) && (HasinZoneKeyCard(CardLocation.Hand) + || (Bot.Hand.Count(ccard=> ccard != null && ccard.HasSetcode(SETCODE))>0 && HasinZoneKeyCard(CardLocation.Deck)))&& IsShouldSummonFusion(SETCODE, (int)CardRace.Aqua))) && IsCanSpSummon()) + { + List cards = Enemy.GetMonsters().Where(ecard=> ecard != null && !ecard.IsShouldNotBeTarget() && ecard.IsFaceup()).ToList(); + if (cards.Count > 0) + { + cards.Sort(CardContainer.CompareCardAttack); + cards.Reverse(); + chain_TearlamentsSulliek = cards[0]; + } + else chain_TearlamentsSulliek = null; + return true; + + } + } + } + return false; + } + else + { + return true; + } + + } + } +} \ No newline at end of file diff --git a/libWindbot/Game/AI/Decks/ThunderDragonExecutor.cs b/libWindbot/Game/AI/Decks/ThunderDragonExecutor.cs new file mode 100644 index 0000000..b073f9a --- /dev/null +++ b/libWindbot/Game/AI/Decks/ThunderDragonExecutor.cs @@ -0,0 +1,2563 @@ +using YGOSharp.OCGWrapper.Enums; +using System.Collections.Generic; +using System.Linq; +using WindBot; +using WindBot.Game; +using WindBot.Game.AI; + +namespace WindBot.Game.AI.Decks +{ + [Deck("ThunderDragon", "AI_ThunderDragon")] + class ThunderDragonExecutor : DefaultExecutor + { + public class CardId + { + public const int ThunderDragonlord = 5206415; + public const int TheBystialLubellion = 32731036; + public const int TheChaosCreator = 90488465; + public const int BystialDruiswurm = 6637331; + public const int BystialMagnamhut = 33854624; + public const int ThunderDragonroar = 29596581; + public const int ThunderDragonhawk = 83107873; + public const int NormalThunderDragon = 31786629; + public const int ThunderDragondark = 56713174; + public const int BlackDragonCollapserpent = 61901281; + public const int WhiteDragonWyverburster = 99234526; + public const int AloofLupine = 92998610; + public const int BatterymanSolar = 44586426; + public const int AshBlossom = 14558127; + public const int G = 23434538; + public const int DragonBusterDestructionSword = 76218313; + public const int ThunderDragonmatrix = 20318029; + public const int AllureofDarkness = 1475311; + public const int GoldSarcophagus = 75500286; + public const int ThunderDragonFusion = 95238394; + public const int ChaosSpace = 99266988; + public const int CalledbytheGrave = 24224830; + public const int BrandedRegained = 34090915; + public const int InfiniteImpermanence = 10045474; + public const int BatterymanToken = 44586427; + + public const int ThunderDragonTitan = 41685633; + public const int ThunderDragonColossus = 15291624; + public const int AbyssDweller = 21044178; + public const int UnderworldGoddessoftheClosedWorld = 98127546; + public const int MekkKnightCrusadiaAvramax = 21887175; + public const int AccesscodeTalker = 86066372; + public const int BowoftheGoddess = 4280258; + public const int KnightmareUnicorn = 38342335; + public const int UnionCarrier = 83152482; + public const int IP = 65741786; + public const int CrossSheep = 50277355; + public const int PredaplantVerteAnaconda = 70369116; + public const int StrikerDragon = 73539069; + public const int Linkuriboh = 41999284; + } + private enum Select + { + NormalThunderDragon, + TheChaosCreator, + ChaosSpace_1, + ChaosSpace_2, + ThunderDragonColossus, + AccesscodeTalker, + DestroyReplace + }; + private const int THUNDER_COUNTD = 18; + List selectFlag = new List() + { + false,false,false,false,false,false,false + }; + List selectAtt = new List() + { + false,false,false,false,false,false,false + }; + + bool isSummoned = false; + bool handActivated = false; + bool place_CrossSheep = false; + bool place_ThunderDragonColossus = false; + bool place_Link_4 = false; + bool summon_WhiteDragonWyverburster = false; + bool summon_BlackDragonCollapserpent = false; + bool summon_UnionCarrier = false; + bool summon_TheBystialLubellion = false; + bool activate_ThunderDragonFusion = false; + bool activate_ThunderDragondark = false; + bool activate_ThunderDragonroar = false; + bool activate_ThunderDragonhawk = false; + bool activate_ThunderDragonmatrix = false; + bool activate_TheBystialLubellion_hand = false; + bool activate_BystialMagnamhut_hand = false; + bool activate_BystialDruiswurm_hand = false; + bool activate_ChaosSpace_grave = false; + bool activate_ChaosSpace_hand = false; + bool No_SpSummon = false; + + List SpSummonCardsId = new List() + { + CardId.ThunderDragonmatrix,CardId.BatterymanSolar , + CardId.AshBlossom,CardId.G, + CardId.DragonBusterDestructionSword,CardId.AloofLupine + }; + List NotSpSummonCardsId = new List() + { + CardId.ThunderDragonlord,CardId.TheBystialLubellion,CardId.TheChaosCreator, + CardId.BlackDragonCollapserpent,CardId.WhiteDragonWyverburster + }; + List Impermanence_list = new List(); + List should_not_negate = new List + { + 81275020, 28985331 + }; + public ThunderDragonExecutor(GameAI ai, Duel duel) + : base(ai, duel) + { + AddExecutor(ExecutorType.Activate, CardId.InfiniteImpermanence, Impermanence_activate); + AddExecutor(ExecutorType.Activate, CardId.G, GEffect); + AddExecutor(ExecutorType.Activate, CardId.BowoftheGoddess); + AddExecutor(ExecutorType.Activate, CardId.UnderworldGoddessoftheClosedWorld); + AddExecutor(ExecutorType.Activate, CardId.AshBlossom, AshBlossomEffect); + AddExecutor(ExecutorType.Activate, CardId.TheBystialLubellion, TheBystialLubellionEffect); + AddExecutor(ExecutorType.Activate, CardId.CalledbytheGrave, CalledbytheGraveEffect); + AddExecutor(ExecutorType.Activate, CardId.AccesscodeTalker, AccesscodeTalkerEffect); + AddExecutor(ExecutorType.Activate, CardId.BrandedRegained, BrandedRegainedEffect); + AddExecutor(ExecutorType.Activate, CardId.UnionCarrier, UnionCarrierEffect); + AddExecutor(ExecutorType.SpSummon, CardId.TheBystialLubellion, TheBystialLubellionSummon); + AddExecutor(ExecutorType.Activate, CardId.GoldSarcophagus, GoldSarcophagusEffect); + AddExecutor(ExecutorType.Activate, CardId.NormalThunderDragon, NormalThunderDragonEffect); + AddExecutor(ExecutorType.Activate, CardId.ThunderDragonmatrix, ThunderDragonmatrixEffect); + AddExecutor(ExecutorType.SpSummon, CardId.StrikerDragon, StrikerDragonSummon); + AddExecutor(ExecutorType.SpSummon, CardId.ThunderDragonColossus, ThunderDragonColossusSummon_2); + AddExecutor(ExecutorType.SpSummon, CardId.CrossSheep, CrossSheepSummon); + AddExecutor(ExecutorType.Activate, CardId.CrossSheep, CrossSheepEffect); + AddExecutor(ExecutorType.Activate, CardId.TheChaosCreator); + AddExecutor(ExecutorType.Activate, CardId.ThunderDragonTitan, ThunderDragonTitanEffect); + AddExecutor(ExecutorType.Activate, CardId.ThunderDragonColossus, ThunderDragonColossusEffect); + AddExecutor(ExecutorType.SpSummon, CardId.ThunderDragonColossus, ThunderDragonColossusSummon); + AddExecutor(ExecutorType.Summon, CardId.AloofLupine, AloofLupineSummon); + AddExecutor(ExecutorType.Activate, CardId.AloofLupine, AloofLupineEffect); + AddExecutor(ExecutorType.Summon, CardId.BatterymanSolar, BatterymanSolarSummon); + AddExecutor(ExecutorType.Activate, CardId.BatterymanSolar, BatterymanSolarEffect); + AddExecutor(ExecutorType.SpSummon, CardId.WhiteDragonWyverburster, WhiteDragonWyverbursterSummon); + AddExecutor(ExecutorType.Activate, CardId.WhiteDragonWyverburster); + AddExecutor(ExecutorType.SpSummon, CardId.BlackDragonCollapserpent, BlackDragonCollapserpentSummon); + AddExecutor(ExecutorType.Activate, CardId.BlackDragonCollapserpent); + AddExecutor(ExecutorType.SpSummon, CardId.UnionCarrier, UnionCarrierSummon); + AddExecutor(ExecutorType.Activate, CardId.AllureofDarkness, AllureofDarknessEffect); + AddExecutor(ExecutorType.Activate, CardId.ThunderDragonhawk, ThunderDragonhawkEffect); + AddExecutor(ExecutorType.Activate, CardId.ChaosSpace, ChaosSpaceEffect); + AddExecutor(ExecutorType.Activate, CardId.BystialMagnamhut, BystialMagnamhutEffect); + AddExecutor(ExecutorType.Activate, CardId.BystialDruiswurm, BystialDruiswurmEffect); + AddExecutor(ExecutorType.SpSummon, CardId.ThunderDragonlord, ThunderDragonlordSummon); + AddExecutor(ExecutorType.Activate, CardId.PredaplantVerteAnaconda, PredaplantVerteAnacondaEffect); + AddExecutor(ExecutorType.MonsterSet, CardId.ThunderDragonmatrix, ThunderDragonmatrixSet); + AddExecutor(ExecutorType.Activate, CardId.ThunderDragonFusion, ThunderDragonFusionEffect); + AddExecutor(ExecutorType.Activate, CardId.ThunderDragondark, ThunderDragondarkEffect); + AddExecutor(ExecutorType.Activate, CardId.ThunderDragonroar, ThunderDragonroarEffect); + AddExecutor(ExecutorType.Activate, CardId.ThunderDragonlord, ThunderDragonlordEffect); + AddExecutor(ExecutorType.SpSummon, CardId.TheChaosCreator, TheChaosCreatorSummon); + AddExecutor(ExecutorType.SpSummon, CardId.UnderworldGoddessoftheClosedWorld, UnderworldGoddessoftheClosedWorldSummon); + AddExecutor(ExecutorType.SpSummon, CardId.BowoftheGoddess, BowoftheGoddessSummon); + AddExecutor(ExecutorType.SpSummon, CardId.UnionCarrier, UnionCarrierSummon_2); + AddExecutor(ExecutorType.Activate, CardId.IP, IPEffect); + AddExecutor(ExecutorType.SpSummon, CardId.IP,IPSummon); + AddExecutor(ExecutorType.Activate, CardId.KnightmareUnicorn, KnightmareUnicornEffect); + AddExecutor(ExecutorType.SpSummon, CardId.KnightmareUnicorn, KnightmareUnicornSummon); + AddExecutor(ExecutorType.SpSummon, CardId.AccesscodeTalker, BowoftheGoddessSummon); + AddExecutor(ExecutorType.Activate, CardId.MekkKnightCrusadiaAvramax, MekkKnightCrusadiaAvramaxEffect); + AddExecutor(ExecutorType.SpSummon, CardId.MekkKnightCrusadiaAvramax, MekkKnightCrusadiaAvramaxSummon); + AddExecutor(ExecutorType.SpSummon, CardId.PredaplantVerteAnaconda, PredaplantVerteAnacondaSummon); + AddExecutor(ExecutorType.Activate, CardId.Linkuriboh); + AddExecutor(ExecutorType.SpSummon, CardId.Linkuriboh); + AddExecutor(ExecutorType.SpSummon, CardId.AbyssDweller); + AddExecutor(ExecutorType.Activate, CardId.AbyssDweller, GEffect); + AddExecutor(ExecutorType.Activate, CardId.ChaosSpace, ChaosSpaceEffect_2); + AddExecutor(ExecutorType.Activate, CardId.ThunderDragonmatrix, ThunderDragonmatrixEffect_2); + AddExecutor(ExecutorType.Summon, CardId.ThunderDragonmatrix, ThunderDragonmatrixSummon); + AddExecutor(ExecutorType.SpSummon, CardId.BlackDragonCollapserpent, BlackDragonCollapserpentSummon_2); + AddExecutor(ExecutorType.Summon, CardId.ThunderDragonroar, DefaultSummon); + AddExecutor(ExecutorType.Summon, CardId.ThunderDragondark, DefaultSummon); + AddExecutor(ExecutorType.Summon, CardId.NormalThunderDragon, DefaultSummon); + AddExecutor(ExecutorType.Summon, CardId.DragonBusterDestructionSword, ThunderDragonmatrixSummon); + AddExecutor(ExecutorType.Summon, CardId.AloofLupine, DefaultSummon); + AddExecutor(ExecutorType.Summon, CardId.AshBlossom, DefaultSummon); + AddExecutor(ExecutorType.Summon, CardId.G, DefaultSummon); + AddExecutor(ExecutorType.Activate, CardId.ThunderDragondark, ThunderDragondarkEffect_2); + AddExecutor(ExecutorType.SpellSet, SpellSet); + AddExecutor(ExecutorType.Activate, CardId.AllureofDarkness, AllureofDarknessEffect_2); + AddExecutor(ExecutorType.Activate, CardId.UnionCarrier, UnionCarrierEffect_2); + AddExecutor(ExecutorType.Repos, DefaultMonsterRepos); + + } + #region DeckCheck + public int CheckRemainInDeck(int id) + { + switch (id) + { + case CardId.ThunderDragonlord: + return Bot.GetRemainingCount(CardId.ThunderDragonlord, 1); + case CardId.TheBystialLubellion: + return Bot.GetRemainingCount(CardId.TheBystialLubellion, 2); + case CardId.TheChaosCreator: + return Bot.GetRemainingCount(CardId.TheChaosCreator, 1); + case CardId.BystialDruiswurm: + return Bot.GetRemainingCount(CardId.BystialDruiswurm, 2); + case CardId.BystialMagnamhut: + return Bot.GetRemainingCount(CardId.BystialMagnamhut, 2); + case CardId.ThunderDragonroar: + return Bot.GetRemainingCount(CardId.ThunderDragonroar, 2); + case CardId.ThunderDragonhawk: + return Bot.GetRemainingCount(CardId.ThunderDragonhawk, 2); + case CardId.NormalThunderDragon: + return Bot.GetRemainingCount(CardId.NormalThunderDragon, 3); + case CardId.ThunderDragondark: + return Bot.GetRemainingCount(CardId.ThunderDragondark, 3); + case CardId.BlackDragonCollapserpent: + return Bot.GetRemainingCount(CardId.BlackDragonCollapserpent, 2); + case CardId.WhiteDragonWyverburster: + return Bot.GetRemainingCount(CardId.WhiteDragonWyverburster, 2); + case CardId.AloofLupine: + return Bot.GetRemainingCount(CardId.AloofLupine, 2); + case CardId.BatterymanSolar: + return Bot.GetRemainingCount(CardId.BatterymanSolar, 3); + case CardId.AshBlossom: + return Bot.GetRemainingCount(CardId.AshBlossom, 2); + case CardId.G: + return Bot.GetRemainingCount(CardId.G, 3); + case CardId.DragonBusterDestructionSword: + return Bot.GetRemainingCount(CardId.DragonBusterDestructionSword, 1); + case CardId.ThunderDragonmatrix: + return Bot.GetRemainingCount(CardId.ThunderDragonmatrix, 3); + case CardId.AllureofDarkness: + return Bot.GetRemainingCount(CardId.AllureofDarkness, 3); + case CardId.GoldSarcophagus: + return Bot.GetRemainingCount(CardId.GoldSarcophagus, 1); + case CardId.ThunderDragonFusion: + return Bot.GetRemainingCount(CardId.ThunderDragonFusion, 2); + case CardId.ChaosSpace: + return Bot.GetRemainingCount(CardId.ChaosSpace, 3); + case CardId.CalledbytheGrave: + return Bot.GetRemainingCount(CardId.CalledbytheGrave, 2); + case CardId.BrandedRegained: + return Bot.GetRemainingCount(CardId.BrandedRegained, 1); + case CardId.InfiniteImpermanence: + return Bot.GetRemainingCount(CardId.InfiniteImpermanence, 2); + default: + return 0; + } + } + #endregion + + public override bool OnSelectHand() + { + // go first + return true; + } + + public override void OnNewTurn() + { + handActivated = false; + isSummoned = false; + No_SpSummon = false; + + activate_ThunderDragonFusion = false; + activate_ThunderDragondark = false; + activate_ThunderDragonroar = false; + activate_ThunderDragonhawk = false; + activate_ThunderDragonmatrix = false; + activate_TheBystialLubellion_hand = false; + activate_BystialMagnamhut_hand = false; + activate_BystialDruiswurm_hand = false; + activate_ChaosSpace_grave = false; + + summon_WhiteDragonWyverburster = false; + summon_BlackDragonCollapserpent = false; + summon_TheBystialLubellion = false; + summon_UnionCarrier = false; + + for (int i = 0; i < selectAtt.Count; i++) + selectAtt[i] = false; + } + private bool IsAvailableZone(int seq) + { + ClientCard card = Bot.MonsterZone[seq]; + if (seq == 5 && Bot.MonsterZone[6] != null && Bot.MonsterZone[6].Controller == 0) return false; + if (seq == 6 && Bot.MonsterZone[5] != null && Bot.MonsterZone[5].Controller == 0) return false; + if (card == null) return true; + if (card.Controller != 0) return false; + if (card.IsFacedown()) return false; + if (card.IsDisabled()) return true; + if (card.Id == CardId.ThunderDragonColossus + || card.Id == CardId.ThunderDragonTitan + || card.Id == CardId.UnderworldGoddessoftheClosedWorld + || card.Id == CardId.MekkKnightCrusadiaAvramax + || card.Id == CardId.AccesscodeTalker + || (card.Id == CardId.BowoftheGoddess && card.Attack > 800) + || (card.Id == CardId.UnionCarrier && summon_UnionCarrier)) return false; + return true; + } + private bool IsAvailableLinkZone() + { + int zones = 0; + List cards = Bot.GetMonstersInMainZone().Where(card => card != null && card.IsFaceup()).ToList(); + foreach (var card in cards) + { + zones |= card.GetLinkedZones(); + } + ClientCard e_card = Bot.MonsterZone[5]; + if (e_card != null && e_card.IsFaceup() && e_card.HasType(CardType.Link)) + { + if (e_card.Controller == 0) + { + if (e_card.HasLinkMarker(CardLinkMarker.BottomLeft)) + zones |= 1 << 0; + if (e_card.HasLinkMarker(CardLinkMarker.Bottom)) + zones |= 1 << 1; + if (e_card.HasLinkMarker(CardLinkMarker.BottomRight)) + zones |= 1 << 2; + } + if (e_card.Controller == 1) + { + if (e_card.HasLinkMarker(CardLinkMarker.TopLeft)) + zones |= 1 << 2; + if (e_card.HasLinkMarker(CardLinkMarker.Top)) + zones |= 1 << 1; + if (e_card.HasLinkMarker(CardLinkMarker.TopRight)) + zones |= 1 << 0; + } + } + e_card = Bot.MonsterZone[6]; + if (e_card != null && e_card.IsFaceup() && e_card.HasType(CardType.Link)) + { + if (e_card.Controller == 0) + { + if (e_card.HasLinkMarker(CardLinkMarker.BottomLeft)) + zones |= 1 << 2; + if (e_card.HasLinkMarker(CardLinkMarker.Bottom)) + zones |= 1 << 3; + if (e_card.HasLinkMarker(CardLinkMarker.BottomRight)) + zones |= 1 << 4; + } + if (e_card.Controller == 1) + { + if (e_card.HasLinkMarker(CardLinkMarker.TopLeft)) + zones |= 1 << 4; + if (e_card.HasLinkMarker(CardLinkMarker.Top)) + zones |= 1 << 3; + if (e_card.HasLinkMarker(CardLinkMarker.TopRight)) + zones |= 1 << 2; + } + } + zones &= 0x7f; + if ((zones & Zones.z0) > 0 && IsAvailableZone(0)) return true; + if ((zones & Zones.z1) > 0 && IsAvailableZone(1)) return true; + if ((zones & Zones.z2) > 0 && IsAvailableZone(2)) return true; + if ((zones & Zones.z3) > 0 && IsAvailableZone(3)) return true; + if ((zones & Zones.z4) > 0 && IsAvailableZone(4)) return true; + if (IsAvailableZone(5)) return true; + if (IsAvailableZone(6)) return true; + return false; + } + private void ResetFlag() + { + for (int i = 0; i < selectFlag.Count; ++i) + { + selectFlag[i] = false; + } + } + public override int OnSelectPlace(int cardId, int player, CardLocation location, int available) + { + if (player == 0 && location==CardLocation.MonsterZone) + { + if (place_CrossSheep) + { + place_CrossSheep = false; + if ((Zones.z5 & available) > 0) return Zones.z5; + if ((Zones.z6 & available) > 0) return Zones.z6; + } + if (place_ThunderDragonColossus) + { + place_ThunderDragonColossus = false; + if (Bot.MonsterZone[5] != null && Bot.MonsterZone[5].IsCode(CardId.CrossSheep)) + { + if ((Zones.z0 & available) > 0) return Zones.z0; + if ((Zones.z2 & available) > 0) return Zones.z2; + } + if (Bot.MonsterZone[6] != null && Bot.MonsterZone[6].IsCode(CardId.CrossSheep)) + { + if ((Zones.z2 & available) > 0) return Zones.z2; + if ((Zones.z4 & available) > 0) return Zones.z4; + } + if ((Zones.z2 & available) > 0) return Zones.z2; + if ((Zones.z0 & available) > 0) return Zones.z0; + if ((Zones.z4 & available) > 0) return Zones.z4; + } + if (place_Link_4) + { + place_Link_4 = false; + if ((Zones.z5 & available) > 0) return Zones.z5; + if ((Zones.z6 & available) > 0) return Zones.z6; + } + if (Bot.MonsterZone[5] != null && Bot.MonsterZone[5].IsCode(CardId.CrossSheep)) + { + if ((Zones.z0 & available) > 0 && Bot.MonsterZone[2] != null && Bot.MonsterZone[2].HasType(CardType.Fusion) && Bot.MonsterZone[2].IsFaceup()) return Zones.z0; + if ((Zones.z2 & available) > 0 && Bot.MonsterZone[0] != null && Bot.MonsterZone[0].HasType(CardType.Fusion) && Bot.MonsterZone[0].IsFaceup()) return Zones.z2; + } + if (Bot.MonsterZone[6] != null && Bot.MonsterZone[6].IsCode(CardId.CrossSheep)) + { + if ((Zones.z2 & available) > 0 && Bot.MonsterZone[4] != null && Bot.MonsterZone[4].HasType(CardType.Fusion) && Bot.MonsterZone[4].IsFaceup()) return Zones.z2; + if ((Zones.z4 & available) > 0 && Bot.MonsterZone[2] != null && Bot.MonsterZone[2].HasType(CardType.Fusion) && Bot.MonsterZone[2].IsFaceup()) return Zones.z4; + } + return base.OnSelectPlace(cardId, player, location, available); + } + return base.OnSelectPlace(cardId, player, location, available); + } + public override IList OnSelectCard(IList cards, int min, int max, int hint, bool cancelable) + { + if (selectFlag.Count(flag => flag) > 1) + { + if (selectFlag.Count(flag => flag) == 2 && selectFlag[(int)Select.TheChaosCreator] && !selectFlag[(int)Select.DestroyReplace]) + { + selectFlag[(int)Select.TheChaosCreator] = false; + } + else if (selectFlag.Count(flag => flag) == 2 && selectFlag[(int)Select.DestroyReplace]) + { + selectFlag[(int)Select.DestroyReplace] = false; + } + else + { + ResetFlag(); + return null; + } + } + if (selectFlag[(int)Select.NormalThunderDragon]) + { + selectFlag[(int)Select.NormalThunderDragon] = false; + //ThunderDragonTitan + if (cards.Any(card => card != null && card.Controller != 0)) return null; + if (cards.Count <= 1) return null; + if (Bot.HasInHand(CardId.ChaosSpace) && !activate_ChaosSpace_hand) + return Util.CheckSelectCount(cards, cards, max, max); + if(Bot.HasInHand(CardId.AloofLupine) && !isSummoned && GetRemainingThunderCount(true)>0) + return Util.CheckSelectCount(cards, cards, max, max); + if (Bot.HasInHand(CardId.ThunderDragonFusion) && !activate_ThunderDragonFusion) + return Util.CheckSelectCount(cards, cards, min, min); + if(HasInZoneNoActivate(CardId.BlackDragonCollapserpent,CardLocation.Hand) + || HasInZoneNoActivate(CardId.BystialDruiswurm, CardLocation.Hand) + || HasInZoneNoActivate(CardId.BystialMagnamhut, CardLocation.Hand) + || HasInZoneNoActivate(CardId.TheBystialLubellion, CardLocation.Hand)) + return Util.CheckSelectCount(cards, cards, min, min); + if(HasInZoneNoActivate(CardId.ThunderDragonhawk,CardLocation.Hand)) + return Util.CheckSelectCount(cards, cards, min, min); + return Util.CheckSelectCount(cards, cards, max, max); + } + if (selectFlag[(int)Select.ChaosSpace_1]) + { + selectFlag[(int)Select.ChaosSpace_1] = false; + selectFlag[(int)Select.ChaosSpace_2] = true; + List res = new List(); + if (cards.Any(card => card != null && card.IsCode(CardId.ThunderDragonroar)) && !activate_ThunderDragonroar) + res.AddRange(cards.Where(card => card != null && card.IsCode(CardId.ThunderDragonroar)).ToList()); + if (cards.Any(card => card != null && card.IsCode(CardId.ThunderDragondark)) && !activate_ThunderDragondark) + res.AddRange(cards.Where(card => card != null && card.IsCode(CardId.ThunderDragondark)).ToList()); + if (cards.Any(card => card != null && card.IsCode(CardId.ThunderDragondark)) && !activate_ThunderDragondark) + res.AddRange(cards.Where(card => card != null && card.IsCode(CardId.ThunderDragondark)).ToList()); + if (cards.Any(card => card != null && card.IsCode(CardId.NormalThunderDragon))) + res.AddRange(cards.Where(card => card != null && card.IsCode(CardId.NormalThunderDragon)).ToList()); + if (cards.Any(card => card != null && card.IsCode(CardId.ThunderDragonmatrix))) + res.AddRange(cards.Where(card => card != null && card.IsCode(CardId.ThunderDragonmatrix)).ToList()); + if (res.Count <= 0) return null; + return Util.CheckSelectCount(res, cards, min, max); + } + if (selectFlag[(int)Select.ChaosSpace_2]) + { + selectFlag[(int)Select.ChaosSpace_2] = false; + List res = new List(); + //can't get CardAttributes in deck + if (cards.Any(card => card != null && (card.Id == CardId.BlackDragonCollapserpent + || card.Id == CardId.TheChaosCreator))) + { + if (!summon_BlackDragonCollapserpent && cards.Any(card => card != null && card.IsCode(CardId.BlackDragonCollapserpent) && !Bot.HasInHand(CardId.BlackDragonCollapserpent))) + { + IList cards_1 = cards.Where(card => card != null && card.IsCode(CardId.BlackDragonCollapserpent)).ToList(); + IList cards_2 = cards.Where(card => card != null && !card.IsCode(CardId.BlackDragonCollapserpent)).ToList(); + res.AddRange(cards_1); + res.AddRange(cards_2); + return Util.CheckSelectCount(res, cards, min, max); + } + else + { + res = cards.ToList(); + res.Sort(CardContainer.CompareCardLevel); + res.Reverse(); + return Util.CheckSelectCount(res, cards, min, max); + } + } + else if (cards.Any(card => card != null && (card.Id == CardId.WhiteDragonWyverburster + ||card.Id == CardId.ThunderDragonlord || card.Id == CardId.TheBystialLubellion))) + { + if (!summon_WhiteDragonWyverburster && cards.Any(card => card != null && card.IsCode(CardId.WhiteDragonWyverburster) + && (Bot.HasInExtra(CardId.StrikerDragon) || Bot.HasInExtra(CardId.UnionCarrier)) && !Bot.HasInHand(CardId.WhiteDragonWyverburster))) + { + IList cards_1 = cards.Where(card => card != null && card.IsCode(CardId.WhiteDragonWyverburster)).ToList(); + IList cards_2 = cards.Where(card => card != null && !card.IsCode(CardId.WhiteDragonWyverburster)).ToList(); + res.AddRange(cards_1); + res.AddRange(cards_2); + return Util.CheckSelectCount(res, cards, min, max); + } + else if (!activate_TheBystialLubellion_hand && (HasInZoneNoActivate(CardId.BystialMagnamhut, CardLocation.Deck) + || HasInZoneNoActivate(CardId.BystialDruiswurm, CardLocation.Deck) && !Bot.HasInHand(CardId.TheBystialLubellion)) + && cards.Any(card => card != null && card.IsCode(CardId.TheBystialLubellion))) + { + IList cards_1 = cards.Where(card => card != null && card.IsCode(CardId.TheBystialLubellion)).ToList(); + IList cards_2 = cards.Where(card => card != null && !card.IsCode(CardId.TheBystialLubellion)).ToList(); + res.AddRange(cards_1); + res.AddRange(cards_2); + return Util.CheckSelectCount(res, cards, min, max); + } + else if (!summon_WhiteDragonWyverburster && !Bot.HasInHand(CardId.WhiteDragonWyverburster) && cards.Any(card => card != null && card.IsCode(CardId.WhiteDragonWyverburster))) + { + IList cards_1 = cards.Where(card => card != null && card.IsCode(CardId.WhiteDragonWyverburster)).ToList(); + IList cards_2 = cards.Where(card => card != null && !card.IsCode(CardId.WhiteDragonWyverburster)).ToList(); + res.AddRange(cards_1); + res.AddRange(cards_2); + return Util.CheckSelectCount(res, cards, min, max); + } + else + { + res = cards.ToList(); + res.Sort(CardContainer.CompareCardLevel); + return Util.CheckSelectCount(res, cards, min, max); + } + } + return null; + } + if (selectFlag[(int)Select.ThunderDragonColossus]) + { + selectFlag[(int)Select.ThunderDragonColossus] = false; + if (cards.Count < 2) return null; + List copy_cards = new List(cards); + copy_cards.Sort(CardContainer.CompareCardAttack); + IList res = new List(); + for (int i = 0; i < copy_cards.Count; ++i) + { + if ((copy_cards[i].Id == CardId.ThunderDragonroar && HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.MonsterZone) && Bot.GetMonstersInMainZone().Count < 5) + || (copy_cards[i].Id == CardId.ThunderDragondark && HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.MonsterZone)) + || (copy_cards[i].Id == CardId.ThunderDragonmatrix && HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.MonsterZone))) + { + if (i <= 0) continue; + ClientCard temp = copy_cards[0]; + copy_cards[0] = copy_cards[i]; + copy_cards[i] = temp; + } + } + return Util.CheckSelectCount(copy_cards, cards, min, max); + } + if (selectFlag[(int)Select.AccesscodeTalker]) + { + selectFlag[(int)Select.AccesscodeTalker] = false; + List copy_cards = new List(cards); + copy_cards.Sort(CardContainer.CompareCardAttack); + List res = new List(); + res.AddRange(copy_cards.Where(card => card != null && card.Location == CardLocation.Grave)); + res.AddRange(copy_cards.Where(card => card != null && card.Location != CardLocation.Grave)); + if (res.Count <= 0) return null; + CardAttribute att = (CardAttribute)res[0].Attribute; + if (GetAttIndex(att) > 0) selectAtt[GetAttIndex(att)] = true; + return Util.CheckSelectCount(res, cards, min, max); + } + if (selectFlag[(int)Select.DestroyReplace]) + { + selectFlag[(int)Select.DestroyReplace] = false; + if (min == 1 && max == 1) + { + List copy_cards = new List(cards); + copy_cards.Sort(CardContainer.CompareCardAttack); + List res = new List(); + List pre_res = new List(); + foreach (var card in copy_cards) + { + if (card == null) continue; + if (card.Id == CardId.ThunderDragonroar && !activate_ThunderDragonroar && Bot.GetMonstersInMainZone().Count < 5) + res.Add(card); + else if (card.Id == CardId.ThunderDragondark && !activate_ThunderDragondark) + res.Add(card); + else + pre_res.Add(card); + } + res.Reverse(); + res.AddRange(pre_res); + if(res.Count>=0) return Util.CheckSelectCount(res, cards, min, max); + return null; + } + if (min == 2 && max == 2) + { + List res = new List(); + if (!activate_ThunderDragonroar && Bot.GetMonstersInMainZone().Count < 5) + { + foreach (var card in cards) + if (card.Id == CardId.ThunderDragonroar && res.Count(_card => _card != null && _card.Id == CardId.ThunderDragonroar) <= 0) + res.Add(card); + } + if (!activate_ThunderDragondark) + { + foreach (var card in cards) + if (card.Id == CardId.ThunderDragondark && res.Count(_card => _card != null && _card.Id == CardId.ThunderDragondark) <= 0) + res.Add(card); + } + if (!activate_ThunderDragonhawk && !GetZoneRepeatCardsId(0,Bot.Hand).Contains(-1)) + { + foreach (var card in cards) + if (card.Id == CardId.ThunderDragonhawk && res.Count(_card => _card != null && _card.Id == CardId.ThunderDragonhawk) <= 0) + res.Add(card); + } + if (HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.Deck)) + { + foreach (var card in cards) + if (card.Id == CardId.ThunderDragonmatrix && res.Count(_card => _card != null && _card.Id == CardId.ThunderDragonmatrix) <= 0) + res.Add(card); + } + List scards = cards.Where(card => card != null && card.Id != CardId.ChaosSpace && card.Id != CardId.ThunderDragonFusion).ToList(); + if (scards.Count > 0) res.AddRange(scards); + List mcards = cards.Where(card => card != null && !card.HasRace(CardRace.Thunder)).ToList(); + mcards.Sort(CardContainer.CompareCardAttack); + mcards.Reverse(); + if (mcards.Count > 0) res.AddRange(mcards); + if(res.Count>0) return Util.CheckSelectCount(res, cards, min, max); + return null; + + } + } + if (hint == HintMsg.FusionMaterial) + { + List res = new List(); + List banish = cards.Where(card => card != null && card.Location == CardLocation.Removed).ToList(); + if (banish.Count > 0) res.AddRange(banish); + List grave_1 = cards.Where(card => card != null && card.Location == CardLocation.Grave && card.Id != CardId.ThunderDragonroar && card.Id != CardId.ThunderDragondark).ToList(); + List grave_2 = cards.Where(card => card != null && card.Location == CardLocation.Grave && (card.Id == CardId.ThunderDragonroar || card.Id == CardId.ThunderDragondark)).ToList(); + if (grave_1.Count > 0) res.AddRange(grave_1); + if (grave_2.Count > 0) res.AddRange(grave_2); + List monsters = cards.Where(card => card != null && card.Location == CardLocation.MonsterZone).ToList(); + monsters.Sort(CardContainer.CompareCardAttack); + if (monsters.Count > 0) res.AddRange(monsters); + if (res.Count > 0) return Util.CheckSelectCount(res, cards, min, max); + return null; + } + if (Duel.Phase == DuelPhase.End && hint == HintMsg.AddToHand) + { + List res = new List(); + List cards_1 = cards.Where(card => card != null && card.Id == CardId.BystialDruiswurm).ToList(); + List cards_2 = cards.Where(card => card != null && (card.Id == CardId.WhiteDragonWyverburster || card.Id == CardId.BlackDragonCollapserpent)).ToList(); + List cards_3 = cards.Where(card => card != null && card.Id != CardId.BystialDruiswurm && card.Id != CardId.WhiteDragonWyverburster && card.Id != CardId.BlackDragonCollapserpent).ToList(); + if (cards_1.Count > 0) res.AddRange(cards_1); + if (cards_2.Count > 0) res.AddRange(cards_2); + if (cards_3.Count > 0) res.AddRange(cards_3); + if (res.Count > 0) return Util.CheckSelectCount(res, cards, min, max); + return null; + } + if (hint == HintMsg.OperateCard) + { + if (cards.Any(card => card != null && card.Location == CardLocation.Removed)) + { + selectFlag[(int)Select.TheChaosCreator] = true; + List res = new List(); + List cards_1 = cards.Where(card => card != null && card.Controller == 0 && (card.IsCode(CardId.ThunderDragonColossus) || card.IsCode(CardId.ThunderDragonTitan))).ToList(); + if (cards_1.Count > 0) res.AddRange(cards_1); + List cards_2 = cards.Where(card => card != null && card.Controller == 0 && !card.IsCode(CardId.ThunderDragonColossus) && !card.IsCode(CardId.ThunderDragonTitan)).ToList(); + if (cards_2.Count > 0) res.AddRange(cards_2); + List cards_3 = cards.Where(card => card != null && card.Controller == 1).ToList(); + if (cards_3.Count > 0) res.AddRange(cards_3); + if (res.Count > 0) return Util.CheckSelectCount(res, cards, min, max); + return null; + } + return null; + } + if (selectFlag[(int)Select.TheChaosCreator]) + { + selectFlag[(int)Select.TheChaosCreator] = false; + List res = new List(cards); + res.Sort(CardContainer.CompareCardAttack); + if (res.Count <= 0) return null; + if(res[0].Attack= 0 && this_seq + that_seq == 4) + || (Util.IsChainTarget(Card)) + || (LastChainCard != null && LastChainCard.Controller == 1 && LastChainCard.IsCode(_CardId.HarpiesFeatherDuster))) + { + List enemy_monsters = Enemy.GetMonsters(); + enemy_monsters.Sort(CardContainer.CompareCardAttack); + enemy_monsters.Reverse(); + foreach (ClientCard card in enemy_monsters) + { + if (card.IsFaceup() && !card.IsShouldNotBeTarget() && !card.IsShouldNotBeSpellTrapTarget()) + { + AI.SelectCard(card); + Impermanence_list.Add(this_seq); + return true; + } + } + } + } + if ((LastChainCard == null || LastChainCard.Controller != 1 || LastChainCard.Location != CardLocation.MonsterZone + || LastChainCard.IsDisabled() || LastChainCard.IsShouldNotBeTarget() || LastChainCard.IsShouldNotBeSpellTrapTarget())) + return false; + // negate monsters + if (is_should_not_negate() && LastChainCard.Location == CardLocation.MonsterZone) return false; + if (Card.Location == CardLocation.SpellZone) + { + for (int i = 0; i < 5; ++i) + { + if (Bot.SpellZone[i] == Card) + { + Impermanence_list.Add(i); + break; + } + } + } + if (Card.Location == CardLocation.Hand) + { + AI.SelectPlace(SelectSTPlace(Card, true)); + } + if (LastChainCard != null) AI.SelectCard(LastChainCard); + else + { + List enemy_monsters = Enemy.GetMonsters(); + enemy_monsters.Sort(CardContainer.CompareCardAttack); + enemy_monsters.Reverse(); + foreach (ClientCard card in enemy_monsters) + { + if (card.IsFaceup() && !card.IsShouldNotBeTarget() && !card.IsShouldNotBeSpellTrapTarget()) + { + AI.SelectCard(card); + return true; + } + } + } + return true; + } + 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 bool is_should_not_negate() + { + ClientCard last_card = Util.GetLastChainCard(); + if (last_card != null + && last_card.Controller == 1 && last_card.IsCode(should_not_negate)) + return true; + return false; + } + private bool MekkKnightCrusadiaAvramaxEffect() + { + if (Card.Location == CardLocation.Grave) + { + List cards = Enemy.GetMonsters(); + cards.Sort(CardContainer.CompareCardAttack); + cards.Reverse(); + cards.AddRange(Enemy.GetSpells()); + if (cards.Count <= 0) return false; + AI.SelectCard(cards); + return true; + } + else return true; + } + private bool ThunderDragonColossusEffect() + { + selectFlag[(int)Select.DestroyReplace] = true; + return true; + } + private IList GetAttUsed() + { + IList attributes = new List(); + for (int i = 0; i < selectAtt.Count; ++i) + if (selectAtt[i]) attributes.Add((CardAttribute)(System.Math.Pow(2, i))); + if (attributes.Count > 0) return attributes; + return null; + } + private int GetRemainingThunderCount(bool isOnlyTunder = false) + { + int remaining = THUNDER_COUNTD; + if (isOnlyTunder) remaining -= 4; + remaining = remaining - Bot.Hand.Count(card => card != null && card.HasRace(CardRace.Thunder) && !card.IsExtraCard() && !(isOnlyTunder & !Card.HasSetcode(0x11c))); + remaining = remaining - Bot.SpellZone.Count(card => card != null && card.HasRace(CardRace.Thunder) && !card.IsExtraCard() && !(isOnlyTunder & !Card.HasSetcode(0x11c))); + remaining = remaining - Bot.MonsterZone.Count(card => card != null && card.HasRace(CardRace.Thunder) && !card.IsExtraCard() && !(isOnlyTunder & !Card.HasSetcode(0x11c))); + remaining = remaining - Bot.Graveyard.Count(card => card != null && card.HasRace(CardRace.Thunder) && !card.IsExtraCard() && !(isOnlyTunder & !Card.HasSetcode(0x11c))); + remaining = remaining - Bot.Banished.Count(card => card != null && card.HasRace(CardRace.Thunder) && !card.IsExtraCard() && !(isOnlyTunder & !Card.HasSetcode(0x11c))); + return (remaining < 0) ? 0 : remaining; + } + private int GetLinkMark(int cardId) + { + if (cardId == CardId.Linkuriboh || cardId == CardId.StrikerDragon) return 1; + if (cardId == CardId.PredaplantVerteAnaconda || cardId == CardId.CrossSheep || cardId == CardId.IP || cardId == CardId.UnionCarrier) return 2; + if (cardId == CardId.KnightmareUnicorn) return 3; + if (cardId == CardId.BowoftheGoddess || cardId == CardId.AccesscodeTalker || cardId == CardId.MekkKnightCrusadiaAvramax) return 4; + if (cardId == CardId.UnderworldGoddessoftheClosedWorld) return 5; + return 1; + } + private bool AshBlossomEffect() + { + return Duel.CurrentChain.Count > 0 && Duel.LastChainPlayer != 0; + } + public int CompareCardLink(ClientCard cardA, ClientCard cardB) + { + if (cardA.LinkCount < cardB.LinkCount) + return -1; + if (cardA.LinkCount == cardB.LinkCount) + return 0; + return 1; + } + private IList CardsIdToClientCards(IList cardsId, IList cardsList, bool uniqueId = true, bool alias = true) + { + if (cardsList?.Count() <= 0 || cardsId?.Count() <= 0) return new List(); + List res = new List(); + foreach (var cardid in cardsId) + { + List cards = cardsList.Where(card => card != null && (card.Id == cardid || ((card.Alias != 0 && cardid == card.Alias) & alias))).ToList(); + if (cards?.Count <= 0) continue; + cards.Sort(CardContainer.CompareCardAttack); + if (uniqueId) res.Add(cards.First()); + else res.AddRange(cards); + } + return res; + } + private bool IPEffect() + { + if (Duel.LastChainPlayer == 0) return false; + if (!Bot.HasInExtra(CardId.KnightmareUnicorn) && !Bot.HasInExtra(CardId.MekkKnightCrusadiaAvramax)) return false; + int[] materials = new[] { + CardId.PredaplantVerteAnaconda, + CardId.UnionCarrier, + CardId.CrossSheep + }; + if (Bot.HasInExtra(CardId.MekkKnightCrusadiaAvramax)) + { + List m = new List(); + IList pre_m = CardsIdToClientCards(materials, Bot.GetMonsters().Where(card=>card!=null && card.IsFaceup()).ToList()); + if (pre_m?.Count <= 0) return false; + int link_count = 0; + foreach (var card in pre_m) + { + m.Add(card); + link_count += (card.HasType(CardType.Link)) ? card.LinkCount : 1; + if (link_count >= 4) break; + } + if (link_count < 4) return false; + AI.SelectCard(CardId.MekkKnightCrusadiaAvramax); + AI.SelectMaterials(m); + return true; + } + else if (Bot.HasInExtra(CardId.KnightmareUnicorn)) + { + if (Bot.Hand.Count <= 0) return false; + List pre_cards = Enemy.GetMonsters(); + pre_cards.AddRange(Enemy.GetSpells()); + if (pre_cards.Count(card => card != null && !card.IsShouldNotBeTarget()) <= 0) return false; + List materials_2 = new List(); + List resMaterials = new List(); + foreach (var card in Bot.GetMonsters()) + { + if (card == null) continue; + if (card.Id == CardId.UnionCarrier && summon_UnionCarrier) continue; + if ((GetLinkMark(card.Id) < 3 || (card.Id == CardId.BowoftheGoddess && card.Attack <= 800)) && card.Id != CardId.ThunderDragonTitan + && card.Id != CardId.ThunderDragonColossus && card.IsFaceup() && materials_2.Count(_card => _card != null && _card.Id == card.Id) <= 0) + materials_2.Add(card); + } + int link_count = 0; + materials_2.Sort(CardContainer.CompareCardAttack); + materials_2.Sort(CompareCardLink); + materials_2.Reverse(); + if (materials_2.Count <= 0) return false; + foreach (var card in materials_2) + { + if (!resMaterials.Contains(card)) + { + resMaterials.Add(card); + link_count += (card.HasType(CardType.Link)) ? card.LinkCount : 1; + if (link_count >= 3) break; + } + } + if (link_count >= 3) { AI.SelectCard(CardId.KnightmareUnicorn); AI.SelectMaterials(resMaterials); return true; } + } + return false; + } + private bool AccesscodeTalkerEffect() + { + if (ActivateDescription == Util.GetStringId(CardId.AccesscodeTalker, 1)) + { + if (Card.IsDisabled()) return false; + if (Bot.Graveyard.Count(card => card != null && card.HasType(CardType.Link)) <= 0) return false; + IList attributes = GetAttUsed(); + if (attributes == null || attributes.Count <= 0) { ResetFlag(); selectFlag[(int)Select.AccesscodeTalker] = true; return true; } + if (Bot.Graveyard.Count(card => card != null && card.HasType(CardType.Link) && !attributes.Contains((CardAttribute)card.Attribute)) <= 0) return false; + ResetFlag(); + selectFlag[(int)Select.AccesscodeTalker] = true; + return true; + } + else + { + List cards = Bot.GetGraveyardMonsters(); + cards.Sort(CompareCardLink); + cards.Reverse(); + AI.SelectCard(cards); + return true; + } + } + private bool CalledbytheGraveEffect() + { + ClientCard card = Util.GetLastChainCard(); + if (card == null) return false; + int id = card.Id; + List g_cards = Enemy.GetGraveyardMonsters().Where(g_card => g_card != null && g_card.Id == id).ToList(); + if (Duel.LastChainPlayer != 0 && card != null) + { + if (Card.Location == CardLocation.Hand) + { + AI.SelectPlace(SelectSTPlace(Card, true)); + } + if (card.Location == CardLocation.Grave && card.HasType(CardType.Monster)) + { + AI.SelectCard(card); + } + else if (g_cards.Count() > 0 && card.HasType(CardType.Monster)) + { + AI.SelectCard(g_cards); + } + else return false; + return true; + } + return false; + } + private bool MekkKnightCrusadiaAvramaxSummon() + { + List materials_1 = new List{ + CardId.PredaplantVerteAnaconda,CardId.CrossSheep, + CardId.IP + }; + List materials_2 = new List{ + CardId.KnightmareUnicorn + }; + List materials_3 = new List{ + CardId.StrikerDragon,CardId.Linkuriboh,CardId.AbyssDweller + }; + if (Bot.GetMonsters().Count(card => card != null && card.IsFaceup() && card.Id == CardId.BowoftheGoddess && card.Attack <= 800) > 0) + materials_3.Add(CardId.BowoftheGoddess); + if (!summon_UnionCarrier) materials_1.Add(CardId.UnionCarrier); + if (Bot.MonsterZone.GetMatchingCardsCount(card => card.IsCode(materials_1) && card.IsFaceup()) >= 2) + { + AI.SelectMaterials(materials_1); + place_Link_4 = true; + return true; + } + else if (Bot.MonsterZone.GetMatchingCardsCount(card => card.IsCode(materials_2) && card.IsFaceup()) > 0 + && Bot.MonsterZone.GetMatchingCardsCount(card => card.IsCode(materials_3) && card.IsFaceup()) > 0) + { + materials_2.AddRange(materials_3); + AI.SelectMaterials(materials_2); + place_Link_4 = true; + return true; + } + return false; + } + private bool GEffect() + { + return Duel.Player != 0; + } + private bool ThunderDragonColossusSummon_2() + { + if (handActivated && activate_ThunderDragonmatrix) + return ThunderDragonColossusSummon(); + return false; + } + private bool ThunderDragonTitanEffect() + { + //if (Duel.CurrentChain.Count > 0) + if(ActivateDescription == Util.GetStringId(CardId.ThunderDragonTitan, 0)) + { + List res = new List(); + List mcards = Enemy.GetMonsters(); + List scards = Enemy.GetSpells(); + if (mcards.Count <= 0 && scards.Count <= 0) return false; + if (Duel.CurrentChain.Count(card => card != null && card.Controller == 1) > 0) + { + foreach (var card in Duel.CurrentChain) + { + if (card != null && card.Controller == 1 && (card.Location == CardLocation.MonsterZone || card.Location == CardLocation.SpellZone) + && !card.IsDisabled() && (card.HasType(CardType.Monster) + || card.HasType(CardType.Field) || card.HasType(CardType.Continuous) + || card.HasType(CardType.Equip))) + { + res.Add(card); + } + } + } + mcards.Sort(CardContainer.CompareCardAttack); + mcards.Reverse(); + res.AddRange(mcards); + res.AddRange(scards); + AI.SelectCard(res); + return true; + } + else + { + selectFlag[(int)Select.DestroyReplace] = true; + return true; + } + + } + private bool PredaplantVerteAnacondaEffect() + { + if (ActivateDescription == Util.GetStringId(CardId.PredaplantVerteAnaconda, 1)) + { + if (CheckRemainInDeck(CardId.ThunderDragonFusion) <= 0) return false; + if (Bot.GetMonstersInMainZone().Count > 4 && Bot.GetMonstersInMainZone().Count(card => card != null && !card.IsExtraCard() && card.HasSetcode(0x11c) && card.HasType(CardType.Monster) && card.IsFaceup()) <= 0) return false; + List g_card = Bot.Graveyard.ToList(); + List b_card = Bot.Banished.ToList(); + g_card.AddRange(b_card); + int count = 0; + int Lcount = 0; + foreach (var card in g_card) + { + if (card == null) continue; + if (card.HasType(CardType.Monster) && card.HasSetcode(0x11c)) + ++count; + if (card.IsCode(CardId.NormalThunderDragon)) + ++Lcount; + } + if (Bot.HasInExtra(CardId.ThunderDragonColossus) && Lcount > 0 && g_card.Count(card => card != null && card.HasRace(CardRace.Thunder)) > 1) + { + AI.SelectCard(CardId.ThunderDragonFusion); + AI.SelectNextCard(CardId.ThunderDragonColossus,CardId.ThunderDragonTitan); + No_SpSummon = true; + return true; + } + else if (count >= 3 && Bot.HasInExtra(CardId.ThunderDragonTitan)) + { + AI.SelectCard(CardId.ThunderDragonFusion); + AI.SelectNextCard(CardId.ThunderDragonTitan, CardId.ThunderDragonColossus); + No_SpSummon = true; + return true; + } + return false; + } + return false; + } + private bool CrossSheepEffect() + { + if (Bot.HasInExtra(CardId.UnionCarrier) + && (Bot.HasInGraveyard(CardId.AloofLupine)|| Bot.HasInGraveyard(CardId.G))) + AI.SelectCard(CardId.AloofLupine, CardId.G); + else if (HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.Grave)) + AI.SelectCard(CardId.ThunderDragonmatrix); + else if (Bot.HasInExtra(CardId.Linkuriboh)) + AI.SelectCard(CardId.ThunderDragonmatrix, CardId.DragonBusterDestructionSword); + else AI.SelectCard(CardId.BatterymanSolar, CardId.AshBlossom,CardId.G); + return true; + } + private bool KnightmareUnicornEffect() + { + List cards = new List(); + cards.AddRange(Enemy.SpellZone); + cards.AddRange(Enemy.MonsterZone); + cards = cards.Where(card => card != null && !card.IsShouldNotBeTarget()).ToList(); + if (cards.Count <= 0) return false; + List disCardId = new List(); + IList repeatId = GetZoneRepeatCardsId(0, Bot.Hand); + if (!repeatId.Contains(-1)) disCardId.AddRange(repeatId); + foreach (var card in Bot.Hand) + if (card != null && card.HasSetcode(0x11c) && card.HasType(CardType.Monster)) + disCardId.Add(card.Id); + AI.SelectCard(disCardId); + cards.Sort(CardContainer.CompareCardAttack); + cards.Reverse(); + AI.SelectNextCard(cards); + return true; + } + private bool ThunderDragonlordEffect() + { + if (Duel.Phase == DuelPhase.End) + { + int count = Bot.Graveyard.Count(card => card != null && card.HasRace(CardRace.Thunder)); + if ((Bot.HasInGraveyard(CardId.ThunderDragonroar) || Bot.HasInGraveyard(CardId.ThunderDragondark) && count > 1) && CheckRemainInDeck(CardId.ThunderDragonFusion) >0 ) + AI.SelectCard(CardId.ThunderDragonFusion); + else if(!Bot.HasInGraveyard(CardId.ThunderDragonroar) && CheckRemainInDeck(CardId.ThunderDragonroar) > 0) + AI.SelectCard(CardId.ThunderDragonroar); + else if(!Bot.HasInGraveyard(CardId.ThunderDragondark) && CheckRemainInDeck(CardId.ThunderDragondark) > 0) + AI.SelectCard(CardId.ThunderDragondark); + else AI.SelectCard(CardId.ThunderDragonmatrix,CardId.NormalThunderDragon,CardId.BatterymanSolar); + return true; + } + if (Duel.Phase == DuelPhase.Standby) + { + List Thundercards = Bot.Graveyard.Where(card => card != null && card.HasRace(CardRace.Thunder)).ToList(); + List NoThundercards = Bot.Graveyard.Where(card => card != null && !card.HasRace(CardRace.Thunder) && !card.IsCode(CardId.ThunderDragonFusion) && !card.IsCode(CardId.ChaosSpace)).ToList(); + if (HasInZoneNoActivate(CardId.ThunderDragonroar,CardLocation.Grave) && Bot.GetMonstersInMainZone().Count < 5) + AI.SelectCard(CardId.ThunderDragonroar); + else if(HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Grave)) + AI.SelectCard(CardId.ThunderDragondark); + else if (HasInZoneNoActivate(CardId.ThunderDragonhawk, CardLocation.Grave) && !GetZoneRepeatCardsId(0,Bot.Hand).Contains(-1)) + AI.SelectCard(CardId.ThunderDragonhawk); + else if (HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.Grave)) + AI.SelectCard(CardId.ThunderDragonmatrix); + else if(Thundercards.Count > 0) + AI.SelectCard(Thundercards); + else AI.SelectCard(CardId.ThunderDragonmatrix); + + List Spellcards = Bot.GetGraveyardSpells().Where(card => card != null && !card.IsCode(CardId.ThunderDragonFusion) && !card.IsCode(CardId.ChaosSpace)).ToList(); + if (Spellcards.Count > 0) AI.SelectNextCard(Spellcards); + else if(NoThundercards.Count > 0 ) AI.SelectNextCard(Spellcards); + else if(Thundercards.Count > 0) AI.SelectNextCard(Thundercards); + else AI.SelectNextCard(CardId.ChaosSpace); + AI.SelectThirdCard(CardId.ThunderDragonColossus, CardId.ThunderDragonTitan, CardId.ThunderDragonlord,CardId.TheChaosCreator); + return true; + } + return false; + } + private bool PredaplantVerteAnacondaSummon() + { + if (CheckRemainInDeck(CardId.ThunderDragonFusion) <= 0) return false; + List g_card = Bot.Graveyard.ToList(); + List b_card = Bot.Banished.ToList(); + g_card.AddRange(b_card); + int count = 0; + int Lcount = 0; + foreach (var card in g_card) + { + if (card == null) continue; + if (card.HasType(CardType.Monster) && card.HasSetcode(0x11c)) + ++count; + if (card.IsCode(CardId.NormalThunderDragon)) + ++Lcount; + } + if (!IsAvailableLinkZone()) return false; + if ((count >= 3 && Bot.HasInExtra(CardId.ThunderDragonTitan)) || + (Bot.HasInExtra(CardId.ThunderDragonColossus) && Lcount > 0 && g_card.Count(card => card != null && card.HasRace(CardRace.Thunder)) > 1)) + { + List cards = Bot.GetMonsters().Where(card => card != null && card.IsFaceup() && GetLinkMark(card.Id) < 3 && !card.HasType(CardType.Normal) && !card.IsCode(CardId.ThunderDragonColossus) && !card.IsCode(CardId.ThunderDragonTitan) && !card.IsCode(CardId.ThunderDragonlord) && !(card.IsCode(CardId.UnionCarrier) && summon_UnionCarrier)).ToList(); + if (cards.Count < 2) return false; + cards.Sort(CardContainer.CompareCardAttack); + if (cards.Count(card => card != null && card.Id == CardId.IP) > 0 && cards.Count <= 2) return false; + AI.SelectMaterials(cards); + return true; + } + return false; + } + private bool AllureofDarknessEffect_2() + { + return !Bot.HasInHand(CardId.G) && Bot.Hand.Count <= 3 && Bot.Deck.Count > 2; + } + private bool KnightmareUnicornSummon() + { + if (Bot.Hand.Count <= 0) return false; + if (!IsAvailableLinkZone()) return false; + List pre_cards = Enemy.GetMonsters(); + pre_cards.AddRange(Enemy.GetSpells()); + if (pre_cards.Count(card => card != null && !card.IsShouldNotBeTarget()) <= 0) return false; + List tmepMaterials = new List(); + List resMaterials = new List(); + foreach (var card in Bot.GetMonsters()) + { + if (card == null) continue; + if (card.Id == CardId.UnionCarrier && summon_UnionCarrier) continue; + if ((GetLinkMark(card.Id) < 3 || (card.Id == CardId.BowoftheGoddess && card.Attack <= 800)) && card.Id != CardId.ThunderDragonTitan + && card.Id != CardId.ThunderDragonColossus && card.IsFaceup() && tmepMaterials.Count(_card=> _card != null && _card.Id==card.Id) <= 0) + tmepMaterials.Add(card); + } + int link_count = 0; + tmepMaterials.Sort(CardContainer.CompareCardAttack); + List materials = new List(); + List link_materials = tmepMaterials.Where(card => card != null && card.LinkCount == 2).ToList(); + List normal_materials = tmepMaterials.Where(card => card != null && card.LinkCount != 2).ToList(); + if (link_materials.Count() >= 1) + { + link_materials.InsertRange(1, normal_materials); + materials.AddRange(link_materials); + } + else + { + materials.AddRange(normal_materials); + materials.AddRange(link_materials); + } + if (materials.Count(card => card != null && card.LinkCount >= 2) > 1 + && materials.Count(card => card != null && card.LinkCount < 2) < 1) return false; + foreach (var card in materials) + { + if (!resMaterials.Contains(card) && card.LinkCount < 3) + { + resMaterials.Add(card); + link_count += (card.HasType(CardType.Link)) ? card.LinkCount : 1; + if (link_count >= 3) break; + } + } + if (link_count >= 3) { AI.SelectMaterials(resMaterials); return true; } + return false; + } + private bool UnderworldGoddessoftheClosedWorldSummon() + { + if (Duel.Turn == 0 || Enemy.GetMonsterCount() <= 0) return false; + if (Util.GetBestAttack(Bot) >= Util.GetBestAttack(Enemy) && Enemy.MonsterZone.GetDangerousMonster() == null) return false; + List e_materials = new List(); + List m_materials = new List(); + List resMaterials = new List(); + foreach (var card in Enemy.GetMonsters()) + { + if (card != null && card.HasType(CardType.Effect) && card.IsFaceup()) + e_materials.Add(card); + } + if (e_materials.Count() <= 0) return false; + foreach (var card in Bot.GetMonsters()) + { + if (card == null) continue; + if (card.Id == CardId.UnionCarrier && summon_UnionCarrier) continue; + if (GetLinkMark(card.Id) < 3 && card.Id != CardId.ThunderDragonTitan + && card.Id != CardId.ThunderDragonColossus && card.IsFaceup() && card.HasType(CardType.Effect)) + m_materials.Add(card); + } + if (m_materials.Count() < 3) return false; + int link_count = 0; + int e_link_count = 0; + e_materials.Sort(CardContainer.CompareCardAttack); + e_materials.Reverse(); + foreach (var card in e_materials) + { + if (!resMaterials.Contains(card)) + resMaterials.Add(card); + e_link_count += (card.HasType(CardType.Link)) ? (card.LinkCount == 2 ? 2:1): 1; + if (e_link_count >= 1) break; + } + if (e_link_count <= 0) return false; + link_count += e_link_count; + foreach (var card in m_materials) + { + if (e_link_count <= 1) + { + if (!resMaterials.Contains(card) && card.LinkCount < 3) + { + resMaterials.Add(card); + link_count += (card.HasType(CardType.Link)) ? card.LinkCount : 1; + if (link_count >= 5) break; + } + } + else + { + resMaterials.Add(card); + link_count += 1; + if (link_count >= 5) break; + } + } + if (link_count >= 5) { AI.SelectMaterials(resMaterials); place_Link_4 = true; return true; } + return false; + } + private bool BowoftheGoddessSummon() + { + if (!IsAvailableLinkZone()) return false; + if (Card.Id == CardId.AccesscodeTalker) + { + if (Duel.Turn == 0 || Enemy.GetMonsterCount() + Enemy.GetSpellCount() <= 0) return false; + } + else + { + if (Duel.Turn > 0 && Enemy.GetMonsterCount() + Enemy.GetSpellCount() > 0 + && (Bot.HasInExtra(CardId.UnderworldGoddessoftheClosedWorld) || Bot.HasInExtra(CardId.MekkKnightCrusadiaAvramax) + || Bot.HasInExtra(CardId.AccesscodeTalker))) return false; + } + List tempmaterials = new List(); + List resMaterials = new List(); + foreach (var card in Bot.GetMonsters()) + { + if (card == null) continue; + if(card.Id == CardId.UnionCarrier && summon_UnionCarrier) continue; + if (GetLinkMark(card.Id) < 4 && card.Id != CardId.ThunderDragonTitan + && card.Id != CardId.ThunderDragonColossus && card.IsFaceup() && !card.HasType(CardType.Token)) + tempmaterials.Add(card); + } + int link_count = 0; + List materials = new List(); + List link_materials = tempmaterials.Where(card => card != null && (card.LinkCount == 3 || card.LinkCount == 2)).ToList(); + List normal_materials = tempmaterials.Where(card => card != null && card.LinkCount != 3 && card.LinkCount != 2).ToList(); + normal_materials.Sort(CardContainer.CompareCardAttack); + if (link_materials.Count <= 0 && Card.Id == CardId.AccesscodeTalker) return false; + if (link_materials.Count(card => card != null && card.LinkCount == 3) > 0 && normal_materials.Count() > 0) + { + int index = -1; + for (int i = 0; i < link_materials.Count(); i++) + { + if (link_materials[i] != null && link_materials[i].LinkCount == 3) + { + if (i > 0) + { + ClientCard temp = link_materials[0]; + link_materials[0] = link_materials[i]; + link_materials[i] = temp; + } + index = i; + break; + } + } + resMaterials.Sort(CardContainer.CompareCardAttack); + if (index >= 0) link_materials.InsertRange(index + 1, normal_materials); + materials.AddRange(link_materials); + } + else + { + link_materials.Sort(CompareCardLink); + materials.AddRange(link_materials); + materials.AddRange(normal_materials); + } + foreach (var card in materials) + { + if (!resMaterials.Contains(card) && card.LinkCount < 4) + { + if (Card.Id == CardId.BowoftheGoddess && resMaterials.Count(_card => _card != null && _card.Id == card.Id) > 0) break; + resMaterials.Add(card); + link_count += (card.HasType(CardType.Link)) ? card.LinkCount : 1; + if (link_count >= 4) break; + } + } + resMaterials.Sort(CardContainer.CompareCardAttack); + if (link_count >= 4) { AI.SelectMaterials(resMaterials); place_Link_4 = true; return true; } + return false; + } + private bool TheChaosCreatorSummon() + { + IList cardsid = new List(); + if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Grave) && Bot.GetMonstersInMainZone().Count < 4) + cardsid.Add(CardId.ThunderDragonroar); + if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Grave)) + cardsid.Add(CardId.ThunderDragondark); + if (HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.Grave)) + cardsid.Add(CardId.ThunderDragonmatrix); + if (Bot.HasInGraveyard(CardId.ChaosSpace) && !activate_ChaosSpace_grave) + { + cardsid.Add(CardId.BlackDragonCollapserpent); + cardsid.Add(CardId.WhiteDragonWyverburster); + cardsid.Add(CardId.TheBystialLubellion); + cardsid.Add(CardId.ThunderDragonlord); + } + if (!Bot.HasInSpellZone(CardId.BrandedRegained, true, true) + || Bot.GetCountCardInZone(Bot.GetGraveyardMonsters(),CardId.BystialMagnamhut) + Bot.GetCountCardInZone(Bot.GetGraveyardMonsters(), CardId.BystialDruiswurm) > 1) + { + cardsid.Add(CardId.BystialMagnamhut); + cardsid.Add(CardId.BystialDruiswurm); + } + List cards = Bot.GetGraveyardMonsters().Where(card => card != null && (card.HasAttribute(CardAttribute.Dark) || card.HasAttribute(CardAttribute.Light))).ToList(); + cards.Sort(CardContainer.CompareCardAttack); + foreach (var card in cards) + if (card != null) cardsid.Add(card.Id); + AI.SelectCard(cardsid); + AI.SelectCard(cardsid); + return true; + } + private bool ThunderDragonColossusSummon() + { + ResetFlag(); + selectFlag[(int)Select.ThunderDragonColossus] = true; + place_ThunderDragonColossus = true; + return true; + } + private bool ThunderDragonmatrixSet() + { + if (handActivated && Bot.HasInExtra(CardId.ThunderDragonColossus) + && Bot.GetMonsters().Count(card=>card != null && card.HasRace(CardRace.Thunder) + && card.IsFaceup() && card.HasType(CardType.Effect)) <= 0) + { + isSummoned = true; + return true; + } + return false; + } + private bool IPSummon() + { + if (Duel.Turn > 0 && Duel.Phase < DuelPhase.Main2) return false; + if (Bot.GetMonsterCount() <= 2) return false; + if (Bot.HasInMonstersZone(CardId.ThunderDragonColossus) && Bot.GetMonsterCount() <= 3) return false; + if (!Bot.HasInExtra(CardId.KnightmareUnicorn) && !Bot.HasInExtra(CardId.BowoftheGoddess) + && !Bot.HasInExtra(CardId.MekkKnightCrusadiaAvramax) && !Bot.HasInExtra(CardId.AccesscodeTalker) && !Bot.HasInExtra(CardId.UnderworldGoddessoftheClosedWorld)) return false; + List cards = Bot.GetMonsters().Where(card => card != null && GetLinkMark(card.Id) < 3 && card.Id != CardId.ThunderDragonTitan && card.Id != CardId.ThunderDragonColossus && !card.HasType(CardType.Link) && card.Attack <= 2500 && card.EquipCards.Count(ecard=> ecard != null && ecard.Id==CardId.DragonBusterDestructionSword && !ecard.IsDisabled())<=0).ToList(); + if (cards.Count < 2) return false; + if (!IsAvailableLinkZone()) return false; + cards.Sort(CardContainer.CompareCardAttack); + List cardsId = new List(); + if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.MonsterZone)) + cardsId.Add(CardId.ThunderDragonroar); + if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.MonsterZone)) + cardsId.Add(CardId.ThunderDragondark); + if (HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.MonsterZone)) + cardsId.Add(CardId.ThunderDragonmatrix); + foreach (var card in cards) + if (card != null) cardsId.Add(card.Id); + AI.SelectMaterials(cardsId); + return true; + } + private bool ThunderDragonlordSummon() + { + if (Bot.GetMonstersInMainZone().Count > 4 && Bot.GetMonstersInMainZone().Count(card => card != null && card.Level <= 8 && card.HasType(CardType.Tuner) && !card.IsExtraCard() && card.IsFaceup()) <= 0) return false; + IList cardsId = new List(); + if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Hand) + || HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.MonsterZone, true)) + cardsId.Add(CardId.ThunderDragonroar); + if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Hand) + || HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.MonsterZone, true)) + cardsId.Add(CardId.ThunderDragondark); + if (HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.Hand) + || HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.MonsterZone, true)) + cardsId.Add(CardId.ThunderDragonmatrix); + List handCards = Bot.Hand.Where(card=>card != null).ToList(); + handCards.Sort(CardContainer.CompareCardLevel); + List monsterCards = Bot.GetMonsters().ToList(); + monsterCards.Sort(CardContainer.CompareCardAttack); + foreach (var card in handCards) + { + if (card != null && card.HasRace(CardRace.Thunder) && card.Level <= 8) + cardsId.Add(card.Id); + } + foreach (var card in monsterCards) + { + if (card != null && card.HasRace(CardRace.Thunder) && card.Level <= 8 + && card.Id != CardId.ThunderDragonColossus && card.IsFaceup()) + cardsId.Add(card.Id); + } + if (cardsId.Count <= 0) return false; + AI.SelectCard(cardsId); + return true; + } + private bool UnionCarrierEffect() + { + if (!Bot.HasInMonstersZone(CardId.ThunderDragonColossus)) return false; + return UnionCarrierEffect_2(); + } + private bool UnionCarrierEffect_2() + { + IList cardsId = new List(); + cardsId.Add(CardId.ThunderDragonColossus); + cardsId.Add(CardId.TheChaosCreator); + List cards_1 = Bot.GetMonsters().Where(card => card != null && card.IsFaceup() && (card.HasAttribute(CardAttribute.Dark) || card.HasRace(CardRace.Dragon))).ToList(); + if (cards_1.Count <= 0) + { + List cards_2 = Bot.GetMonsters(); + cards_2.Sort(CardContainer.CompareCardAttack); + cards_2.Reverse(); + foreach (var card in cards_2) + if (card != null && !cardsId.Contains(card.Id)) + cardsId.Add(card.Id); + } + else + { + cards_1.Sort(CardContainer.CompareCardAttack); + cards_1.Reverse(); + foreach (var card in cards_1) + if (card != null && !cardsId.Contains(card.Id)) + cardsId.Add(card.Id); + } + AI.SelectCard(cardsId); + AI.SelectNextCard(CardId.DragonBusterDestructionSword,CardId.ThunderDragonroar,CardId.ThunderDragondark,CardId.ThunderDragonmatrix,CardId.NormalThunderDragon); + return true; + } + private bool StrikerDragonSummon() + { + if ((summon_WhiteDragonWyverburster && summon_BlackDragonCollapserpent) || CheckRemainInDeck(CardId.WhiteDragonWyverburster) <= 0 || CheckRemainInDeck(CardId.BlackDragonCollapserpent) <= 0) return false; + return Bot.GetMonsters().Count(card => card != null && card.HasRace(CardRace.Dragon) && card.Level > 1) > 0; + } + private bool DefaultSummon() + { + if (No_SpSummon) return false; + if (Card.Id == CardId.AshBlossom || Card.Id == CardId.G) + { + if (Bot.GetMonsterCount() >= 2 || handActivated) return false; + if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.MonsterZone, true) + || HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.MonsterZone, true)) + { + if (Bot.HasInExtra(CardId.PredaplantVerteAnaconda) || Bot.HasInExtra(CardId.IP) || Bot.HasInExtra(CardId.CrossSheep)) return true; + } + return false; + } + if (Card.Level == 1) + { + if (Bot.ExtraDeck.Count(card => card != null && card.LinkCount <= 2) <= 0) return false; + } + else + { + if (Bot.ExtraDeck.Count(card => card != null && card.LinkCount == 2) <= 0) return false; + } + if (Card.Id == CardId.ThunderDragonroar || Card.Id == CardId.ThunderDragondark || Card.Id == CardId.NormalThunderDragon) + { + if (!Bot.HasInExtra(CardId.ThunderDragonColossus) || !handActivated) return false; + } + if (Card.Level > 4) + { + List cards = Bot.GetMonsters().Where(card => card != null && GetLinkMark(card.Id) < 3 && card.Id != CardId.ThunderDragonTitan && card.Id != CardId.ThunderDragonColossus && card.Id != CardId.IP && card.Id != CardId.UnionCarrier).ToList(); + if (cards.Count <= 0) return false; + cards.Sort(CardContainer.CompareCardAttack); + if (handActivated && cards[0].Attack >= Card.Attack && !Bot.HasInExtra(CardId.ThunderDragonColossus)) return false; + AI.SelectCard(cards); + } + isSummoned = true; + return true; + } + private bool CheckThunderRemove() + { + if(HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Hand) && GetRemainingThunderCount() > 0) return true; + if(HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Hand) && GetRemainingThunderCount() > 0) return true; + if(Bot.Hand.Any(card=> card != null && card.HasRace(CardRace.Thunder) && !card.IsOriginalCode(CardId.AloofLupine) + && (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Deck) || HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Deck)))) return true; + return false; + } + private bool ThunderDragonhawkEffect() + { + if (Card.Location == CardLocation.Hand) + { + List banish_cards = new List(); + List grave_cards = new List(); + foreach (var card in Bot.Banished) + if (card != null && card.HasType(CardType.Monster) && card.HasSetcode(0x11c)) + banish_cards.Add(card); + foreach (var card in Bot.Graveyard) + if (card != null && card.HasType(CardType.Monster) && card.HasSetcode(0x11c)) + grave_cards.Add(card); + banish_cards.Sort(CardContainer.CompareCardAttack); + banish_cards.Reverse(); + grave_cards.Sort(CardContainer.CompareCardAttack); + grave_cards.Reverse(); + banish_cards.AddRange(grave_cards); + List res = new List(); + foreach (var card in banish_cards) + { + if (!activate_ThunderDragonroar && card != null && card.Id == CardId.ThunderDragonroar) + res.Add(card); + else if (!activate_ThunderDragondark && card != null && card.Id == CardId.ThunderDragondark) + res.Add(card); + } + res.AddRange(banish_cards); + AI.SelectCard(res); + handActivated = true; + activate_ThunderDragonhawk = true; + return true; + + } + else + { + activate_ThunderDragonhawk = true; + List cardsid = new List() { CardId.DragonBusterDestructionSword }; + cardsid.AddRange(GetZoneRepeatCardsId(0, Bot.Hand)); + List resCards = new List(); + foreach (var card in Bot.Hand) + { + if (card != null && cardsid.Contains(card.Id) && resCards.Count(_card => _card != null && _card.Id == card.Id) <= 0) + { + resCards.Add(card); + } + } + if (resCards.Count() <= 0) return false; + AI.SelectCard(resCards); + return true; + } + } + private bool BlackDragonCollapserpentSummon_2() + { + if (Bot.HasInGraveyard(CardId.WhiteDragonWyverburster) && Bot.HasInGraveyard(CardId.ChaosSpace) + && !activate_ChaosSpace_grave) + AI.SelectCard(CardId.WhiteDragonWyverburster); + else if (Bot.HasInGraveyard(CardId.ThunderDragonlord) && Bot.HasInGraveyard(CardId.ChaosSpace) + && !activate_ChaosSpace_grave) + AI.SelectCard(CardId.ThunderDragonlord); + else if (HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.Grave)) + AI.SelectCard(CardId.ThunderDragonmatrix); + else if (HasInZoneNoActivate(CardId.ThunderDragonhawk, CardLocation.Grave) && !(GetZoneRepeatCardsId(0, Bot.Hand, false)).Contains(-1)) + AI.SelectCard(CardId.ThunderDragonhawk); + else + AI.SelectCard(CardId.WhiteDragonWyverburster, CardId.BatterymanSolar); + summon_BlackDragonCollapserpent = true; + return true; + } + private bool BlackDragonCollapserpentSummon() + { + if (Bot.Graveyard.Count(card => card != null && card.HasAttribute(CardAttribute.Light)) <= 1 + && Bot.HasInGraveyard(CardId.TheBystialLubellion) && CheckRemainInDeck(CardId.BrandedRegained) > 0 && !summon_TheBystialLubellion) + return false; + return BlackDragonCollapserpentSummon_2(); + } + private bool GoldSarcophagusEffect() + { + if (GetRemainingThunderCount() <= 0) return false; + if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Deck) && Bot.GetMonstersInMainZone().Count < 5) + AI.SelectCard(CardId.ThunderDragonroar); + else if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Deck)) + AI.SelectCard(CardId.ThunderDragondark); + else if (HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.Deck)) + AI.SelectCard(CardId.ThunderDragonmatrix); + else AI.SelectCard(CardId.ThunderDragonmatrix); + if (Card.Location == CardLocation.Hand) + { + AI.SelectPlace(SelectSTPlace(Card, true)); + } + return true; + } + private bool UnionCarrierSummon() + { + if (CheckRemainInDeck(CardId.DragonBusterDestructionSword) <= 0 || !Bot.HasInMonstersZone(CardId.ThunderDragonColossus,false,false,true)) return false; + return UnionCarrierSummon_2(); + } + private bool LinkCheck(bool exZone_1) + { + int exSq = 0; + int linkSq_1 = 0; + int linkSq_2 = 0; + if (exZone_1) + { + exSq = 5; + linkSq_1 = 0; + linkSq_2 = 2; + } + else + { + exSq = 6; + linkSq_1 = 2; + linkSq_2 = 4; + } + if (Bot.MonsterZone[exSq] != null && Bot.HasInMonstersZone(CardId.ThunderDragonColossus, false, false, true)) + { + CardRace linkRace = (CardRace)Bot.MonsterZone[exSq].Race; + CardAttribute linkAtt = (CardAttribute)Bot.MonsterZone[exSq].Attribute; + int linkRaceCount = Bot.GetMonsters().Count(card => card != null && card.IsFaceup() && !card.IsCode(CardId.ThunderDragonColossus) && card.HasRace(linkRace)); + int linkAttCount = Bot.GetMonsters().Count(card => card != null && card.IsFaceup() && !card.IsCode(CardId.ThunderDragonColossus) && card.HasAttribute(linkAtt)); + if (Bot.MonsterZone[exSq].Id == CardId.CrossSheep + || Bot.MonsterZone[exSq].Id == CardId.PredaplantVerteAnaconda + || Bot.MonsterZone[exSq].Id == CardId.IP + || Bot.MonsterZone[exSq].Id == CardId.MekkKnightCrusadiaAvramax) + { + if (Bot.MonsterZone[linkSq_1] != null && Bot.MonsterZone[linkSq_1].Id == CardId.ThunderDragonColossus) + { + if (Bot.MonsterZone[linkSq_2] != null) + { + CardRace race = (CardRace)Bot.MonsterZone[linkSq_2].Race; + CardAttribute att = (CardAttribute)Bot.MonsterZone[linkSq_2].Attribute; + int raceCount = Bot.GetMonsters().Count(card => card != null && card.IsFaceup() && !card.IsCode(CardId.ThunderDragonColossus) && card.HasRace(race)); + int attCount = Bot.GetMonsters().Count(card => card != null && card.IsFaceup() && !card.IsCode(CardId.ThunderDragonColossus) && card.HasAttribute(att)); + if (raceCount < 2 && attCount < 2 && linkRaceCount < 2 && linkAttCount < 2) return false; + } + } + else if (Bot.MonsterZone[linkSq_2] != null && Bot.MonsterZone[linkSq_2].Id == CardId.ThunderDragonColossus) + { + if (Bot.MonsterZone[linkSq_1] != null) + { + CardRace race = (CardRace)Bot.MonsterZone[linkSq_1].Race; + CardAttribute att = (CardAttribute)Bot.MonsterZone[linkSq_1].Attribute; + int raceCount = Bot.GetMonsters().Count(card => card != null && card.IsFaceup() && !card.IsCode(CardId.ThunderDragonColossus) && card.HasRace(race)); + int attCount = Bot.GetMonsters().Count(card => card != null && card.IsFaceup() && !card.IsCode(CardId.ThunderDragonColossus) && card.HasAttribute(att)); + if (raceCount < 2 && attCount < 2 && linkRaceCount < 2 && linkAttCount < 2) return false; + } + + } + } + } + return true; + } + private bool UnionCarrierSummon_2() + { + if (Bot.GetMonsterCount() <= 2 && (Bot.HasInMonstersZone(CardId.ThunderDragonColossus) || Bot.HasInMonstersZone(CardId.ThunderDragonTitan))) return false; + List attDarkCards = Bot.GetMonsters().Where(card => card != null && card.HasAttribute(CardAttribute.Dark) && card.IsFaceup() && !card.IsOriginalCode(CardId.ThunderDragonColossus) && GetLinkMark(card.Id) < 3).ToList(); + List attLightCards = Bot.GetMonsters().Where(card => card != null && card.HasAttribute(CardAttribute.Light) && card.IsFaceup() && GetLinkMark(card.Id) < 3).ToList(); + List attEarthCards = Bot.GetMonsters().Where(card => card != null && card.HasAttribute(CardAttribute.Earth) && card.IsFaceup() && GetLinkMark(card.Id) < 3).ToList(); + List raceThunderCards = Bot.GetMonsters().Where(card => card != null && card.HasRace(CardRace.Thunder) && card.IsFaceup() && !card.IsOriginalCode(CardId.ThunderDragonColossus) && GetLinkMark(card.Id) < 3).ToList(); + List raceDragonCards = Bot.GetMonsters().Where(card => card != null && card.HasRace(CardRace.Dragon) && card.IsFaceup() && GetLinkMark(card.Id) < 3).ToList(); + List raceBeastCards = Bot.GetMonsters().Where(card => card != null && card.HasRace(CardRace.Beast) && card.IsFaceup() && GetLinkMark(card.Id) < 3).ToList(); + if (attDarkCards.Count() < 2 && attLightCards.Count() < 2 && attEarthCards.Count() < 2 + && raceThunderCards.Count() < 2 && raceDragonCards.Count() < 2 && raceBeastCards.Count() < 2) + return false; + if (!LinkCheck(false) || !LinkCheck(true)) return false; + if (!IsAvailableLinkZone()) return false; + if (Bot.MonsterZone[6] != null && Bot.MonsterZone[6].Controller == 0 && GetLinkMark(Bot.MonsterZone[6].Id) > 1) return false; + int[] materials = new[] { + CardId.StrikerDragon,CardId.BatterymanToken,CardId.BatterymanSolar, + CardId.ThunderDragonmatrix,CardId.NormalThunderDragon, CardId.WhiteDragonWyverburster, + CardId.ThunderDragonhawk,CardId.G, CardId.AloofLupine, CardId.CrossSheep, + CardId.ThunderDragonroar,CardId.ThunderDragondark,CardId.BlackDragonCollapserpent, + CardId.DragonBusterDestructionSword,CardId.BystialMagnamhut,CardId.BystialDruiswurm, + CardId.TheChaosCreator,CardId.Linkuriboh,CardId.TheBystialLubellion, + CardId.ThunderDragonlord,CardId.PredaplantVerteAnaconda,CardId.IP + }; + if (Bot.MonsterZone.GetMatchingCardsCount(card => card.IsCode(materials)) >= 2) + { + AI.SelectMaterials(materials); + summon_UnionCarrier = true; + return true; + } + return false; + } + private bool BatterymanSolarSummon() + { + if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Deck) || HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Deck) + || HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.Deck) || HasInZoneNoActivate(CardId.BlackDragonCollapserpent, CardLocation.Hand) + || HasInZoneNoActivate(CardId.WhiteDragonWyverburster, CardLocation.Hand) || HasInZoneNoActivate(CardId.BystialDruiswurm, CardLocation.Hand) + || HasInZoneNoActivate(CardId.BystialMagnamhut, CardLocation.Hand) || Bot.HasInHand(CardId.TheChaosCreator)) + { + isSummoned = true; + return true; + } + return false; + } + private bool ThunderDragonroarEffect() + { + if (Card.Location == CardLocation.Hand) + { + if (handActivated) return false; + handActivated = true; + activate_ThunderDragonroar = true; + if (HasInZoneNoActivate(CardId.ThunderDragonhawk, CardLocation.Grave) + || HasInZoneNoActivate(CardId.ThunderDragonhawk, CardLocation.Removed)) + { + AI.SelectCard(CardId.ThunderDragonhawk); + } + else AI.SelectCard(CardId.ThunderDragonmatrix,CardId.ThunderDragondark,CardId.ThunderDragonhawk); + return true; + } + else + { + if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Deck)) + AI.SelectCard(CardId.ThunderDragondark); + else if(HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.Deck)) + AI.SelectCard(CardId.ThunderDragonmatrix); + else if(HasInZoneNoActivate(CardId.NormalThunderDragon, CardLocation.Deck)) + AI.SelectCard(CardId.NormalThunderDragon); + else + AI.SelectCard(CardId.NormalThunderDragon, CardId.ThunderDragondark, CardId.NormalThunderDragon, CardId.ThunderDragonmatrix); + activate_ThunderDragonroar = true; + return true; + } + } + private bool S_SpSummon() + { + if (Duel.Player == 0) + { + if (Duel.CurrentChain.Count > 0) return false; + List cards = new List(); + if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Grave) + && Bot.GetMonstersInMainZone().Count < 4) + { + foreach (var card_1 in Bot.Graveyard) + { + if (card_1 != null && card_1.Id == CardId.ThunderDragonroar) + cards.Add(card_1); + } + } + else if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Grave)) + { + foreach (var card_2 in Bot.Graveyard) + { + if (card_2 != null && card_2.Id == CardId.ThunderDragondark) + cards.Add(card_2); + } + } + else if (HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.Grave)) + { + foreach (var card_3 in Bot.Graveyard) + { + if (card_3 != null && card_3.Id == CardId.ThunderDragonmatrix) + cards.Add(card_3); + } + } + else if (Bot.HasInGraveyard(CardId.ChaosSpace) && !activate_ChaosSpace_grave) + { + foreach (var card_4 in Bot.Graveyard) + { + if (card_4 != null && NotSpSummonCardsId.Contains(card_4.Id)) + cards.Add(card_4); + } + } + else + { + foreach (var card_5 in Enemy.Graveyard) + { + if (card_5 != null && (card_5.HasAttribute(CardAttribute.Light) + || card_5.HasAttribute(CardAttribute.Dark))) + cards.Add(card_5); + } + foreach (var card_6 in Bot.Graveyard) + { + if (card_6 != null && (card_6.HasAttribute(CardAttribute.Light) + || card_6.HasAttribute(CardAttribute.Dark)) && !card_6.IsCode(CardId.TheBystialLubellion) && !card_6.HasRace(CardRace.Thunder)) + cards.Add(card_6); + } + foreach (var card_7 in Bot.Graveyard) + { + if (card_7 != null && (card_7.HasAttribute(CardAttribute.Light) + || card_7.HasAttribute(CardAttribute.Dark)) && card_7.HasRace(CardRace.Thunder)) + cards.Add(card_7); + } + } + AI.SelectCard(cards); + return true; + } + else + { + if (Duel.Phase < DuelPhase.Battle && Duel.CurrentChain.Count <= 0) return false; + ClientCard card = Util.GetLastChainCard(); + if (card != null && card.Controller != 0 && + card.Location == CardLocation.Grave + && (card.HasAttribute(CardAttribute.Dark) + || card.HasAttribute(CardAttribute.Light))) + { + AI.SelectCard(card); + } + else if (Duel.CurrentChain.Count > 0 && Duel.CurrentChain.Count(_card => _card != null && (_card.Id == CardId.BystialDruiswurm || _card.Id == CardId.BystialMagnamhut)) <= 0 + && Duel.LastChainPlayer == 1 && Enemy.Graveyard.Count(_card => _card != null && (_card.HasAttribute(CardAttribute.Dark) || _card.HasAttribute(CardAttribute.Light))) > 0) + { + List graveCards = Enemy.GetGraveyardMonsters(); + graveCards.Reverse(); + AI.SelectCard(graveCards); + } + else + { + if (Duel.CurrentChain.Count > 0 && Duel.CurrentChain.Count(_card => _card != null && _card.Controller == 0 && (_card.Id == CardId.BystialDruiswurm || _card.Id == CardId.BystialMagnamhut)) > 0) return false; + List res = new List(); + List pre_res = new List(); + foreach (var mcard in Enemy.Graveyard) + { + if (mcard != null && (mcard.HasAttribute(CardAttribute.Dark) + || mcard.HasAttribute(CardAttribute.Light))) + res.Add(mcard); + } + foreach (var mcard in Bot.Graveyard) + { + if (mcard != null && (mcard.HasAttribute(CardAttribute.Dark) + || mcard.HasAttribute(CardAttribute.Light))) + { + if (mcard.Id == CardId.ThunderDragonroar && !activate_ThunderDragonroar && Bot.GetMonstersInMainZone().Count < 5) + res.Add(mcard); + else if(mcard.Id == CardId.ThunderDragondark && !activate_ThunderDragondark) + res.Add(mcard); + else + pre_res.Add(mcard); + } + } + if (res.Count() <= 0) return false; + if (pre_res.Count > 0) res.AddRange(pre_res); + AI.SelectCard(res); + } + return true; + } + } + private bool BystialDruiswurmEffect() + { + if (Card.Location == CardLocation.Hand) return S_SpSummon(); + else + { + List cards = Enemy.GetMonsters(); + cards.Sort(CardContainer.CompareCardAttack); + cards.Reverse(); + AI.SelectCard(cards); + return true; + } + } + private bool BystialMagnamhutEffect() + { + if (Card.Location == CardLocation.Hand) return S_SpSummon(); + return true; + } + private bool CrossSheepSummon() + { + if (Bot.MonsterZone[5] != null && Bot.MonsterZone[5].Controller == 0 && GetLinkMark(Bot.MonsterZone[5].Id) > 1) return false; + if (Bot.MonsterZone[6] != null && Bot.MonsterZone[6].Controller == 0 && GetLinkMark(Bot.MonsterZone[6].Id) > 1) return false; + if (!handActivated && Bot.Hand.Count(card => card != null && card.HasSetcode(0x11c) && card.HasType(CardType.Monster)) + + Bot.MonsterZone.Count(card => card != null && card.HasSetcode(0x11c) && card.IsFaceup() && card.HasType(CardType.Monster)) + + Bot.Graveyard.Count(card => card != null && card.HasSetcode(0x11c) && card.HasType(CardType.Monster)) + + Bot.Banished.Count(card => card != null && card.HasSetcode(0x11c) && card.IsFaceup() && card.HasType(CardType.Monster)) < 2) return false; + if ((Bot.HasInMonstersZone(CardId.ThunderDragonColossus, false, false, true) || Bot.HasInMonstersZone(CardId.ThunderDragonTitan, false, false, true))) + { + bool isShoudlSummon_1 = false; + int light_count = Bot.Graveyard.Count(card => card != null && card.HasAttribute(CardAttribute.Light)); + int dark_count = Bot.Graveyard.Count(card => card != null && card.HasAttribute(CardAttribute.Dark)); + if (HasInZoneNoActivate(CardId.WhiteDragonWyverburster, CardLocation.Hand) && dark_count > 0) isShoudlSummon_1 = true; + else if (HasInZoneNoActivate(CardId.BlackDragonCollapserpent, CardLocation.Hand) && light_count > 0) isShoudlSummon_1 = true; + else if ((HasInZoneNoActivate(CardId.BystialMagnamhut, CardLocation.Hand) || HasInZoneNoActivate(CardId.BystialDruiswurm, CardLocation.Hand)) + && (dark_count > 0 || light_count > 0)) isShoudlSummon_1 = true; + else if (HasInZoneNoActivate(CardId.ThunderDragonhawk, CardLocation.Hand)) + { + List mcards = Bot.GetMonsters().ToList(); + List grave = Bot.Graveyard.ToList(); + List banish = Bot.Banished.ToList(); + mcards.AddRange(grave); + mcards.AddRange(banish); + int mcount = mcards.Count(card => card != null && card.HasType(CardType.Monster) && card.HasSetcode(0x11c) && !card.IsCode(CardId.ThunderDragonColossus) && !card.IsCode(CardId.ThunderDragonTitan)); + isShoudlSummon_1 = mcount > 0 ? true : false; + } + else if(Bot.HasInHand(CardId.TheChaosCreator) && light_count > 0 && dark_count > 0) isShoudlSummon_1 = true; + else if (Bot.HasInHand(CardId.ThunderDragonlord) && Bot.Hand.Count(card=>card != null && card.HasType(CardType.Monster) && card.HasSetcode(0x11c))>1) isShoudlSummon_1 = true; + if (!isShoudlSummon_1) return false; + + } + if (!IsAvailableLinkZone()) return false; + IList cardsid = GetZoneRepeatCardsId(0, Bot.MonsterZone,true); + if (!cardsid.Contains(-1) && Bot.MonsterZone.Count(card => card != null && card.IsFaceup() && !card.IsOriginalCode(CardId.ThunderDragonColossus) && GetLinkMark(card.Id) <= 1) + - cardsid.Count() < 2) return false; + if (cardsid.Contains(-1) && Bot.MonsterZone.Count(card => card != null && card.IsFaceup() && !card.IsOriginalCode(CardId.ThunderDragonColossus) && !card.IsOriginalCode(CardId.ThunderDragonTitan) && GetLinkMark(card.Id) <= 1 ) < 2) return false; + bool isShoudlSummon_2 = false; + foreach (var card in Bot.GetMonsters()) + if (card != null && card.IsFaceup() && SpSummonCardsId.Contains(card.Id)) { isShoudlSummon_2 = true; break; } + if (Bot.Graveyard.Count(card => card != null && card.HasType(CardType.Monster) && card.Level <= 4 && !card.IsCode(CardId.BlackDragonCollapserpent) && !card.IsCode(CardId.WhiteDragonWyverburster)) > 0) isShoudlSummon_2 = true; + if (!isShoudlSummon_2) return false; + List cards = Bot.GetMonsters(); + if (cards.Count < 2) return false; + cards.Sort(CardContainer.CompareCardAttack); + HashSet MaterialsIdSet = new HashSet(); + foreach (var card in cards) + { + if (card == null) continue; + if (card.Id == CardId.UnionCarrier && summon_UnionCarrier) continue; + if (GetLinkMark(card.Id) <= 1 && card.Id != CardId.ThunderDragonColossus && card.Id != CardId.ThunderDragonTitan + && (card.EquipCards == null || (card.EquipCards != null && card.EquipCards.Count(ecard => ecard != null + && ecard.Id == CardId.DragonBusterDestructionSword) <= 0))) + MaterialsIdSet.Add(card.Id); + } + if (MaterialsIdSet.Count() < 2) return false; + List material = new List(); + if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.MonsterZone)) + material.Add(CardId.ThunderDragonroar); + if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.MonsterZone)) + material.Add(CardId.ThunderDragondark); + if (HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.MonsterZone)) + material.Add(CardId.ThunderDragonmatrix); + IList materials = MaterialsIdSet.ToList(); + material.AddRange(materials); + AI.SelectMaterials(material); + place_CrossSheep = true; + return true; + } + private bool ThunderDragonmatrixEffect() + { + if (Card.Location != CardLocation.Hand) + { + activate_ThunderDragonmatrix = true; + return true; + } + return false; + } + private bool IsShouldChainTunder() + { + ClientCard card = Util.GetLastChainCard(); + return card != null && card.Controller != 0 && Bot.HasInMonstersZone(CardId.ThunderDragonTitan, true, false, true) + && !card.IsDisabled() && (card.HasType(CardType.Monster) + || card.HasType(CardType.Continuous) || card.HasType(CardType.Equip) || card.HasType(CardType.Field)) && (card.Location == CardLocation.MonsterZone || card.Location == CardLocation.SpellZone); + } + private bool ThunderDragonmatrixEffect_2() + { + if (Card.Location == CardLocation.Hand) + { + if (Duel.Player == 0) + { + if (IsShouldChainTunder()) + { + activate_ThunderDragondark = true; + handActivated = true; + return true; + } + if (Duel.CurrentChain.Count > 0) return false; + List cards = Bot.Graveyard.ToList(); + cards.AddRange(Bot.Banished.ToList()); + if (handActivated || (HasInZoneNoActivate(CardId.ThunderDragonhawk, CardLocation.Hand) && Bot.GetMonstersInMainZone().Count < 5 + && cards.Count(card => card != null && card.HasSetcode(0x11c) && card.HasType(CardType.Monster) + && !card.IsCode(CardId.ThunderDragonhawk) && !card.IsExtraCard() && !card.IsCode(CardId.ThunderDragonlord)) > 0)) return false; + activate_ThunderDragonmatrix = true; + handActivated = true; + return true; + } + else + { + if (IsShouldChainTunder()) + { + AI.SelectCard(CardId.ThunderDragonColossus, CardId.ThunderDragonTitan); + activate_ThunderDragonmatrix = true; + handActivated = true; + return true; + } + else if (Duel.Phase == DuelPhase.Battle) + { + if (Bot.HasInMonstersZone(CardId.ThunderDragonTitan, true, false, true) && Enemy.GetMonsterCount() > 0) + { + AI.SelectCard(CardId.ThunderDragonColossus, CardId.ThunderDragonTitan); + activate_ThunderDragonmatrix = true; + handActivated = true; + return true; + } + } + else if (Duel.Phase == DuelPhase.BattleStep) + { + if (Bot.BattlingMonster != null && Bot.BattlingMonster.HasRace(CardRace.Thunder) + && !Bot.BattlingMonster.IsShouldNotBeTarget()) + { + AI.SelectCard(Bot.BattlingMonster); + activate_ThunderDragonmatrix = true; + handActivated = true; + return true; + } + } + else if(Duel.Phase == DuelPhase.End) + { + AI.SelectCard(CardId.ThunderDragonColossus, CardId.ThunderDragonTitan); + activate_ThunderDragonmatrix = true; + handActivated = true; + return true; + } + return false; + } + } + return false; + } + private bool WhiteDragonWyverbursterSummon() + { + if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Grave) + && Bot.GetMonstersInMainZone().Count < 5) + AI.SelectCard(CardId.ThunderDragonroar); + else if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Grave)) + AI.SelectCard(CardId.ThunderDragondark); + else + { + List cardsid = new List(); + cardsid.Add(CardId.BlackDragonCollapserpent); + cardsid.Add(CardId.TheChaosCreator); + foreach (var card in Bot.Graveyard) + { + if (card != null && !card.HasSetcode(0x11c) && card.HasAttribute(CardAttribute.Dark)) + cardsid.Add(card.Id); + } + foreach (var card in Bot.Graveyard) + { + if (card != null && card.HasSetcode(0x11c) && card.HasAttribute(CardAttribute.Dark)) + cardsid.Add(card.Id); + } + + AI.SelectCard(cardsid); + } + summon_WhiteDragonWyverburster = true; + return true; + } + private bool HasInZoneNoActivate(int cardId , CardLocation location , bool isFaceUp = false) + { + switch (location) + { + case CardLocation.Deck: if (CheckRemainInDeck(cardId) <= 0) return false; break; + case CardLocation.Hand: if (!Bot.HasInHand(cardId)) return false; break; + case CardLocation.Grave: if (!Bot.HasInGraveyard(cardId)) return false; break; + case CardLocation.Removed: if (!Bot.HasInBanished(cardId)) return false; break; + case CardLocation.MonsterZone: if (!Bot.HasInMonstersZone(cardId,false,false, isFaceUp)) return false; break; + default: return false; + } + switch (cardId) + { + case CardId.ThunderDragonroar: return !activate_ThunderDragonroar; + case CardId.ThunderDragondark: return !activate_ThunderDragondark; + case CardId.ThunderDragonhawk: return !activate_ThunderDragonhawk; + case CardId.ThunderDragonmatrix: return !activate_ThunderDragonmatrix; + case CardId.BystialDruiswurm: return !activate_BystialDruiswurm_hand; + case CardId.BystialMagnamhut: return !activate_BystialMagnamhut_hand; + case CardId.TheBystialLubellion: return !activate_TheBystialLubellion_hand; + case CardId.BlackDragonCollapserpent: return !summon_BlackDragonCollapserpent; + case CardId.WhiteDragonWyverburster: return !summon_WhiteDragonWyverburster; + default: return false; + } + } + private bool AloofLupineEffect() + { + if (Card.Location == CardLocation.MonsterZone) + { + if (Bot.Hand.Count(card => card != null && card.HasRace(CardRace.Thunder)) <= 0) return false; + bool _ThunderDragonroar = false, _ThunderDragondark = false, _ThunderDragonmatrix = false; + if (Bot.Hand.Count(card => card != null && card.HasRace(CardRace.Thunder) && !(card.IsCode(CardId.ThunderDragonhawk) && activate_ThunderDragonhawk)) <= 0 + && GetRemainingThunderCount(true) <= 0) return false; + if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Hand) && Bot.GetMonstersInMainZone().Count() < 5 + && GetRemainingThunderCount() > 0) + { + AI.SelectCard(CardId.ThunderDragonroar); + _ThunderDragonroar = true; + } + else if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Hand) && GetRemainingThunderCount() > 0) + { + AI.SelectCard(CardId.ThunderDragondark); + _ThunderDragondark = true; + } + else if (HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.Hand) && GetRemainingThunderCount() > 0) + { + AI.SelectCard(CardId.ThunderDragonmatrix); + _ThunderDragonmatrix = true; + } + else if (Bot.GetCountCardInZone(Bot.Hand, CardId.NormalThunderDragon) > 1) + AI.SelectCard(CardId.NormalThunderDragon); + else + { + IList cards = Bot.Hand.Where(card => card != null && card.HasRace(CardRace.Thunder)).ToList(); + if (cards.Count() > 0) AI.SelectCard(cards); + else AI.SelectCard(CardId.ThunderDragonlord, CardId.BatterymanSolar, CardId.TheChaosCreator, CardId.NormalThunderDragon); + } + if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Deck) && !_ThunderDragonroar + && Bot.GetMonstersInMainZone().Count < 5 && !Bot.HasInMonstersZone(CardId.ThunderDragonroar,false,false,true)) + AI.SelectNextCard(CardId.ThunderDragonroar); + else if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Deck) && !_ThunderDragondark + && !Bot.HasInMonstersZone(CardId.ThunderDragondark, false, false, true)) + AI.SelectNextCard(CardId.ThunderDragondark); + else if (HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.Deck) && !_ThunderDragonmatrix + && !Bot.HasInMonstersZone(CardId.ThunderDragonmatrix, false, false, true)) + AI.SelectNextCard(CardId.ThunderDragonmatrix); + else if(Bot.HasInGraveyard(CardId.TheChaosCreator) && !activate_ChaosSpace_grave && CheckRemainInDeck(CardId.ThunderDragonlord) > 0) + AI.SelectNextCard(CardId.ThunderDragonlord); + else + AI.SelectNextCard(CardId.NormalThunderDragon); + return true; + } + else + { + int[] ids = new int[] + { + CardId.ThunderDragonhawk,CardId.ThunderDragonColossus, + CardId.BystialMagnamhut,CardId.BystialDruiswurm, + CardId.BlackDragonCollapserpent,CardId.WhiteDragonWyverburster, + CardId.TheChaosCreator,CardId.TheBystialLubellion + }; + AI.SelectCard(ids); + return true; + } + + } + private bool ThunderDragonmatrixSummon() + { + if (No_SpSummon) return false; + if (Bot.HasInExtra(CardId.Linkuriboh)) + { + if (Bot.MonsterZone[5] != null && Bot.MonsterZone[5].Id == CardId.UnionCarrier && Bot.MonsterZone[5].Controller == 0) + { + if (Bot.MonsterZone[1] != null) return false; + } + if (Bot.MonsterZone[6] != null && Bot.MonsterZone[6].Id == CardId.UnionCarrier && Bot.MonsterZone[6].Controller == 0) + { + if (Bot.MonsterZone[3] != null) return false; + } + isSummoned = true; + return true; + } + if (Bot.GetMonsters().Count(card => card != null && card.Id != CardId.ThunderDragonTitan && card.Id != CardId.ThunderDragonColossus && GetLinkMark(card.Id) < 3 && card.IsFaceup()) < 1) return false; + switch (Card.Id) + { + case CardId.ThunderDragonmatrix: + if((Bot.HasInExtra(CardId.CrossSheep) || Bot.HasInExtra(CardId.IP)) + && (Bot.GetMonsterCount()>0 && !Bot.HasInMonstersZone(CardId.ThunderDragonColossus) + && !Bot.HasInMonstersZone(CardId.ThunderDragonTitan))) + { isSummoned = true; return true; } + break; + default: + break; + } + return false; + } + private bool TheBystialLubellionEffect() + { + if (Card.Location == CardLocation.Hand) + { + if (HasInZoneNoActivate(CardId.BystialMagnamhut,CardLocation.Deck) && !Bot.HasInHand(CardId.BystialMagnamhut)) + AI.SelectCard(CardId.BystialMagnamhut); + else if(HasInZoneNoActivate(CardId.BystialDruiswurm, CardLocation.Deck) && !Bot.HasInHand(CardId.BystialDruiswurm)) + AI.SelectCard(CardId.BystialDruiswurm); + else + AI.SelectCard(CardId.BystialDruiswurm, CardId.BystialMagnamhut); + activate_TheBystialLubellion_hand = true; + return true; + } + return Card.Location == CardLocation.MonsterZone; + } + private bool ThunderDragonFusionEffect() + { + if (Card.Location == CardLocation.Grave) + { + if (Bot.Graveyard.Count(card => card != null && card.HasAttribute(CardAttribute.Dark)) > 0 + && Bot.Graveyard.Count(card => card != null && card.HasAttribute(CardAttribute.Light)) > 0 + && CheckRemainInDeck(CardId.TheChaosCreator) > 0) + AI.SelectCard(CardId.TheChaosCreator); + else if(Bot.HasInGraveyardOrInBanished(CardId.ThunderDragonroar) || Bot.HasInGraveyardOrInBanished(CardId.ThunderDragondark) + || Bot.HasInGraveyardOrInBanished(CardId.ThunderDragonlord) || Bot.HasInGraveyardOrInBanished(CardId.ThunderDragonmatrix) + || Bot.HasInGraveyardOrInBanished(CardId.NormalThunderDragon) && CheckRemainInDeck(CardId.ThunderDragonhawk) > 0) + AI.SelectCard(CardId.ThunderDragonhawk); + else if((HasInZoneNoActivate(CardId.BystialDruiswurm,CardLocation.Hand) || HasInZoneNoActivate(CardId.BystialMagnamhut, CardLocation.Hand) + || HasInZoneNoActivate(CardId.WhiteDragonWyverburster, CardLocation.Hand) || HasInZoneNoActivate(CardId.BlackDragonCollapserpent, CardLocation.Hand) + || HasInZoneNoActivate(CardId.TheChaosCreator, CardLocation.Hand)) && CheckRemainInDeck(CardId.BatterymanSolar) > 0) + AI.SelectCard(CardId.BatterymanSolar); + else if(Bot.HasInMonstersZone(CardId.ThunderDragonTitan,true,false,true) && CheckRemainInDeck(CardId.NormalThunderDragon)>1) + AI.SelectCard(CardId.NormalThunderDragon); + else if(!HasInZoneNoActivate(CardId.ThunderDragonroar,CardLocation.Deck)) + AI.SelectCard(CardId.ThunderDragonroar); + else if(handActivated && CheckRemainInDeck(CardId.ThunderDragonlord) > 0) + AI.SelectCard(CardId.ThunderDragonlord); + else + AI.SelectCard(CardId.TheChaosCreator,CardId.ThunderDragondark,CardId.ThunderDragonlord); + return true; + } + else + { + if (Bot.GetMonstersInMainZone().Count > 4 && Bot.GetMonstersInMainZone().Count(card => card != null && !card.IsExtraCard() && card.HasSetcode(0x11c) && card.HasType(CardType.Monster) && card.IsFaceup()) <= 0) return false; + List cards = Bot.Graveyard.ToList(); + IList banish = Bot.Banished; + cards.AddRange(banish); + if (Bot.HasInExtra(CardId.ThunderDragonColossus) && Bot.GetCountCardInZone(cards, CardId.NormalThunderDragon) >= 1 && + Bot.GetCountCardInZone(cards, CardId.NormalThunderDragon) + cards.Count(card => card != null && card.HasSetcode(0x11c) && card.HasType(CardType.Monster) && !card.IsCode(CardId.NormalThunderDragon)) > 1) + { + AI.SelectCard(CardId.ThunderDragonColossus, CardId.ThunderDragonTitan); + return true; + } + else if (Bot.HasInExtra(CardId.ThunderDragonTitan) && cards.Count(card => card != null && card.HasSetcode(0x11c) && card.HasType(CardType.Monster)) >= 3) + { + AI.SelectCard(CardId.ThunderDragonColossus, CardId.ThunderDragonTitan); + return true; + } + if (Card.Location == CardLocation.Hand) + { + AI.SelectPlace(SelectSTPlace(Card, true)); + } + return false; + } + } + private bool TheBystialLubellionSummon() + { + if (Bot.HasInGraveyard(CardId.TheBystialLubellion) && Card.Location == CardLocation.Hand) return false; + if (Card.Location == CardLocation.Hand && activate_TheBystialLubellion_hand && !Bot.HasInGraveyard(CardId.TheBystialLubellion)) { summon_TheBystialLubellion = true; return true; } + if (Card.Location == CardLocation.Grave) { summon_TheBystialLubellion = true; return true; } + return false; + } + private bool CheckHandThunder() + { + if (HasInZoneNoActivate(CardId.ThunderDragonroar,CardLocation.Hand)) return true; + if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Hand)) return true; + if (HasInZoneNoActivate(CardId.ThunderDragonhawk, CardLocation.Hand)) return true; + if (Bot.HasInHand(CardId.NormalThunderDragon)) return true; + return false; + } + private bool ChaosSpaceEffect_2() + { + if (Card.Location == CardLocation.Grave) + { + if((CheckRemainInDeck(CardId.ThunderDragonFusion)>0 || Bot.HasInHandOrInSpellZone(CardId.ThunderDragonFusion)) + && !Bot.HasInExtra(CardId.ThunderDragonTitan)) + AI.SelectCard(CardId.ThunderDragonTitan,CardId.ThunderDragonColossus, CardId.BlackDragonCollapserpent, CardId.WhiteDragonWyverburster, CardId.TheBystialLubellion); + else + AI.SelectCard(CardId.ThunderDragonColossus,CardId.WhiteDragonWyverburster, CardId.BlackDragonCollapserpent, CardId.TheBystialLubellion); + activate_ChaosSpace_grave = true; + return true; + } + return false; + } + private bool ChaosSpaceEffect() + { + if (Card.Location != CardLocation.Grave) + { + if (Bot.GetCountCardInZone(Bot.Hand, CardId.ThunderDragonmatrix) > 1 && !activate_ThunderDragonmatrix + && !CheckHandThunder() && Bot.Hand.Any(card => card != null && + (card.HasAttribute(CardAttribute.Dark) || card.HasAttribute(CardAttribute.Light)) + && !card.IsCode(CardId.ThunderDragonroar) && !card.IsCode(CardId.ThunderDragondark) && !card.IsCode(CardId.ThunderDragonhawk) + && !card.IsCode(CardId.NormalThunderDragon))) return false; + ResetFlag(); + selectFlag[(int)Select.ChaosSpace_1] = true; + activate_ChaosSpace_hand = true; + if (Card.Location == CardLocation.Hand) + { + AI.SelectPlace(SelectSTPlace(Card, true)); + } + return true; + } + return false; + } + private bool AloofLupineSummon() + { + if (Bot.Hand.Count <= 1 || !Bot.Hand.Any(card => card!=null && card.HasRace(CardRace.Thunder) && card != Card)) return false; + if (CheckThunderRemove()) + { + isSummoned = true; + return true; + } + return false; + } + private IList GetZoneRepeatCardsId(int att, IList zoneCards,bool isFaceUp = false) + { + if (zoneCards.Count <= 0) return new List() { -1 }; + IList cards = zoneCards; + if (att > 0) cards = cards.Where(card => card != null && card.HasAttribute((CardAttribute)att)).ToList(); + if(cards.Count <= 0) return new List() { -1 }; + IList cardsid = new List(); + IList res = new List(); + foreach (var card in cards) + if(card != null && !(!card.IsFaceup() & isFaceUp)) + cardsid.Add(card.Id); + for (int i = 0; i < cardsid.Count; i++) + { + if (res.Count >= 0 && res.Contains(cardsid[i])) continue; + int times = 0; + for (int j = 0; j < cardsid.Count; j++) + { + if (times > 1) { res.Add(cardsid[i]); break; } + if (cardsid[i] == cardsid[j]) ++times; + } + } + if (res.Count <= 0) return new List() { -1 }; + return res; + } + private bool AllureofDarknessEffect() + { + if (Bot.Deck.Count <= 2) return false; + if (Bot.Hand.Count(card => card != null && card.HasAttribute(CardAttribute.Dark)) <= 0) return false; + if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Hand) && Bot.GetMonstersInMainZone().Count < 5) + AI.SelectCard(CardId.ThunderDragonroar); + else if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Hand)) + AI.SelectCard(CardId.ThunderDragondark); + else + { + List cardsid = new List(); + IList cardsid_1 = GetZoneRepeatCardsId((int)CardAttribute.Dark, Bot.Hand).ToList(); + IList cardsid_2 = new List(); + if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Deck) && Bot.GetMonstersInMainZone().Count < 5) cardsid.Add(CardId.ThunderDragonroar); + if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Deck)) cardsid.Add(CardId.ThunderDragondark); + if (HasInZoneNoActivate(CardId.TheBystialLubellion, CardLocation.Hand)) { cardsid_2.Add(CardId.BystialDruiswurm); cardsid_2.Add(CardId.BystialMagnamhut); } + if (!Bot.HasInExtra(CardId.Linkuriboh) || isSummoned) cardsid_2.Add(CardId.DragonBusterDestructionSword); + if (!HasInZoneNoActivate(CardId.BlackDragonCollapserpent, CardLocation.Hand)) cardsid_2.Add(CardId.BlackDragonCollapserpent); + if (isSummoned) cardsid_2.Add(CardId.AloofLupine); + cardsid.AddRange(cardsid_1); + cardsid.AddRange(cardsid_2); + AI.SelectCard(cardsid); + } + if (Card.Location == CardLocation.Hand) + { + AI.SelectPlace(SelectSTPlace(Card, true)); + } + return true; + } + private bool ThunderDragondarkEffect_2() + { + if (Card.Location == CardLocation.Hand) + { + if (Duel.Player == 0) + { + if (IsShouldChainTunder()) + { + activate_ThunderDragondark = true; + handActivated = true; + return true; + } + if (Duel.CurrentChain.Count > 0 || Duel.Phase < DuelPhase.Main1) return false; + if (handActivated || (Bot.HasInHand(CardId.NormalThunderDragon) && CheckRemainInDeck(CardId.NormalThunderDragon) > 0) || !Bot.HasInExtra(CardId.ThunderDragonColossus)) return false; + if (!isSummoned && (Bot.HasInHand(CardId.BatterymanSolar) || Bot.HasInHand(CardId.AloofLupine))) return false; + activate_ThunderDragondark = true; + handActivated = true; + return true; + } + else + { + if (IsShouldChainTunder() || (Duel.Phase == DuelPhase.End + && Bot.HasInMonstersZone(CardId.ThunderDragonTitan, true, false, true) + && Enemy.GetMonsterCount() + Enemy.GetSpellCount() > 0) + || (!Bot.HasInMonstersZone(CardId.ThunderDragonTitan, true, false, true) + && !Bot.HasInGraveyard(CardId.ThunderDragondark))) + { + activate_ThunderDragondark = true; + handActivated = true; + return true; + } + return false; + } + } + return false; + } + private bool ThunderDragondarkEffect() + { + if (Card.Location != CardLocation.Hand) + { + if (Duel.Player == 0) + { + if (handActivated && CheckRemainInDeck(CardId.ThunderDragonlord) > 0 && + Bot.Hand.Count(card => card != null && card.HasRace(CardRace.Thunder)) > 0 && + (Bot.HasInMonstersZone(CardId.ThunderDragonColossus) || (!isSummoned && Bot.Hand.Count(card => card != null && card.HasRace(CardRace.Thunder)) > 1))) + AI.SelectCard(CardId.ThunderDragonlord); + else if (HasInZoneNoActivate(CardId.ThunderDragonhawk, CardLocation.Deck) && !Bot.HasInHand(CardId.ThunderDragonhawk)) + AI.SelectCard(CardId.ThunderDragonhawk); + else if (handActivated && Bot.Hand.Count(card => card != null && card.HasRace(CardRace.Thunder) && card.Level < 8) > 0 + && Bot.HasInMonstersZone(CardId.ThunderDragonColossus) && CheckRemainInDeck(CardId.ThunderDragonlord) > 0) + AI.SelectCard(CardId.ThunderDragonlord); + else if (HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.Deck)) + AI.SelectCard(CardId.ThunderDragonmatrix); + else if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Hand) && handActivated + && CheckRemainInDeck(CardId.ThunderDragonlord) > 0) + AI.SelectCard(CardId.ThunderDragonlord); + else if (CheckRemainInDeck(CardId.ThunderDragonlord) > 0 && CheckRemainInDeck(CardId.NormalThunderDragon) > 1) + AI.SelectCard(CardId.ThunderDragonlord); + else if (handActivated && Bot.HasInHand(CardId.ThunderDragonlord) && CheckRemainInDeck(CardId.ThunderDragonroar) > 0) + AI.SelectCard(CardId.ThunderDragonroar); + else if (CheckRemainInDeck(CardId.NormalThunderDragon) > 1 && !handActivated) + AI.SelectCard(CardId.NormalThunderDragon); + else + AI.SelectCard(CardId.ThunderDragonmatrix, CardId.ThunderDragondark, CardId.ThunderDragonroar, CardId.NormalThunderDragon); + activate_ThunderDragondark = true; + return true; + } + else + { + if (!Bot.HasInHand(CardId.ThunderDragonmatrix) && HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.Deck) + &&(Bot.HasInMonstersZone(CardId.ThunderDragonTitan, true, false, true) + || (Bot.HasInMonstersZone(CardId.ThunderDragonColossus, true, false, true) && Bot.GetGraveyardMonsters().Count(card=>card != null && card.HasRace(CardRace.Thunder)) < 2 ))) + AI.SelectCard(CardId.ThunderDragonmatrix); + else AI.SelectCard(CardId.ThunderDragonFusion, CardId.ThunderDragonhawk,CardId.ThunderDragonroar,CardId.NormalThunderDragon) ; + activate_ThunderDragondark = true; + return true; + } + } + return false; + } + private bool NormalThunderDragonEffect() + { + handActivated = true; + ResetFlag(); + selectFlag[(int)Select.NormalThunderDragon] = true; + return true; + } + private bool BatterymanSolarEffect() + { + if (HasInZoneNoActivate(CardId.BystialDruiswurm, CardLocation.Hand) + || HasInZoneNoActivate(CardId.BystialMagnamhut, CardLocation.Hand)) + { + if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Deck)) + AI.SelectCard(CardId.ThunderDragonroar); + else if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Deck) + && !Bot.HasInMonstersZone(CardId.ThunderDragondark,false,false,true)) + AI.SelectCard(CardId.ThunderDragondark); + else if ((HasInZoneNoActivate(CardId.ThunderDragonmatrix, CardLocation.Deck))) + AI.SelectCard(CardId.ThunderDragonmatrix); + else if (CheckRemainInDeck(CardId.NormalThunderDragon) > 0) + AI.SelectCard(CardId.NormalThunderDragon); + else if (CheckRemainInDeck(CardId.TheChaosCreator) > 0) + AI.SelectCard(CardId.TheChaosCreator); + else AI.SelectCard(CardId.ThunderDragonmatrix); + } + else if (HasInZoneNoActivate(CardId.WhiteDragonWyverburster, CardLocation.Hand)) + { + if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Deck)) + AI.SelectCard(CardId.ThunderDragonroar); + else if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Deck)) + AI.SelectCard(CardId.ThunderDragondark); + else if (CheckRemainInDeck(CardId.TheChaosCreator) > 0) + AI.SelectCard(CardId.TheChaosCreator); + else AI.SelectCard(CardId.ThunderDragonmatrix); + + } + else if (Bot.HasInHand(CardId.ChaosSpace) && !activate_ChaosSpace_hand) + { + if ((Bot.Hand.Count(card => card != null && card.HasAttribute(CardAttribute.Dark)) > 0 + || Bot.Hand.Count(card => card != null && card.HasAttribute(CardAttribute.Light)) > 0) + && HasInZoneNoActivate(CardId.WhiteDragonWyverburster, CardLocation.Deck) + && HasInZoneNoActivate(CardId.BlackDragonCollapserpent, CardLocation.Deck)) + { + if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Deck)) + AI.SelectCard(CardId.ThunderDragonroar); + else if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Deck)) + AI.SelectCard(CardId.ThunderDragondark); + else + AI.SelectCard(CardId.ThunderDragonmatrix, CardId.ThunderDragonhawk, CardId.NormalThunderDragon); + } + } + else if (HasInZoneNoActivate(CardId.BlackDragonCollapserpent, CardLocation.Hand)) + AI.SelectCard(CardId.ThunderDragonmatrix, CardId.ThunderDragonhawk); + else + { + if (HasInZoneNoActivate(CardId.ThunderDragonroar, CardLocation.Deck)) + AI.SelectCard(CardId.ThunderDragonroar); + else if (HasInZoneNoActivate(CardId.ThunderDragondark, CardLocation.Deck)) + AI.SelectCard(CardId.ThunderDragondark); + else AI.SelectCard(CardId.ThunderDragonmatrix, CardId.ThunderDragonhawk); + } + return true; + } + } +} diff --git a/libWindbot/Game/AI/Decks/ZefraExecutor.cs b/libWindbot/Game/AI/Decks/ZefraExecutor.cs new file mode 100644 index 0000000..40bef73 --- /dev/null +++ b/libWindbot/Game/AI/Decks/ZefraExecutor.cs @@ -0,0 +1,2211 @@ +using YGOSharp.OCGWrapper; +using YGOSharp.OCGWrapper.Enums; +using System.Collections.Generic; +using System.Linq; +using System; +using WindBot; +using WindBot.Game; +using WindBot.Game.AI; +namespace WindBot.Game.AI.Decks +{ + [Deck("Zefra", "AI_Zefra")] + class ZefraExecutor : DefaultExecutor + { + public class CardId + { + //main code + public const int PSY_FrameDriver = 49036338; + public const int Zefraath = 29432356; + public const int TheMightyMasterofMagic = 3611830; + public const int AstrographSorcerer = 76794549; + public const int DestrudotheLostDragon_Frisson = 5560911; + public const int SupremeKingGateZero = 96227613; + public const int MythicalBeastJackalKing = 27354732; + public const int SecretoftheYangZing = 58990362; + public const int FlameBeastoftheNekroz = 20773176; + public const int StellarknightZefraxciton = 22617205; + public const int SupremeKingDragonDarkwurm = 69610326; + public const int Blackwing_ZephyrostheElite = 14785765; + public const int ShaddollZefracore = 95401059; + public const int Raidraptor_SingingLanius = 31314549; + public const int SatellarknightZefrathuban = 96223501; + public const int Raider_Wing = 52159691; + public const int Zefraxi_TreasureoftheYangZing = 21495657; + public const int RitualBeastTamerZeframpilica = 57777714; + public const int ServantofEndymion = 92559258; + public const int PSY_FramegearGamma = 38814750; + public const int MechaPhantomBeastO_Lion = 72291078; + public const int MaxxC = 23434538; + public const int Deskbot001 = 94693857; + public const int JetSynchron = 9742784; + public const int DDLamia = 19580308; + public const int DDSavantKepler = 11609969; + public const int LightoftheYangZing = 61488417; + public const int Rank_Up_MagicSoulShaveForce = 23581825; + public const int SpellPowerMastery = 38943357; + public const int DragonShrine = 41620959; + public const int Terraforming = 73628505; + public const int ZefraProvidence = 74580251; + public const int FoolishBurial = 81439173; + public const int CalledbytheGrave = 24224830; + public const int DarkContractwiththGate = 46372010; + public const int OracleofZefra = 32354768; + public const int ZefraWar = 96073342; + public const int ZefraDivineStrike = 35561352; + public const int NinePillarsofYangZing = 57831349; + public const int OneforOne = 2295440; + + //extra code + public const int BorreloadSavageDragon = 27548199; + public const int Odd_EyesMeteorburstDragon = 80696379; + public const int F_A_DawnDragster = 33158448; + public const int Denglong_FirstoftheYangZing = 65536818; + public const int HeraldoftheArcLight = 79606837; + public const int TruKingofAllCalamities = 88581108; + public const int Raidraptor_ArsenalFalcon = 96157835; + public const int Raidraptor_ForceStrix = 73347079; + public const int SaryujaSkullDread = 74997493; + public const int MechaPhantomBeastAuroradon = 44097050; + public const int HeavymetalfoesElectrumite = 24094258; + public const int CrystronHalqifibrax = 50588353; + public const int Raidraptor_WiseStrix = 36429703; + public const int Linkuriboh = 41999284; + public const int PSY_FramelordOmega = 74586817; + + public const int MechaPhantomBeastToken = 44097051; + } + private bool opt_0 = false; + private bool opt_1 = false; + private bool opt_2 = false; + //edo false + private const bool IS_YGOPRO = true; + private const int P_ACTIVATE_DESC = 1160; + //private const int P_SPSUMMON_DESC = 1163; + private int p_count = 0; + private int spell_activate_count = 0; + private bool summoned = false; + private bool link_summoned = false; + private bool p_summoned = false; + private bool p_summoning = false; + private bool activate_SupremeKingDragonDarkwurm_1 = false; + private bool activate_p_Zefraath = false; + private bool activate_OracleofZefra = false; + private bool activate_ZefraProvidence = false; + private bool activate_SupremeKingDragonDarkwurm_2 = false; + private bool activate_JetSynchron = false; + private bool activate_Blackwing_ZephyrostheElite = false; + private bool activate_DragonShrine = false; + private bool activate_SpellPowerMastery = false; + private bool activate_DestrudotheLostDragon_Frisson = false; + private bool activate_DarkContractwiththGate = false; + private bool activate_SecretoftheYangZing = false; + private bool activate_ShaddollZefracore = false; + private bool activate_DDLamia = false; + private bool xyz_mode = false; + private bool Blackwing_ZephyrostheElite_activate = false; + private bool HeavymetalfoesElectrumite_activate = false; + private bool should_destory = false; + private List Odd_EyesMeteorburstDragon_materials = new List(); + private bool duel_start = true; + private int activate_count = 0; + private int summon_count = 0; + private bool enemy_activate = false; + private enum CustomMessage + { + Happy, + Angry, + Surprise + } + private static class Toos + { + public delegate bool Delegate(ClientCard card); + private static bool DefaultFunc(ClientCard card) + { + return true; + } + public static bool LinqAny(IList cards, Delegate @delegate = null) + { + if (cards == null) return false; + @delegate = @delegate ?? DefaultFunc; + return cards.Any(card => card != null && @delegate(card)); + } + public static bool LinqAll(IList cards, Delegate @delegate = null, bool flag = true) + { + if (cards == null) return false; + IList rcards = new List(cards); + if (flag) rcards = cards.Where(card => card != null).ToList(); + @delegate = @delegate ?? DefaultFunc; + return rcards.All(card => card != null && @delegate(card)); + } + public static int LinqCount(IList cards, Delegate @delegate = null) + { + if (cards == null) return -1; + @delegate = @delegate ?? DefaultFunc; + return cards.Count(card => card != null && @delegate(card)); + } + public static List LinqWhere(IList cards, Delegate @delegate = null) + { + if (cards == null) return new List(); + @delegate = @delegate ?? DefaultFunc; + return cards.Where(card => card != null && @delegate(card)).ToList(); + } + } + private class Func + { + private IList _parameters = new List(); + private List no_p_spsummon_ids = new List() + { + CardId.Zefraath + }; + private List selectCardList = null; + private List selectCardIdList = null; + public List GetSelectCardList() + { + if (selectCardList == null) + { + selectCardList = new List(); + } + else + { + selectCardList.Clear(); + } + return selectCardList; + } + public List GetSelectCardIdList() + { + if (selectCardIdList == null) + { + selectCardIdList = new List(); + } + else + { + selectCardIdList.Clear(); + } + return selectCardIdList; + } + public bool IsLocation(ClientCard card) + { + return card.Location == (CardLocation)_parameters[0]; + } + public bool IsCode(ClientCard card) + { + return card.IsCode((int)_parameters[0]); + } + public static bool IsCode(ClientCard card, params int[] ids) + { + if (card == null) return false; + foreach (var id in ids) + { + if (card.IsCode(id)) return true; + } + return false; + } + public bool HasSetCode(ClientCard card) + { + return card.HasSetcode((int)_parameters[0]); + } + public static bool HasSetCode(ClientCard card, params int[] set_codes) + { + if (card == null) return false; + foreach (var set_code in set_codes) + { + if (card.HasSetcode(set_code)) return true; + } + return false; + } + public static bool IsFaceUp(ClientCard card) + { + return card.IsFaceup(); + } + public bool HasAttribute(ClientCard card) + { + return card.HasAttribute((CardAttribute)_parameters[0]); + } + public bool HasRace(ClientCard card) + { + return card.HasRace((CardRace)_parameters[0]); + } + public bool HasLevel(ClientCard card) + { + return card.Level == (int)_parameters[0]; + } + public bool HasType(ClientCard card) + { + return card.HasType((CardType)_parameters[0]); + } + public static bool IsOnfield(ClientCard card) + { + return (card.Location & CardLocation.MonsterZone) > 0 || (card.Location & CardLocation.SpellZone) > 0; + } + public static Toos.Delegate NegateFunc(Toos.Delegate @delegate) + { + return card => { return !@delegate(card); }; + } + private void SetParameters(IList parameters) + { + ClearParameters(); + for (int i = 0; i < parameters?.Count(); ++i) + { + _parameters.Add(parameters[i]); + } + } + private void ClearParameters() + { + _parameters.Clear(); + } + public bool CardsCheckAny(IList cards, Toos.Delegate @delegate = null, params object[] parameters) + { + SetParameters(parameters); + return Toos.LinqAny(cards, @delegate); + } + public bool CardsCheckALL(IList cards, Toos.Delegate @delegate = null, bool all = true, params object[] parameters) + { + SetParameters(parameters); + return Toos.LinqAll(cards, @delegate, all); + } + public int CardsCheckCount(IList cards, Toos.Delegate @delegate = null, params object[] parameters) + { + SetParameters(parameters); + return Toos.LinqCount(cards, @delegate); + } + public List CardsCheckWhere(IList cards, Toos.Delegate @delegate = null, params object[] parameters) + { + SetParameters(parameters); + return Toos.LinqWhere(cards, @delegate); + } + public static List MergeList(params List[] lists) + { + List result = new List(); + foreach (var list in lists) + { + if (list == null) continue; + result.AddRange(list); + } + return result; + } + public List CardsIdToClientCards(IList cardsId, IList cardsList, bool uniqueId = true) + { + if (cardsList?.Count() <= 0 || cardsId?.Count() <= 0) return new List(); + List result = new List(); + cardsId = cardsId.Distinct().ToList(); + foreach (var cardid in cardsId) + { + List cards = CardsCheckWhere(cardsList, IsCode, cardid); + if (cards.Count <= 0) continue; + if (uniqueId) result.Add(cards.First()); + else result.AddRange(cards); + } + return result; + } + public static List ClientCardsToCardsId(IList cardsList, bool uniqueId = false, bool alias = false) + { + if (cardsList?.Count <= 0) return new List(); + List res = new List(); + foreach (var card in cardsList) + { + if (card == null) continue; + if (card.Alias != 0 && alias && !(res.Contains(card.Alias) & uniqueId)) res.Add(card.Alias); + else if (card.Id != 0 && !(res.Contains(card.Id) & uniqueId)) res.Add(card.Id); + } + return res; + } + //AIUtil + public static IList CheckSelectCount(AIUtil util, IList _selected, IList cards, int min, int max) + { + return _selected?.Count() <= 0 ? null : util.CheckSelectCount(_selected, cards, min, max); + } + public static List GetZoneCards(ClientField player, CardLocation loc, bool feceup = false, bool disable = false) + { + if (!feceup) disable = false; + List result = new List(); + if ((loc & CardLocation.Hand) > 0) result.AddRange(Toos.LinqWhere(player.Hand)); + if ((loc & CardLocation.MonsterZone) > 0) result.AddRange(Toos.LinqWhere(player.MonsterZone, card => !(!card.IsFaceup() & feceup) && !(!card.IsDisabled() & disable))); + if ((loc & CardLocation.SpellZone) > 0) result.AddRange(Toos.LinqWhere(player.SpellZone, card => !(!card.IsFaceup() & feceup) && !(!card.IsDisabled() & disable))); + if ((loc & CardLocation.PendulumZone) > 0) result.AddRange(Toos.LinqWhere(new List() { player.SpellZone[0], player.SpellZone[4] }, card => !(!card.IsFaceup() & feceup) && !(!card.IsDisabled() & disable))); + if ((loc & CardLocation.Grave) > 0) result.AddRange(Toos.LinqWhere(player.Graveyard)); + if ((loc & CardLocation.Removed) > 0) result.AddRange(Toos.LinqWhere(player.Banished, card => !(!card.IsFaceup() & feceup))); + if ((loc & CardLocation.Extra) > 0) result.AddRange(Toos.LinqWhere(player.ExtraDeck, card => !(!card.IsFaceup() & feceup))); + result = result.Distinct().ToList(); + return result; + } + public bool HasInZone(ClientField player, CardLocation loc, int id, bool feceup = false, bool disable = false) + { + return CardsCheckAny(GetZoneCards(player, loc, feceup, disable), IsCode, id); + } + public static bool SpellActivate(ClientCard card) + { + return card.Location == CardLocation.Hand || (card.Location == CardLocation.SpellZone && card.IsFacedown()); + } + public static bool PendulumActivate(int desc, ClientCard card) + { + return desc == P_ACTIVATE_DESC && card.Location == CardLocation.Hand; + } + private static Toos.Delegate GetPSpSummonLimilt(ClientCard pcard) + { + int setcode = -1; + int setcode2 = -1; + switch (pcard.Id) + { + case CardId.SecretoftheYangZing: + case CardId.Zefraxi_TreasureoftheYangZing: { setcode = 0xc4; setcode2 = 0x9e; break; } + case CardId.FlameBeastoftheNekroz: { setcode = 0xc4; setcode2 = 0xb4; break; } + case CardId.StellarknightZefraxciton: + case CardId.SatellarknightZefrathuban: { setcode = 0xc4; setcode2 = 0x109c; break; } + case CardId.RitualBeastTamerZeframpilica: { setcode = 0xc4; setcode2 = 0x10b5; break; } + case CardId.ShaddollZefracore: { setcode = 0xc4; setcode2 = 0x9d; break; } + case CardId.DDSavantKepler: { setcode = 0xaf; break; } + default: break; + } + return card => { + return (setcode == -1 ? true : card.HasSetcode(setcode)) + || (setcode2 == -1 ? true : card.HasSetcode(setcode2)); + }; + } + public static int[] GetPScales(ClientField bot) + { + int[] pScales = new int[2]; + ClientCard lcard = bot.SpellZone[0]; + ClientCard rcard = bot.SpellZone[4]; + pScales[0] = (lcard == null || lcard.IsFacedown() || !lcard.HasType(CardType.Pendulum)) ? -1 : lcard.RScale; + pScales[1] = (rcard == null || rcard.IsFacedown() || !rcard.HasType(CardType.Pendulum)) ? -1 : rcard.LScale; + return pScales; + } + public static int GetPScale(ClientField bot, int id) + { + bool rscale = false; + ClientCard pcard = null; + if (bot.SpellZone[0] != null && bot.SpellZone[0].Id == id) + { + pcard = bot.SpellZone[4]; + } + else + { + pcard = bot.SpellZone[0]; + rscale = true; + } + if (pcard == null || pcard.IsFacedown() || !pcard.HasType(CardType.Pendulum)) return -1; + return rscale ? pcard.RScale : pcard.LScale; + } + public List GetPSpSummonMonster(ClientField bot, ClientCard lcard, ClientCard rcard) + { + if (lcard == null || rcard == null || !lcard.HasType(CardType.Pendulum) || !rcard.HasType(CardType.Pendulum) || (IsOnfield(lcard) & lcard.IsFacedown()) || (IsOnfield(lcard) & rcard.IsFacedown())) return null; + int MaxScale = Math.Max(lcard.RScale, rcard.LScale); + int MinScale = Math.Min(lcard.RScale, rcard.LScale); + Toos.Delegate @llimit = GetPSpSummonLimilt(lcard); + Toos.Delegate @rlimit = GetPSpSummonLimilt(rcard); + return CardsCheckWhere(GetZoneCards(bot, CardLocation.Hand | CardLocation.Extra, true), + card => { + return card != lcard && card != rcard && card.HasType(CardType.Monster) && card.Level > MinScale && card.Level < MaxScale + && !no_p_spsummon_ids.Contains(card.Id) && @llimit(card) && @rlimit(card); + }); ; + } + public bool IsActivateScale(ClientField bot, ClientCard card) + { + ClientCard lcard = bot.SpellZone[0]; + ClientCard rcard = bot.SpellZone[4]; + List spSummonMonster = null; + if (lcard != null && rcard != null) return false; + if (lcard == null && rcard == null) return true; + + spSummonMonster = lcard == null ? GetPSpSummonMonster(bot, card, rcard) : GetPSpSummonMonster(bot, lcard, card); + return spSummonMonster?.Count() > 0; + } + public static int CompareCardScale(ClientCard cardA, ClientCard cardB) + { + if (cardA.RScale < cardB.RScale) + return -1; + if (cardA.RScale == cardB.RScale) + return 0; + return 1; + } + public static List GetCardsRepeatCardsId(IList cards) + { + if (cards?.Count <= 0) return new List() { -1 }; + IList cardsid = new List(); + List res = new List(); + foreach (var card in cards) + { + if (card == null) continue; + cardsid.Add(card.Id); + } + for (int i = 0; i < cardsid.Count; i++) + { + if (res.Count >= 0 && res.Contains(cardsid[i])) continue; + int times = 0; + for (int j = 0; j < cardsid.Count; j++) + { + if (times > 1) { res.Add(cardsid[i]); break; } + if (cardsid[i] == cardsid[j]) ++times; + } + } + if (res.Count <= 0) return new List() { -1 }; + return res; + } + } + private Func func = new Func(); + public ZefraExecutor(GameAI ai, Duel duel) : base(ai, duel) + { + AddExecutor(ExecutorType.Activate, CardId.CalledbytheGrave, CalledbytheGraveEffect); + AddExecutor(ExecutorType.Activate, CardId.BorreloadSavageDragon, BorreloadSavageDragonEffect_2); + AddExecutor(ExecutorType.Activate, CardId.F_A_DawnDragster, ResetFlag); + AddExecutor(ExecutorType.Activate, CardId.NinePillarsofYangZing, NinePillarsofYangZingEffect); + AddExecutor(ExecutorType.Activate, CardId.ZefraDivineStrike, ZefraDivineStrikeEffect); + AddExecutor(ExecutorType.Activate, CardId.HeraldoftheArcLight, HeraldoftheArcLightEffect); + AddExecutor(ExecutorType.Activate, CardId.TruKingofAllCalamities, TruKingofAllCalamitiesEffect); + AddExecutor(ExecutorType.Activate, CardId.PSY_FramegearGamma, ResetFlag); + AddExecutor(ExecutorType.Activate, CardId.MaxxC, DefaultMaxxC); + AddExecutor(ExecutorType.Activate, CardId.SupremeKingDragonDarkwurm, SupremeKingDragonDarkwurmEffect); + AddExecutor(ExecutorType.Activate, CardId.ServantofEndymion, ServantofEndymionEffect); + AddExecutor(ExecutorType.Activate, CardId.Terraforming, TerraformingEffect); + AddExecutor(ExecutorType.Activate, CardId.SpellPowerMastery, ResetFlag); + AddExecutor(ExecutorType.Activate, CardId.DragonShrine, DragonShrineEffect); + AddExecutor(ExecutorType.Activate, CardId.FoolishBurial, FoolishBurialEffect); + AddExecutor(ExecutorType.Activate, CardId.DarkContractwiththGate, DarkContractwiththGateEffect); + AddExecutor(ExecutorType.Activate, CardId.Terraforming, ResetFlag); + AddExecutor(ExecutorType.Activate, CardId.OracleofZefra, OracleofZefraEffect); + AddExecutor(ExecutorType.Activate, CardId.ZefraProvidence, ZefraProvidenceEffect); + AddExecutor(ExecutorType.Activate, CardId.AstrographSorcerer, AstrographSorcererEffect); + AddExecutor(ExecutorType.Activate, CardId.HeavymetalfoesElectrumite, HeavymetalfoesElectrumiteEffect); + AddExecutor(ExecutorType.Summon, CardId.SupremeKingDragonDarkwurm, SupremeKingDragonDarkwurmSummon); + AddExecutor(ExecutorType.Activate, CardId.SupremeKingGateZero, SupremeKingGateZeroEffect); + AddExecutor(ExecutorType.Activate, CardId.Zefraxi_TreasureoftheYangZing, Zefraxi_TreasureoftheYangZingEffect); + AddExecutor(ExecutorType.Activate, CardId.SatellarknightZefrathuban, SatellarknightZefrathubanEffect); + AddExecutor(ExecutorType.Activate, CardId.RitualBeastTamerZeframpilica, RitualBeastTamerZeframpilicaEffect); + AddExecutor(ExecutorType.Activate, CardId.SecretoftheYangZing, SecretoftheYangZingEffect); + AddExecutor(ExecutorType.Activate, CardId.FlameBeastoftheNekroz, FlameBeastoftheNekrozEffect); + AddExecutor(ExecutorType.Activate, CardId.ShaddollZefracore, ShaddollZefracoreEffect); + AddExecutor(ExecutorType.Activate, CardId.StellarknightZefraxciton, StellarknightZefraxcitonEffect); + AddExecutor(ExecutorType.Activate, CardId.SupremeKingDragonDarkwurm, SupremeKingGateZeroEffect); + AddExecutor(ExecutorType.Activate, CardId.AstrographSorcerer, SupremeKingGateZeroEffect); + AddExecutor(ExecutorType.Activate, CardId.Zefraath, ZefraathEffect); + AddExecutor(ExecutorType.Activate, CardId.DDSavantKepler, DDSavantKeplerEffect); + AddExecutor(ExecutorType.Summon, CardId.DDSavantKepler, DDSavantKeplerSummon); + AddExecutor(ExecutorType.Activate, CardId.ServantofEndymion, ServantofEndymionEffect_3); + AddExecutor(ExecutorType.Activate, CardId.MythicalBeastJackalKing, MythicalBeastJackalKingEffect); + AddExecutor(ExecutorType.SpSummon, Psummon); + AddExecutor(ExecutorType.Activate, CardId.OneforOne, OneforOneEffect); + AddExecutor(ExecutorType.Activate, CardId.ServantofEndymion, ServantofEndymionEffect_2); + AddExecutor(ExecutorType.Activate, CardId.CrystronHalqifibrax, CrystronHalqifibraxEffect); + AddExecutor(ExecutorType.SpSummon, CardId.Raidraptor_ArsenalFalcon, Raidraptor_ArsenalFalconSummon); + AddExecutor(ExecutorType.Activate, CardId.Raidraptor_ArsenalFalcon, Raidraptor_ArsenalFalconEffect); + AddExecutor(ExecutorType.SpSummon, CardId.HeavymetalfoesElectrumite, HeavymetalfoesElectrumiteSummon); + //xyz mode + AddExecutor(ExecutorType.SpSummon, CardId.Odd_EyesMeteorburstDragon, Odd_EyesMeteorburstDragonSummon); + AddExecutor(ExecutorType.Activate, CardId.Odd_EyesMeteorburstDragon, Odd_EyesMeteorburstDragonEffect); + AddExecutor(ExecutorType.SpSummon, CardId.Raidraptor_WiseStrix, Raidraptor_WiseStrixSummon); + AddExecutor(ExecutorType.Activate, CardId.Raidraptor_WiseStrix, Raidraptor_WiseStrixEffect); + AddExecutor(ExecutorType.Activate, CardId.Blackwing_ZephyrostheElite, Blackwing_ZephyrostheEliteEffect); + AddExecutor(ExecutorType.SpSummon, CardId.Raidraptor_ForceStrix, Raidraptor_ForceStrixSummon); + AddExecutor(ExecutorType.Activate, CardId.Raidraptor_ForceStrix, Raidraptor_ForceStrixEffect); + AddExecutor(ExecutorType.Activate, CardId.Rank_Up_MagicSoulShaveForce, ResetFlag); + AddExecutor(ExecutorType.Activate, CardId.Raider_Wing, Raider_WingEffect); + AddExecutor(ExecutorType.SpSummon, CardId.Raidraptor_SingingLanius); + //xyz mode + AddExecutor(ExecutorType.SpSummon, CardId.SaryujaSkullDread, SaryujaSkullDreadSummon); + AddExecutor(ExecutorType.Activate, CardId.SaryujaSkullDread, SaryujaSkullDreadEffect); + AddExecutor(ExecutorType.SpSummon, CardId.Denglong_FirstoftheYangZing, Denglong_FirstoftheYangZingSummon_2); + AddExecutor(ExecutorType.SpSummon, CardId.BorreloadSavageDragon, BorreloadSavageDragonSummon_2); + AddExecutor(ExecutorType.SpSummon, CardId.CrystronHalqifibrax, CrystronHalqifibraxSummon); + AddExecutor(ExecutorType.SpSummon, CardId.Linkuriboh, LinkuribohSummon); + AddExecutor(ExecutorType.Activate, CardId.DDLamia, DDLamiaEffect); + AddExecutor(ExecutorType.SpSummon, CardId.MechaPhantomBeastAuroradon, MechaPhantomBeastAuroradonSummon); + AddExecutor(ExecutorType.Activate, CardId.MechaPhantomBeastAuroradon, MechaPhantomBeastAuroradonEffect); + AddExecutor(ExecutorType.SpSummon, CardId.Denglong_FirstoftheYangZing, Denglong_FirstoftheYangZingSummon); + AddExecutor(ExecutorType.Activate, CardId.Denglong_FirstoftheYangZing, Denglong_FirstoftheYangZingEffect); + AddExecutor(ExecutorType.SpSummon, CardId.BorreloadSavageDragon, BorreloadSavageDragonSummon); + AddExecutor(ExecutorType.Activate, CardId.BorreloadSavageDragon, BorreloadSavageDragonEffect); + AddExecutor(ExecutorType.SpSummon, CardId.HeraldoftheArcLight); + AddExecutor(ExecutorType.SpSummon, CardId.F_A_DawnDragster, F_A_DawnDragsterSummon); + AddExecutor(ExecutorType.SpSummon, CardId.PSY_FramelordOmega, BorreloadSavageDragonSummon); + AddExecutor(ExecutorType.Activate, CardId.PSY_FramelordOmega, PSY_FramelordOmegaEffect); + AddExecutor(ExecutorType.Activate, CardId.Linkuriboh, LinkuribohEffect); + AddExecutor(ExecutorType.Activate, CardId.MechaPhantomBeastO_Lion); + AddExecutor(ExecutorType.Activate, CardId.JetSynchron, JetSynchronEffect); + AddExecutor(ExecutorType.Activate, CardId.Blackwing_ZephyrostheElite, Blackwing_ZephyrostheEliteEffect_2); + AddExecutor(ExecutorType.Summon, CardId.JetSynchron, DDLamiaSummon); + AddExecutor(ExecutorType.Summon, CardId.DDLamia, DDLamiaSummon); + AddExecutor(ExecutorType.Summon, CardId.Deskbot001, DDLamiaSummon); + AddExecutor(ExecutorType.Summon, CardId.LightoftheYangZing, DDLamiaSummon); + List p_summon_ids = new List() {CardId.Zefraxi_TreasureoftheYangZing,CardId.SatellarknightZefrathuban,CardId.ServantofEndymion,CardId.RitualBeastTamerZeframpilica, + CardId.DDSavantKepler,CardId.StellarknightZefraxciton,CardId.ShaddollZefracore,CardId.SupremeKingDragonDarkwurm}; + for (int i = 0; i < p_summon_ids.Count; ++i) AddExecutor(ExecutorType.Summon, p_summon_ids[i], DefaultSummon); + AddExecutor(ExecutorType.Summon, DefaultSummon); + AddExecutor(ExecutorType.Activate, CardId.Deskbot001, ResetFlag); + AddExecutor(ExecutorType.Activate, CardId.TheMightyMasterofMagic, TheMightyMasterofMagicEffect); + AddExecutor(ExecutorType.Activate, CardId.DestrudotheLostDragon_Frisson, DestrudotheLostDragon_FrissonEffect); + AddExecutor(ExecutorType.Summon, CardId.Blackwing_ZephyrostheElite, DefaultSummon_2); + AddExecutor(ExecutorType.Summon, DefaultSummon_2); + AddExecutor(ExecutorType.SpSummon, CardId.Linkuriboh); + AddExecutor(ExecutorType.SpellSet, SpellSet); + AddExecutor(ExecutorType.SpellSet, SpellSet_2); + AddExecutor(ExecutorType.Repos, DefaultMonsterRepos); + AddExecutor(ExecutorType.Activate, DefaultPActivate); + AddExecutor(ExecutorType.GoToEndPhase, GoToEndPhase); + } + public override void OnNewTurn() + { + if (duel_start) + { + duel_start = false; + AI.SendCustomChat((int)CustomMessage.Happy); + } + activate_SupremeKingDragonDarkwurm_1 = false; + activate_SupremeKingDragonDarkwurm_2 = false; + activate_JetSynchron = false; + activate_DestrudotheLostDragon_Frisson = false; + activate_ZefraProvidence = false; + activate_OracleofZefra = false; + activate_DragonShrine = false; + activate_p_Zefraath = false; + p_summoned = false; + summoned = false; + activate_DarkContractwiththGate = false; + activate_SecretoftheYangZing = false; + activate_ShaddollZefracore = false; + activate_SpellPowerMastery = false; + link_summoned = false; + activate_DDLamia = false; + xyz_mode = false; + Blackwing_ZephyrostheElite_activate = false; + HeavymetalfoesElectrumite_activate = false; + spell_activate_count = 0; + p_count = 0; + activate_count = 0; + summon_count = 0; + enemy_activate = false; + } + private bool ZefraProvidenceEffect() + { + if (ActivateDescription == 96) + { + if (should_destory) + { + should_destory = false; + return false; + } + return BeforeResult(ExecutorType.Activate); + } + else + { + activate_ZefraProvidence = true; + return BeforeResult(ExecutorType.Activate); + } + + } + private List CheckShouldSpsummonExtraMonster() + { + List extra_ids = new List() { CardId.HeavymetalfoesElectrumite, CardId.CrystronHalqifibrax }; + if (!Bot.HasInExtra(CardId.HeavymetalfoesElectrumite)) extra_ids.Remove(CardId.HeavymetalfoesElectrumite); + if (!Bot.HasInExtra(CardId.CrystronHalqifibrax)) extra_ids.Remove(CardId.CrystronHalqifibrax); + if (extra_ids.Count <= 0) return extra_ids; + bool DD_summon_check = false; + if (Bot.HasInExtra(CardId.CrystronHalqifibrax) && ((!summoned && HasInDeck(CardId.DDSavantKepler) && (HasInDeck(CardId.DarkContractwiththGate) || Bot.HasInHandOrInSpellZone(CardId.DarkContractwiththGate) + ) && !activate_DarkContractwiththGate && HasInDeck(CardId.DDLamia)) || (func.CardsCheckAny(Bot.Hand, func.HasType, CardType.Tuner) && + (HasInDeck(CardId.AstrographSorcerer) || Bot.HasInHand(CardId.AstrographSorcerer))))) + { + DD_summon_check = true; + } + if (Bot.SpellZone[0] != null && Bot.SpellZone[4] != null) + { + List spSummonMonster = func.GetPSpSummonMonster(Bot, Bot.SpellZone[0], Bot.SpellZone[4]); + if (DD_summon_check && spSummonMonster != null) + { + + List pSpsummonMonster = func.CardsCheckWhere(spSummonMonster, func.HasType, CardType.Pendulum); + List monsterCards = func.CardsCheckWhere(Func.GetZoneCards(Bot, CardLocation.MonsterZone), card => + { return card.IsFaceup() && card.HasType(CardType.Pendulum); }); + if (Func.MergeList(pSpsummonMonster, monsterCards).Count <= 0) extra_ids.Remove(CardId.HeavymetalfoesElectrumite); + } + else + { + extra_ids.Remove(CardId.HeavymetalfoesElectrumite); + } + } + else + { + if (!((Bot.HasInHand(CardId.OracleofZefra) && !activate_OracleofZefra) || (Bot.HasInHand(CardId.ZefraProvidence) + && !activate_ZefraProvidence) || (Bot.HasInHand(CardId.Zefraath) && !activate_p_Zefraath))) + { + extra_ids.Clear(); + } + } + if (!DD_summon_check) extra_ids.Remove(CardId.HeavymetalfoesElectrumite); + return extra_ids; + } + private bool DDLamiaSummon() + { + if (!IsCanSynchroSummon(Card.Level)) return false; + if (Bot.HasInExtra(CardId.Linkuriboh) || (Bot.HasInExtra(CardId.CrystronHalqifibrax) && + Func.GetZoneCards(Bot, CardLocation.MonsterZone, true).Count > 0)) + { + summoned = true; + return BeforeResult(ExecutorType.Summon); + } + return false; + } + private bool XyzModeCheck(bool flag1 = false) + { + return !link_summoned && !(!Bot.HasInExtra(CardId.Raidraptor_ArsenalFalcon) & flag1) && HasInDeck(CardId.Blackwing_ZephyrostheElite) && Bot.HasInExtra(CardId.Raidraptor_ForceStrix) && Bot.HasInExtra(CardId.Raidraptor_WiseStrix) + && Bot.HasInExtra(CardId.TruKingofAllCalamities) && (HasInDeck(CardId.Raider_Wing) || Bot.HasInHand(CardId.Raider_Wing)) + && (HasInDeck(CardId.Raidraptor_SingingLanius) || Bot.HasInHand(CardId.Raidraptor_SingingLanius)) + && (HasInDeck(CardId.Rank_Up_MagicSoulShaveForce) || Bot.HasInHand(CardId.Rank_Up_MagicSoulShaveForce)); + } + private bool Raidraptor_ForceStrixEffect() + { + AI.SelectCard(CardId.Raider_Wing); + AI.SelectNextCard(CardId.Raidraptor_SingingLanius); + return BeforeResult(ExecutorType.Activate); + } + private bool Raidraptor_ForceStrixSummon() + { + return xyz_mode && BeforeResult(ExecutorType.Summon); + } + + private bool Blackwing_ZephyrostheEliteEffect_2() + { + if (!xyz_mode && Bot.GetMonstersInMainZone().Count > 4) return false; + List cards = func.CardsCheckWhere(Func.GetZoneCards(Bot, CardLocation.Onfield, true), card => { + return !IsNoLinkCards(card) && !card.IsExtraCard() && !(card.Location == CardLocation.SpellZone + && Func.IsCode(card, CardId.SaryujaSkullDread, CardId.MechaPhantomBeastAuroradon, CardId.HeavymetalfoesElectrumite, CardId.CrystronHalqifibrax, CardId.Raidraptor_WiseStrix, + CardId.Linkuriboh)); + }); + if (cards.Count <= 0 || (cards.Count < 2 && func.CardsCheckCount(cards, func.HasLevel, 4) == cards.Count)) + { + Blackwing_ZephyrostheElite_activate = true; + return false; + } + cards.Sort((cardA, cardB) => + { + if (cardA.Location != CardLocation.MonsterZone && cardB.Location == CardLocation.MonsterZone) return -1; + if (cardA.Location == CardLocation.MonsterZone && cardB.Location != CardLocation.MonsterZone) return 1; + if (cardA.Location == CardLocation.SpellZone && cardB.Location == CardLocation.SpellZone) + { + if (cardA.IsCode(CardId.OracleofZefra) && !cardB.IsCode(CardId.OracleofZefra)) return -1; + if (!cardA.IsCode(CardId.OracleofZefra) && cardB.IsCode(CardId.OracleofZefra)) return 1; + return 0; + } + if (xyz_mode) + { + if (cardA.Level == 4 && cardB.Level != 4) return 1; + if (cardA.Level != 4 && cardB.Level == 4) return -1; + return CardContainer.CompareCardAttack(cardA, cardB); + } + else + { + return CardContainer.CompareCardAttack(cardA, cardB); + } + }); + Blackwing_ZephyrostheElite_activate = false; + AI.SelectCard(cards); + return BeforeResult(ExecutorType.Activate); + } + public override void OnChaining(int player, ClientCard card) + { + if (card == null) return; + if (player == 1 && Func.IsCode(card, 14558127, 59438930, 94145021, 38814750, 73642296, 97268402)) + enemy_activate = true; + base.OnChaining(player, card); + } + private bool BeforeResult(ExecutorType type) + { + if (type == ExecutorType.Activate) + { + ResetFlag(); + ++activate_count; + } + if (type == ExecutorType.Summon) + { + ++summon_count; + } + return true; + } + private bool GoToEndPhase() + { + if (Duel.Player == 0 && Duel.Turn == 1 && func.CardsCheckCount(Func.GetZoneCards(Bot, CardLocation.MonsterZone, true), IsNoLinkCards) <= 0 + && activate_count + summon_count < 5 && !enemy_activate) + { + + AI.SendCustomChat((int)CustomMessage.Angry); + return true; + } + return false; + + } + private bool DefaultPActivate() + { + if (PendulumActivate() && Func.IsCode(Card, CardId.Zefraxi_TreasureoftheYangZing, CardId.SecretoftheYangZing)) + { + return Bot.HasInHandOrInSpellZone(CardId.NinePillarsofYangZing) && func.CardsCheckCount(Func.GetZoneCards(Bot, CardLocation.SpellZone, + true), card => { return Func.IsCode(Card, CardId.Zefraxi_TreasureoftheYangZing, CardId.SecretoftheYangZing); }) <= 0 && BeforeResult(ExecutorType.Activate); + } + return false; + } + private bool Blackwing_ZephyrostheEliteEffect() + { + if (!xyz_mode) return false; + return Blackwing_ZephyrostheEliteEffect_2(); + } + private bool Raidraptor_WiseStrixSummon() + { + if (!xyz_mode) return false; + AI.SelectMaterials(CardId.Raidraptor_ArsenalFalcon, CardId.Blackwing_ZephyrostheElite); + return BeforeResult(ExecutorType.Summon); + } + private bool Raidraptor_WiseStrixEffect() + { + if (ActivateDescription == -1) + { + int count = 0; + if (HasInDeck(CardId.Raidraptor_SingingLanius)) ++count; + if (HasInDeck(CardId.Blackwing_ZephyrostheElite)) ++count; + if (HasInDeck(CardId.Raider_Wing)) ++count; + if (count <= 1) return false; + AI.SelectCard(CardId.Raider_Wing); + return BeforeResult(ExecutorType.Activate); + } + return BeforeResult(ExecutorType.Activate); + } + private bool Raidraptor_ArsenalFalconEffect() + { + if (Card.Location == CardLocation.MonsterZone) + { + AI.SelectCard(CardId.SupremeKingGateZero); + AI.SelectNextCard(new int[] { CardId.Blackwing_ZephyrostheElite, CardId.Raider_Wing, CardId.Raidraptor_SingingLanius }); + return BeforeResult(ExecutorType.Activate); + } + return false; + } + private bool Raidraptor_ArsenalFalconSummon() + { + if (!XyzModeCheck(true)) return false; + var materials_lists = Util.GetXyzMaterials(Bot.MonsterZone, 7, 2, false, + card => { return !card.IsCode(CardId.F_A_DawnDragster) && !card.IsCode(CardId.TheMightyMasterofMagic); }); + if (materials_lists.Count <= 0) return false; + AI.SelectMaterials(materials_lists[0]); + xyz_mode = true; + return BeforeResult(ExecutorType.Summon); + } + private bool Odd_EyesMeteorburstDragonCheck() + { + if (!XyzModeCheck()) return false; + var materials_lists = Util.GetXyzMaterials(Func.MergeList(new List() { Card }, + Func.GetZoneCards(Bot, CardLocation.MonsterZone | CardLocation.PendulumZone)), 7, 2, false, + card => { return !card.IsCode(CardId.F_A_DawnDragster) && !card.IsCode(CardId.TheMightyMasterofMagic); }); + if (materials_lists.Count <= 0) return false; + List pre_materials = func.CardsCheckWhere(Func.GetZoneCards(Bot, CardLocation.MonsterZone, true), SecretoftheYangZingCheck); + var materials_sy_lists = Util.GetSynchroMaterials(pre_materials, 7, 1, 1, false, true, null, card => { return !card.IsCode(CardId.MythicalBeastJackalKing) && !card.IsCode(CardId.HeraldoftheArcLight); }); + if (materials_sy_lists.Count <= 0) return false; + Odd_EyesMeteorburstDragon_materials.Clear(); + foreach (var materials in materials_sy_lists) + { + if (func.CardsCheckCount(materials, func.IsCode, CardId.SupremeKingGateZero) > 0) + { + Odd_EyesMeteorburstDragon_materials.AddRange(materials); + return true; + } + } + Odd_EyesMeteorburstDragon_materials.AddRange(materials_sy_lists[0]); + return true; + } + private bool Odd_EyesMeteorburstDragonSummon() + { + if (!Odd_EyesMeteorburstDragonCheck()) return false; + AI.SelectMaterials(Odd_EyesMeteorburstDragon_materials); + return BeforeResult(ExecutorType.Summon); + } + private bool Odd_EyesMeteorburstDragonEffect() + { + AI.SelectCard(CardId.SupremeKingGateZero); + return BeforeResult(ExecutorType.Activate); + } + private bool DDSavantKeplerSummon() + { + if (HasInDeck(CardId.DarkContractwiththGate)) + { + summoned = true; + return BeforeResult(ExecutorType.Summon); + } + return false; + } + // private void DebugCards(string msg, IList cards) + // { + //#if DEBUG + // Logger.DebugWriteLine(cards.Count + msg); + // foreach (var card in cards) + // { + // if (card == null) continue; + // NamedCard namedCard = NamedCard.Get(card.Id); + // if (namedCard == null) continue; + // Logger.DebugWriteLine(msg + namedCard.Name); + // } + //#endif + // } + private bool ServantofEndymionEffect_2() + { + if (Card.Location == CardLocation.SpellZone) return BeforeResult(ExecutorType.Activate); + return false; + } + private bool IsSpsummonPMonster(ClientCard card) + { + return IsZefraScaleAbove(card) || IsZefraScaleBelow(card) || card.Id == CardId.SupremeKingGateZero || card.Id == CardId.ServantofEndymion; + } + private int GetSpellActivateCount() + { + int count = 0; + if (!activate_DragonShrine && func.CardsCheckAny(Bot.Hand, func.IsCode, CardId.DragonShrine) && + (HasInDeck(CardId.FlameBeastoftheNekroz) || HasInDeck(CardId.DestrudotheLostDragon_Frisson) || HasInDeck(CardId.SupremeKingDragonDarkwurm))) ++count; + if (!activate_SpellPowerMastery && func.CardsCheckAny(Bot.Hand, func.IsCode, CardId.SpellPowerMastery) + && (HasInDeck(CardId.TheMightyMasterofMagic) || HasInDeck(CardId.ServantofEndymion))) ++count; + if (func.CardsCheckAny(Bot.Hand, func.IsCode, CardId.DarkContractwiththGate)) ++count; + if (!activate_ZefraProvidence && func.CardsCheckAny(Bot.Hand, func.IsCode, CardId.ZefraProvidence)) + { + if (func.CardsCheckCount(Bot.Hand, func.IsCode, CardId.OracleofZefra) <= 0 && !activate_OracleofZefra + && HasInDeck(CardId.OracleofZefra)) + { + count += 2; + } + else + { + ++count; + } + } + if (!activate_OracleofZefra && func.CardsCheckAny(Bot.Hand, func.IsCode, CardId.OracleofZefra)) ++count; + if (func.CardsCheckAny(Bot.Hand, func.IsCode, CardId.Terraforming) && HasInDeck(CardId.OracleofZefra)) ++count; + if (func.CardsCheckAny(Bot.Hand, func.IsCode, CardId.FoolishBurial)) ++count; + if (func.CardsCheckCount(Bot.Hand, func.HasType, CardType.Pendulum) > 1 && Bot.SpellZone[0] == null && + Bot.SpellZone[4] == null) ++count; + if (!summoned && Bot.HasInHand(CardId.DDSavantKepler) && HasInDeck(CardId.DarkContractwiththGate)) ++count; + return count; + } + private bool ServantofEndymionEffect_3() + { + if (PendulumActivate()) + { + return PendulumDefaultActivate() && BeforeResult(ExecutorType.Activate); + } + return false; + } + private bool ZefraDivineStrikeEffect() + { + if (Duel.LastChainPlayer == 0) return false; + AI.SelectCard(CardId.RitualBeastTamerZeframpilica, CardId.SatellarknightZefrathuban, CardId.StellarknightZefraxciton, CardId.FlameBeastoftheNekroz, CardId.ShaddollZefracore, + CardId.SecretoftheYangZing, CardId.Zefraxi_TreasureoftheYangZing); + return BeforeResult(ExecutorType.Activate); + } + private bool NinePillarsofYangZingEffect() + { + if (Duel.LastChainPlayer == 0) return false; + List cards = func.CardsIdToClientCards(new List { CardId.SecretoftheYangZing }, Bot.MonsterZone); + cards.AddRange(func.CardsIdToClientCards(new List { CardId.SecretoftheYangZing, CardId.Zefraxi_TreasureoftheYangZing }, Bot.SpellZone)); + AI.SelectCard(cards); + should_destory = true; + return BeforeResult(ExecutorType.Activate); + } + private bool IsActivateBlackwing_ZephyrostheElite() + { + return (Blackwing_ZephyrostheElite_activate || HeavymetalfoesElectrumite_activate) && Func.GetZoneCards(Bot, CardLocation.PendulumZone, true).Count <= 0; + } + private bool PendulumDefaultActivate() + { + return IsActivateBlackwing_ZephyrostheElite() || (checkPActivate() && IsActivateScale()); + } + private bool ServantofEndymionEffect() + { + if (PendulumActivate()) + { + if (IsActivateBlackwing_ZephyrostheElite()) return BeforeResult(ExecutorType.Activate); + if ((!HasInDeck(CardId.TheMightyMasterofMagic) && !HasInDeck(CardId.MythicalBeastJackalKing) || GetSpellActivateCount() < 2)) return false; + return BeforeResult(ExecutorType.Activate); + } + else if (Card.Location == CardLocation.SpellZone) + { + if (func.HasInZone(Bot, CardLocation.Hand | CardLocation.PendulumZone, CardId.Zefraath, true)) + { + return func.CardsCheckAny(Bot.Hand, IsSpsummonPMonster) && BeforeResult(ExecutorType.Activate); + } + return BeforeResult(ExecutorType.Activate); + } + else if (Card.Location == CardLocation.MonsterZone) return BeforeResult(ExecutorType.Activate); + else return false; + } + private bool IsZefraScaleAbove(ClientCard card) + { + return Func.IsCode(card, CardId.StellarknightZefraxciton, CardId.SecretoftheYangZing, CardId.FlameBeastoftheNekroz, CardId.ShaddollZefracore); + } + private bool IsZefraScaleBelow(ClientCard card) + { + return Func.IsCode(card, CardId.RitualBeastTamerZeframpilica, CardId.Zefraxi_TreasureoftheYangZing, CardId.SatellarknightZefrathuban); + } + private bool TerraformingEffect() + { + return Bot.HasInHand(CardId.OracleofZefra) && BeforeResult(ExecutorType.Activate); + } + private bool DDSavantKeplerEffect() + { + if (PendulumActivate()) return false; + return BeforeResult(ExecutorType.Activate); + } + private bool FoolishBurialEffect() + { + return BeforeResult(ExecutorType.Activate); + } + private List GetSynchroMaterials() + { + List materials = func.CardsCheckWhere(Func.GetZoneCards(Bot, CardLocation.MonsterZone, true), + card => { return !IsNoLinkCards(card) && !card.HasType(CardType.Link | CardType.Xyz); }); + return materials; + } + private bool DestrudotheLostDragon_FrissonEffect() + { + if (Bot.HasInExtra(CardId.CrystronHalqifibrax)) return BeforeResult(ExecutorType.Activate); + if (!Bot.HasInExtra(CardId.F_A_DawnDragster) && !Bot.HasInExtra(CardId.Odd_EyesMeteorburstDragon)) return false; + List pre_materials = func.CardsCheckWhere(Func.GetZoneCards(Bot, CardLocation.MonsterZone, true), card => { return SecretoftheYangZingCheck(card) && !IsNoLinkCards(card) && !card.HasType(CardType.Tuner) && card.Level > 0; }); + if (pre_materials.Count <= 0) return false; + List cards = func.CardsCheckWhere(Func.GetZoneCards(Bot, CardLocation.MonsterZone, true), card => + { + return !IsNoLinkCards(card) && card.Level > 0 && !card.HasType(CardType.Tuner); + }); + if (cards.Count <= 0) return false; + AI.SelectCard(cards); + return BeforeResult(ExecutorType.Activate); + } + private bool IsCanSynchroSummon(int level) + { + return func.CardsCheckAny(GetSynchroMaterials(), card => { + return (card.Level + level == 8 + && func.CardsCheckAny(Bot.ExtraDeck, synchro_card => { return Func.IsCode(synchro_card, CardId.BorreloadSavageDragon, CardId.PSY_FramelordOmega); })) + || (card.Level + level == 7 && SecretoftheYangZingCheck(card) && func.CardsCheckAny(Bot.ExtraDeck, synchro_card => { return Func.IsCode(synchro_card, CardId.Odd_EyesMeteorburstDragon, CardId.F_A_DawnDragster); })) + || (card.Level + level == 5 && Bot.HasInExtra(CardId.Denglong_FirstoftheYangZing)) + || (card.Level + level == 4 && Bot.HasInExtra(CardId.HeraldoftheArcLight)); + }); + } + private bool DDLamiaEffect() + { + if (Bot.HasInExtra(CardId.MechaPhantomBeastAuroradon) && Bot.GetMonstersInMainZone().Count >= 3) return false; + if (!Bot.HasInExtra(CardId.CrystronHalqifibrax) && !IsCanSynchroSummon(Card.Level)) return false; + AI.SelectCard(CardId.DarkContractwiththGate, CardId.DDSavantKepler); + activate_DDLamia = true; + return true; + } + private bool DragonShrineEffect() + { + return BeforeResult(ExecutorType.Activate); + } + private bool ZefraathEffect() + { + if (PendulumActivate()) return !activate_p_Zefraath || IsActivateBlackwing_ZephyrostheElite(); + if (Card.Location == CardLocation.SpellZone) + { + activate_p_Zefraath = true; + return BeforeResult(ExecutorType.Activate); + } + return false; + } + private bool RitualBeastTamerZeframpilicaEffect() + { + if (PendulumActivate()) + { + return PendulumDefaultActivate() && BeforeResult(ExecutorType.Activate); + } + return BeforeResult(ExecutorType.Activate); + } + private bool BorreloadSavageDragonSummon_2() + { + if (xyz_mode) return BorreloadSavageDragonSummon(); + return false; + } + private bool BorreloadSavageDragonSummon() + { + var materials_lists = Util.GetSynchroMaterials(Bot.MonsterZone, Card.Level, 1, 1, false, true, null, + card => { return !card.IsCode(CardId.F_A_DawnDragster) && !card.IsCode(CardId.TheMightyMasterofMagic) && !card.IsCode(CardId.HeraldoftheArcLight); }); + if (materials_lists.Count <= 0) return false; + foreach (var materials in materials_lists) + { + if (func.CardsCheckAny(materials, func.IsCode, CardId.MechaPhantomBeastToken)) + { + AI.SelectMaterials(materials); + return BeforeResult(ExecutorType.Summon); + } + } + AI.SelectMaterials(materials_lists[0]); + return BeforeResult(ExecutorType.Summon); + } + private bool BorreloadSavageDragonEffect() + { + /* + * effect1 bug: Unable to read card info in the func "OnselectCard" + * Unable to run in the "ActivateDescription == -1" + */ + AI.SelectCard(new[] + { + CardId.SaryujaSkullDread, + CardId.MechaPhantomBeastAuroradon, + CardId.HeavymetalfoesElectrumite, + CardId.CrystronHalqifibrax, + CardId.Raidraptor_WiseStrix + }); + return BeforeResult(ExecutorType.Activate); + } + private bool TheMightyMasterofMagicEffect() + { + if (PendulumActivate()) + { + return PendulumDefaultActivate() && BeforeResult(ExecutorType.Activate); + } + else if (Card.Location == CardLocation.MonsterZone) + { + if (Duel.LastChainPlayer == 0) return false; + AI.SelectCard(CardId.ServantofEndymion, CardId.TheMightyMasterofMagic); + return BeforeResult(ExecutorType.Activate); + } + else + { + return BeforeResult(ExecutorType.Activate); + } + } + private bool checkPActivate() + { + if (p_summoned) return false; + if (func.HasInZone(Bot, CardLocation.PendulumZone, CardId.Zefraath, true)) return true; + if (Bot.HasInHand(CardId.Zefraath) && (Bot.SpellZone[0] != null || Bot.SpellZone[4] != null)) return false; + if (Bot.SpellZone[0] == null && Bot.SpellZone[4] == null) + { + if (!Bot.HasInHand(CardId.Zefraath) && !func.CardsCheckAny(Bot.Hand, card => { + return IsSpsummonPMonster(card) && +(Card.LScale >= 5 ? card.LScale < 5 : card.LScale > 5) && func.GetPSpSummonMonster(Bot, card, Card)?.Count > 0; + })) return false; + } + else + { + if (func.GetPSpSummonMonster(Bot, Bot.SpellZone[0], Card)?.Count <= 0 && func.GetPSpSummonMonster(Bot, Bot.SpellZone[4], Card)?.Count <= 0) return false; + } + + return true; + } + private bool SecretoftheYangZingEffect() + { + if (PendulumActivate()) + { + return PendulumDefaultActivate() && BeforeResult(ExecutorType.Activate); + } + activate_SecretoftheYangZing = true; + return BeforeResult(ExecutorType.Activate); + } + private bool SatellarknightZefrathubanEffect() + { + + if (PendulumActivate()) + { + return PendulumDefaultActivate() && BeforeResult(ExecutorType.Activate); + } + return false; + } + private bool BorreloadSavageDragonEffect_2() + { + if (Duel.LastChainPlayer == 1) + { + ClientCard card = Util.GetLastChainCard(); + return card != null && !card.HasType(CardType.Continuous | CardType.Field) && card.HasType(CardType.Spell | CardType.Trap) && BeforeResult(ExecutorType.Activate); + } + return false; + } + private bool Zefraxi_TreasureoftheYangZingEffect() + { + if (PendulumActivate()) + { + return PendulumDefaultActivate() && BeforeResult(ExecutorType.Activate); + } + return BeforeResult(ExecutorType.Activate); + } + private bool OracleofZefraEffect() + { + activate_OracleofZefra = true; + return BeforeResult(ExecutorType.Activate); + + } + private bool FlameBeastoftheNekrozEffect() + { + if (PendulumActivate()) + { + return PendulumDefaultActivate() && BeforeResult(ExecutorType.Activate); + } + else + { + return BeforeResult(ExecutorType.Activate); + } + + } + private bool AstrographSorcererEffect() + { + if (PendulumActivate()) return false; + return BeforeResult(ExecutorType.Activate); + } + private bool StellarknightZefraxcitonEffect() + { + if (PendulumActivate()) + { + return PendulumDefaultActivate() && BeforeResult(ExecutorType.Activate); + } + else + { + return BeforeResult(ExecutorType.Activate); + } + } + private bool IsNoLinkCards(ClientCard card) + { + if (card == null) return false; + return ((card.IsCode(CardId.MythicalBeastJackalKing) || card.IsCode(CardId.TheMightyMasterofMagic)) && !card.IsDisabled()) + || card.IsCode(CardId.BorreloadSavageDragon) || card.IsCode(CardId.PSY_FramelordOmega) || card.IsCode(CardId.F_A_DawnDragster) + || card.IsCode(CardId.TruKingofAllCalamities) || card.IsCode(CardId.HeraldoftheArcLight) || card.LinkCount >= 3; + } + private bool LinkuribohSummon() + { + List materials = func.CardsCheckWhere(Func.GetZoneCards(Bot, CardLocation.MonsterZone, true), func.HasLevel, 1); + if (func.CardsCheckCount(materials, Func.NegateFunc(func.HasType), CardType.Tuner) <= 0 && + func.CardsCheckCount(materials, func.HasType, CardType.Tuner) <= 1) return false; + materials.Sort((cardA, cardB) => + { + if (cardA.HasType(CardType.Tuner) && !cardB.HasType(CardType.Tuner)) return 1; + if (!cardA.HasType(CardType.Tuner) && cardB.HasType(CardType.Tuner)) return -1; + return 0; + }); + AI.SelectMaterials(materials); + return true; + } + private bool SpellSet() + { + if (Card.HasType(CardType.Trap)) + { + AI.SelectPlace(Zones.z1 | Zones.z2 | Zones.z3 | Zones.z4 | Zones.z0); + return true; + } + return false; + } + private bool SpellSet_2() + { + if (Card.HasType(CardType.QuickPlay)) + { + AI.SelectPlace(Zones.z1 | Zones.z2 | Zones.z3 | Zones.z4 | Zones.z0); + return true; + } + return false; + } + private bool ShaddollZefracoreEffect() + { + if (PendulumActivate()) + { + return PendulumDefaultActivate() && BeforeResult(ExecutorType.Activate); + } + else + { + return BeforeResult(ExecutorType.Activate); + } + } + private bool PSY_FramelordOmegaEffect() + { + if (Card.Location == CardLocation.MonsterZone) + { + if (Duel.Player == 0) return BeforeResult(ExecutorType.Activate); + else + { + if (Bot.Banished.Count <= 0) return false; + AI.SelectCard(func.CardsIdToClientCards(new List { CardId.JetSynchron, CardId.DDLamia }, Bot.Banished)); + return BeforeResult(ExecutorType.Activate); + } + } + else + { + if (Bot.Graveyard.Count <= 0) return false; + AI.SelectCard(func.CardsIdToClientCards(new List { CardId.Zefraath, CardId.CrystronHalqifibrax, CardId.Denglong_FirstoftheYangZing, CardId.BorreloadSavageDragon, CardId.DDLamia }, Bot.Graveyard)); + return BeforeResult(ExecutorType.Activate); + } + } + private bool Psummon() + { + //if (ActivateDescription == P_SPSUMMON_DESC) + if (Card.Location == CardLocation.SpellZone) + { + p_summoning = true; + p_summoned = true; + return true; + } + return false; + } + private bool IsExtraZoneCard(ClientCard card) + { + if (card == null) return false; + ClientCard ex_card = Bot.MonsterZone[5]; + if (ex_card == card) return true; + ex_card = Bot.MonsterZone[6]; + if (ex_card == card) return true; + return false; + } + private bool HeavymetalfoesElectrumiteSummon() + { + if (Odd_EyesMeteorburstDragonCheck()) return false; + List materials = func.CardsCheckWhere(Func.GetZoneCards(Bot, CardLocation.MonsterZone, true), func.HasType, CardType.Pendulum); + if (materials.Count > 0) + { + materials.Sort((cardA, cardB) => + { + if ((cardA.Level == 3 || cardA.HasType(CardType.Tuner)) && cardB.Level != 3 && !cardB.HasType(CardType.Tuner)) return -1; + if (cardA.Level != 3 && !cardA.HasType(CardType.Tuner) && (cardB.Level == 3 || cardB.HasType(CardType.Tuner))) return 1; + return CardContainer.CompareCardLevel(cardA, cardB); + }); + materials.Reverse(); + List result = new List(); + foreach (var material in materials) + { + if (IsExtraZoneCard(material)) result.Insert(0, material); + else if (IsNoLinkCards(material) || (material.HasType(CardType.Tuner) && Bot.HasInExtra(CardId.CrystronHalqifibrax) + && func.CardsCheckCount(Func.GetZoneCards(Bot, CardLocation.MonsterZone, true), func.HasType, CardType.Tuner) <= 0)) continue; + else result.Add(material); + } + if (result.Count < 2) return false; + AI.SelectMaterials(result); + return BeforeResult(ExecutorType.Summon); + } + return false; + } + private bool SecretoftheYangZingCheck(ClientCard card) + { + if (card.IsCode(CardId.SecretoftheYangZing) && Bot.HasInHandOrInSpellZone(CardId.NinePillarsofYangZing)) + { + return func.CardsCheckCount(Func.GetZoneCards(Bot, CardLocation.Hand | CardLocation.PendulumZone | CardLocation.MonsterZone, true), p_card => { + return p_card.HasSetcode(0xc4) && p_card.HasType(CardType.Pendulum); + }) <= 0; + } + return true; + } + private bool F_A_DawnDragsterSummon() + { + List pre_materials = func.CardsCheckWhere(Func.GetZoneCards(Bot, CardLocation.MonsterZone, true), SecretoftheYangZingCheck); + var materials_lists = Util.GetSynchroMaterials(pre_materials, 7, 1, 1, false, true, null, card => { return !card.IsCode(CardId.MythicalBeastJackalKing) && !card.IsCode(CardId.HeraldoftheArcLight); }); + if (materials_lists.Count <= 0) return false; + foreach (var materials in materials_lists) + { + if (func.CardsCheckCount(materials, card => + { + return card.HasType(CardType.Tuner) && card.HasRace(CardRace.Machine); + }) <= 0) + { + AI.SelectMaterials(materials); + return BeforeResult(ExecutorType.Summon); + } + } + AI.SelectMaterials(materials_lists[0]); + return BeforeResult(ExecutorType.Summon); + } + private bool CrystronHalqifibraxEffect() + { + return BeforeResult(ExecutorType.Activate); + } + private bool MechaPhantomBeastAuroradonSummon() + { + if (Bot.GetMonstersInMainZone().Count >= 4 || (!HasInDeck(CardId.MechaPhantomBeastO_Lion) && !IsCanSPSummonTunerLevel1() + && !func.CardsCheckAny(Func.GetZoneCards(Bot, CardLocation.MonsterZone | CardLocation.Grave, true), func.IsCode, CardId.Deskbot001))) return false; + if (XyzModeCheck()) + { + List pre_materials = new List(); + List key_materials = func.CardsCheckWhere(Func.GetZoneCards(Bot, CardLocation.Grave), card => { + return (card.IsCode(CardId.DDLamia) && !activate_DDLamia && func.CardsCheckCount(Func.GetZoneCards(Bot, CardLocation.Onfield | CardLocation.Hand, true), scard => + { return Func.HasSetCode(scard, 0xaf, 0xae) && scard.Id != CardId.DDLamia; }) > 0); + }); + List key_materials_2 = func.CardsCheckWhere(Func.GetZoneCards(Bot, CardLocation.Grave), card => { return card.IsCode(CardId.JetSynchron) && !activate_JetSynchron; }); + pre_materials.AddRange(key_materials); + pre_materials.AddRange(key_materials_2); + if (!summoned) pre_materials.AddRange(func.CardsCheckWhere(Bot.Hand, card => { return !card.IsCode(CardId.DestrudotheLostDragon_Frisson) && card.Level < 5; })); + pre_materials.AddRange(Bot.MonsterZone); + var synchro_materials_lists = Util.GetSynchroMaterials(pre_materials, 7, 1, 1, false, true, null, card => { return !card.IsCode(CardId.MythicalBeastJackalKing); }); + var xyz_materials_lists = Util.GetXyzMaterials(Func.GetZoneCards(Bot, CardLocation.MonsterZone | CardLocation.PendulumZone), 7, 1, false, + card => { return !card.IsCode(CardId.F_A_DawnDragster) && !card.IsCode(CardId.TheMightyMasterofMagic); }); + var xyz_materials_lists_2 = Util.GetXyzMaterials(Func.GetZoneCards(Bot, CardLocation.MonsterZone), 7, 2, false, + card => { return !card.IsCode(CardId.F_A_DawnDragster) && !card.IsCode(CardId.TheMightyMasterofMagic); }); + if ((synchro_materials_lists.Count > 0 && xyz_materials_lists.Count > 0) || xyz_materials_lists_2.Count > 0) return false; + } + List m = new List(); + int link_count = 0; + List cards = Bot.GetMonsters(); + cards.Sort(CardContainer.CompareCardLink); + cards.Reverse(); + foreach (var card in Bot.GetMonsters()) + { + if (card == null) continue; + if (card.IsFacedown() || !card.HasRace(CardRace.Machine) || IsNoLinkCards(card)) continue; + m.Add(card); + link_count += (card.HasType(CardType.Link)) ? card.LinkCount : 1; + if (link_count >= 3) break; + } + if (link_count < 3) return false; + AI.SelectMaterials(m); + return true; + } + private bool SaryujaSkullDreadEffect() + { + if (ActivateDescription == Util.GetStringId(CardId.SaryujaSkullDread, 2)) + { + AI.SelectCard(GetSendToDeckIds()); + return BeforeResult(ExecutorType.Activate); + } + return BeforeResult(ExecutorType.Activate); + } + private bool SaryujaSkullDreadSummon() + { + if (Bot.GetMonstersInMainZone().Count < 4 || (!Bot.HasInExtra(CardId.CrystronHalqifibrax) && !xyz_mode)) return false; + List materials = new List(); + int link_count = 0; + int materials_count = 0; + int tuner_count = func.CardsCheckCount(Bot.MonsterZone, func.HasType, CardType.Tuner); + List temp_materials = Bot.GetMonsters(); + temp_materials.Sort((cardA, cardB) => + { + if ((cardA.HasType(CardType.Tuner) && cardB.HasType(CardType.Tuner)) + || (!cardA.HasType(CardType.Tuner) && !cardB.HasType(CardType.Tuner))) + { + return CardContainer.CompareCardLevel(cardA, cardB); + } + else if (cardA.HasType(CardType.Tuner) && !cardB.HasType(CardType.Tuner)) return 1; + return -1; + }); + foreach (var material in temp_materials) + { + ++materials_count; + if (IsExtraZoneCard(material)) materials.Insert(0, material); + else if (IsNoLinkCards(material)) { --materials_count; continue; } + else materials.Add(material); + link_count += material.HasType(CardType.Link) ? material.LinkCount : 1; + if (link_count >= 4) + { + if (materials_count == 3 && Bot.Deck.Count > 4 && ((func.CardsCheckCount(Bot.Hand, func.HasType, CardType.Tuner) > 0 + || (Bot.HasInMonstersZone(CardId.DDLamia, false, false, true) && !activate_DDLamia && func.CardsCheckCount(Func.GetZoneCards + (Bot, CardLocation.Onfield | CardLocation.Hand, true), card => { return Func.HasSetCode(card, 0xaf, 0xae) && card.Id != CardId.DDLamia; }) + > 0) || (Bot.HasInMonstersZone(CardId.JetSynchron, false, false, true) && !activate_JetSynchron)) || xyz_mode)) + { + --link_count; + continue; + } + break; + } + } + if (materials.Count < 3) return false; + AI.SelectMaterials(materials); + return BeforeResult(ExecutorType.Summon); + } + private bool CrystronHalqifibraxSummon() + { + List materials = new List(); + if (Bot.HasInExtra(CardId.MechaPhantomBeastAuroradon)) + { + materials.Add(Bot.MonsterZone[5]); + materials.Add(Bot.MonsterZone[6]); + } + List mainMonsters = Bot.GetMonstersInMainZone(); + mainMonsters.Sort(CardContainer.CompareCardAttack); + materials.AddRange(mainMonsters); + AI.SelectMaterials(materials); + if (materials.Distinct().Count() <= 3) + { + AI.SendCustomChat((int)CustomMessage.Surprise); + } + return true; + } + private bool PendulumActivate() + { + return Func.PendulumActivate(ActivateDescription, Card); + } + private bool IsActivateScale() + { + return func.IsActivateScale(Bot, Card); + } + private bool SpellActivate() + { + return Func.SpellActivate(Card); + } + private bool SupremeKingGateZeroEffect() + { + if (PendulumActivate()) return PendulumDefaultActivate() && BeforeResult(ExecutorType.Activate); + return false; + } + private bool MythicalBeastJackalKingEffect() + { + if (PendulumActivate()) return PendulumDefaultActivate() && BeforeResult(ExecutorType.Activate); + return BeforeResult(ExecutorType.Activate); + } + private bool Denglong_FirstoftheYangZingSummon_2() + { + if (xyz_mode) return Denglong_FirstoftheYangZingSummon(); + return false; + } + private bool Denglong_FirstoftheYangZingSummon() + { + var materials_lists = Util.GetSynchroMaterials(Bot.MonsterZone, 5, 1, 1, false, true, null, + card => { return !card.IsCode(CardId.HeraldoftheArcLight); }); + if (materials_lists.Count <= 0) return false; + AI.SelectMaterials(materials_lists[0]); + return BeforeResult(ExecutorType.Summon); + } + private bool Denglong_FirstoftheYangZingEffect() + { + if (ActivateDescription == Util.GetStringId(CardId.Denglong_FirstoftheYangZing, 1)) return false; + if (Card.Location == CardLocation.MonsterZone) + { + AI.SelectCard(CardId.NinePillarsofYangZing, CardId.SecretoftheYangZing, CardId.Zefraxi_TreasureoftheYangZing); + } + else + { + AI.SelectCard(CardId.SecretoftheYangZing, CardId.Zefraxi_TreasureoftheYangZing, CardId.LightoftheYangZing); + } + return true; + } + private bool DarkContractwiththGateEffect() + { + if (SpellActivate()) + { + return (HasInDeck(CardId.DDLamia) || func.HasInZone(Bot, CardLocation.PendulumZone, CardId.ServantofEndymion, true, true)) && BeforeResult(ExecutorType.Activate); + } + return BeforeResult(ExecutorType.Activate); + } + private int DisabledSort(ClientCard cardA, ClientCard cardB) + { + bool RitualBeastTamerZeframpilica_flag = !summoned && Bot.HasInExtra(CardId.HeraldoftheArcLight) && IsCanSPSummonTunerLevel1(); + if (((cardA.IsCode(CardId.RitualBeastTamerZeframpilica) && RitualBeastTamerZeframpilica_flag) || Func.IsCode(cardA, CardId.MaxxC, CardId.Zefraath, CardId.MythicalBeastJackalKing, CardId.TheMightyMasterofMagic) || cardA.HasType(CardType.Trap) || cardA.HasType(CardType.Tuner)) + && !cardB.IsCode(CardId.RitualBeastTamerZeframpilica) && !cardB.HasType(CardType.Trap) && !Func.IsCode(cardB, CardId.MaxxC, CardId.Zefraath, CardId.MythicalBeastJackalKing, CardId.TheMightyMasterofMagic) && !cardB.HasType(CardType.Tuner)) return 1; + else if (!cardA.IsCode(CardId.RitualBeastTamerZeframpilica) && !cardA.HasType(CardType.Trap) && !Func.IsCode(cardA, CardId.MaxxC, CardId.Zefraath, CardId.MythicalBeastJackalKing, CardId.TheMightyMasterofMagic) && !cardA.HasType(CardType.Tuner) + && ((cardB.IsCode(CardId.RitualBeastTamerZeframpilica) && RitualBeastTamerZeframpilica_flag) || Func.IsCode(cardB, CardId.MaxxC, CardId.Zefraath, CardId.MythicalBeastJackalKing, CardId.TheMightyMasterofMagic) || cardB.HasType(CardType.Trap) || cardB.HasType(CardType.Tuner))) return -1; + return 0; + } + private List GetDisabledIds() + { + List ids = new List(); + ids.Add(CardId.DestrudotheLostDragon_Frisson); + ids.Add(CardId.Blackwing_ZephyrostheElite); + ids.Add(CardId.Raider_Wing); + ids.Add(CardId.Raidraptor_SingingLanius); + ids.Add(CardId.PSY_FrameDriver); + if (!Bot.HasInGraveyard(CardId.Raidraptor_ArsenalFalcon) || !Bot.HasInExtra(CardId.TruKingofAllCalamities)) ids.Add(CardId.Rank_Up_MagicSoulShaveForce); + if (Bot.HasInBanished(CardId.PSY_FrameDriver)) ids.Add(CardId.PSY_FramegearGamma); + ids.Add(CardId.LightoftheYangZing); + ids.Add(CardId.DDLamia); + ids.AddRange(Func.GetCardsRepeatCardsId(Bot.Hand)); + List hands = Func.GetZoneCards(Bot, CardLocation.Hand); + hands.Sort(DisabledSort); + List hand_ids = Func.ClientCardsToCardsId(hands, true); + ids.AddRange(hand_ids); + return ids; + } + private List GetSendToDeckIds() + { + List ids = new List(); + List repeat_ids = Func.GetCardsRepeatCardsId(Func.GetZoneCards(Bot, CardLocation.Hand)); + ids.Add(CardId.MechaPhantomBeastO_Lion); + ids.AddRange(repeat_ids); + ids.Add(CardId.Raidraptor_SingingLanius); + ids.Add(CardId.Raider_Wing); + ids.Add(CardId.Blackwing_ZephyrostheElite); + ids.Add(CardId.PSY_FrameDriver); + ids.Add(CardId.LightoftheYangZing); + ids.Add(CardId.Rank_Up_MagicSoulShaveForce); + if (activate_ZefraProvidence) ids.Add(CardId.ZefraProvidence); + if (activate_OracleofZefra) ids.Add(CardId.OracleofZefra); + if (activate_DragonShrine) ids.Add(CardId.DragonShrine); + if (activate_SpellPowerMastery) ids.Add(CardId.SpellPowerMastery); + List hands = Func.GetZoneCards(Bot, CardLocation.Hand); + hands.Sort(DisabledSort); + List hand_ids = Func.ClientCardsToCardsId(hands, true); + ids.AddRange(hand_ids); + return ids; + } + private bool TruKingofAllCalamitiesEffect() + { + if (Duel.Player == 1) + { + AI.SelectAttributes(new CardAttribute[] { CardAttribute.Divine }); + return BeforeResult(ExecutorType.Activate); + } + return false; + } + private bool JetSynchronEffect() + { + + if (Card.Location == CardLocation.Grave) + { + if (!IsCanSynchroSummon(Card.Level)) return false; + if (func.CardsCheckAny(Func.GetZoneCards(Bot, CardLocation.Extra), card => { return card.HasType(CardType.Synchro) || Func.IsCode(card, CardId.CrystronHalqifibrax, CardId.Linkuriboh); })) + { + activate_JetSynchron = true; + List dcards = func.CardsIdToClientCards(GetDisabledIds(), Bot.Hand); + if (!Bot.HasInExtra(CardId.CrystronHalqifibrax) && dcards.Count <= 0) return false; + AI.SelectCard(dcards); + return BeforeResult(ExecutorType.Activate); + } + } + return false; + } + private bool MechaPhantomBeastAuroradonEffect() + { + if (ActivateDescription == -1) { link_summoned = true; return true; } + else + { + if (!HasInDeck(CardId.MechaPhantomBeastO_Lion) + && Func.GetZoneCards(Enemy, CardLocation.Onfield).Count <= 0) return false; + List tRelease = new List(); + List nRelease = new List(); + foreach (var card in Bot.GetMonsters()) + { + if (card == null || IsNoLinkCards(card)) continue; + if (card.Id == CardId.MechaPhantomBeastToken) tRelease.Add(card); else nRelease.Add(card); + } + int count = tRelease.Count() + nRelease.Count(); + opt_0 = false; + opt_1 = false; + opt_2 = false; + if (count >= 3 && func.CardsCheckCount(Bot.Graveyard, func.HasType, CardType.Trap) > 0) opt_2 = true; + if (count >= 2 && CheckRemainInDeck(CardId.MechaPhantomBeastO_Lion) > 0) opt_1 = true; + if (count >= 1 && Func.GetZoneCards(Enemy, CardLocation.Onfield).Count > 0) opt_0 = true; + if (!opt_0 && !opt_1 && !opt_2) return false; + return true; + } + } + private bool SupremeKingDragonDarkwurmEffect() + { + if (Card.Location == CardLocation.Grave) + { + activate_SupremeKingDragonDarkwurm_1 = true; + return BeforeResult(ExecutorType.Activate); + } + if (Card.Location == CardLocation.MonsterZone) + { + activate_SupremeKingDragonDarkwurm_2 = true; + return BeforeResult(ExecutorType.Activate); + } + return false; + } + private bool SupremeKingDragonDarkwurmSummon() + { + if ((!activate_p_Zefraath && Bot.HasInHand(CardId.Zefraath) && !activate_SupremeKingDragonDarkwurm_1 && HasInDeck(CardId.SupremeKingGateZero) && func.CardsCheckAny(Bot.Hand, func.HasType, CardType.Tuner)) + || (func.CardsCheckAny(Func.GetZoneCards(Bot, CardLocation.Hand), card => { return card.LinkCount > 5; }) && + !Bot.HasInHand(CardId.SupremeKingGateZero) && !activate_SupremeKingDragonDarkwurm_2)) + { + summoned = true; + return BeforeResult(ExecutorType.Summon); + } + return false; + } + private bool DefaultSummon_2() + { + if (Card.Location == CardLocation.Hand && Card.Level <= 4 + && Bot.HasInExtra(CardId.CrystronHalqifibrax) && (func.CardsCheckAny(Func.GetZoneCards(Bot, CardLocation.MonsterZone, true), card => { return Card.HasType(CardType.Tuner) ? true : card.HasType(CardType.Tuner); }))) + { + summoned = true; + return BeforeResult(ExecutorType.Summon); + } + return false; + } + private bool IsCanSPSummonTunerLevel1() + { + return func.CardsCheckAny(Func.GetZoneCards(Bot, CardLocation.MonsterZone | CardLocation.Grave, true), card => { + return (card.IsCode(CardId.DDLamia) && !activate_DDLamia && func.CardsCheckCount(Func.GetZoneCards(Bot, CardLocation.Onfield | CardLocation.Hand, true), scard => { return Func.HasSetCode(scard, 0xaf, 0xae) && scard.Id != CardId.DDLamia; }) + > 0) || (card.IsCode(CardId.JetSynchron) && !activate_JetSynchron) && Bot.GetMonstersInMainZone().Count <= 3; + }); + } + private bool DefaultSummon() + { + if (Card.Level > 4) return false; + if ((!link_summoned && Bot.HasInExtra(CardId.HeavymetalfoesElectrumite) && func.CardsCheckCount(Func.GetZoneCards(Bot, CardLocation.MonsterZone, true), func.HasType, CardType.Pendulum) > 0 + && Card.HasType(CardType.Pendulum)) + || (IsCanSPSummonTunerLevel1() && ((Card.Level == 3 && Bot.HasInExtra(CardId.HeraldoftheArcLight)) || ( + Card.Level == 4 && Bot.HasInExtra(CardId.Denglong_FirstoftheYangZing)))) || + (Card.Id == CardId.SupremeKingDragonDarkwurm && !activate_SupremeKingDragonDarkwurm_2) + || (Bot.HasInExtra(CardId.CrystronHalqifibrax) && Bot.HasInHandOrInGraveyard(CardId.DestrudotheLostDragon_Frisson) && !activate_DestrudotheLostDragon_Frisson)) + { + summoned = true; + return BeforeResult(ExecutorType.Summon); + } + return false; + } + private bool OneforOneEffect() + { + AI.SelectCard(GetDisabledIds()); + AI.SelectNextCard(CardId.JetSynchron, CardId.LightoftheYangZing, CardId.DDLamia); + return BeforeResult(ExecutorType.Activate); + } + private void HeavymetalfoesElectrumiteAddIds(List ids) + { + if (!summoned && HasInDeck(CardId.DarkContractwiththGate) && HasInDeck(CardId.DDLamia)) + { + if (!func.CardsCheckAny(Func.GetZoneCards(Bot, CardLocation.MonsterZone, true), func.HasType, CardType.Tuner)) + { + ids.Add(CardId.DDSavantKepler); + } + else + { + ids.Add(CardId.AstrographSorcerer); + ids.Add(CardId.DDSavantKepler); + } + } + ids.Add(CardId.AstrographSorcerer); + ids.Add(CardId.FlameBeastoftheNekroz); + ids.Add(CardId.DDSavantKepler); + } + private bool LinkuribohEffect() + { + if (Card.Location == CardLocation.Grave) + { + if (Duel.Player != 0) return BeforeResult(ExecutorType.Activate); + return false; + } + return BeforeResult(ExecutorType.Activate); + } + private bool Raider_WingEffect() + { + if (!Bot.HasInMonstersZone(CardId.Raidraptor_ForceStrix, false, true, true)) return false; + AI.SelectCard(CardId.Raidraptor_ForceStrix); + return BeforeResult(ExecutorType.Activate); + } + private bool HeavymetalfoesElectrumiteEffect() + { + if (ActivateDescription != -1) + { + List cards = func.CardsCheckWhere(Func.GetZoneCards(Bot, CardLocation.SpellZone, true), Func.NegateFunc(func.IsCode), CardId.DarkContractwiththGate); + if (cards.Count <= 0) + { + HeavymetalfoesElectrumite_activate = true; + return false; + } + HeavymetalfoesElectrumite_activate = false; + return BeforeResult(ExecutorType.Activate); + } + return BeforeResult(ExecutorType.Activate); + } + public override bool OnSelectHand() + { + return true; + } + private bool ResetFlag() + { + should_destory = false; + return true; + } + private bool HeraldoftheArcLightEffect() + { + if (Card.Location == CardLocation.MonsterZone) + { + return Duel.LastChainPlayer != 0 && BeforeResult(ExecutorType.Activate); + } + return false; + } + private bool CalledbytheGraveEffect() + { + if ((Bot.SpellZone[5] == Card || Bot.SpellZone[0] == Card) && Duel.Player == 0) return BeforeResult(ExecutorType.Activate); + ClientCard card = Util.GetLastChainCard(); + if (card == null) return false; + int id = card.Id; + List g_cards = func.CardsCheckWhere(Enemy.Graveyard, func.IsCode, id); + if (Duel.LastChainPlayer != 0) + { + if (card.Location == CardLocation.Grave && card.HasType(CardType.Monster)) + { + AI.SelectCard(card); + return BeforeResult(ExecutorType.Activate); + } + else if (g_cards.Count() > 0 && card.HasType(CardType.Monster)) + { + AI.SelectCard(g_cards); + return BeforeResult(ExecutorType.Activate); + } + } + return false; + } + public override CardPosition OnSelectPosition(int cardId, IList positions) + { + NamedCard card = NamedCard.Get(cardId); + if (cardId == CardId.F_A_DawnDragster && Duel.Turn > 1) return CardPosition.FaceUpAttack; + if (card.Attack <= 1000) return CardPosition.FaceUpDefence; + return base.OnSelectPosition(cardId, positions); + } + public override int OnSelectOption(IList options) + { + if (options.Contains(Util.GetStringId(CardId.MechaPhantomBeastAuroradon, 3))) + { + if (opt_1) return options.IndexOf(Util.GetStringId(CardId.MechaPhantomBeastAuroradon, 3)); + else if (opt_0) return 0; + return options[options.Count - 1]; + } + return base.OnSelectOption(options); + } + + public override int OnSelectPlace(int cardId, int player, CardLocation location, int available) + { + NamedCard card = NamedCard.Get(cardId); + if (player == 0) + { + if (location == CardLocation.SpellZone) + { + if (card.HasType(CardType.Pendulum)) + { + if ((available & Zones.z4) > 0) return Zones.z4; + if ((available & Zones.z0) > 0) return Zones.z0; + } + else + { + List keys = new List() { 1, 2, 3 }; + while (keys.Count > 0) + { + int index = Program.Rand.Next(keys.Count); + int key = keys[index]; + int zone = 1 << key; + if ((zone & available) > 0) return zone; + keys.Remove(key); + } + } + } + else if (location == CardLocation.MonsterZone) + { + if (card.HasType(CardType.Link)) + { + if ((available & Zones.z5) > 0) return Zones.z5; + if ((available & Zones.z6) > 0) return Zones.z6; + } + } + } + + return base.OnSelectPlace(cardId, player, location, available); + } + private IList _OnSelectPendulumSummon(IList cards, int min, int max) + { + List ids = func.GetSelectCardIdList(); + List result = func.GetSelectCardList(); + List exs = func.CardsCheckWhere(cards, func.IsLocation, CardLocation.Extra); + List hs = func.CardsCheckWhere(cards, Func.NegateFunc(func.IsLocation), CardLocation.Extra); + if (func.CardsCheckAny(Func.GetZoneCards(Bot, CardLocation.PendulumZone, true), card => { + return card.HasSetcode(0xc4) && !card.IsCode(CardId.Zefraath); + }) && func.CardsCheckAny(exs, func.IsCode, CardId.ShaddollZefracore)) ids.Add(CardId.ShaddollZefracore); + result = func.CardsIdToClientCards(ids, cards); + List temp_cards = func.CardsCheckWhere(cards, Func.NegateFunc(func.IsCode), CardId.MaxxC); + result.AddRange(temp_cards); + if (result.Count <= 0) return Func.CheckSelectCount(Util, result, cards, min, min); + if (result[0] != null && result[0].Location != CardLocation.Extra) ++p_count; + return Func.CheckSelectCount(Util, result, cards, max, max); + } + + public override IList OnSelectCard(IList cards, int min, int max, int hint, bool cancelable) + { + if (AI.HaveSelectedCards()) return null; + List ids = func.GetSelectCardIdList(); + List result = func.GetSelectCardList(); + if (hint == HintMsg.AddToHand) + { + if (func.CardsCheckAny(cards, card => { return card.Location == CardLocation.Deck && card.HasSetcode(0xc4); })) + { + if (!activate_ZefraProvidence) ids.Add(CardId.ZefraProvidence); + if (p_summoned) + { + if (!summoned && Bot.HasInExtra(CardId.HeavymetalfoesElectrumite) && func.CardsCheckCount(Func.GetZoneCards(Bot, CardLocation.MonsterZone, true), func.HasType, CardType.Pendulum) == 1) + { + List pre_ids = new List {CardId.Zefraxi_TreasureoftheYangZing,CardId.StellarknightZefraxciton,CardId.RitualBeastTamerZeframpilica,CardId.NinePillarsofYangZing + ,CardId.StellarknightZefraxciton,CardId.ShaddollZefracore}; + ids.AddRange(pre_ids); + } + ids.Add(CardId.ZefraDivineStrike); + } + if (!activate_OracleofZefra) ids.Add(CardId.OracleofZefra); + if (!activate_p_Zefraath && !func.HasInZone(Bot, CardLocation.Hand | CardLocation.PendulumZone, CardId.Zefraath, true)) ids.Add(CardId.Zefraath); + if (func.HasInZone(Bot, CardLocation.Hand | CardLocation.PendulumZone, CardId.SupremeKingGateZero, true) && !func.CardsCheckAny(Bot.Hand, func.HasType, CardType.Tuner) + && !Bot.HasInHand(CardId.Zefraxi_TreasureoftheYangZing)) ids.Add(CardId.Zefraxi_TreasureoftheYangZing); + List pMonsters = func.CardsCheckWhere(Func.GetZoneCards(Bot, CardLocation.Hand), card => + { + return card.HasType(CardType.Pendulum) && !card.IsCode(CardId.Zefraath); + }); + if (pMonsters.Count > 0) + { + List zefraPMonsters = func.CardsCheckWhere(pMonsters, func.HasSetCode, 0xc4); + if (zefraPMonsters.Count > 0) + { + zefraPMonsters.Sort(Func.CompareCardScale); + int minScale = zefraPMonsters[0].RScale; + if (Bot.HasInHand(CardId.Zefraath)) + { + if (minScale < 5) + { + if (func.CardsCheckCount(cards, IsZefraScaleAbove) > 1) + { + ids.Add(CardId.ShaddollZefracore); + if (!Bot.HasInHand(CardId.Zefraxi_TreasureoftheYangZing)) ids.Add(CardId.Zefraxi_TreasureoftheYangZing); + ids.Add(CardId.SecretoftheYangZing); + ids.Add(CardId.FlameBeastoftheNekroz); + ids.Add(CardId.StellarknightZefraxciton); + ids.Add(CardId.SatellarknightZefrathuban); + ids.Add(CardId.RitualBeastTamerZeframpilica); + } + else + { + ids.Add(CardId.Zefraxi_TreasureoftheYangZing); + ids.Add(CardId.RitualBeastTamerZeframpilica); + ids.Add(CardId.SatellarknightZefrathuban); + } + } + else + { + if (func.CardsCheckCount(cards, IsZefraScaleBelow) > 1) + { + ids.Add(CardId.ShaddollZefracore); + if (!Bot.HasInHand(CardId.Zefraxi_TreasureoftheYangZing)) ids.Add(CardId.Zefraxi_TreasureoftheYangZing); + ids.Add(CardId.SecretoftheYangZing); + ids.Add(CardId.FlameBeastoftheNekroz); + ids.Add(CardId.StellarknightZefraxciton); + ids.Add(CardId.SatellarknightZefrathuban); + ids.Add(CardId.RitualBeastTamerZeframpilica); + } + else + { + ids.Add(CardId.StellarknightZefraxciton); + ids.Add(CardId.SecretoftheYangZing); + ids.Add(CardId.FlameBeastoftheNekroz); + ids.Add(CardId.ShaddollZefracore); + } + } + } + else + { + if (Bot.HasInGraveyard(CardId.FlameBeastoftheNekroz)) ids.Add(CardId.RitualBeastTamerZeframpilica); + ids.Add(CardId.SecretoftheYangZing); + ids.Add(CardId.Zefraxi_TreasureoftheYangZing); + } + } + else + { + ids.Add(CardId.SecretoftheYangZing); + ids.Add(CardId.FlameBeastoftheNekroz); + ids.Add(CardId.StellarknightZefraxciton); + ids.Add(CardId.SatellarknightZefrathuban); + ids.Add(CardId.RitualBeastTamerZeframpilica); + ids.Add(CardId.Zefraxi_TreasureoftheYangZing); + } + } + else + { + if (func.HasInZone(Bot, CardLocation.Hand | CardLocation.PendulumZone, CardId.Zefraath, true) && + !activate_p_Zefraath) + { + ids.Add(CardId.Zefraxi_TreasureoftheYangZing); + ids.Add(CardId.SatellarknightZefrathuban); + ids.Add(CardId.RitualBeastTamerZeframpilica); + } + ids.Add(CardId.SecretoftheYangZing); + ids.Add(CardId.FlameBeastoftheNekroz); + ids.Add(CardId.StellarknightZefraxciton); + ids.Add(CardId.SatellarknightZefrathuban); + ids.Add(CardId.RitualBeastTamerZeframpilica); + ids.Add(CardId.Zefraxi_TreasureoftheYangZing); + } + result = func.CardsIdToClientCards(ids, cards); + } + else if (func.CardsCheckALL(cards, func.IsLocation, true, CardLocation.Extra)) + { + HeavymetalfoesElectrumiteAddIds(ids); + result = func.CardsIdToClientCards(ids, cards); + } + else if (func.CardsCheckALL(cards, func.HasSetCode, true, 0x12a)) + { + if (!func.HasInZone(Bot, CardLocation.PendulumZone | CardLocation.Hand, CardId.ServantofEndymion, true) || + (func.HasInZone(Bot, CardLocation.PendulumZone | CardLocation.Hand, CardId.ServantofEndymion, true) && (!HasInDeck(CardId.TheMightyMasterofMagic) || !HasInDeck(CardId.MythicalBeastJackalKing)))) ids.Add(CardId.ServantofEndymion); + ids.Add(CardId.TheMightyMasterofMagic); + ids.Add(CardId.MythicalBeastJackalKing); + result = func.CardsIdToClientCards(ids, cards); + } + else if (func.CardsCheckALL(cards, func.HasSetCode, true, 0xaf)) + { + ids.Add(CardId.DDLamia); + ids.Add(CardId.DDSavantKepler); + result = func.CardsIdToClientCards(ids, cards); + } + } + else if (hint == HintMsg.ToDeck && func.CardsCheckALL(cards, func.IsLocation, true, CardLocation.Hand) && min == 3 && max == 3) + { + result = func.CardsIdToClientCards(GetSendToDeckIds(), cards); + } + else if (hint == HintMsg.ToGrave && func.CardsCheckALL(cards, func.IsLocation, true, CardLocation.Deck)) + { + List extra_ids = CheckShouldSpsummonExtraMonster(); + //if (func.CardsCheckAny(cards, Func.HasRace, CardRace.Dragon)) + if (extra_ids.Count <= 0) + { + if (!activate_SupremeKingDragonDarkwurm_2 && Bot.GetMonsterCount() <= 0) ids.Add(CardId.SupremeKingDragonDarkwurm); + if (!activate_DestrudotheLostDragon_Frisson) ids.Add(CardId.DestrudotheLostDragon_Frisson); + if (!activate_JetSynchron) ids.Add(CardId.JetSynchron); + ids.Add(CardId.FlameBeastoftheNekroz); + } + else if (extra_ids.Count > 1) + { + if (Bot.GetMonsterCount() <= 0 && !activate_SupremeKingDragonDarkwurm_2) ids.Add(CardId.SupremeKingDragonDarkwurm); + if (func.CardsCheckAny(Bot.Hand, card => { return card.Level < 7 && card.HasType(CardType.Monster); })) ids.Add(CardId.DestrudotheLostDragon_Frisson); + if (Bot.GetHandCount() > 0) ids.Add(CardId.JetSynchron); + if (!summoned && Bot.HasInHand(CardId.RitualBeastTamerZeframpilica)) ids.Add(CardId.FlameBeastoftheNekroz); + ids.Add(CardId.DestrudotheLostDragon_Frisson); + ids.Add(CardId.JetSynchron); + ids.Add(CardId.SupremeKingDragonDarkwurm); + ids.Add(CardId.FlameBeastoftheNekroz); + } + else if (extra_ids.Contains(CardId.HeavymetalfoesElectrumite)) + { + if (Bot.GetMonsterCount() <= 0 && !activate_SupremeKingDragonDarkwurm_2) ids.Add(CardId.SupremeKingDragonDarkwurm); + if (!summoned && Bot.HasInHand(CardId.RitualBeastTamerZeframpilica)) ids.Add(CardId.FlameBeastoftheNekroz); + //if (!summoned && func.CardsCheckAny(Bot.Hand, card => { return card.Level < 7 && card.HasType(CardType.Monster); })) ids.Add(CardId.DestrudotheLostDragon_Frisson); + //if (Bot.GetHandCount() > 0) ids.Add(CardId.JetSynchron); + ids.Add(CardId.DestrudotheLostDragon_Frisson); + ids.Add(CardId.JetSynchron); + ids.Add(CardId.SupremeKingDragonDarkwurm); + ids.Add(CardId.FlameBeastoftheNekroz); + } + else if (extra_ids.Contains(CardId.CrystronHalqifibrax)) + { + if (func.CardsCheckAny(Func.GetZoneCards(Bot, CardLocation.Hand | CardLocation.MonsterZone, true), func.HasType, CardType.Tuner)) + { + if (Bot.GetMonsterCount() <= 0 && !activate_SupremeKingDragonDarkwurm_2) ids.Add(CardId.SupremeKingDragonDarkwurm); + ids.Add(CardId.DestrudotheLostDragon_Frisson); + ids.Add(CardId.JetSynchron); + ids.Add(CardId.SupremeKingDragonDarkwurm); + ids.Add(CardId.FlameBeastoftheNekroz); + } + else + { + ids.Add(CardId.DestrudotheLostDragon_Frisson); + ids.Add(CardId.JetSynchron); + ids.Add(CardId.SupremeKingDragonDarkwurm); + ids.Add(CardId.FlameBeastoftheNekroz); + + } + } + result = func.CardsIdToClientCards(ids, cards); + } + else if (hint == Util.GetStringId(CardId.Zefraath, 1)) + { + int[] pScales = Func.GetPScales(Bot); + int rScale = pScales[0]; + int lScale = pScales[1]; + int pScale = (rScale != 5) ? rScale : lScale; + if (pScale < 5) + { + if (!activate_SecretoftheYangZing && !func.CardsCheckAny(Func.GetZoneCards(Bot, CardLocation.Hand | CardLocation.Extra, true), func.IsCode, CardId.SecretoftheYangZing)) ids.Add(CardId.SecretoftheYangZing); + if (!activate_ShaddollZefracore && func.CardsCheckAny(Func.GetZoneCards(Bot, CardLocation.PendulumZone, true), card => { return !card.IsCode(CardId.Zefraath) && card.HasSetcode(0xc4); })) ids.Add(CardId.ShaddollZefracore); + ids.Add(CardId.StellarknightZefraxciton); + ids.Add(CardId.SecretoftheYangZing); + ids.Add(CardId.ShaddollZefracore); + } + else + { + ids.Add(CardId.Zefraxi_TreasureoftheYangZing); + ids.Add(CardId.SatellarknightZefrathuban); + ids.Add(CardId.RitualBeastTamerZeframpilica); + } + result = func.CardsIdToClientCards(ids, cards); + } + else if (hint == Util.GetStringId(CardId.HeavymetalfoesElectrumite, 3)) + { + HeavymetalfoesElectrumiteAddIds(ids); + result = func.CardsIdToClientCards(ids, cards); + } + else if (!(IS_YGOPRO & !(hint == HintMsg.SpSummon)) && func.CardsCheckALL(cards, card => { + return card.IsCode(CardId.TheMightyMasterofMagic) || card.IsCode(CardId.MythicalBeastJackalKing); + }, true)) + { + ids.Add(CardId.MythicalBeastJackalKing); + ids.Add(CardId.TheMightyMasterofMagic); + result = func.CardsIdToClientCards(ids, cards); + } + else if (p_summoning || ((Card == Bot.SpellZone[0] || Card == Bot.SpellZone[4]) && hint == HintMsg.SpSummon && + Card.HasType(CardType.Pendulum))) + { + p_summoning = false; + if (p_count >= 3 && !Bot.HasInExtra(CardId.SaryujaSkullDread) && Bot.HasInExtra(CardId.MechaPhantomBeastAuroradon)) return Func.CheckSelectCount(Util, result, cards, min, min); + return _OnSelectPendulumSummon(cards, min, max); + } + else if (hint == HintMsg.Destroy) + { + if (func.CardsCheckALL(cards, card => { return card.Controller == 0 && card.IsFaceup(); }, true)) + { + should_destory = true; + if (func.CardsCheckALL(cards, func.HasSetCode, true, 0x9e)) + { + if (!activate_SecretoftheYangZing) result = func.CardsIdToClientCards(new List { CardId.SecretoftheYangZing }, func.CardsCheckWhere(cards, + func.IsLocation, CardLocation.MonsterZone)); + result.AddRange(func.CardsIdToClientCards(new List { CardId.SecretoftheYangZing, CardId.Zefraxi_TreasureoftheYangZing }, func.CardsCheckWhere(cards, + Func.NegateFunc(func.IsLocation), CardLocation.MonsterZone))); + } + else + { + List scards = func.CardsCheckWhere(cards, card => { return card.Location == CardLocation.SpellZone; }); + scards.Sort((cardA, cardB) => + { + if (Func.IsCode(cardA, CardId.OracleofZefra, CardId.DarkContractwiththGate) && !Func.IsCode(cardB, CardId.OracleofZefra, CardId.DarkContractwiththGate)) return 1; + if (!Func.IsCode(cardA, CardId.OracleofZefra, CardId.DarkContractwiththGate) && Func.IsCode(cardB, CardId.OracleofZefra, CardId.DarkContractwiththGate)) return -1; + return 0; + }); + result.AddRange(scards); + } + + } + else if (func.CardsCheckAny(cards, card => { return card.Controller == 1 && (card.Location & CardLocation.Onfield) > 0; }) && min == 1 && max == 1) + { + ClientCard card = Util.GetBestEnemyCard(); + if (card != null && cards.Contains(card)) result.Add(card); + else + { + result = new List(func.CardsCheckWhere(cards, ecard => { return ecard.Controller == 1; })); + if (result.Count <= 0) return null; + result.Sort(CardContainer.CompareCardAttack); + result.Reverse(); + } + } + } + else if (hint == HintMsg.SpSummon) + { + List tuner_ids = new List() + { + CardId.DestrudotheLostDragon_Frisson, CardId.PSY_FrameDriver, CardId.JetSynchron, CardId.PSY_FramegearGamma,CardId.LightoftheYangZing + }; + List no_tuner_ids = new List() + { + CardId.TheMightyMasterofMagic, CardId.MythicalBeastJackalKing, CardId.SecretoftheYangZing + }; + if (func.CardsCheckALL(cards, func.IsLocation, true, CardLocation.Hand)) + { + if (summoned && Bot.HasInExtra(CardId.CrystronHalqifibrax) && func.CardsCheckCount(Bot.MonsterZone, card => { + return card.IsFaceup() && card.HasType(CardType.Tuner); + }) <= 0 && !(Bot.HasInGraveyard(CardId.DDLamia) && !activate_DDLamia + && func.CardsCheckCount(Func.GetZoneCards(Bot, CardLocation.Onfield | CardLocation.Hand, true), card => { return Func.HasSetCode(card, 0xaf, 0xae) && card.Id != CardId.DDLamia; }) + <= 0) && !(Bot.HasInGraveyard(CardId.JetSynchron) && !activate_JetSynchron) + && !(Bot.HasInGraveyard(CardId.DestrudotheLostDragon_Frisson) && !activate_DestrudotheLostDragon_Frisson)) + { + ids.AddRange(tuner_ids); + ids.AddRange(no_tuner_ids); + } + else + { + ids.AddRange(no_tuner_ids); + ids.AddRange(tuner_ids); + } + result = func.CardsIdToClientCards(ids, cards); + } + else if (func.CardsCheckALL(cards, card => { + return Func.IsCode(card, CardId.LightoftheYangZing, CardId.PSY_FramegearGamma, + CardId.MechaPhantomBeastO_Lion, CardId.JetSynchron, CardId.Deskbot001, CardId.DDLamia); + })) + { + if (Bot.GetMonstersInMainZone().Count <= 1) ids.Add(CardId.Deskbot001); + ids.Add(CardId.JetSynchron); + ids.Add(CardId.Deskbot001); + ids.Add(CardId.LightoftheYangZing); + ids.Add(CardId.PSY_FramegearGamma); + result = func.CardsIdToClientCards(ids, cards); + } + + } + else if (hint == HintMsg.Release && func.CardsCheckAny(cards, func.IsLocation, CardLocation.MonsterZone)) + { + List tRelease = new List(); + List nRelease = new List(); + foreach (var card in cards) + { + if (card == null || IsNoLinkCards(card)) continue; + if (card.Id == CardId.MechaPhantomBeastToken) tRelease.Add(card); + else if (card.Id == CardId.Raidraptor_WiseStrix) tRelease.Insert(0, card); + else nRelease.Add(card); + } + result.AddRange(tRelease); + result.AddRange(nRelease); + } + return Func.CheckSelectCount(Util, result, cards, min, max); + } + private bool HasInDeck(int id) + { + return CheckRemainInDeck(id) > 0; + } + private int CheckRemainInDeck(int id) + { + switch (id) + { + case CardId.PSY_FrameDriver: + return Bot.GetRemainingCount(CardId.PSY_FrameDriver, 1); + case CardId.Zefraath: + return Bot.GetRemainingCount(CardId.Zefraath, 3); + case CardId.TheMightyMasterofMagic: + return Bot.GetRemainingCount(CardId.TheMightyMasterofMagic, 1); + case CardId.AstrographSorcerer: + return Bot.GetRemainingCount(CardId.AstrographSorcerer, 1); + case CardId.DestrudotheLostDragon_Frisson: + return Bot.GetRemainingCount(CardId.DestrudotheLostDragon_Frisson, 1); + case CardId.SupremeKingGateZero: + return Bot.GetRemainingCount(CardId.SupremeKingGateZero, 2); + case CardId.MythicalBeastJackalKing: + return Bot.GetRemainingCount(CardId.MythicalBeastJackalKing, 1); + case CardId.SecretoftheYangZing: + return Bot.GetRemainingCount(CardId.SecretoftheYangZing, 3); + case CardId.FlameBeastoftheNekroz: + return Bot.GetRemainingCount(CardId.FlameBeastoftheNekroz, 1); + case CardId.StellarknightZefraxciton: + return Bot.GetRemainingCount(CardId.StellarknightZefraxciton, 1); + case CardId.SupremeKingDragonDarkwurm: + return Bot.GetRemainingCount(CardId.SupremeKingDragonDarkwurm, 1); + case CardId.Blackwing_ZephyrostheElite: + return Bot.GetRemainingCount(CardId.Blackwing_ZephyrostheElite, 1); + case CardId.ShaddollZefracore: + return Bot.GetRemainingCount(CardId.ShaddollZefracore, 1); + case CardId.Raidraptor_SingingLanius: + return Bot.GetRemainingCount(CardId.Raidraptor_SingingLanius, 1); + case CardId.SatellarknightZefrathuban: + return Bot.GetRemainingCount(CardId.SatellarknightZefrathuban, 1); + case CardId.Raider_Wing: + return Bot.GetRemainingCount(CardId.Raider_Wing, 1); + case CardId.Zefraxi_TreasureoftheYangZing: + return Bot.GetRemainingCount(CardId.Zefraxi_TreasureoftheYangZing, 2); + case CardId.RitualBeastTamerZeframpilica: + return Bot.GetRemainingCount(CardId.RitualBeastTamerZeframpilica, 1); + case CardId.ServantofEndymion: + return Bot.GetRemainingCount(CardId.ServantofEndymion, 3); + case CardId.PSY_FramegearGamma: + return Bot.GetRemainingCount(CardId.PSY_FramegearGamma, 3); + case CardId.MechaPhantomBeastO_Lion: + return Bot.GetRemainingCount(CardId.MechaPhantomBeastO_Lion, 1); + case CardId.MaxxC: + return Bot.GetRemainingCount(CardId.MaxxC, 3); + case CardId.Deskbot001: + return Bot.GetRemainingCount(CardId.Deskbot001, 1); + case CardId.JetSynchron: + return Bot.GetRemainingCount(CardId.JetSynchron, 1); + case CardId.DDLamia: + return Bot.GetRemainingCount(CardId.DDLamia, 1); + case CardId.DDSavantKepler: + return Bot.GetRemainingCount(CardId.DDSavantKepler, 1); + case CardId.LightoftheYangZing: + return Bot.GetRemainingCount(CardId.LightoftheYangZing, 1); + case CardId.Rank_Up_MagicSoulShaveForce: + return Bot.GetRemainingCount(CardId.Rank_Up_MagicSoulShaveForce, 1); + case CardId.SpellPowerMastery: + return Bot.GetRemainingCount(CardId.SpellPowerMastery, 3); + case CardId.DragonShrine: + return Bot.GetRemainingCount(CardId.DragonShrine, 3); + case CardId.Terraforming: + return Bot.GetRemainingCount(CardId.Terraforming, 1); + case CardId.ZefraProvidence: + return Bot.GetRemainingCount(CardId.ZefraProvidence, 3); + case CardId.FoolishBurial: + return Bot.GetRemainingCount(CardId.FoolishBurial, 1); + case CardId.CalledbytheGrave: + return Bot.GetRemainingCount(CardId.CalledbytheGrave, 2); + case CardId.DarkContractwiththGate: + return Bot.GetRemainingCount(CardId.DarkContractwiththGate, 1); + case CardId.OracleofZefra: + return Bot.GetRemainingCount(CardId.OracleofZefra, 3); + case CardId.ZefraWar: + return Bot.GetRemainingCount(CardId.ZefraWar, 1); + case CardId.ZefraDivineStrike: + return Bot.GetRemainingCount(CardId.ZefraDivineStrike, 1); + case CardId.NinePillarsofYangZing: + return Bot.GetRemainingCount(CardId.NinePillarsofYangZing, 1); + default: + return 0; + } + } + } +} diff --git a/libWindbot/Game/AI/DefaultExecutor.cs b/libWindbot/Game/AI/DefaultExecutor.cs index 0f72f09..30c20fd 100644 --- a/libWindbot/Game/AI/DefaultExecutor.cs +++ b/libWindbot/Game/AI/DefaultExecutor.cs @@ -121,12 +121,18 @@ protected class _CardId public const int RoyalDecreel = 51452091; public const int NaturiaBeast = 33198837; public const int AntiSpellFragrance = 58921041; + + public const int VaylantzWorld_ShinraBansho = 49568943; + public const int VaylantzWorld_KonigWissen = 75952542; + public const int DivineArsenalAAZEUS_SkyThunder = 90448279; } protected DefaultExecutor(GameAI ai, Duel duel) : base(ai, duel) { AddExecutor(ExecutorType.Activate, _CardId.ChickenGame, DefaultChickenGame); + AddExecutor(ExecutorType.Activate, _CardId.VaylantzWorld_ShinraBansho, DefaultVaylantzWorld_ShinraBansho); + AddExecutor(ExecutorType.Activate, _CardId.VaylantzWorld_KonigWissen, DefaultVaylantzWorld_KonigWissen); AddExecutor(ExecutorType.Activate, _CardId.SantaClaws); } @@ -313,6 +319,40 @@ public override bool OnSelectMonsterSummonOrSet(ClientCard card) return card.Level <= 4 && Bot.GetMonsters().Count(m => m.IsFaceup()) == 0 && Util.IsAllEnemyBetterThanValue(card.Attack, true); } + /// + /// Called when the AI has to select one or more cards. + /// + /// List of available cards. + /// Minimal quantity. + /// Maximal quantity. + /// The hint message of the select. + /// True if you can return an empty list. + /// A new list containing the selected cards. + public override IList OnSelectCard(IList cards, int min, int max, int hint, bool cancelable) + { + // wordaround for Dogmatika Alba Zoa + int albaZoaCount = Bot.ExtraDeck.Count / 2; + if (!cancelable && min == albaZoaCount && max == albaZoaCount + && Duel.Player == 1 && (Duel.Phase == DuelPhase.Main1 || Duel.Phase == DuelPhase.Main2) && cards.All(card => + card.Controller == 0 && (card.Location == CardLocation.Hand || card.Location == CardLocation.Extra))) + { + Logger.DebugWriteLine("Dogmatika Alba Zoa solved"); + List extraDeck = new List(Bot.ExtraDeck); + int shuffleCount = extraDeck.Count; + while (shuffleCount-- > 1) + { + int index = Program.Rand.Next(extraDeck.Count); + ClientCard tempCard = extraDeck[shuffleCount]; + extraDeck[shuffleCount] = extraDeck[index]; + extraDeck[index] = tempCard; + } + + return Util.CheckSelectCount(extraDeck, cards, min, max); + } + + return null; + } + /// /// Destroy face-down cards first, in our turn. /// @@ -793,7 +833,8 @@ protected bool DefaultOnBecomeTarget() _CardId.BlackRoseDragon, _CardId.JudgmentDragon, _CardId.TopologicTrisbaena, - _CardId.EvenlyMatched + _CardId.EvenlyMatched, + _CardId.DivineArsenalAAZEUS_SkyThunder }; int[] destroyAllOpponentSpellList = { @@ -1182,5 +1223,55 @@ protected bool DefaultHonestEffect() return Util.IsTurn1OrMain2(); } + + /// + /// Always activate + /// + protected bool DefaultVaylantzWorld_ShinraBansho() + { + if (DefaultSpellWillBeNegated()) { + return false; + } + + return true; + } + + /// + /// Select enemy's best monster + /// + protected bool DefaultVaylantzWorld_KonigWissen() + { + if (DefaultSpellWillBeNegated()) { + return false; + } + + List monsters = Enemy.GetMonsters(); + if (monsters.Count == 0) { + return false; + } + + List targetList = new List(); + List floodgateCards = monsters + .Where(card => card?.Data != null && card.IsFloodgate() && card.IsFaceup() && !card.IsShouldNotBeTarget()) + .OrderBy(card => card.Attack).ToList(); + List dangerousCards = monsters + .Where(card => card?.Data != null && card.IsMonsterDangerous() && card.IsFaceup() && !card.IsShouldNotBeTarget()) + .OrderBy(card => card.Attack).ToList(); + List attackOrderedCards = monsters + .Where(card => card?.Data != null && card.HasType(CardType.Monster) && card.IsFaceup() && card.IsShouldNotBeTarget()) + .OrderBy(card => card.Attack).ToList(); + + targetList.AddRange(floodgateCards); + targetList.AddRange(dangerousCards); + targetList.AddRange(attackOrderedCards); + + if (targetList?.Count > 0) + { + AI.SelectCard(targetList); + return true; + } + + return false; + } } } diff --git a/libWindbot/Game/AI/Dialogs.cs b/libWindbot/Game/AI/Dialogs.cs index 478783e..0083564 100644 --- a/libWindbot/Game/AI/Dialogs.cs +++ b/libWindbot/Game/AI/Dialogs.cs @@ -34,7 +34,9 @@ public class DialogsData [DataMember] public string[] setmonster { get; set; } [DataMember] - public string[] chaining { get; set; } + public string[] chaining { get; set; } + [DataMember] + public string[] custom { get; set; } } public class Dialogs { @@ -53,7 +55,8 @@ public class Dialogs private string[] _summon; private string[] _setmonster; private string[] _chaining; - + private string[] _custom; + public Dialogs(GameClient game) { _game = game; @@ -75,6 +78,7 @@ public Dialogs(GameClient game) _summon = data.summon; _setmonster = data.setmonster; _chaining = data.chaining; + _custom = data.custom; } } @@ -173,5 +177,14 @@ private void InternalSendMessageForced(IList array, params object[] opts if (message != "") _game.Chat(message); } + + public void SendCustomChat(int index, params object[] opts) + { + if (!_game._chat || _custom == null) + return; + string message = string.Format(_custom[index], opts); + if (message != "") + _game.Chat(message); + } } } diff --git a/libWindbot/Game/AI/Enums/DangerousMonster.cs b/libWindbot/Game/AI/Enums/DangerousMonster.cs index 6627653..fe956dd 100644 --- a/libWindbot/Game/AI/Enums/DangerousMonster.cs +++ b/libWindbot/Game/AI/Enums/DangerousMonster.cs @@ -24,5 +24,7 @@ public enum DangerousMonster ZushintheSleepingGiant = 67547370, Heart_eartHDragon = 97403510, DaigustoSphreeze = 29552709, + OhimetheManifestedMikanko = 81260679, + ArahimetheManifestedMikanko = 75771170 } } diff --git a/libWindbot/Game/AI/Enums/Floodgate.cs b/libWindbot/Game/AI/Enums/Floodgate.cs index 9141c50..e740408 100644 --- a/libWindbot/Game/AI/Enums/Floodgate.cs +++ b/libWindbot/Game/AI/Enums/Floodgate.cs @@ -106,6 +106,110 @@ public enum Floodgate AdamancipatorRisenDragite = 9464441, TeardroptheRikkaQueen = 33779875, CeruleanSkyFire = 54828837, - SacredBeastAwakening = 53701259 + SacredBeastAwakening = 53701259, + GrandSpiritualArtIchirin = 38057522, + DualAvatarFeetArmoredUnGyo = 7631534, + VirtualWorldKyubiShenshen = 92519087, + VirtualWorldGateChuche = 13364097, + DragunityKnightAreadbhair = 88234821, + AiwasstheMagistusSpellSpirit = 35877582, + OneirostheDreamMirrorErlking = 35187185, + PlunderPatrollshipBrann = 94253655, + PlunderPatrollshipMoerk = 20248754, + PlunderPatrollshipLys = 18832779, + HollowGiants = 15462014, + GrozaTyrantofThunder = 45420955, + SpringansCaptainSargas = 29601381, + S_ForceOrrafist = 95974848, + AncientWarriors_RebelliousLuFeng = 82791472, + OneirostheDreamMirrorTormentor = 37678339, + SacredTreeBeastHyperyton = 9349094, + S_ForceJustify = 35334193, + UnderworldGoddessoftheClosedWorld = 98127546, + VampireVoivode = 4918855, + NekrozofAreadbhair = 39468724, + NekrozofUnicore = 89463537, + BenghalancertheResurgent = 73345237, + UrsarcticSeptentrion = 53087962, + TheIrisSwordsoul = 62849088, + AntihumanIntelligenceME_PSY_YA = 58844135, + MagikeyMechmortar_Garesglasser = 45877457, + ShootingMajesticStarDragon = 40939228, + StellarWindWolfrayet = 3322931, + ChronomalyVimana = 2609443, + CyberdarknessDragon = 18967507, + ClearWingSynchroDragon = 82044279, + CrystalClearWingSynchroDragon = 59765225, + BaronnedeFleur = 84815190, + Lyrilusc_EnsemblueRobin = 72971064, + Number4StealthKragen = 67557908, + Floowandereeze_Snowl = 53212882, + Floowandereeze_Empen = 80611581, + MasqueradetheBlazingDragon = 6855503, + DestinyHERO_DestroyerPhoenixEnforcer = 60461804, + SwordsoulGrandmaster_Chixiao = 69248256, + ZoroatheMagistusConflagrantCalamity = 95911373, + MasterflareHyperion = 63101468, + FallenSanctuary = 90312154, + MyutantBeast = 34695290, + MyutantArsenal = 7574904, + MyutantUltimus = 6182103, + Underdog = 5779502, + IcejadeKosmochlor = 3355732, + IllusionofChaos = 12266229, + SwordsoulSinisterSovereign_QixingLongyuan = 47710198, + DDDDeviserKingDeusMachinex = 46593546, + IcejadeErosion = 46593546, + NordicRelicSvalinn = 64797746, + OceanDragonLord_Kairyu_Shin = 23931679, + MarincessAquaArgonaut = 20934852, + MirrorjadetheIcebladeDragon = 44146295, + WitchcrafterVice_Madame = 9603252, + Therion_King_Regulus = 10604644, + StarvingVenomPredapowerFusionDragon = 39915560, + DinomorphiaRexterm = 92798873, + ExosistersMagnifica = 59242457, + IcejadeCurse = 83670388, + MamonakatheVaylantzUnited = 40680521, + LabrynthLabyrinth = 33407125, + RunickFountain = 92107604, + SprightRed = 75922381, + SprightCarrot = 2311090, + RikkaKonkon = 76869711, + PowerToolBraverDragon = 63265554, + MagikeyDeity_Ashtartu = 26988374, + RainbowOverdragon = 37440988, + TheBystialAlbaLos = 69120785, + KashtiraFenrir = 32909498, + MitsutheInsectNinja = 67282505, + VeratheVernusylphGoddess = 55125728, + TearlamentsRulkallos = 84330567, + Black_WingedAssaultDragon = 73218989, + BrandedBeast = 32756828, + GraphaDragonOverlordofDarkWorld = 39552584, + EpurrelyBeauty = 98049934, + ExpurrelyNoir = 83827392, + BeetrooperScaleBomber = 39041550, + EvigishkiNeremanas = 88926295, + ArktosXII_ChronochasmVaylantz = 50687050, + IcejadeGymirAegirine = 86682165, + KashtiraArise_Heart = 48626373, + LaevateinGeneraiderBossofShadows = 74615388, + SynchroZone = 60306277, + BystialDisPater = 27572350, + DespianLuluwalilith = 53971455, + FirewallDragonSingularity = 21637210, + BrandedEtude = 45675980, + EvolzarLars = 35103106, + AltergeistAdminia = 61470213, + EmperorCharlesTheGreat = 97864322, + YouReFinished = 88346805, + VolcanicEmperor = 46412900, + VolcanicInferno = 84138874, + RedZone = 50056656, + TGGlaiveBlaster = 95973569, + StellarNemesisTPHON_DoomsdayStar = 93039339, + SPLittleKnight = 29301450, + AngelRing = 40678060 } } diff --git a/libWindbot/Game/AI/Enums/FusionSpell.cs b/libWindbot/Game/AI/Enums/FusionSpell.cs index b4859b5..f157cc3 100644 --- a/libWindbot/Game/AI/Enums/FusionSpell.cs +++ b/libWindbot/Game/AI/Enums/FusionSpell.cs @@ -51,9 +51,40 @@ public enum FusionSpell FusionGate = 33550694, DFusion = 26841274, + FusionDestiny = 52947044, PyroxeneFusion = 55824220, FragmentFusion = 72029628, NecroFusion = 81223446, PredaplantVerteAnaconda = 70369116, + + DreamMirrorofChaos = 98570539, + PlunderPatrollShipshapeShipsShipping = 44227727, + FireFormationIngen = 29143457, + ParametalfoesFusion = 58549532, + ReadyFusion = 63854005, + BrandedinWhite = 34995106, + BrandedinRed = 82738008, + FaceCardFusion = 29062925, + MyutantFusion = 42577802, + MyutantCry = 31855260, + GreaterPolymerization = 7614732, + UltimateFusion = 71143015, + BrandedFusion = 44362883, + GhostFusion = 35705817, + WitchcrafterConfusionConfession = 35098357, + BrandedBanishment = 6763530, + DinomorphiaDomain = 26631975, + DinomorphiaFrenzy = 78420796, + SouloftheSupremeKing = 92428405, + InstantContact = 16169772, + ScatterFusion = 40597694, + FavoriteContact = 75047173, + AmazonessSecretArts = 86758746, + DarkWorldAccession = 65956182, + BeetrooperLanding = 13234975, + FusionReproduction = 43331750, + ChimeraFusion = 63136489, + HarmonicSynchroFusion = 7473735, + SouloftheSupremeCelestialKing = 76840111 } } diff --git a/libWindbot/Game/AI/Enums/InvincibleMonster.cs b/libWindbot/Game/AI/Enums/InvincibleMonster.cs index c4f4cc9..fe9a32c 100644 --- a/libWindbot/Game/AI/Enums/InvincibleMonster.cs +++ b/libWindbot/Game/AI/Enums/InvincibleMonster.cs @@ -25,7 +25,11 @@ public enum InvincibleBotMonster DaigustoSphreez = 29552709, Number92HearteartHDragon = 97403510, NumberC96DarkStorm = 77205367, - Number54LionHeart = 54366836 + Number54LionHeart = 54366836, + Number2NinjaShadowMosquito = 32453837, + OhimetheManifestedMikanko = 81260679, + NightmareMagician = 40221691, + ArahimetheManifestedMikanko = 75771170 } /// /// Cards that are invincible to battle. @@ -93,6 +97,18 @@ public enum InvincibleEnemyMonster GoukiTheGiantOgre = 47946130, BorrelswordDragon = 85289965, NumberF0UtopicFutureDragon = 26973555, - BorrelendDragon = 98630720 + BorrelendDragon = 98630720, + MimickingMan_EaterBug = 72427512, + ShiningPiecephilia = 49776811, + BrigrandtheGloryDragon = 34848821, + AmazonessQueen = 15951532, + Number2NinjaShadowMosquito = 32453837, + OhimetheManifestedMikanko = 81260679, + CornfieldCoatl = 92565383, + MirrorSwordknight = 28954097, + NightmareMagician = 40221691, + ArahimetheManifestedMikanko = 75771170, + UFOLight = 9275482, + TaotheGreatChanter = 34541543 } } diff --git a/libWindbot/Game/AI/Enums/NotBeSynchroMaterialMonster.cs b/libWindbot/Game/AI/Enums/NotBeSynchroMaterialMonster.cs new file mode 100644 index 0000000..0323312 --- /dev/null +++ b/libWindbot/Game/AI/Enums/NotBeSynchroMaterialMonster.cs @@ -0,0 +1,33 @@ +namespace WindBot.Game.AI.Enums +{ + public enum NotBeSynchroMaterialMonster + { + Ronintoadin = 1357146, + GagagaCaesar = 9583383, + VagueShadowToken = 9929399, + TourGuideFromtheUnderworld = 10802915, + PhotonToken = 17418745, + KagemuchaKnight = 19353570, + SharkStickers = 20838380, + GagagaMagician = 26082117, + RadianToken = 28674153, + Kurivolt = 40817915, + BlueMountainButterspy = 54582424, + Lightserpent = 55501446, + SaberShark = 63193879, + ConstellarKaus = 70908596, + CeremonialToken = 82340057, + HeroicChallenger_DoubleLance = 89774530, + SteelswarmScout = 90727556, + Kagetokage = 94656263, + YellowDuston = 16366810, + BlueDuston = 40217358, + Centerfrog = 47346782, + GreenDuston = 52182715, + RedDuston = 61019812, + EaterofMillions = 63845230, + PutridPuddingBodyBuddies = 85101097, + Click_Echo = 2992467 + + } +} \ No newline at end of file diff --git a/libWindbot/Game/AI/Enums/NotBeXyzMaterialMonster.cs b/libWindbot/Game/AI/Enums/NotBeXyzMaterialMonster.cs new file mode 100644 index 0000000..94c8f1f --- /dev/null +++ b/libWindbot/Game/AI/Enums/NotBeXyzMaterialMonster.cs @@ -0,0 +1,14 @@ +namespace WindBot.Game.AI.Enums +{ + public enum NotBeXyzMaterialMonster + { + YellowDuston = 16366810, + BlueDuston = 40217358, + Centerfrog = 47346782, + GreenDuston = 52182715, + RedDuston = 61019812, + EaterofMillions = 63845230, + PutridPuddingBodyBuddies = 85101097, + Click_Echo = 2992467 + } +} \ No newline at end of file diff --git a/libWindbot/Game/AI/Enums/PreventActivationEffectInBattle.cs b/libWindbot/Game/AI/Enums/PreventActivationEffectInBattle.cs index 34f98e6..a916f8b 100644 --- a/libWindbot/Game/AI/Enums/PreventActivationEffectInBattle.cs +++ b/libWindbot/Game/AI/Enums/PreventActivationEffectInBattle.cs @@ -11,5 +11,10 @@ public enum PreventActivationEffectInBattle SamuraiDestroyer = 40509732, ArmadesKeeperOfBoundaries = 88033975, NumberS39UtopiaTheLightning = 56832966, + DualAvatarEmpoweredKonGyo = 33026283, + GGolemRockHammer = 98875863, + WishDragon = 64583600, + ChaosWitch = 30327674, + FissioningMotherSpider = 34034150 } } diff --git a/libWindbot/Game/AI/Enums/ShouldBeDisabledBeforeItUseEffectMonster.cs b/libWindbot/Game/AI/Enums/ShouldBeDisabledBeforeItUseEffectMonster.cs index ff5df10..0eaa629 100644 --- a/libWindbot/Game/AI/Enums/ShouldBeDisabledBeforeItUseEffectMonster.cs +++ b/libWindbot/Game/AI/Enums/ShouldBeDisabledBeforeItUseEffectMonster.cs @@ -56,6 +56,13 @@ public enum ShouldBeDisabledBeforeItUseEffectMonster ShiranuiSolitaire = 94801854, Mixeroid = 71340250, LonefireBlossom = 48686504, - BrotherhoodoftheFireFist_Leopard = 39699564 + BrotherhoodoftheFireFist_Leopard = 39699564, + SpringansPedor = 56818977, + GizmekNaganakitheSunriseSignaler = 96399967, + MyutantMutant = 26561172, + ThreeEyedGhost = 31464658, + UrsarcticPolarStar = 62714453, + BattlinBoxerPromoter = 83315222, + TGRocketSalamander = 77392987 } } diff --git a/libWindbot/Game/AI/Enums/ShouldNotBeMonsterTarget.cs b/libWindbot/Game/AI/Enums/ShouldNotBeMonsterTarget.cs index b5cb0f6..8ed6cb9 100644 --- a/libWindbot/Game/AI/Enums/ShouldNotBeMonsterTarget.cs +++ b/libWindbot/Game/AI/Enums/ShouldNotBeMonsterTarget.cs @@ -14,6 +14,8 @@ public enum ShouldNotBeMonsterTarget PaleozoicAnomalocaris = 61307542, PaleozoicOpabinia = 37649320, BorreloadDragon = 31833038, - BorrelendDragon = 98630720 + BorrelendDragon = 98630720, + DrytronMeteonisDraconids = 69815951, + MyutantBeast = 34695290 } } diff --git a/libWindbot/Game/AI/Enums/ShouldNotBeSpellTarget.cs b/libWindbot/Game/AI/Enums/ShouldNotBeSpellTarget.cs index ba8e69c..e045246 100644 --- a/libWindbot/Game/AI/Enums/ShouldNotBeSpellTarget.cs +++ b/libWindbot/Game/AI/Enums/ShouldNotBeSpellTarget.cs @@ -9,6 +9,7 @@ public enum ShouldNotBeSpellTrapTarget ApoqliphortTowers = 27279764, ApoqliphortSkybase = 40061558, TheLegendaryFishermanIII = 44968687, - ChaosAncientGearGiant = 51788412 + ChaosAncientGearGiant = 51788412, + DrytronMeteonisQuadrantids = 95209656 } } diff --git a/libWindbot/Game/AI/Executor.cs b/libWindbot/Game/AI/Executor.cs index 6ef82be..b6a804a 100644 --- a/libWindbot/Game/AI/Executor.cs +++ b/libWindbot/Game/AI/Executor.cs @@ -22,6 +22,7 @@ public abstract class Executor protected ExecutorType Type { get; private set; } protected ClientCard Card { get; private set; } protected int ActivateDescription { get; private set; } + protected int CurrentTiming { get; private set; } protected ClientField Bot { get; private set; } protected ClientField Enemy { get; private set; } @@ -166,6 +167,11 @@ public virtual IList OnCardSorting(IList cards) return null; } + public virtual void OnSelectChain(IList cards) + { + return; + } + public virtual bool OnSelectYesNo(int desc) { return true; @@ -228,11 +234,12 @@ public void SetBattle(BattlePhase battle) /// /// Set global variables Type, Card, ActivateDescription for Executor /// - public void SetCard(ExecutorType type, ClientCard card, int description) + public void SetCard(ExecutorType type, ClientCard card, int description, int timing = -1) { Type = type; Card = card; ActivateDescription = description; + CurrentTiming = timing; } /// diff --git a/libWindbot/Game/Duel.cs b/libWindbot/Game/Duel.cs index 34f73a3..cf4ed7d 100644 --- a/libWindbot/Game/Duel.cs +++ b/libWindbot/Game/Duel.cs @@ -18,8 +18,10 @@ public class Duel public BattlePhase BattlePhase { get; set; } public int LastChainPlayer { get; set; } + public CardLocation LastChainLocation { get; set; } public IList CurrentChain { get; set; } public IList ChainTargets { get; set; } + public IList LastChainTargets { get; set; } public IList ChainTargetOnly { get; set; } public int LastSummonPlayer { get; set; } public IList SummoningCards { get; set; } @@ -31,8 +33,10 @@ public Duel() Fields[0] = new ClientField(); Fields[1] = new ClientField(); LastChainPlayer = -1; + LastChainLocation = 0; CurrentChain = new List(); ChainTargets = new List(); + LastChainTargets = new List(); ChainTargetOnly = new List(); LastSummonPlayer = -1; SummoningCards = new List(); diff --git a/libWindbot/Game/GameAI.cs b/libWindbot/Game/GameAI.cs index a40c859..d25a1f8 100644 --- a/libWindbot/Game/GameAI.cs +++ b/libWindbot/Game/GameAI.cs @@ -54,6 +54,14 @@ public void OnStart() _dialogs.SendDuelStart(); } + /// + /// Customized called when the AI do something in a duel. + /// + public void SendCustomChat(int index, params object[] opts) + { + _dialogs.SendCustomChat(index, opts); + } + /// /// Called when the AI do the rock-paper-scissors. /// @@ -301,15 +309,17 @@ public IList OnSelectCard(IList cards, int min, int max, /// List of activable cards. /// List of effect descriptions. /// You can't return -1 if this param is true. + /// Current hint timing /// Index of the activated card or -1. - public int OnSelectChain(IList cards, IList descs, bool forced) + public int OnSelectChain(IList cards, IList descs, bool forced, int timing = -1) { + Executor.OnSelectChain(cards); foreach (CardExecutor exec in Executor.Executors) { for (int i = 0; i < cards.Count; ++i) { ClientCard card = cards[i]; - if (ShouldExecute(exec, card, ExecutorType.Activate, descs[i])) + if (ShouldExecute(exec, card, ExecutorType.Activate, descs[i], timing)) { _dialogs.SendChaining(card.Name); return i; @@ -1112,7 +1122,7 @@ public BattlePhaseAction ToMainPhase2() return new BattlePhaseAction(BattlePhaseAction.BattleAction.ToMainPhaseTwo); } - private bool ShouldExecute(CardExecutor exec, ClientCard card, ExecutorType type, int desc = -1) + private bool ShouldExecute(CardExecutor exec, ClientCard card, ExecutorType type, int desc = -1, int timing = -1) { if (card.Id != 0 && type == ExecutorType.Activate) { @@ -1121,7 +1131,7 @@ private bool ShouldExecute(CardExecutor exec, ClientCard card, ExecutorType type if (!Executor.OnPreActivate(card)) return false; } - Executor.SetCard(type, card, desc); + Executor.SetCard(type, card, desc, timing); bool result = card != null && exec.Type == type && (exec.CardId == -1 || exec.CardId == card.Id) && (exec.Func == null || exec.Func()); diff --git a/libWindbot/Game/GameBehavior.cs b/libWindbot/Game/GameBehavior.cs index d5111be..e41527a 100644 --- a/libWindbot/Game/GameBehavior.cs +++ b/libWindbot/Game/GameBehavior.cs @@ -728,7 +728,8 @@ private void OnChaining(BinaryReader packet) card.SetId(cardId); int cc = GetLocalPlayer(packet.ReadByte()); if (_debug) - if (card != null) Logger.WriteLine("(" + cc.ToString() + " 's " + (card.Name ?? "UnKnowCard") + " activate effect)"); + if (card != null) Logger.WriteLine("(" + cc.ToString() + " 's " + (card.Name ?? "UnKnowCard") + " activate effect from " + (CardLocation)pcl + ")"); + _duel.LastChainLocation = (CardLocation)pcl; _ai.OnChaining(card, cc); //_duel.ChainTargets.Clear(); _duel.ChainTargetOnly.Clear(); @@ -742,8 +743,10 @@ private void OnChainEnd(BinaryReader packet) { _ai.OnChainEnd(); _duel.LastChainPlayer = -1; + _duel.LastChainLocation = 0; _duel.CurrentChain.Clear(); _duel.ChainTargets.Clear(); + _duel.LastChainTargets.Clear(); _duel.ChainTargetOnly.Clear(); } @@ -856,6 +859,7 @@ private void OnUpdateData(BinaryReader packet) private void OnBecomeTarget(BinaryReader packet) { + _duel.LastChainTargets.Clear(); int count = packet.ReadByte(); for (int i = 0; i < count; ++i) { @@ -868,6 +872,7 @@ private void OnBecomeTarget(BinaryReader packet) if (_debug) Logger.WriteLine("(" + (CardLocation)loc + " 's " + (card.Name ?? "UnKnowCard") + " become target)"); _duel.ChainTargets.Add(card); + _duel.LastChainTargets.Add(card); _duel.ChainTargetOnly.Add(card); } } @@ -1073,7 +1078,7 @@ private void OnSelectChain(BinaryReader packet) packet.ReadByte(); // specount bool forced = packet.ReadByte() != 0; packet.ReadInt32(); // hint1 - packet.ReadInt32(); // hint2 + int hint2 = packet.ReadInt32(); // hint2 IList cards = new List(); IList descs = new List(); @@ -1113,7 +1118,7 @@ private void OnSelectChain(BinaryReader packet) return; } - Connection.Send(CtosMessage.Response, _ai.OnSelectChain(cards, descs, forced)); + Connection.Send(CtosMessage.Response, _ai.OnSelectChain(cards, descs, forced, hint2)); } private void OnSelectCounter(BinaryReader packet) @@ -1150,7 +1155,96 @@ private void OnSelectCounter(BinaryReader packet) private void OnSelectDisfield(BinaryReader packet) { - OnSelectPlace(packet); + packet.ReadByte(); // player + packet.ReadByte(); // TODO: min + int field = ~packet.ReadInt32(); + + int player; + CardLocation location; + int filter; + if ((field & 0x7f0000) != 0) + { + player = 1; + location = CardLocation.MonsterZone; + filter = (field >> 16) & Zones.MonsterZones; + } + else if ((field & 0x1f000000) != 0) + { + player = 1; + location = CardLocation.SpellZone; + filter = (field >> 24) & Zones.SpellZones; + } + else if ((field & 0x7f) != 0) + { + player = 0; + location = CardLocation.MonsterZone; + filter = field & Zones.MonsterZones; + } + else if ((field & 0x1f00) != 0) + { + player = 0; + location = CardLocation.SpellZone; + filter = (field >> 8) & Zones.SpellZones; + } + else if ((field & 0x2000) != 0) + { + player = 0; + location = CardLocation.FieldZone; + filter = Zones.FieldZone; + } + else if ((field & 0xc000) != 0) + { + player = 0; + location = CardLocation.PendulumZone; + filter = (field >> 14) & Zones.PendulumZones; + } + else if ((field & 0x20000000) != 0) + { + player = 1; + location = CardLocation.FieldZone; + filter = Zones.FieldZone; + } + else + { + player = 1; + location = CardLocation.PendulumZone; + filter = (field >> 30) & Zones.PendulumZones; + } + + int selected = _ai.OnSelectPlace(_select_hint, player, location, filter); + _select_hint = 0; + + byte[] resp = new byte[3]; + resp[0] = (byte)GetLocalPlayer(player); + + if (location != CardLocation.PendulumZone && location != CardLocation.FieldZone) + { + resp[1] = (byte)location; + if ((selected & filter) > 0) + filter &= selected; + + if ((filter & Zones.z2) != 0) resp[2] = 2; + else if ((filter & Zones.z1) != 0) resp[2] = 1; + else if ((filter & Zones.z3) != 0) resp[2] = 3; + else if ((filter & Zones.z0) != 0) resp[2] = 0; + else if ((filter & Zones.z4) != 0) resp[2] = 4; + else if ((filter & Zones.z6) != 0) resp[2] = 6; + else if ((filter & Zones.z5) != 0) resp[2] = 5; + } + else + { + resp[1] = (byte)CardLocation.SpellZone; + if ((selected & filter) > 0) + filter &= selected; + + if ((filter & Zones.FieldZone) != 0) resp[2] = 5; + if ((filter & Zones.z0) != 0) resp[2] = 6; // left pendulum zone + if ((filter & Zones.z1) != 0) resp[2] = 7; // right pendulum zone + } + + BinaryWriter reply = GamePacketFactory.Create(CtosMessage.Response); + reply.Write(resp); + Connection.Send(reply); } private void OnSelectEffectYn(BinaryReader packet) @@ -1661,7 +1755,7 @@ private void OnAnnounceRace(BinaryReader packet) int count = packet.ReadByte(); int available = packet.ReadInt32(); int filter = 0x1; - for (int i = 0; i < 23; ++i) + for (int i = 0; i < 26; ++i) { if ((available & filter) != 0) races.Add((CardRace)filter); diff --git a/libWindbot/WindBotInfo.cs b/libWindbot/WindBotInfo.cs index 6cae2a5..589670c 100644 --- a/libWindbot/WindBotInfo.cs +++ b/libWindbot/WindBotInfo.cs @@ -24,7 +24,7 @@ public WindBotInfo() Host = "127.0.0.1"; Port = 7911; HostInfo = ""; - Version = 0x1353; + Version = 0x1360; Hand = 0; Debug = false; Chat = true; diff --git a/libWindbot/YGOSharp.Network/BinaryClient.cs b/libWindbot/YGOSharp.Network/BinaryClient.cs index c945a95..024f9d8 100644 --- a/libWindbot/YGOSharp.Network/BinaryClient.cs +++ b/libWindbot/YGOSharp.Network/BinaryClient.cs @@ -1,229 +1,230 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Net.Sockets; - -namespace YGOSharp.Network -{ - public class BinaryClient - { - public event Action Connected; - public event Action Disconnected; - public event Action PacketReceived; - - protected int MaxPacketLength = 0xFFFF; - protected int HeaderSize = 2; - protected bool IsHeaderSizeIncluded = false; - - private NetworkClient _client; - - private List _receiveBuffer = new List(); - private Queue _pendingPackets = new Queue(); - private byte[] _lengthBuffer = new byte[16]; - - private int _pendingLength; - private bool _wasConnected; - private bool _wasDisconnected; - private bool _wasDisconnectedEventFired; - private Exception _closingException; - - public bool IsConnected - { - get { return !_wasDisconnectedEventFired; } - } - - public IPAddress RemoteIPAddress - { - get { return _client.RemoteIPAddress; } - } - - public BinaryClient(NetworkClient client) - { - _client = client; - - client.Connected += Client_Connected; - client.Disconnected += Client_Disconnected; - client.DataReceived += Client_DataReceived; - - if (_client.IsConnected) - { - _client.BeginReceive(); - } - } - - public void Connect(IPAddress address, int port) - { - _client.BeginConnect(address, port); - } - - public void Initialize(Socket socket) - { - _client.Initialize(socket); - } - - public void Update() - { - if (_wasConnected) - { - _wasConnected = false; - Connected?.Invoke(); - } - ReceivePendingPackets(); - if (_wasDisconnected && !_wasDisconnectedEventFired) - { - _wasDisconnectedEventFired = true; - Disconnected?.Invoke(_closingException); - } - } - - public void Send(byte[] packet) - { - if (packet.Length > MaxPacketLength) - { - throw new Exception("Tried to send a too large packet"); - } - - int packetLength = packet.Length; - if (IsHeaderSizeIncluded) packetLength += HeaderSize; - - byte[] header; - if (HeaderSize == 2) - { - header = BitConverter.GetBytes((ushort)packetLength); - } - else if (HeaderSize == 4) - { - header = BitConverter.GetBytes(packetLength); - } - else - { - throw new Exception("Unsupported header size: " + HeaderSize); - } - byte[] data = new byte[packet.Length + HeaderSize]; - Array.Copy(header, 0, data, 0, header.Length); - Array.Copy(packet, 0, data, header.Length, packet.Length); - _client.BeginSend(data); - } - - public void Close(Exception error = null) - { - _client.Close(error); - } - - private void ReceivePendingPackets() - { - bool hasReceived; - do - { - byte[] packet = null; - lock (_pendingPackets) - { - if (_pendingPackets.Count > 0) - { - packet = _pendingPackets.Dequeue(); - } - } - hasReceived = false; - if (packet != null) - { - hasReceived = true; - using (MemoryStream stream = new MemoryStream(packet, false)) - { - using (BinaryReader reader = new BinaryReader(stream)) - { - PacketReceived?.Invoke(reader); - } - } - } - } - while (hasReceived); - } - - private void Client_Connected() - { - _wasConnected = true; - } - - private void Client_Disconnected(Exception ex) - { - _wasDisconnected = true; - _closingException = ex; - } - - private void Client_DataReceived(byte[] data) - { - _receiveBuffer.AddRange(data); - ExtractPackets(); - } - - private void ExtractPackets() - { - bool hasExtracted; - do - { - if (_pendingLength == 0) - { - hasExtracted = ExtractPendingLength(); - } - else - { - hasExtracted = ExtractPendingPacket(); - } - } - while (hasExtracted); - } - - private bool ExtractPendingLength() - { - if (_receiveBuffer.Count >= HeaderSize) - { - _receiveBuffer.CopyTo(0, _lengthBuffer, 0, HeaderSize); - if (HeaderSize == 2) - { - _pendingLength = BitConverter.ToUInt16(_lengthBuffer, 0); - } - else if (HeaderSize == 4) - { - _pendingLength = BitConverter.ToInt32(_lengthBuffer, 0); - } - else - { - throw new Exception("Unsupported header size: " + HeaderSize); - } - _receiveBuffer.RemoveRange(0, HeaderSize); - - if (IsHeaderSizeIncluded) _pendingLength -= HeaderSize; - - if (_pendingLength < 0 || _pendingLength > MaxPacketLength) - { - _client.Close(new Exception("Tried to receive a too large packet")); - return false; - } - - return true; - } - return false; - } - - private bool ExtractPendingPacket() - { - if (_receiveBuffer.Count >= _pendingLength) - { - byte[] packet = new byte[_pendingLength]; - - _receiveBuffer.CopyTo(0, packet, 0, _pendingLength); - _receiveBuffer.RemoveRange(0, _pendingLength); - _pendingLength = 0; - - lock (_pendingPackets) - { - _pendingPackets.Enqueue(packet); - } - - return true; - } - return false; - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Sockets; + +namespace YGOSharp.Network +{ + public class BinaryClient + { + public event Action Connected; + public event Action Disconnected; + public event Action PacketReceived; + + protected int MaxPacketLength = 0xFFFF; + protected int HeaderSize = 2; + protected bool IsHeaderSizeIncluded = false; + + private NetworkClient _client; + + private List _receiveBuffer = new List(); + private LinkedList _pendingPackets = new LinkedList(); + private byte[] _lengthBuffer = new byte[16]; + + private int _pendingLength; + private bool _wasConnected; + private bool _wasDisconnected; + private bool _wasDisconnectedEventFired; + private Exception _closingException; + + public bool IsConnected + { + get { return !_wasDisconnectedEventFired; } + } + + public IPAddress RemoteIPAddress + { + get { return _client.RemoteIPAddress; } + } + + public BinaryClient(NetworkClient client) + { + _client = client; + + client.Connected += Client_Connected; + client.Disconnected += Client_Disconnected; + client.DataReceived += Client_DataReceived; + + if (_client.IsConnected) + { + _client.BeginReceive(); + } + } + + public void Connect(IPAddress address, int port) + { + _client.BeginConnect(address, port); + } + + public void Initialize(Socket socket) + { + _client.Initialize(socket); + } + + public void Update() + { + if (_wasConnected) + { + _wasConnected = false; + Connected?.Invoke(); + } + ReceivePendingPackets(); + if (_wasDisconnected && !_wasDisconnectedEventFired) + { + _wasDisconnectedEventFired = true; + Disconnected?.Invoke(_closingException); + } + } + + public void Send(byte[] packet) + { + if (packet.Length > MaxPacketLength) + { + throw new Exception("Tried to send a too large packet"); + } + + int packetLength = packet.Length; + if (IsHeaderSizeIncluded) packetLength += HeaderSize; + + byte[] header; + if (HeaderSize == 2) + { + header = BitConverter.GetBytes((ushort)packetLength); + } + else if (HeaderSize == 4) + { + header = BitConverter.GetBytes(packetLength); + } + else + { + throw new Exception("Unsupported header size: " + HeaderSize); + } + byte[] data = new byte[packet.Length + HeaderSize]; + Array.Copy(header, 0, data, 0, header.Length); + Array.Copy(packet, 0, data, header.Length, packet.Length); + _client.BeginSend(data); + } + + public void Close(Exception error = null) + { + _client.Close(error); + } + + private void ReceivePendingPackets() + { + bool hasReceived; + do + { + byte[] packet = null; + lock (_pendingPackets) + { + if (_pendingPackets.Count > 0) + { + packet = _pendingPackets.First.Value; + _pendingPackets.RemoveFirst(); + } + } + hasReceived = false; + if (packet != null) + { + hasReceived = true; + using (MemoryStream stream = new MemoryStream(packet, false)) + { + using (BinaryReader reader = new BinaryReader(stream)) + { + PacketReceived?.Invoke(reader); + } + } + } + } + while (hasReceived); + } + + private void Client_Connected() + { + _wasConnected = true; + } + + private void Client_Disconnected(Exception ex) + { + _wasDisconnected = true; + _closingException = ex; + } + + private void Client_DataReceived(byte[] data) + { + _receiveBuffer.AddRange(data); + ExtractPackets(); + } + + private void ExtractPackets() + { + bool hasExtracted; + do + { + if (_pendingLength == 0) + { + hasExtracted = ExtractPendingLength(); + } + else + { + hasExtracted = ExtractPendingPacket(); + } + } + while (hasExtracted); + } + + private bool ExtractPendingLength() + { + if (_receiveBuffer.Count >= HeaderSize) + { + _receiveBuffer.CopyTo(0, _lengthBuffer, 0, HeaderSize); + if (HeaderSize == 2) + { + _pendingLength = BitConverter.ToUInt16(_lengthBuffer, 0); + } + else if (HeaderSize == 4) + { + _pendingLength = BitConverter.ToInt32(_lengthBuffer, 0); + } + else + { + throw new Exception("Unsupported header size: " + HeaderSize); + } + _receiveBuffer.RemoveRange(0, HeaderSize); + + if (IsHeaderSizeIncluded) _pendingLength -= HeaderSize; + + if (_pendingLength < 0 || _pendingLength > MaxPacketLength) + { + _client.Close(new Exception("Tried to receive a too large packet")); + return false; + } + + return true; + } + return false; + } + + private bool ExtractPendingPacket() + { + if (_receiveBuffer.Count >= _pendingLength) + { + byte[] packet = new byte[_pendingLength]; + + _receiveBuffer.CopyTo(0, packet, 0, _pendingLength); + _receiveBuffer.RemoveRange(0, _pendingLength); + _pendingLength = 0; + + lock (_pendingPackets) + { + _pendingPackets.AddLast(packet); + } + + return true; + } + return false; + } + } +} diff --git a/libWindbot/libWindbot.csproj b/libWindbot/libWindbot.csproj index fb4a421..d2aa2e6 100644 --- a/libWindbot/libWindbot.csproj +++ b/libWindbot/libWindbot.csproj @@ -65,12 +65,14 @@ + + @@ -89,11 +91,15 @@ + + + + @@ -102,6 +108,8 @@ + +