Commit ec7935f7 authored by wind2009's avatar wind2009 Committed by GitHub

Add ChainInfo (#210)

parent 9c19a04f
......@@ -2186,7 +2186,7 @@ namespace WindBot.Game.AI.Decks
public override int OnSelectOption(IList<int> options)
{
ClientCard currentSolvingChain = Duel.GetCurrentSolvingChainCard();
ChainInfo currentSolvingChain = Duel.GetCurrentSolvingChainInfo();
if (currentSolvingChain != null)
{
// 1190=Add to Hand, 1152=Special Summon
......@@ -2246,8 +2246,8 @@ namespace WindBot.Game.AI.Decks
public override int OnSelectPlace(int cardId, int player, CardLocation location, int available)
{
ClientCard currentSovingChain = Duel.GetCurrentSolvingChainCard();
if (currentSovingChain != null && currentSovingChain.Controller == 0 && currentSovingChain.IsCode(CardId.SprindTheIrondashDragon))
ChainInfo currentSovingChain = Duel.GetCurrentSolvingChainInfo();
if (currentSovingChain != null && currentSovingChain.ActivatePlayer == 0 && currentSovingChain.IsCode(CardId.SprindTheIrondashDragon))
{
return SprindTheIrondashDragonMoveZone(available, null);
}
......@@ -2435,21 +2435,21 @@ namespace WindBot.Game.AI.Decks
public override void OnChainSolved(int chainIndex)
{
ClientCard currentCard = Duel.GetCurrentSolvingChainCard();
ChainInfo currentCard = Duel.GetCurrentSolvingChainInfo();
if (currentCard != null)
{
// if activation is negated, it can activate again.
if (currentCard.Controller == 0)
if (currentCard.ActivatePlayer == 0)
{
List<int> activateCheck = new List<int> { CardId.NadirServant, CardId.FusionDeployment, CardId.BrandedFusion, CardId.BrandedInRed };
if (currentCard.IsCode(activateCheck))
{
activatedCardIdList.Add(currentCard.Id);
activatedCardIdList.Add(currentCard.ActivateId);
}
}
if (!Duel.IsCurrentSolvingChainNegated())
{
if (currentCard.Controller == 1)
if (currentCard.ActivatePlayer == 1)
{
if (currentCard.IsCode(_CardId.MaxxC))
enemyActivateMaxxC = true;
......@@ -2458,7 +2458,7 @@ namespace WindBot.Game.AI.Decks
if (currentCard.IsCode(CardId.DimensionShifter))
dimensionShifterCount = 2;
}
if (currentCard.Controller == 0 && currentCard.IsCode(CardId.NadirServant))
if (currentCard.ActivatePlayer == 0 && currentCard.IsCode(CardId.NadirServant))
{
nadirActivated = true;
}
......
......@@ -1153,8 +1153,8 @@ namespace WindBot.Game.AI.Decks
public override void OnChainSolved(int chainIndex)
{
ClientCard currentCard = Duel.GetCurrentSolvingChainCard();
if (currentCard != null && !Duel.IsCurrentSolvingChainNegated() && currentCard.Controller == 1)
ChainInfo currentCard = Duel.GetCurrentSolvingChainInfo();
if (currentCard != null && !Duel.IsCurrentSolvingChainNegated() && currentCard.ActivatePlayer == 1)
{
if (currentCard.IsCode(_CardId.MaxxC))
enemyActivateMaxxC = true;
......@@ -1166,7 +1166,7 @@ namespace WindBot.Game.AI.Decks
{
for (int i = 0; i < 5; ++i)
{
if (Enemy.SpellZone[i] == currentCard)
if (Enemy.SpellZone[i] == currentCard.RelatedCard)
{
infiniteImpermanenceList.Add(4 - i);
break;
......
......@@ -771,8 +771,8 @@ namespace WindBot.Game.AI.Decks
public override void OnChainSolved(int chainIndex)
{
ClientCard currentCard = Duel.GetCurrentSolvingChainCard();
if (currentCard != null && !Duel.IsCurrentSolvingChainNegated() && currentCard.Controller == 1)
ChainInfo currentCard = Duel.GetCurrentSolvingChainInfo();
if (currentCard != null && !Duel.IsCurrentSolvingChainNegated() && currentCard.ActivatePlayer == 1)
{
if (currentCard.IsCode(_CardId.MaxxC))
enemyActivateMaxxC = true;
......@@ -782,7 +782,7 @@ namespace WindBot.Game.AI.Decks
{
for (int i = 0; i < 5; ++i)
{
if (Enemy.SpellZone[i] == currentCard)
if (Enemy.SpellZone[i] == currentCard.RelatedCard)
{
infiniteImpermanenceList.Add(4 - i);
break;
......
......@@ -1646,17 +1646,17 @@ namespace WindBot.Game.AI.Decks
public override void OnChainSolved(int chainIndex)
{
ClientCard currentCard = Duel.GetCurrentSolvingChainCard();
ChainInfo currentCard = Duel.GetCurrentSolvingChainInfo();
if (currentCard != null && !Duel.IsCurrentSolvingChainNegated())
{
if (currentCard.Controller == 1)
if (currentCard.ActivatePlayer == 1)
{
if (currentCard.IsCode(_CardId.MaxxC))
enemyActivateMaxxC = true;
if (currentCard.IsCode(CardId.DimensionShifter))
dimensionShifterCount = 2;
}
if (currentCard.Controller == 0)
if (currentCard.ActivatePlayer == 0)
{
if (currentCard.IsCode(CardId.LabrynthCooclock))
cooclockAffected = true;
......
......@@ -64,6 +64,7 @@ namespace WindBot.Game.AI.Decks
AddExecutor(ExecutorType.Activate, _CardId.GhostOgreAndSnowRabbit, GhostOgreAndSnowRabbitActivate);
AddExecutor(ExecutorType.Activate, _CardId.AshBlossom, AshBlossomActivate);
AddExecutor(ExecutorType.Activate, CardId.RyzealCross, RyzealCrossActivateCard);
AddExecutor(ExecutorType.Activate, _CardId.EvilswarmExcitonKnight, EvilswarmExcitonKnightActivate);
AddExecutor(ExecutorType.Activate, CardId.RyzealDeadnader, RyzealDeadnaderActivate);
AddExecutor(ExecutorType.Activate, CardId.RyzealDuodrive, RyzealDuodriveActivate);
......@@ -82,7 +83,6 @@ namespace WindBot.Game.AI.Decks
AddExecutor(ExecutorType.Activate, CardId.Bonfire, BonfireActivate);
AddExecutor(ExecutorType.Activate, CardId.DonnerDaggerFurHire, DonnerDaggerFurHireActivate);
AddExecutor(ExecutorType.Activate, CardId.Number60DugaresTheTimeless, Number60DugaresTheTimelessActivate);
AddExecutor(ExecutorType.Activate, CardId.RyzealCross, RyzealCrossActivateCard);
AddExecutor(ExecutorType.Activate, CardId.TripleTacticsTalent, TripleTacticsTalentActivate);
AddExecutor(ExecutorType.Activate, CardId.Bonfire, BonfireActivateToSearchNecessary);
AddExecutor(ExecutorType.Activate, CardId.SeventhTachyon, SeventhTachyonActivate);
......@@ -372,6 +372,26 @@ namespace WindBot.Game.AI.Decks
return true;
}
public bool CheckCardShouldNegate(ChainInfo chainInfo)
{
if (chainInfo == null) return false;
ClientCard card = chainInfo.RelatedCard;
if (card == null) return false;
if (card.IsMonster() && card.HasSetcode(SetcodeTimeLord) && Duel.Phase == DuelPhase.Standby) return false;
if (NotToNegateIdList.Contains(card.Id)) return false;
if (card.HasSetcode(_Setcode.Danger) && card.Location == CardLocation.Hand) return false;
if (card.IsMonster() && chainInfo.HasLocation(CardLocation.MonsterZone) && chainInfo.HasPosition(CardPosition.Defence))
{
if (Enemy.MonsterZone.Any(c => CheckNumber41(c)) || Bot.MonsterZone.Any(c => CheckNumber41(c))) return false;
}
if (DefaultCheckWhetherCardIsNegated(card)) return false;
if (Duel.Player == 1 && card.IsCode(_CardId.MulcharmyPurulia, _CardId.MulcharmyFuwalos, _CardId.MulcharmyNyalus)) return false;
if (card.IsDisabled()) return false;
return true;
}
/// <summary>
/// Check whether bot is at advantage.
/// </summary>
......@@ -901,7 +921,7 @@ namespace WindBot.Game.AI.Decks
public override IList<ClientCard> OnSelectCard(IList<ClientCard> cards, int min, int max, int hint, bool cancelable)
{
ClientCard currentSolvingChain = Duel.GetCurrentSolvingChainCard();
ChainInfo currentSolvingChain = Duel.GetCurrentSolvingChainInfo();
if (currentSolvingChain != null)
{
if (botSolvingCross)
......@@ -933,7 +953,7 @@ namespace WindBot.Game.AI.Decks
}
}
if (currentSolvingChain.Controller == 1 && currentSolvingChain.IsCode(_CardId.EvenlyMatched))
if (currentSolvingChain.ActivatePlayer == 1 && currentSolvingChain.IsCode(_CardId.EvenlyMatched))
{
Logger.DebugWriteLine("=== Evenly Matched activated.");
List<ClientCard> banishList = new List<ClientCard>();
......@@ -975,7 +995,7 @@ namespace WindBot.Game.AI.Decks
return Util.CheckSelectCount(banishList, cards, min, max);
}
if (currentSolvingChain.Controller == 0)
if (currentSolvingChain.ActivatePlayer == 0)
{
if (hint == HintMsg.AddToHand)
{
......@@ -1681,31 +1701,31 @@ namespace WindBot.Game.AI.Decks
public override void OnChainSolved(int chainIndex)
{
botSolvingCross = false;
ClientCard currentCard = Duel.GetCurrentSolvingChainCard();
if (currentCard != null)
ChainInfo currentChain = Duel.GetCurrentSolvingChainInfo();
if (currentChain != null && !Duel.IsCurrentSolvingChainNegated())
{
if (!Duel.IsCurrentSolvingChainNegated())
{
if (currentCard.IsCode(_CardId.LockBird))
if (currentChain.IsCode(_CardId.LockBird))
lockBirdSolved = true;
if (currentCard.IsCode(_CardId.DimensionShifter))
if (currentChain.IsCode(_CardId.DimensionShifter))
dimensionShifterCount = 2;
if (currentCard.Controller == 1)
if (currentChain.ActivatePlayer == 1)
{
if (currentCard.IsCode(_CardId.MaxxC))
if (currentChain.IsCode(_CardId.MaxxC))
enemyActivateMaxxC = true;
if (currentCard.IsCode(_CardId.MulcharmyPurulia))
if (currentChain.IsCode(_CardId.MulcharmyPurulia))
enemyActivatePurulia = true;
if (currentCard.IsCode(_CardId.MulcharmyFuwalos))
if (currentChain.IsCode(_CardId.MulcharmyFuwalos))
enemyActivateFuwalos = true;
if (currentCard.IsCode(_CardId.MulcharmyNyalus))
if (currentChain.IsCode(_CardId.MulcharmyNyalus))
enemyActivateNyalus = true;
}
if (currentCard.Controller == 0)
if (currentChain.ActivatePlayer == 0)
{
foreach (int checkId in CheckBotSolvedList)
{
if (currentCard.IsCode(checkId))
if (currentChain.IsCode(checkId))
{
botSolvedCardIdList.Add(checkId);
}
......@@ -2758,10 +2778,10 @@ namespace WindBot.Game.AI.Decks
// whether to negate by cross
if (ActivateDescription == Util.GetStringId(CardId.RyzealCross, 3))
{
ClientCard currentSolvingChain = Duel.GetCurrentSolvingChainCard();
if (currentSolvingChain != null && !Duel.IsCurrentSolvingChainNegated())
ChainInfo currentChainInfo = Duel.GetCurrentSolvingChainInfo();
if (currentChainInfo != null && !Duel.IsCurrentSolvingChainNegated())
{
if (CheckCardShouldNegate(currentSolvingChain))
if (CheckCardShouldNegate(currentChainInfo))
{
Logger.DebugWriteLine("** cross negate");
activatedCardIdList.Add(CardId.RyzealCross + 2);
......@@ -2780,6 +2800,11 @@ namespace WindBot.Game.AI.Decks
Bot.Banished.Any(c => c != null && c.IsFaceup() && c.HasSetcode(SetcodeRyzeal) && (c.IsCanRevive() || !c.HasType(CardType.Xyz))));
flag |= Bot.MonsterZone.Count(c => c != null && c.IsFaceup() && c.HasType(CardType.Xyz) && c.HasSetcode(SetcodeRyzeal) && (c.Overlays.Count() > 0 || canSetMaterial)) > 0;
if (Duel.MainPhase.SpecialSummonableCards.Any(c => c.IsCode(CardId.RyzealDuodrive)))
{
flag |= RyzealDuodriveSpSummonCheck();
}
return flag;
}
......
......@@ -695,8 +695,8 @@ namespace WindBot.Game.AI.Decks
public override void OnChainSolved(int chainIndex)
{
ClientCard currentCard = Duel.GetCurrentSolvingChainCard();
if (currentCard != null && !Duel.IsCurrentSolvingChainNegated() && currentCard.Controller == 1)
ChainInfo currentCard = Duel.GetCurrentSolvingChainInfo();
if (currentCard != null && !Duel.IsCurrentSolvingChainNegated() && currentCard.ActivatePlayer == 1)
{
if (currentCard.IsCode(_CardId.MaxxC))
enemyActivateMaxxC = true;
......@@ -706,7 +706,7 @@ namespace WindBot.Game.AI.Decks
{
for (int i = 0; i < 5; ++i)
{
if (Enemy.SpellZone[i] == currentCard)
if (Enemy.SpellZone[i] == currentCard.RelatedCard)
{
infiniteImpermanenceList.Add(4 - i);
break;
......
......@@ -201,8 +201,8 @@ namespace WindBot.Game.AI.Decks
public override void OnChainSolved(int chainIndex)
{
ClientCard currentCard = Duel.GetCurrentSolvingChainCard();
if (currentCard != null && currentCard.Controller == 1)
ChainInfo currentCard = Duel.GetCurrentSolvingChainInfo();
if (currentCard != null && currentCard.ActivatePlayer == 1)
{
if (Duel.IsCurrentSolvingChainNegated())
{
......@@ -212,16 +212,16 @@ namespace WindBot.Game.AI.Decks
if (Bot.MonsterZone.GetFirstMatchingCard(c => c.HasRace(CardRace.SpellCaster) && c.IsFaceup()) != null
&& Bot.HasInSpellZone(CardId.MagicianRightHand, true))
{
Logger.DebugWriteLine("MagicianRightHand negate: " + currentCard.Name ?? "???");
Logger.DebugWriteLine("MagicianRightHand negate: " + currentCard.RelatedCard.Name ?? "???");
MagicianRightHand_used = true;
}
}
if (!MagiciansLeftHand_used && currentCard.IsTrap() && currentCard.Controller == 1)
if (!MagiciansLeftHand_used && currentCard.IsTrap() && currentCard.ActivatePlayer == 1)
{
if (Bot.MonsterZone.GetFirstMatchingCard(c => c.HasRace(CardRace.SpellCaster) && c.IsFaceup()) != null
&& Bot.HasInSpellZone(CardId.MagiciansLeftHand, true))
{
Logger.DebugWriteLine("MagiciansLeftHand negate: " + currentCard.Name ?? "???");
Logger.DebugWriteLine("MagiciansLeftHand negate: " + currentCard.RelatedCard.Name ?? "???");
MagiciansLeftHand_used = true;
}
}
......@@ -236,7 +236,7 @@ namespace WindBot.Game.AI.Decks
{
for (int i = 0; i < 5; ++i)
{
if (Enemy.SpellZone[i] == currentCard)
if (Enemy.SpellZone[i] == currentCard.RelatedCard)
{
Impermanence_list.Add(4 - i);
break;
......
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using YGOSharp.OCGWrapper;
using YGOSharp.OCGWrapper.Enums;
namespace WindBot.Game
{
public class ChainInfo
{
public ClientCard RelatedCard { get; private set; }
public int ActivatePlayer { get; private set; }
public int ActivateId { get; private set; }
public int ActivateController { get; private set; }
public int ActivatePosition { get; private set; }
public int ActivateSequence { get; private set; }
public CardLocation ActivateLocation { get; private set; }
public int ActivateLevel { get; private set; }
public int ActivateRank { get; private set; }
public int ActivateType { get; private set; }
public int ActivateRace { get; private set; }
public int ActivateAttack { get; private set; }
public int ActivateDefense { get; private set; }
public bool IsSpecialSummoned { get; private set; }
public int ActivateDescription { get; private set; }
public ChainInfo(ClientCard card)
: this(card, card.Controller, 0)
{
}
public ChainInfo(ClientCard card, int player, int desc)
{
RelatedCard = card;
ActivatePlayer = player;
ActivateId = card.Id;
ActivateController = card.Controller;
ActivatePosition = card.Position;
ActivateSequence = card.Sequence;
ActivateLocation = card.Location;
ActivateLevel = card.Level;
ActivateRank = card.Rank;
ActivateType = card.Type;
ActivateRace = card.Race;
ActivateAttack = card.Attack;
ActivateDefense = card.Defense;
ActivateAttack = card.Attack;
ActivateDefense = card.Defense;
IsSpecialSummoned = card.IsSpecialSummoned;
ActivateDescription = desc;
}
public bool HasPosition(CardPosition position)
{
return (ActivatePosition & (int)position) != 0;
}
public bool HasLocation(CardLocation location)
{
return ((int)ActivateLocation & (int)location) != 0;
}
public bool IsCode(int id)
{
return RelatedCard != null && RelatedCard.IsCode(id);
}
public bool IsCode(IList<int> ids)
{
return RelatedCard != null && RelatedCard.IsCode(ids);
}
public bool IsCode(params int[] ids)
{
return RelatedCard != null && RelatedCard.IsCode(ids);
}
public bool HasType(CardType type)
{
return RelatedCard != null && (RelatedCard.Type & (int)type) != 0;
}
public bool IsSpell()
{
return HasType(CardType.Spell);
}
public bool IsTrap()
{
return HasType(CardType.Trap);
}
}
}
......@@ -20,6 +20,7 @@ namespace WindBot.Game
public int LastChainPlayer { get; set; }
public CardLocation LastChainLocation { get; set; }
public IList<ClientCard> CurrentChain { get; set; }
public IList<ChainInfo> CurrentChainInfo { get; set; }
public IList<ClientCard> ChainTargets { get; set; }
public IList<ClientCard> LastChainTargets { get; set; }
public IList<ClientCard> ChainTargetOnly { get; set; }
......@@ -37,6 +38,7 @@ namespace WindBot.Game
LastChainPlayer = -1;
LastChainLocation = 0;
CurrentChain = new List<ClientCard>();
CurrentChainInfo = new List<ChainInfo>();
ChainTargets = new List<ClientCard>();
LastChainTargets = new List<ClientCard>();
ChainTargetOnly = new List<ClientCard>();
......@@ -180,6 +182,12 @@ namespace WindBot.Game
return CurrentChain[SolvingChainIndex - 1];
}
public ChainInfo GetCurrentSolvingChainInfo()
{
if (SolvingChainIndex == 0 || SolvingChainIndex > CurrentChainInfo.Count) return null;
return CurrentChainInfo[SolvingChainIndex - 1];
}
public bool IsCurrentSolvingChainNegated()
{
return SolvingChainIndex > 0 && NegatedChainIndexList.Contains(SolvingChainIndex);
......
......@@ -386,6 +386,7 @@ namespace WindBot.Game
// in case of ending duel in chain's solving
_duel.CurrentChain.Clear();
_duel.CurrentChainInfo.Clear();
_duel.ChainTargets.Clear();
_duel.ChainTargetOnly.Clear();
_duel.SummoningCards.Clear();
......@@ -764,6 +765,8 @@ namespace WindBot.Game
if (card.Id == 0)
card.SetId(cardId);
int cc = GetLocalPlayer(packet.ReadByte());
packet.ReadInt16(); // trigger location + trigger sequence
int desc = packet.ReadInt32();
if (_debug)
if (card != null) Logger.WriteLine("(" + cc.ToString() + " 's " + (card.Name ?? "UnKnowCard") + " activate effect from " + (CardLocation)pcl + ")");
_duel.LastChainLocation = (CardLocation)pcl;
......@@ -772,6 +775,7 @@ namespace WindBot.Game
_duel.ChainTargetOnly.Clear();
_duel.LastSummonPlayer = -1;
_duel.CurrentChain.Add(card);
_duel.CurrentChainInfo.Add(new ChainInfo(card, cc, desc));
_duel.LastChainPlayer = cc;
}
......@@ -806,6 +810,7 @@ namespace WindBot.Game
_duel.LastChainPlayer = -1;
_duel.LastChainLocation = 0;
_duel.CurrentChain.Clear();
_duel.CurrentChainInfo.Clear();
_duel.ChainTargets.Clear();
_duel.LastChainTargets.Clear();
_duel.ChainTargetOnly.Clear();
......
......@@ -144,6 +144,7 @@
<Compile Include="Game\AI\ExecutorType.cs" />
<Compile Include="Game\BattlePhase.cs" />
<Compile Include="Game\BattlePhaseAction.cs" />
<Compile Include="Game\ChainInfo.cs" />
<Compile Include="Game\ClientCard.cs" />
<Compile Include="Game\ClientField.cs" />
<Compile Include="Game\Deck.cs" />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment