Commit 35750167 authored by mercury233's avatar mercury233

add AI.SelectMaterials, OnSelectFusionMaterial, OnSelectPendulumSummon etc.

parent fae602cf
......@@ -296,5 +296,25 @@ namespace WindBot.Game.AI
return Duel.ChainTargets.Count == 1 && card.Equals(Duel.ChainTargets[0]);
}
/// <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,25 +157,16 @@ 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);
}
AI.Utils.CheckSelectCount(result, cards, min, max);
return result;
}
if (max == 2 && min == 2 && cards[0].Location == CardLocation.MonsterZone)
Logger.DebugWriteLine("Use default.");
return null;
}
public override IList<ClientCard> OnSelectXyzMaterial(IList<ClientCard> cards, int min, int max)
{
Logger.DebugWriteLine("OnSelectCard XYZ");
Logger.DebugWriteLine("OnSelectXyzMaterial " + cards.Count + " " + min + " " + max);
IList<ClientCard> avail = new List<ClientCard>();
foreach (ClientCard card in cards)
{
......@@ -191,26 +182,14 @@ namespace WindBot.Game.AI.Decks
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> 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)
......
......@@ -25,7 +25,7 @@ namespace WindBot.Game.AI.Decks
AddExecutor(ExecutorType.SpellSet);
}
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)
{
if (Duel.Phase == DuelPhase.BattleStart)
return null;
......
......@@ -103,11 +103,9 @@ 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("OnSelectCard XYZ");
Logger.DebugWriteLine("OnSelectXyzMaterial " + cards.Count + " " + min + " " + max);
IList<ClientCard> avail = new List<ClientCard>();
foreach (ClientCard card in cards)
{
......@@ -119,24 +117,12 @@ namespace WindBot.Game.AI.Decks
{
if (!result.Contains(card) && (!ClownUsed || card.Id != CardId.PerformageTrickClown))
result.Add(card);
if (result.Count >= 2)
if (result.Count >= max)
break;
}
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;
}
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)
......
......@@ -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;
......
......@@ -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;
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.
CardSelector selector = GetSelectedCards();
selector = GetSelectedCards();
}
}
else
{
// Update the next selector.
selector = GetSelectedCards();
}
// If we selected a card, use this card.
if (selector != null)
......@@ -373,13 +418,44 @@ 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)
{
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)
{
IList<ClientCard> selected = Executor.OnSelectSum(cards, sum, min, max, mode);
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)
{
......@@ -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
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