Commit 9e43b313 authored by wind2009's avatar wind2009

Merge remote-tracking branch 'wind/AI_Apophis' into server_preupdate

parents 69ab5898 69846aef
...@@ -272,4 +272,9 @@ AI_LV4 SUPPORT_MASTER_RULE_2020 ...@@ -272,4 +272,9 @@ AI_LV4 SUPPORT_MASTER_RULE_2020
!今晚有宵夜吗-码丽丝 !今晚有宵夜吗-码丽丝
Name=今晚有宵夜吗 Deck=MalissOCG Dialog=Xiaoye.zh-CN Name=今晚有宵夜吗 Deck=MalissOCG Dialog=Xiaoye.zh-CN
码丽丝卡组。 码丽丝卡组。
AI_LV4 SUPPORT_MASTER_RULE_2020
!尼亚-王家的神殿
Name=尼亚 Deck=Apophis Dialog=near.zh-CN
王家的神殿卡组。
AI_LV4 SUPPORT_MASTER_RULE_2020 AI_LV4 SUPPORT_MASTER_RULE_2020
\ No newline at end of file
#created by ...
#main
62514770
60411677
60411677
63198739
63198739
97522863
97522863
97522863
49238328
49238328
73628505
29095457
56506740
56506740
56506740
69299029
69299029
69299029
6325660
6325660
6325660
10045474
10045474
10045474
40366667
40366667
58053438
58053438
58053438
97045737
97045737
97045737
85888377
85888377
95561146
95561146
95561146
59576447
78114463
78114463
#extra
97800311
97800311
97800311
96633955
96633955
84815190
84815190
26096328
38354018
46772449
29301450
1528054
1528054
98978921
98978921
!side
This source diff could not be displayed because it is too large. You can view the blob instead.
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using YGOSharp.OCGWrapper.Enums; using YGOSharp.OCGWrapper.Enums;
...@@ -143,6 +143,12 @@ namespace WindBot.Game.AI ...@@ -143,6 +143,12 @@ namespace WindBot.Game.AI
public const int VaylantzWorld_KonigWissen = 75952542; public const int VaylantzWorld_KonigWissen = 75952542;
public const int DivineArsenalAAZEUS_SkyThunder = 90448279; public const int DivineArsenalAAZEUS_SkyThunder = 90448279;
public const int LightningStorm = 14532163; public const int LightningStorm = 14532163;
public const int MistakenArrest = 4227096;
public const int ThunderKingRaiOh = 71564252;
public const int ThunderDragonColossus = 15291624;
public const int DeckLockdown = 1149109;
public const int DoomZDestruction = 80320877;
public const int Mistake = 59305593;
public const int BelialMarquisOfDarkness = 33655493; public const int BelialMarquisOfDarkness = 33655493;
public const int ChirubiméPrincessOfAutumnLeaves = 87294988; public const int ChirubiméPrincessOfAutumnLeaves = 87294988;
...@@ -224,6 +230,8 @@ namespace WindBot.Game.AI ...@@ -224,6 +230,8 @@ namespace WindBot.Game.AI
public const int EarthboundImmortal = 0x1021; public const int EarthboundImmortal = 0x1021;
public const int Naturia = 0x2a; public const int Naturia = 0x2a;
public const int Nordic = 0x42; public const int Nordic = 0x42;
public const int TimeLord = 0x4a;
public const int Harpie = 0x64; public const int Harpie = 0x64;
public const int Madolche = 0x71; public const int Madolche = 0x71;
public const int Ghostrick = 0x8d; public const int Ghostrick = 0x8d;
...@@ -255,6 +263,18 @@ namespace WindBot.Game.AI ...@@ -255,6 +263,18 @@ namespace WindBot.Game.AI
protected int lightningStormOption = -1; protected int lightningStormOption = -1;
Dictionary<int, int> calledbytheGraveIdCountMap = new Dictionary<int, int>(); Dictionary<int, int> calledbytheGraveIdCountMap = new Dictionary<int, int>();
List<int> crossoutDesignatorIdList = new List<int>(); List<int> crossoutDesignatorIdList = new List<int>();
int mistakenArrestAffectedCount = 0;
/// <summary>
/// List of effect IDs that have been resolved this turn.
/// </summary>
protected List<int> resolvedEffectIdList = new List<int>();
/// <summary>
/// List of effect IDs that have been resolved by enemy this turn.
/// </summary>
protected List<int> enemyResolvedEffectIdList = new List<int>();
/// <summary>Columns 0-4 on Bot's field negated by Infinite Impermanence (enemy's col converted to ours: 4-col). Cleared at turn start.</summary>
protected List<int> infiniteImpermanenceNegatedColumns = new List<int>();
/// <summary> /// <summary>
/// Defined: /// Defined:
...@@ -578,6 +598,42 @@ namespace WindBot.Game.AI ...@@ -578,6 +598,42 @@ namespace WindBot.Game.AI
return null; return null;
} }
public override void OnPlayerHint(int player, int hintType, int description)
{
base.OnPlayerHint(player, hintType, description);
if (player != 0 && player != 1)
return;
ClientField field = (player == 0) ? Bot : Enemy;
if (hintType == (int)PlayerHintType.DescAdd)
field.HintDescriptions.Add(description);
else if (hintType == (int)PlayerHintType.DescRemove)
field.HintDescriptions.Remove(description);
}
public override void OnHintZone(int player, int zone)
{
base.OnHintZone(player, zone);
ChainInfo currentChainInfo = Duel.GetCurrentSolvingChainInfo();
if (currentChainInfo != null) {
if (currentChainInfo.IsCode(_CardId.InfiniteImpermanence)) {
// Zone bit mapping: 0x100=col0, 0x200=col1, 0x400=col2, 0x800=col3, 0x1000=col4.
for (int i = 0; i <= 4; i++)
{
if ((zone & (0x100 << i)) == 0)
continue;
if (currentChainInfo.ActivatePlayer == 0)
{
infiniteImpermanenceNegatedColumns.Add(i);
}
else
{
infiniteImpermanenceNegatedColumns.Add(4 - i);
}
}
}
}
}
public override void OnReceivingAnnouce(int player, int data) public override void OnReceivingAnnouce(int player, int data)
{ {
if (player == 1 && data == Util.GetStringId(_CardId.LightningStorm, 0) || data == Util.GetStringId(_CardId.LightningStorm, 1)) if (player == 1 && data == Util.GetStringId(_CardId.LightningStorm, 0) || data == Util.GetStringId(_CardId.LightningStorm, 1))
...@@ -588,6 +644,39 @@ namespace WindBot.Game.AI ...@@ -588,6 +644,39 @@ namespace WindBot.Game.AI
base.OnReceivingAnnouce(player, data); base.OnReceivingAnnouce(player, data);
} }
public override void OnChainSolved(int chainIndex)
{
ChainInfo currentChain = Duel.GetCurrentSolvingChainInfo();
if (currentChain != null && !Duel.IsCurrentSolvingChainNegated())
{
if (currentChain.IsActivateCode(_CardId.LockBird))
{
resolvedEffectIdList.Add(_CardId.LockBird);
}
if (currentChain.ActivatePlayer == 1)
{
if (currentChain.IsActivateCode(_CardId.MaxxC))
enemyResolvedEffectIdList.Add(_CardId.MaxxC);
if (currentChain.IsActivateCode(_CardId.MulcharmyPurulia))
enemyResolvedEffectIdList.Add(_CardId.MulcharmyPurulia);
if (currentChain.IsActivateCode(_CardId.MulcharmyFuwalos))
enemyResolvedEffectIdList.Add(_CardId.MulcharmyFuwalos);
if (currentChain.IsActivateCode(_CardId.MulcharmyNyalus))
enemyResolvedEffectIdList.Add(_CardId.MulcharmyNyalus);
if (currentChain.IsActivateCode(_CardId.MistakenArrest))
{
if (Duel.Player == 1)
{
mistakenArrestAffectedCount = Math.Max(mistakenArrestAffectedCount, 3);
} else
{
mistakenArrestAffectedCount = Math.Max(mistakenArrestAffectedCount, 2);
}
}
}
}
}
public override void OnChainEnd() public override void OnChainEnd()
{ {
lightningStormOption = -1; lightningStormOption = -1;
...@@ -599,7 +688,15 @@ namespace WindBot.Game.AI ...@@ -599,7 +688,15 @@ namespace WindBot.Game.AI
/// </summary> /// </summary>
public override void OnNewTurn() public override void OnNewTurn()
{ {
if (Duel.Turn <= 1) calledbytheGraveIdCountMap.Clear(); infiniteImpermanenceNegatedColumns.Clear();
resolvedEffectIdList.Clear();
enemyResolvedEffectIdList.Clear();
if (Duel.Turn <= 1)
{
calledbytheGraveIdCountMap.Clear();
mistakenArrestAffectedCount = 0;
}
mistakenArrestAffectedCount = Math.Max(mistakenArrestAffectedCount - 1, 0);
List<int> keyList = calledbytheGraveIdCountMap.Keys.ToList(); List<int> keyList = calledbytheGraveIdCountMap.Keys.ToList();
foreach (int dic in keyList) foreach (int dic in keyList)
{ {
...@@ -1653,5 +1750,79 @@ namespace WindBot.Game.AI ...@@ -1653,5 +1750,79 @@ namespace WindBot.Game.AI
} }
return false; return false;
} }
/// <summary>
/// Check whether all available spell columns are negated.
/// </summary>
/// <returns></returns>
protected bool DefaultCheckAllAvailableSpellColumnNegated()
{
for (int i = 0; i < 5; i++) {
// occupied
if (Bot.SpellZone[i] != null) {
continue;
}
// negated
if (infiniteImpermanenceNegatedColumns.Contains(i)) {
continue;
}
// have empty column that's not negated
return false;
}
// all columns are negated
return true;
}
/// <summary>
/// Check whether the spells will be negated.
/// </summary>
/// <param name="card"></param>
/// <returns></returns>
protected bool DefaultCheckWhetherSpellActivateWillBeNegated(ClientCard card)
{
if (card == null) return false;
if (card.Location == CardLocation.SpellZone)
{
return infiniteImpermanenceNegatedColumns.Contains(card.Sequence);
}
// check whether will be negated by Infinite Impermanence
return DefaultCheckAllAvailableSpellColumnNegated();
}
/// <summary>
/// Check whether bot can search cards from deck.
/// </summary>
/// <returns></returns>
protected bool DefaultCheckWhetherBotCanSearch()
{
if (resolvedEffectIdList.Contains(_CardId.LockBird))
return false;
if (mistakenArrestAffectedCount > 0)
return false;
if (Bot.HasInMonstersZone(_CardId.ThunderKingRaiOh, notDisabled: true, faceUp: true)
|| Enemy.HasInMonstersZone(_CardId.ThunderKingRaiOh, notDisabled: true, faceUp: true))
return false;
if (Enemy.HasInMonstersZone(_CardId.ThunderDragonColossus))
return false;
if (Bot.HasInSpellZone(_CardId.DeckLockdown, notDisabled: true, faceUp: true)
|| Enemy.HasInSpellZone(_CardId.DeckLockdown, notDisabled: true, faceUp: true)
|| Bot.HasInSpellZone(_CardId.Mistake, notDisabled: true, faceUp: true)
|| Enemy.HasInSpellZone(_CardId.Mistake, notDisabled: true, faceUp: true))
return false;
if (Enemy.HasInSpellZone(_CardId.DoomZDestruction, notDisabled: true, faceUp: true))
return false;
return true;
}
/// <summary>
/// Check whether enemy can draw cards.
/// </summary>
/// <returns></returns>
protected bool DefaultCheckWhetherEnemyCanDraw()
{
if (resolvedEffectIdList.Contains(_CardId.LockBird))
return false;
return true;
}
} }
} }
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using YGOSharp.OCGWrapper.Enums; using YGOSharp.OCGWrapper.Enums;
...@@ -121,6 +121,27 @@ namespace WindBot.Game.AI ...@@ -121,6 +121,27 @@ namespace WindBot.Game.AI
// Some AI need do something on draw // Some AI need do something on draw
} }
/// <summary>
/// Called when a PlayerHint is received (e.g. effect description add/remove; can be used to track "once per turn" usage).
/// </summary>
/// <param name="player">Player index</param>
/// <param name="hintType">Hint type, see PlayerHintType (DescAdd=6, DescRemove=7)</param>
/// <param name="description">Effect description id (peffect->description)</param>
public virtual void OnPlayerHint(int player, int hintType, int description)
{
// For overriding
}
/// <summary>
/// Called when a zone hint is received.
/// </summary>
/// <param name="player">Player index.</param>
/// <param name="zone">Zone data (hinted zones, bit field).</param>
public virtual void OnHintZone(int player, int zone)
{
// For overriding
}
public virtual void OnMove(ClientCard card, int previousControler, int previousLocation, int currentControler, int currentLocation) public virtual void OnMove(ClientCard card, int previousControler, int previousLocation, int currentControler, int currentLocation)
{ {
// Some AI need do something on card's moving // Some AI need do something on card's moving
......
...@@ -12,6 +12,7 @@ namespace WindBot.Game ...@@ -12,6 +12,7 @@ namespace WindBot.Game
public ClientCard RelatedCard { get; private set; } public ClientCard RelatedCard { get; private set; }
public int ActivatePlayer { get; private set; } public int ActivatePlayer { get; private set; }
public int ActivateId { get; private set; } public int ActivateId { get; private set; }
public int ActivateAlias { get; private set; }
public int ActivateController { get; private set; } public int ActivateController { get; private set; }
public int ActivatePosition { get; private set; } public int ActivatePosition { get; private set; }
public int ActivateSequence { get; private set; } public int ActivateSequence { get; private set; }
...@@ -35,6 +36,7 @@ namespace WindBot.Game ...@@ -35,6 +36,7 @@ namespace WindBot.Game
RelatedCard = card; RelatedCard = card;
ActivatePlayer = player; ActivatePlayer = player;
ActivateId = card.Id; ActivateId = card.Id;
ActivateAlias = card.Alias;
ActivateController = card.Controller; ActivateController = card.Controller;
ActivatePosition = card.Position; ActivatePosition = card.Position;
ActivateSequence = card.Sequence; ActivateSequence = card.Sequence;
...@@ -61,6 +63,11 @@ namespace WindBot.Game ...@@ -61,6 +63,11 @@ namespace WindBot.Game
return ((int)ActivateLocation & (int)location) != 0; return ((int)ActivateLocation & (int)location) != 0;
} }
public bool IsActivateCode(int id)
{
return ActivateId == id || Math.Abs(ActivateAlias - ActivateId) <= 20 && ActivateAlias == id;
}
public bool IsCode(int id) public bool IsCode(int id)
{ {
return RelatedCard != null && RelatedCard.IsCode(id); return RelatedCard != null && RelatedCard.IsCode(id);
......
...@@ -19,6 +19,8 @@ namespace WindBot.Game ...@@ -19,6 +19,8 @@ namespace WindBot.Game
public ClientCard BattlingMonster; public ClientCard BattlingMonster;
public bool UnderAttack; public bool UnderAttack;
public HashSet<int> HintDescriptions { get; private set; }
public ClientField() public ClientField()
{ {
} }
...@@ -32,6 +34,7 @@ namespace WindBot.Game ...@@ -32,6 +34,7 @@ namespace WindBot.Game
Banished = new List<ClientCard>(); Banished = new List<ClientCard>();
Deck = new List<ClientCard>(); Deck = new List<ClientCard>();
ExtraDeck = new List<ClientCard>(); ExtraDeck = new List<ClientCard>();
HintDescriptions = new HashSet<int>();
for (int i = 0; i < deck; ++i) for (int i = 0; i < deck; ++i)
Deck.Add(new ClientCard(0, CardLocation.Deck, -1)); Deck.Add(new ClientCard(0, CardLocation.Deck, -1));
......
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using WindBot.Game.AI; using WindBot.Game.AI;
...@@ -185,6 +185,27 @@ namespace WindBot.Game ...@@ -185,6 +185,27 @@ namespace WindBot.Game
CheckSurrender(); CheckSurrender();
} }
/// <summary>
/// Called when a PlayerHint message is received (e.g. effect description add/remove hints).
/// </summary>
/// <param name="player">Player index</param>
/// <param name="hintType">Hint type, see PlayerHintType (DescAdd=6, DescRemove=7)</param>
/// <param name="description">Effect description id (peffect->description)</param>
public void OnPlayerHint(int player, int hintType, int description)
{
Executor.OnPlayerHint(player, hintType, description);
}
/// <summary>
/// Called when a zone hint is received.
/// </summary>
/// <param name="player">Player index.</param>
/// <param name="zone">Zone data (hinted zones, bit field).</param>
public void OnHintZone(int player, int zone)
{
Executor.OnHintZone(player, zone);
}
/// <summary> /// <summary>
/// Called when receiving annouce /// Called when receiving annouce
/// </summary> /// </summary>
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
...@@ -151,6 +151,7 @@ namespace WindBot.Game ...@@ -151,6 +151,7 @@ namespace WindBot.Game
_messages.Add(GameMessage.FlipSummoning, OnSummoning); _messages.Add(GameMessage.FlipSummoning, OnSummoning);
_messages.Add(GameMessage.FlipSummoned, OnSummoned); _messages.Add(GameMessage.FlipSummoned, OnSummoned);
_messages.Add(GameMessage.ConfirmCards, OnConfirmCards); _messages.Add(GameMessage.ConfirmCards, OnConfirmCards);
_messages.Add(GameMessage.PlayerHint, OnPlayerHint);
} }
private void OnJoinGame(BinaryReader packet) private void OnJoinGame(BinaryReader packet)
...@@ -363,6 +364,11 @@ namespace WindBot.Game ...@@ -363,6 +364,11 @@ namespace WindBot.Game
{ {
_ai.OnReceivingAnnouce(player, data); _ai.OnReceivingAnnouce(player, data);
} }
if (type == 11) // HINT_ZONE
{
Logger.DebugWriteLine("HINT_ZONE received: player=" + player + ", zone=" + data);
_ai.OnHintZone(player, data);
}
} }
private void OnStart(BinaryReader packet) private void OnStart(BinaryReader packet)
...@@ -2015,5 +2021,18 @@ namespace WindBot.Game ...@@ -2015,5 +2021,18 @@ namespace WindBot.Game
Logger.WriteLine("(Confirm " + player.ToString() + "'s " + (CardLocation)loc + " card: " + (card.Name ?? "UnKnowCard") + ")"); Logger.WriteLine("(Confirm " + player.ToString() + "'s " + (CardLocation)loc + " card: " + (card.Name ?? "UnKnowCard") + ")");
} }
} }
/// <summary>
/// Handles PlayerHint message. Protocol: player(buffer8), hintType(buffer8), description(buffer32).
/// hintType values: PlayerHintType (e.g. PHINT_DESC_ADD=6, PHINT_DESC_REMOVE=7).
/// </summary>
private void OnPlayerHint(BinaryReader packet)
{
int player = GetLocalPlayer(packet.ReadByte());
int hintType = packet.ReadByte();
int description = packet.ReadInt32();
Logger.DebugWriteLine("PlayerHint received: player=" + player + ", hintType=" + hintType + " (" + (PlayerHintType)hintType + "), description=" + description);
_ai.OnPlayerHint(player, hintType, description);
}
} }
} }
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
...@@ -70,6 +70,7 @@ ...@@ -70,6 +70,7 @@
<Compile Include="Game\AI\DecksManager.cs" /> <Compile Include="Game\AI\DecksManager.cs" />
<Compile Include="Game\AI\Decks\MalissExecutor.cs" /> <Compile Include="Game\AI\Decks\MalissExecutor.cs" />
<Compile Include="Game\AI\Decks\RyzealExecutor.cs" /> <Compile Include="Game\AI\Decks\RyzealExecutor.cs" />
<Compile Include="Game\AI\Decks\ApophisExecutor.cs" />
<Compile Include="Game\AI\Decks\AlbazExecutor.cs" /> <Compile Include="Game\AI\Decks\AlbazExecutor.cs" />
<Compile Include="Game\AI\Decks\AltergeistExecutor.cs" /> <Compile Include="Game\AI\Decks\AltergeistExecutor.cs" />
<Compile Include="Game\AI\Decks\BraveExecutor.cs" /> <Compile Include="Game\AI\Decks\BraveExecutor.cs" />
...@@ -181,6 +182,7 @@ ...@@ -181,6 +182,7 @@
<Compile Include="YGOSharp.OCGWrapper.Enums\CardType.cs" /> <Compile Include="YGOSharp.OCGWrapper.Enums\CardType.cs" />
<Compile Include="YGOSharp.OCGWrapper.Enums\DuelPhase.cs" /> <Compile Include="YGOSharp.OCGWrapper.Enums\DuelPhase.cs" />
<Compile Include="YGOSharp.OCGWrapper.Enums\GameMessage.cs" /> <Compile Include="YGOSharp.OCGWrapper.Enums\GameMessage.cs" />
<Compile Include="YGOSharp.OCGWrapper.Enums\PlayerHintType.cs" />
<Compile Include="YGOSharp.OCGWrapper.Enums\Query.cs" /> <Compile Include="YGOSharp.OCGWrapper.Enums\Query.cs" />
<Compile Include="YGOSharp.OCGWrapper\Card.cs" /> <Compile Include="YGOSharp.OCGWrapper\Card.cs" />
<Compile Include="YGOSharp.OCGWrapper\CardsManager.cs" /> <Compile Include="YGOSharp.OCGWrapper\CardsManager.cs" />
......
namespace YGOSharp.OCGWrapper.Enums
{
/// <summary>
/// Hint type for PlayerHint message (matches PHINT constants in core).
/// </summary>
public enum PlayerHintType
{
/// <summary>Add effect description hint</summary>
DescAdd = 6,
/// <summary>Remove effect description hint</summary>
DescRemove = 7
}
}
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