Commit f2f54c2a authored by mercury233's avatar mercury233
parents b489285e c53428bc
......@@ -247,7 +247,7 @@ namespace WindBot.Game.AI
foreach (ClientCard ecard in spells)
{
if (ecard.IsFaceup())
if (ecard.IsFaceup() && ecard.HasType(CardType.Continuous))
return ecard;
}
......@@ -296,5 +296,85 @@ namespace WindBot.Game.AI
return Duel.ChainTargets.Count == 1 && card.Equals(Duel.ChainTargets[0]);
}
/// <summary>
/// Select cards listed in preferred.
/// </summary>
public void SelectPreferredCards(IList<ClientCard> selected, ClientCard preferred, IList<ClientCard> cards, int min, int max)
{
if (cards.IndexOf(preferred) > 0 && selected.Count < max)
{
selected.Add(preferred);
}
}
/// <summary>
/// Select cards listed in preferred.
/// </summary>
public void SelectPreferredCards(IList<ClientCard> selected, int preferred, IList<ClientCard> cards, int min, int max)
{
foreach (ClientCard card in cards)
{
if (card.Id== preferred && selected.Count < max)
selected.Add(card);
}
}
/// <summary>
/// Select cards listed in preferred.
/// </summary>
public void SelectPreferredCards(IList<ClientCard> selected, IList<ClientCard> preferred, IList<ClientCard> cards, int min, int max)
{
IList<ClientCard> avail = new List<ClientCard>();
foreach (ClientCard card in cards)
{
// clone
avail.Add(card);
}
while (preferred.Count > 0 && avail.IndexOf(preferred[0]) > 0 && selected.Count < max)
{
ClientCard card = preferred[0];
preferred.Remove(card);
avail.Remove(card);
selected.Add(card);
}
}
/// <summary>
/// Select cards listed in preferred.
/// </summary>
public void SelectPreferredCards(IList<ClientCard> selected, IList<int> preferred, IList<ClientCard> cards, int min, int max)
{
for (int i = 0; i < preferred.Count; i++)
{
foreach (ClientCard card in cards)
{
if (card.Id == preferred[i] && selected.Count < max && selected.IndexOf(card) <= 0)
selected.Add(card);
}
if (selected.Count >= max)
break;
}
}
/// <summary>
/// Check and fix selected to make sure it meet the count requirement.
/// </summary>
public void CheckSelectCount(IList<ClientCard> selected, IList<ClientCard> cards, int min, int max)
{
if (selected.Count < min)
{
foreach (ClientCard card in cards)
{
if (!selected.Contains(card))
selected.Add(card);
if (selected.Count >= max)
break;
}
}
while (selected.Count > max)
{
selected.RemoveAt(selected.Count - 1);
}
}
}
}
\ No newline at end of file
......@@ -132,7 +132,7 @@ namespace WindBot.Game.AI.Decks
SoulChargeUsed = false;
}
public override IList<ClientCard> OnSelectCard(IList<ClientCard> cards, int min, int max, bool cancelable)
public override IList<ClientCard> OnSelectCard(IList<ClientCard> cards, int min, int max, int hint, bool cancelable)
{
Logger.DebugWriteLine("OnSelectCard " + cards.Count + " " + min + " " + max);
if (max == 2 && cards[0].Location == CardLocation.Deck)
......@@ -157,60 +157,26 @@ namespace WindBot.Game.AI.Decks
result.Add(card);
}
}
if (result.Count < min)
{
foreach (ClientCard card in cards)
{
if (!result.Contains(card))
result.Add(card);
if (result.Count >= min)
break;
}
}
while (result.Count > max)
{
result.RemoveAt(result.Count - 1);
}
return result;
}
if (max == 2 && min == 2 && cards[0].Location == CardLocation.MonsterZone)
{
Logger.DebugWriteLine("OnSelectCard XYZ");
IList<ClientCard> avail = new List<ClientCard>();
foreach (ClientCard card in cards)
{
// clone
avail.Add(card);
}
IList<ClientCard> result = new List<ClientCard>();
while (UsedAlternativeWhiteDragon.Count > 0 && avail.IndexOf(UsedAlternativeWhiteDragon[0]) > 0)
{
Logger.DebugWriteLine("select UsedAlternativeWhiteDragon");
ClientCard card = UsedAlternativeWhiteDragon[0];
UsedAlternativeWhiteDragon.Remove(card);
avail.Remove(card);
result.Add(card);
}
if (result.Count < 2)
{
foreach (ClientCard card in cards)
{
if (!result.Contains(card))
result.Add(card);
if (result.Count >= 2)
break;
}
}
AI.Utils.CheckSelectCount(result, cards, min, max);
return result;
}
Logger.DebugWriteLine("Use default.");
return null;
}
public override IList<ClientCard> OnSelectSum(IList<ClientCard> cards, int sum, int min, int max, bool mode)
public override IList<ClientCard> OnSelectXyzMaterial(IList<ClientCard> cards, int min, int max)
{
Logger.DebugWriteLine("OnSelectXyzMaterial " + cards.Count + " " + min + " " + max);
IList<ClientCard> result = new List<ClientCard>();
AI.Utils.SelectPreferredCards(result, UsedAlternativeWhiteDragon, cards, min, max);
AI.Utils.CheckSelectCount(result, cards, min, max);
return result;
}
public override IList<ClientCard> OnSelectSynchroMaterial(IList<ClientCard> cards, int sum, int min, int max)
{
Logger.DebugWriteLine("OnSelectSum " + cards.Count + " " + sum + " " + min + " " + max);
if (sum != 8 || !mode)
Logger.DebugWriteLine("OnSelectSynchroMaterial " + cards.Count + " " + sum + " " + min + " " + max);
if (sum != 8)
return null;
foreach (ClientCard AlternativeWhiteDragon in UsedAlternativeWhiteDragon)
......
using YGOSharp.OCGWrapper.Enums;
using System.Collections.Generic;
using WindBot;
using WindBot.Game;
using WindBot.Game.AI;
namespace WindBot.Game.AI.Decks
{
[Deck("Test", "AI_Test", "Test")]
public class DoEverythingExecutor : DefaultExecutor
{
public class CardId
{
public const int LeoWizard = 4392470;
public const int Bunilla = 69380702;
}
public DoEverythingExecutor(GameAI ai, Duel duel)
: base(ai, duel)
{
AddExecutor(ExecutorType.SpSummon);
AddExecutor(ExecutorType.Activate, DefaultDontChainMyself);
AddExecutor(ExecutorType.SummonOrSet);
AddExecutor(ExecutorType.Repos, DefaultMonsterRepos);
AddExecutor(ExecutorType.SpellSet);
}
public override IList<ClientCard> OnSelectCard(IList<ClientCard> cards, int min, int max, bool cancelable)
{
if (Duel.Phase == DuelPhase.BattleStart)
return null;
IList<ClientCard> selected = new List<ClientCard>();
// select the last cards
for (int i = 1; i <= max; ++i)
selected.Add(cards[cards.Count-i]);
return selected;
}
public override int OnSelectOption(IList<int> options)
{
return Program.Rand.Next(options.Count);
}
}
using YGOSharp.OCGWrapper.Enums;
using System.Collections.Generic;
using WindBot;
using WindBot.Game;
using WindBot.Game.AI;
namespace WindBot.Game.AI.Decks
{
[Deck("Test", "AI_Test", "Test")]
public class DoEverythingExecutor : DefaultExecutor
{
public class CardId
{
public const int LeoWizard = 4392470;
public const int Bunilla = 69380702;
}
public DoEverythingExecutor(GameAI ai, Duel duel)
: base(ai, duel)
{
AddExecutor(ExecutorType.SpSummon);
AddExecutor(ExecutorType.Activate, DefaultDontChainMyself);
AddExecutor(ExecutorType.SummonOrSet);
AddExecutor(ExecutorType.Repos, DefaultMonsterRepos);
AddExecutor(ExecutorType.SpellSet);
}
public override IList<ClientCard> OnSelectCard(IList<ClientCard> cards, int min, int max, int hint, bool cancelable)
{
if (Duel.Phase == DuelPhase.BattleStart)
return null;
IList<ClientCard> selected = new List<ClientCard>();
// select the last cards
for (int i = 1; i <= max; ++i)
selected.Add(cards[cards.Count-i]);
return selected;
}
public override int OnSelectOption(IList<int> options)
{
return Program.Rand.Next(options.Count);
}
}
}
\ No newline at end of file
......@@ -103,39 +103,19 @@ namespace WindBot.Game.AI.Decks
return base.OnPreBattleBetween(attacker, defender);
}
public override IList<ClientCard> OnSelectCard(IList<ClientCard> cards, int min, int max, bool cancelable)
public override IList<ClientCard> OnSelectXyzMaterial(IList<ClientCard> cards, int min, int max)
{
if (max == 2 && min == 2 && cards[0].Location == CardLocation.MonsterZone)
Logger.DebugWriteLine("OnSelectXyzMaterial " + cards.Count + " " + min + " " + max);
IList<ClientCard> result = new List<ClientCard>();
foreach (ClientCard card in cards)
{
Logger.DebugWriteLine("OnSelectCard XYZ");
IList<ClientCard> avail = new List<ClientCard>();
foreach (ClientCard card in cards)
{
// clone
avail.Add(card);
}
IList<ClientCard> result = new List<ClientCard>();
foreach (ClientCard card in cards)
{
if (!result.Contains(card) && (!ClownUsed || card.Id != CardId.PerformageTrickClown))
result.Add(card);
if (result.Count >= 2)
break;
}
if (result.Count < 2)
{
foreach (ClientCard card in cards)
{
if (!result.Contains(card))
result.Add(card);
if (result.Count >= 2)
break;
}
}
return result;
if (!result.Contains(card) && (!ClownUsed || card.Id != CardId.PerformageTrickClown))
result.Add(card);
if (result.Count >= max)
break;
}
Logger.DebugWriteLine("Use default.");
return null;
AI.Utils.CheckSelectCount(result, cards, min, max);
return result;
}
private bool ReinforcementOfTheArmyEffect()
......
......@@ -132,14 +132,10 @@ namespace WindBot.Game.AI.Decks
CardOfDemiseUsed = false;
}
public override IList<ClientCard> OnSelectCard(IList<ClientCard> cards, int min, int max, bool cancelable)
public override IList<ClientCard> OnSelectPendulumSummon(IList<ClientCard> cards, int max)
{
if (max <= min)
{
return null;
}
// pendulum summon, select the last cards
Logger.DebugWriteLine("OnSelectPendulumSummon");
// select the last cards
IList<ClientCard> selected = new List<ClientCard>();
for (int i = 1; i <= max; ++i)
......
This diff is collapsed.
......@@ -118,6 +118,19 @@ namespace WindBot.Game.AI.Decks
Number61VolcasaurusUsed = false;
}
public override IList<ClientCard> OnSelectXyzMaterial(IList<ClientCard> cards, int min, int max)
{
IList<ClientCard> result = new List<ClientCard>();
AI.Utils.SelectPreferredCards(result, new[] {
CardId.MistArchfiend,
CardId.PanzerDragon,
CardId.SolarWindJammer,
CardId.StarDrawing
}, cards, min, max);
AI.Utils.CheckSelectCount(result, cards, min, max);
return result;
}
private bool NormalSummon()
{
NormalSummoned = true;
......
This diff is collapsed.
This diff is collapsed.
......@@ -136,6 +136,18 @@ namespace WindBot.Game.AI.Decks
return base.OnPreBattleBetween(attacker, defender);
}
public override IList<ClientCard> OnSelectXyzMaterial(IList<ClientCard> cards, int min, int max)
{
IList<ClientCard> result = new List<ClientCard>();
AI.Utils.SelectPreferredCards(result, new[] {
CardId.StarDrawing,
CardId.SolarWindJammer,
CardId.Goblindbergh
}, cards, min, max);
AI.Utils.CheckSelectCount(result, cards, min, max);
return result;
}
private bool Number39Utopia()
{
if (!HasChainedTrap(0) && Duel.Player == 1 && Duel.Phase == DuelPhase.BattleStart && Card.HasXyzMaterial(2))
......@@ -271,7 +283,7 @@ namespace WindBot.Game.AI.Decks
private bool MonsterRepos()
{
if (Card.Id == CardId.NumberS39UtopiatheLightning)
if (Card.Id == CardId.NumberS39UtopiatheLightning && Card.IsAttack())
return false;
return base.DefaultMonsterRepos();
}
......
......@@ -168,6 +168,12 @@ namespace WindBot.Game.AI.Decks
return true;
IList<ClientCard> materials0 = Bot.Graveyard;
IList<ClientCard> materials1 = Enemy.Graveyard;
IList<ClientCard> mats = new List<ClientCard>();
ClientCard aleister = GetAleisterInGrave();
if (aleister != null)
{
mats.Add(aleister);
}
ClientCard mat = null;
foreach (ClientCard card in materials0)
{
......@@ -187,9 +193,9 @@ namespace WindBot.Game.AI.Decks
}
if (mat != null)
{
mats.Add(mat);
AI.SelectCard(CardId.InvokedMechaba);
SelectAleisterInGrave();
AI.SelectThirdCard(mat);
AI.SelectMaterials(mats);
AI.SelectPosition(CardPosition.FaceUpAttack);
return true;
}
......@@ -211,41 +217,39 @@ namespace WindBot.Game.AI.Decks
}
if (mat != null)
{
mats.Add(mat);
AI.SelectCard(CardId.InvokedMagellanica);
SelectAleisterInGrave();
AI.SelectThirdCard(mat);
AI.SelectMaterials(mats);
AI.SelectPosition(CardPosition.FaceUpAttack);
return true;
}
return false;
}
private void SelectAleisterInGrave()
private ClientCard GetAleisterInGrave()
{
foreach (ClientCard card in Enemy.Graveyard)
{
if (card.Id == CardId.AleisterTheInvoker)
{
AI.SelectNextCard(card);
return;
return card;
}
}
foreach (ClientCard card in Bot.Graveyard)
{
if (card.Id == CardId.AleisterTheInvoker)
{
AI.SelectNextCard(card);
return;
return card;
}
}
AI.SelectNextCard(CardId.AleisterTheInvoker);
return null;
}
private bool ChakanineSummon()
{
if (Bot.HasInMonstersZone(CardId.Ratpier) && !ChakanineSpsummoned)
{
AI.SelectCard(CardId.Ratpier);
AI.SelectMaterials(CardId.Ratpier);
AI.SelectYesNo(true);
AI.SelectPosition(CardPosition.FaceUpDefence);
ChakanineSpsummoned = true;
......@@ -253,7 +257,7 @@ namespace WindBot.Game.AI.Decks
}
if (Bot.HasInMonstersZone(CardId.Broadbull) && !ChakanineSpsummoned)
{
AI.SelectCard(CardId.Broadbull);
AI.SelectMaterials(CardId.Broadbull);
AI.SelectYesNo(true);
AI.SelectPosition(CardPosition.FaceUpDefence);
ChakanineSpsummoned = true;
......@@ -289,7 +293,7 @@ namespace WindBot.Game.AI.Decks
{
if (Bot.HasInMonstersZone(CardId.Chakanine) && !TigermortarSpsummoned)
{
AI.SelectCard(CardId.Chakanine);
AI.SelectMaterials(CardId.Chakanine);
AI.SelectYesNo(true);
AI.SelectPosition(CardPosition.FaceUpDefence);
TigermortarSpsummoned = true;
......@@ -297,7 +301,7 @@ namespace WindBot.Game.AI.Decks
}
if (Bot.HasInMonstersZone(CardId.Ratpier) && !TigermortarSpsummoned)
{
AI.SelectCard(CardId.Ratpier);
AI.SelectMaterials(CardId.Ratpier);
AI.SelectYesNo(true);
AI.SelectPosition(CardPosition.FaceUpDefence);
TigermortarSpsummoned = true;
......@@ -310,7 +314,7 @@ namespace WindBot.Game.AI.Decks
CardId.Ratpier
}))
{
AI.SelectCard(CardId.Thoroughblade);
AI.SelectMaterials(CardId.Thoroughblade);
AI.SelectYesNo(true);
TigermortarSpsummoned = true;
return true;
......@@ -318,7 +322,7 @@ namespace WindBot.Game.AI.Decks
if (Bot.HasInMonstersZone(CardId.Whiptail) && !TigermortarSpsummoned
&& Bot.HasInGraveyard(CardId.Ratpier))
{
AI.SelectCard(CardId.Whiptail);
AI.SelectMaterials(CardId.Whiptail);
AI.SelectYesNo(true);
TigermortarSpsummoned = true;
return true;
......@@ -345,7 +349,7 @@ namespace WindBot.Game.AI.Decks
{
if (Bot.HasInMonstersZone(CardId.Tigermortar) && !BroadbullSpsummoned)
{
AI.SelectCard(CardId.Tigermortar);
AI.SelectMaterials(CardId.Tigermortar);
AI.SelectYesNo(true);
AI.SelectPosition(CardPosition.FaceUpDefence);
BroadbullSpsummoned = true;
......@@ -353,7 +357,7 @@ namespace WindBot.Game.AI.Decks
}
if (Bot.HasInMonstersZone(CardId.Chakanine) && !BroadbullSpsummoned)
{
AI.SelectCard(CardId.Chakanine);
AI.SelectMaterials(CardId.Chakanine);
AI.SelectYesNo(true);
AI.SelectPosition(CardPosition.FaceUpDefence);
BroadbullSpsummoned = true;
......@@ -361,7 +365,7 @@ namespace WindBot.Game.AI.Decks
}
if (Bot.HasInMonstersZone(CardId.Ratpier) && !BroadbullSpsummoned)
{
AI.SelectCard(CardId.Ratpier);
AI.SelectMaterials(CardId.Ratpier);
AI.SelectYesNo(true);
AI.SelectPosition(CardPosition.FaceUpDefence);
BroadbullSpsummoned = true;
......@@ -369,7 +373,7 @@ namespace WindBot.Game.AI.Decks
}
if (Bot.HasInMonstersZone(CardId.Thoroughblade) && !BroadbullSpsummoned)
{
AI.SelectCard(CardId.Thoroughblade);
AI.SelectMaterials(CardId.Thoroughblade);
AI.SelectYesNo(true);
AI.SelectPosition(CardPosition.FaceUpDefence);
BroadbullSpsummoned = true;
......@@ -399,7 +403,7 @@ namespace WindBot.Game.AI.Decks
{
AI.SelectYesNo(false);
AI.SelectPosition(CardPosition.FaceUpDefence);
AI.SelectCard(new[]
AI.SelectMaterials(new[]
{
CardId.Ratpier,
CardId.PhotonThrasher,
......@@ -411,7 +415,7 @@ namespace WindBot.Game.AI.Decks
private bool DridentSummon()
{
AI.SelectCard(new[]
AI.SelectMaterials(new[]
{
CardId.Broadbull,
CardId.Tigermortar,
......@@ -502,6 +506,11 @@ namespace WindBot.Game.AI.Decks
private bool DaigustoEmeralSummon()
{
AI.SelectMaterials(new[]
{
CardId.PhotonThrasher,
CardId.AleisterTheInvoker
});
return Bot.GetGraveyardMonsters().Count >= 3;
}
......@@ -595,7 +604,7 @@ namespace WindBot.Game.AI.Decks
private bool MonsterRepos()
{
if (Card.Id == CardId.NumberS39UtopiatheLightning)
if (Card.Id == CardId.NumberS39UtopiatheLightning && Card.IsAttack())
return false;
return base.DefaultMonsterRepos();
}
......
......@@ -58,10 +58,10 @@ namespace WindBot.Game.AI
if (defender.IsMonsterDangerous() || (defender.IsMonsterInvincible() && defender.IsDefense()))
return false;
if (defender.Id == _CardId.CrystalWingSynchroDragon && !defender.IsDisabled() && attacker.Level >= 5)
if (defender.Id == _CardId.CrystalWingSynchroDragon && defender.IsAttack() && !defender.IsDisabled() && attacker.Level >= 5)
return false;
if (defender.Id == _CardId.NumberS39UtopiaTheLightning && !defender.IsDisabled() && defender.HasXyzMaterial(2, _CardId.Number39Utopia))
if (defender.Id == _CardId.NumberS39UtopiaTheLightning && defender.IsAttack() && !defender.IsDisabled() && defender.HasXyzMaterial(2, _CardId.Number39Utopia))
defender.RealPower = 5000;
}
......
......@@ -124,13 +124,49 @@ namespace WindBot.Game.AI
// Some AI need do something on new turn
}
public virtual IList<ClientCard> OnSelectCard(IList<ClientCard> cards, int min, int max, bool cancelable)
public virtual IList<ClientCard> OnSelectCard(IList<ClientCard> cards, int min, int max, int hint, bool cancelable)
{
// For overriding
return null;
}
public virtual IList<ClientCard> OnSelectSum(IList<ClientCard> cards, int sum, int min, int max, bool mode)
public virtual IList<ClientCard> OnSelectSum(IList<ClientCard> cards, int sum, int min, int max, int hint, bool mode)
{
// For overriding
return null;
}
public virtual IList<ClientCard> OnSelectFusionMaterial(IList<ClientCard> cards, int min, int max)
{
// For overriding
return null;
}
public virtual IList<ClientCard> OnSelectSynchroMaterial(IList<ClientCard> cards, int sum, int min, int max)
{
// For overriding
return null;
}
public virtual IList<ClientCard> OnSelectXyzMaterial(IList<ClientCard> cards, int min, int max)
{
// For overriding
return null;
}
public virtual IList<ClientCard> OnSelectLinkMaterial(IList<ClientCard> cards, int min, int max)
{
// For overriding
return null;
}
public virtual IList<ClientCard> OnSelectRitualTribute(IList<ClientCard> cards, int sum, int min, int max)
{
// For overriding
return null;
}
public virtual IList<ClientCard> OnSelectPendulumSummon(IList<ClientCard> cards, int max)
{
// For overriding
return null;
......
......@@ -85,6 +85,8 @@ namespace WindBot.Game
{
m_selector = null;
m_nextSelector = null;
m_thirdSelector = null;
m_materialSelector = null;
m_option = -1;
m_yesno = -1;
m_position = CardPosition.FaceUpAttack;
......@@ -158,17 +160,60 @@ namespace WindBot.Game
/// <param name="cards">List of available cards.</param>
/// <param name="min">Minimal quantity.</param>
/// <param name="max">Maximal quantity.</param>
/// <param name="hint">The hint message of the select.</param>
/// <param name="cancelable">True if you can return an empty list.</param>
/// <returns>A new list containing the selected cards.</returns>
public IList<ClientCard> OnSelectCard(IList<ClientCard> cards, int min, int max, bool cancelable)
public IList<ClientCard> OnSelectCard(IList<ClientCard> cards, int min, int max, int hint, bool cancelable)
{
const int HINTMSG_FMATERIAL = 511;
const int HINTMSG_SMATERIAL = 512;
const int HINTMSG_XMATERIAL = 513;
const int HINTMSG_LMATERIAL = 533;
const int HINTMSG_SPSUMMON = 509;
// Check for the executor.
IList<ClientCard> result = Executor.OnSelectCard(cards, min, max, cancelable);
IList<ClientCard> result = Executor.OnSelectCard(cards, min, max, hint, cancelable);
if (result != null)
return result;
// Update the next selector.
CardSelector selector = GetSelectedCards();
if (hint == HINTMSG_SPSUMMON && min == 1 && max > min) // pendulum summon
{
result = Executor.OnSelectPendulumSummon(cards, max);
if (result != null)
return result;
}
CardSelector selector = null;
if (hint == HINTMSG_FMATERIAL || hint == HINTMSG_SMATERIAL || hint == HINTMSG_XMATERIAL || hint == HINTMSG_LMATERIAL)
{
if (m_materialSelector != null)
{
//Logger.DebugWriteLine("m_materialSelector");
selector = m_materialSelector;
}
else
{
if (hint == HINTMSG_FMATERIAL)
result = Executor.OnSelectFusionMaterial(cards, min, max);
if (hint == HINTMSG_SMATERIAL)
result = Executor.OnSelectSynchroMaterial(cards, 0, min, max);
if (hint == HINTMSG_XMATERIAL)
result = Executor.OnSelectXyzMaterial(cards, min, max);
if (hint == HINTMSG_LMATERIAL)
result = Executor.OnSelectLinkMaterial(cards, min, max);
if (result != null)
return result;
// Update the next selector.
selector = GetSelectedCards();
}
}
else
{
// Update the next selector.
selector = GetSelectedCards();
}
// If we selected a card, use this card.
if (selector != null)
......@@ -373,14 +418,45 @@ namespace WindBot.Game
/// <param name="max">Maximum cards.</param>
/// <param name="mode">True for exact equal.</param>
/// <returns></returns>
public IList<ClientCard> OnSelectSum(IList<ClientCard> cards, int sum, int min, int max, bool mode)
public IList<ClientCard> OnSelectSum(IList<ClientCard> cards, int sum, int min, int max, int hint, bool mode)
{
IList<ClientCard> selected = Executor.OnSelectSum(cards, sum, min, max, mode);
const int HINTMSG_RELEASE = 500;
const int HINTMSG_SMATERIAL = 512;
IList<ClientCard> selected = Executor.OnSelectSum(cards, sum, min, max, hint, mode);
if (selected != null)
{
return selected;
}
if (hint == HINTMSG_RELEASE || hint == HINTMSG_SMATERIAL)
{
if (m_materialSelector != null)
{
selected = m_materialSelector.Select(cards, min, max);
}
else
{
if (hint == HINTMSG_SMATERIAL)
selected = Executor.OnSelectSynchroMaterial(cards, sum, min, max);
if (hint == HINTMSG_RELEASE)
selected = Executor.OnSelectRitualTribute(cards, sum, min, max);
}
if (selected != null)
{
int s1 = 0, s2 = 0;
foreach (ClientCard card in selected)
{
s1 += card.OpParam1;
s2 += (card.OpParam2 != 0) ? card.OpParam2 : card.OpParam1;
}
if ((mode && (s1 == sum || s2 == sum)) || (!mode && (s1 >= sum || s2 >= sum)))
{
return selected;
}
}
}
if (mode)
{
// equal
......@@ -497,9 +573,10 @@ namespace WindBot.Game
/// <param name="cards">List of available cards.</param>
/// <param name="min">Minimal quantity.</param>
/// <param name="max">Maximal quantity.</param>
/// <param name="hint">The hint message of the select.</param>
/// <param name="cancelable">True if you can return an empty list.</param>
/// <returns>A new list containing the tributed cards.</returns>
public IList<ClientCard> OnSelectTribute(IList<ClientCard> cards, int min, int max, bool cancelable)
public IList<ClientCard> OnSelectTribute(IList<ClientCard> cards, int min, int max, int hint, bool cancelable)
{
// Always choose the minimum and lowest atk.
List<ClientCard> sorted = new List<ClientCard>();
......@@ -543,6 +620,7 @@ namespace WindBot.Game
private CardSelector m_selector;
private CardSelector m_nextSelector;
private CardSelector m_thirdSelector;
private CardSelector m_materialSelector;
private CardPosition m_position = CardPosition.FaceUpAttack;
private int m_option;
private int m_number;
......@@ -626,6 +704,36 @@ namespace WindBot.Game
m_thirdSelector = new CardSelector(loc);
}
public void SelectMaterials(ClientCard card)
{
m_materialSelector = new CardSelector(card);
}
public void SelectMaterials(IList<ClientCard> cards)
{
m_materialSelector = new CardSelector(cards);
}
public void SelectMaterials(int cardId)
{
m_materialSelector = new CardSelector(cardId);
}
public void SelectMaterials(IList<int> ids)
{
m_materialSelector = new CardSelector(ids);
}
public void SelectMaterials(CardLocation loc)
{
m_materialSelector = new CardSelector(loc);
}
public void CleanSelectMaterials()
{
m_materialSelector = null;
}
public CardSelector GetSelectedCards()
{
CardSelector selected = m_selector;
......
......@@ -25,6 +25,7 @@ namespace WindBot.Game
private Room _room;
private Duel _duel;
private int _hand;
private int _select_hint;
public GameBehavior(GameClient game)
{
......@@ -42,6 +43,8 @@ namespace WindBot.Game
_ai = new GameAI(Game, _duel);
_ai.Executor = DecksManager.Instantiate(_ai, _duel);
Deck = Deck.Load(_ai.Executor.Deck);
_select_hint = 0;
}
public int GetLocalPlayer(int player)
......@@ -80,6 +83,7 @@ namespace WindBot.Game
_messages.Add(GameMessage.Retry, OnRetry);
_messages.Add(GameMessage.Start, OnStart);
_messages.Add(GameMessage.Hint, OnHint);
_messages.Add(GameMessage.Win, OnWin);
_messages.Add(GameMessage.Draw, OnDraw);
_messages.Add(GameMessage.ShuffleDeck, OnShuffleDeck);
......@@ -120,6 +124,9 @@ namespace WindBot.Game
_messages.Add(GameMessage.AnnounceRace, OnAnnounceRace);
_messages.Add(GameMessage.AnnounceCardFilter, OnAnnounceCard);
_messages.Add(GameMessage.RockPaperScissors, OnRockPaperScissors);
_messages.Add(GameMessage.SpSummoning, OnSpSummon);
_messages.Add(GameMessage.SpSummoned, OnSpSummon);
}
private void OnJoinGame(BinaryReader packet)
......@@ -295,6 +302,17 @@ namespace WindBot.Game
throw new Exception("Got MSG_RETRY.");
}
private void OnHint(BinaryReader packet)
{
int type = packet.ReadByte();
int player = packet.ReadByte();
int data = packet.ReadInt32();
if (type == 3) // HINT_SELECTMSG
{
_select_hint = data;
}
}
private void OnStart(BinaryReader packet)
{
int type = packet.ReadByte();
......@@ -643,7 +661,7 @@ namespace WindBot.Game
Connection.Send(CtosMessage.Response, _ai.OnSelectBattleCmd(battle).ToValue());
}
private void InternalOnSelectCard(BinaryReader packet, Func<IList<ClientCard>, int, int, bool, IList<ClientCard>> func)
private void InternalOnSelectCard(BinaryReader packet, Func<IList<ClientCard>, int, int, int, bool, IList<ClientCard>> func)
{
packet.ReadByte(); // player
bool cancelable = packet.ReadByte() != 0;
......@@ -670,7 +688,8 @@ namespace WindBot.Game
cards.Add(card);
}
IList<ClientCard> selected = func(cards, min, max, cancelable);
IList<ClientCard> selected = func(cards, min, max, _select_hint, cancelable);
_select_hint = 0;
if (selected.Count == 0 && cancelable)
{
......@@ -1027,7 +1046,8 @@ namespace WindBot.Game
sumval -= mandatoryCards[k].OpParam1;
}
IList<ClientCard> selected = _ai.OnSelectSum(cards, sumval, min, max, mode);
IList<ClientCard> selected = _ai.OnSelectSum(cards, sumval, min, max, _select_hint, mode);
_select_hint = 0;
byte[] result = new byte[mandatoryCards.Count + selected.Count + 1];
int index = 0;
......@@ -1125,5 +1145,10 @@ namespace WindBot.Game
result = _ai.OnRockPaperScissors();
Connection.Send(CtosMessage.Response, result);
}
private void OnSpSummon(BinaryReader packet)
{
_ai.CleanSelectMaterials();
}
}
}
\ No newline at end of file
......@@ -111,6 +111,40 @@ The parameters are same as commandlines, but low cased.
* If one chain includes two activation that use `AI.SelectCard`, the second one won't select correctly.
### Changelog
#### v0x1340 (2017-11-06)
- Update YGOPro protrol to 0x1340
- Add support for the New Master Rule
- Decks update
- New commandline parameters
- Add support for Match and TAG duel
- Add server mode
- Bot dialogs now customable
- Only use normal deck when random picking decks
- Send sorry when the AI did something wrong that make the duel can't continue (for example, selected illegal card)
- Send info when the deck of the AI is illegal (for example, lflist dismatch)
- Fix the issue that the bot will attack _Dupe Frog_ with low attack monster when there is monster next to _Dupe Frog_
- Fix the issue that synchro summon stuck in some condition [\#7](https://github.com/IceYGO/windbot/issues/7)
- Fix C#6.0 (VS2015) support
- Fix `OnUpdateData`
- New and updated `DefaultExecutor`
- New and updated `AI.Utils`, `ClientCard`, `ClientField` functions
- Add `OnNewTurn`, `AI.SelectYesNo`, `AI.SelectThirdCard`, `Duel.ChainTargets`, `Duel.LastSummonPlayer`
- Shortcut `Bot` for `Duel.Fields[0]`, `Enemy` for `Duel.Fields[1]`
- `CardId` is now class instead of enum so `(int)` is no longer needed
- Update the known card enums, add `Floodgate`, `OneForXyz`, `FusionSpell`, `MonsterHasPreventActivationEffectInBattle`
- Update `OnPreBattleBetween` to calculate the ATK of cards like _Number S39: Utopia the Lightning_
- Update direct attack handling
#### v0x133D (2017-09-24)
- Update YGOPro protrol to 0x133D
- Use the latest YGOSharp.Network to improve performances
- Update the namespace of `YGOSharp.OCGWrapper`
- Fix the default trap cards not always activating
### TODO list
* More decks
......
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