Commit f6eae0a7 authored by mercury233's avatar mercury233

fully implement announce card

parent 59231c54
......@@ -438,32 +438,6 @@ namespace WindBot.Game.AI.Decks
return base.OnSelectPosition(cardId, positions);
}
/// <summary>
/// Override for CrossoutDesignator
/// </summary>
/// <param name="opcodes">Operation codes for limitation.</param>
/// <param name="preAnnouced">Card's id prepared to annouce.</param>
/// <returns>Card's id to annouce.</returns>
public override int OnAnnounceCard(IList<int> opcodes, int preAnnouced)
{
const int OPCODE_OR = 0x40000005;
const int OPCODE_ISCODE = 0x40000100;
IList<int> codes = new List<int>();
foreach (int opcode in opcodes) {
if (opcode != OPCODE_OR && opcode != OPCODE_ISCODE)
{
codes.Add(opcode);
}
}
// if annouced card not in required list, return random card from list.
if (!codes.Contains(preAnnouced))
{
Logger.DebugWriteLine("No annouced card in required list, annouce randomly.");
return codes[Program.Rand.Next(codes.Count)];
}
return base.OnAnnounceCard(opcodes, preAnnouced);
}
// shuffle List<ClientCard>
public List<ClientCard> CardListShuffle(List<ClientCard> list)
{
......
......@@ -189,16 +189,14 @@ namespace WindBot.Game.AI
}
/// <summary>
/// Called when bot is going to annouce a card, to check whether it's legel(to avoid error)
/// For full implement of opcodes, see ygopro-core/playerop.cpp#is_declarable
/// Called when bot is going to annouce a card
/// </summary>
/// <param name="opcodes">Operation codes for limitation.</param>
/// <param name="preAnnouced">Card's id prepared to annouce.</param>
/// <param name="avail">Available card's ids.</param>
/// <returns>Card's id to annouce.</returns>
public virtual int OnAnnounceCard(IList<int> opcodes, int preAnnouced)
public virtual int OnAnnounceCard(IList<int> avail)
{
// For overriding
return preAnnouced;
return 0;
}
public void SetMain(MainPhase main)
......
namespace WindBot.Game.AI
{
public static class Opcodes
{
public const int OPCODE_ADD = 0x40000000,
OPCODE_SUB = 0x40000001,
OPCODE_MUL = 0x40000002,
OPCODE_DIV = 0x40000003,
OPCODE_AND = 0x40000004,
OPCODE_OR = 0x40000005,
OPCODE_NEG = 0x40000006,
OPCODE_NOT = 0x40000007,
OPCODE_ISCODE = 0x40000100,
OPCODE_ISSETCARD = 0x40000101,
OPCODE_ISTYPE = 0x40000102,
OPCODE_ISRACE = 0x40000103,
OPCODE_ISATTRIBUTE = 0x40000104;
}
}
\ No newline at end of file
......@@ -95,6 +95,7 @@ namespace WindBot.Game
m_materialSelector = null;
m_option = -1;
m_yesno = -1;
m_announce = 0;
m_place = 0;
if (Duel.Player == 0 && Duel.Phase == DuelPhase.Draw)
......@@ -734,14 +735,18 @@ namespace WindBot.Game
/// <summary>
/// Called when the AI has to declare a card.
/// </summary>
/// <param name="opcodes">Operation lists.</param>
/// <param name="avail">Available card's ids.</param>
/// <returns>Id of the selected card.</returns>
public int OnAnnounceCard(IList<int> opcodes)
public int OnAnnounceCard(IList<int> avail)
{
if (m_announce == 0)
return Executor.OnAnnounceCard(opcodes, 89631139); // Blue-eyes white dragon
return Executor.OnAnnounceCard(opcodes, m_announce);
int selected = Executor.OnAnnounceCard(avail);
if (avail.Contains(selected))
return selected;
if (avail.Contains(m_announce))
return m_announce;
else if (m_announce > 0)
Logger.WriteErrorLine("Pre-announced card cant be used: " + m_announce);
return avail[0];
}
// _ Others functions _
......
......@@ -1445,11 +1445,152 @@ namespace WindBot.Game
packet.ReadByte(); // player
int count = packet.ReadByte();
for (int i = 0; i < count; ++i)
{
opcodes.Add(packet.ReadInt32());
IList<int> avail = new List<int>();
IList<NamedCard> all = NamedCardsManager.GetAllCards();
foreach (NamedCard card in all)
{
if (card.HasType(CardType.Token) || (card.Alias > 0 && card.Id - card.Alias < 10)) continue;
Stack<int> stack = new Stack<int>();
for (int i = 0; i < opcodes.Count; i++)
{
switch (opcodes[i])
{
case Opcodes.OPCODE_ADD:
if (stack.Count >= 2)
{
int rhs = stack.Pop();
int lhs = stack.Pop();
stack.Push(lhs + rhs);
}
break;
case Opcodes.OPCODE_SUB:
if (stack.Count >= 2)
{
int rhs = stack.Pop();
int lhs = stack.Pop();
stack.Push(lhs - rhs);
}
break;
case Opcodes.OPCODE_MUL:
if (stack.Count >= 2)
{
int rhs = stack.Pop();
int lhs = stack.Pop();
stack.Push(lhs * rhs);
}
break;
case Opcodes.OPCODE_DIV:
if (stack.Count >= 2)
{
int rhs = stack.Pop();
int lhs = stack.Pop();
stack.Push(lhs / rhs);
}
break;
case Opcodes.OPCODE_AND:
if (stack.Count >= 2)
{
int rhs = stack.Pop();
int lhs = stack.Pop();
bool b0 = rhs != 0;
bool b1 = lhs != 0;
if (b0 && b1)
stack.Push(1);
else
stack.Push(0);
}
break;
case Opcodes.OPCODE_OR:
if (stack.Count >= 2)
{
int rhs = stack.Pop();
int lhs = stack.Pop();
bool b0 = rhs != 0;
bool b1 = lhs != 0;
if (b0 || b1)
stack.Push(1);
else
stack.Push(0);
}
break;
case Opcodes.OPCODE_NEG:
if (stack.Count >= 1)
{
int rhs = stack.Pop();
stack.Push(-rhs);
}
break;
case Opcodes.OPCODE_NOT:
if (stack.Count >= 1)
{
int rhs = stack.Pop();
bool b0 = rhs != 0;
if (b0)
stack.Push(0);
else
stack.Push(1);
}
break;
case Opcodes.OPCODE_ISCODE:
if (stack.Count >= 1)
{
int code = stack.Pop();
bool b0 = code == card.Id;
if (b0)
stack.Push(1);
else
stack.Push(0);
}
break;
case Opcodes.OPCODE_ISSETCARD:
if (stack.Count >= 1)
{
if (card.HasSetcode(stack.Pop()))
stack.Push(1);
else
stack.Push(0);
}
break;
case Opcodes.OPCODE_ISTYPE:
if (stack.Count >= 1)
{
if ((stack.Pop() & card.Type) > 0)
stack.Push(1);
else
stack.Push(0);
}
break;
case Opcodes.OPCODE_ISRACE:
if (stack.Count >= 1)
{
if ((stack.Pop() & card.Race) > 0)
stack.Push(1);
else
stack.Push(0);
}
break;
case Opcodes.OPCODE_ISATTRIBUTE:
if (stack.Count >= 1)
{
if ((stack.Pop() & card.Attribute) > 0)
stack.Push(1);
else
stack.Push(0);
}
break;
default:
stack.Push(opcodes[i]);
break;
}
}
if (stack.Count == 1 && stack.Pop() != 0)
avail.Add(card.Id);
}
// not fully implemented
Connection.Send(CtosMessage.Response, _ai.OnAnnounceCard(opcodes));
if (avail.Count == 0)
throw new Exception("No avail card found for announce!");
Connection.Send(CtosMessage.Response, _ai.OnAnnounceCard(avail));
}
private void OnAnnounceNumber(BinaryReader packet)
......
......@@ -37,6 +37,9 @@
<PropertyGroup>
<ApplicationIcon>WindBot.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Data.Sqlite">
<HintPath>.\Mono.Data.Sqlite.dll</HintPath>
......@@ -120,6 +123,7 @@
<Compile Include="Game\AI\Enums\InvincibleMonster.cs" />
<Compile Include="Game\AI\Enums\Floodgate.cs" />
<Compile Include="Game\AI\Executor.cs" />
<Compile Include="Game\AI\Opcodes.cs" />
<Compile Include="Game\AI\Zones.cs" />
<Compile Include="Game\AI\ExecutorType.cs" />
<Compile Include="Game\BattlePhase.cs" />
......
No preview for this file type
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