Commit f2d7219b authored by mercury233's avatar mercury233

Merge branch 'master' of https://github.com/IceYGO/windbot

parents e6a8cac1 a927ee30
......@@ -2,27 +2,32 @@
# !name
# command
# description
# flags (avail flags: SUPPORT_MASTER_RULE_3, SUPPORT_NEW_MASTER_RULE, SUPPORT_MASTER_RULE_2020)
# flags (avail flags: SUPPORT_MASTER_RULE_3, SUPPORT_NEW_MASTER_RULE, SUPPORT_MASTER_RULE_2020, SELECT_DECKFILE)
!随机-非常简单
Random=AI_LV1
主要是一些沙包。
SUPPORT_NEW_MASTER_RULE SUPPORT_MASTER_RULE_2020
SUPPORT_MASTER_RULE_2020
!随机-简单
Random=AI_LV2
一些比较弱的卡组。
SUPPORT_NEW_MASTER_RULE SUPPORT_MASTER_RULE_2020
SUPPORT_MASTER_RULE_2020
!随机-普通
Random=AI_LV3
一些环境里可以看到的卡组。
SUPPORT_NEW_MASTER_RULE SUPPORT_MASTER_RULE_2020
SUPPORT_MASTER_RULE_2020
!随机-报社
Random=AI_ANTI_META
一些报复社会(针对主流卡组的弱点)的卡组。
SUPPORT_NEW_MASTER_RULE SUPPORT_MASTER_RULE_2020
SUPPORT_MASTER_RULE_2020
!P2-自选卡组
Name=P2 Deck=Lucky Dialog=gugugu.zh-CN
人机卡组由你选择。随缘出牌。可将你的卡组文件(.ydk)复制到WindBot的对应文件夹。
SELECT_DECKFILE SUPPORT_MASTER_RULE_3 SUPPORT_NEW_MASTER_RULE SUPPORT_MASTER_RULE_2020
!悠悠
Name=悠悠 Deck=MokeyMokey Dialog=mokey.zh-CN
......@@ -47,17 +52,17 @@ AI_LV2 SUPPORT_MASTER_RULE_3 SUPPORT_NEW_MASTER_RULE SUPPORT_MASTER_RULE_2020
!谜之剑士LV4-R5
Name=谜之剑士LV4 Deck='Rank V' Dialog=swordsman.zh-CN
5阶超量卡组。
AI_LV2 SUPPORT_MASTER_RULE_3 SUPPORT_NEW_MASTER_RULE SUPPORT_MASTER_RULE_2020
AI_LV2 SUPPORT_MASTER_RULE_3 SUPPORT_MASTER_RULE_2020
!谜之剑士LV4-异热同心武器
Name=谜之剑士LV4 Deck='Zexal Weapons' Dialog=swordsman.zh-CN
神装电光皇卡组。
AI_LV2 SUPPORT_MASTER_RULE_3 SUPPORT_NEW_MASTER_RULE SUPPORT_MASTER_RULE_2020
AI_LV2 SUPPORT_MASTER_RULE_3 SUPPORT_MASTER_RULE_2020
!琪露诺-彩虹
Name=琪露诺 Deck=Rainbow Dialog=cirno.zh-CN
全属性凡骨卡组。
AI_LV2 SUPPORT_MASTER_RULE_3 SUPPORT_NEW_MASTER_RULE SUPPORT_MASTER_RULE_2020
AI_LV2 SUPPORT_MASTER_RULE_3 SUPPORT_MASTER_RULE_2020
!琪露诺-饼蛙
Name=琪露诺 Deck='Toadally Awesome' Dialog=cirno.zh-CN
......@@ -67,7 +72,7 @@ SUPPORT_MASTER_RULE_3 SUPPORT_MASTER_RULE_2020
!复制植物-青眼
Name=复制植物 Deck=Blue-Eyes Dialog=copy.zh-CN
青眼卡组。
AI_LV3 SUPPORT_MASTER_RULE_3 SUPPORT_NEW_MASTER_RULE SUPPORT_MASTER_RULE_2020
AI_LV3 SUPPORT_MASTER_RULE_3 SUPPORT_MASTER_RULE_2020
!复制植物-十二兽
Name=复制植物 Deck=Zoodiac Dialog=copy.zh-CN
......
{
"welcome": [
"大家好我是新人",
"游戏王是怎么玩来着?",
"还好我不玩游戏王"
],
"deckerror": [
"卡组里{0}鸽了"
],
"duelstart": [
"不想干活怎么办",
"智商欠费不想干活怎么办"
],
"newturn": [
"好多可怕的新卡啊",
"这游戏好难玩",
"so lazy cant move"
],
"endturn": [
"搞得我只能鸽了",
"不是在此时,不知在何时",
"too hot need ice cream"
],
"directattack": [
"听起来很鸽",
"老鸽,稳"
],
"attack": [
"听起来不是很鸽",
"可怕"
],
"ondirectattack": [
"哇!",
"这么可怕的吗",
"听起来非常鸽",
"承受不住"
],
"facedownmonstername": "鸽子",
"activate": [
"不明觉鸽",
"鸽了,爽"
],
"summon": [
"可怕",
"不关我事",
"那还是不关我事",
"鸽了,爽"
],
"setmonster": [
"摸鱼中,不想更新",
"那还是鸽置吧"
],
"chaining": [
"那是什么",
"但我鸽了",
"无此服务",
"可怕"
]
}
......@@ -11,7 +11,9 @@ namespace WindBot.Game.AI
/// </summary>
public static bool IsMonsterInvincible(this ClientCard card)
{
return !card.IsDisabled() && Enum.IsDefined(typeof(InvincibleMonster), card.Id);
return !card.IsDisabled() &&
(card.Controller == 0 && Enum.IsDefined(typeof(InvincibleBotMonster), card.Id) ||
card.Controller == 1 && Enum.IsDefined(typeof(InvincibleEnemyMonster), card.Id));
}
/// <summary>
......
......@@ -2742,8 +2742,6 @@ namespace WindBot.Game.AI.Decks
public override IList<ClientCard> OnSelectCard(IList<ClientCard> cards, int min, int max, int hint, bool cancelable)
{
int HIINT_TOGRAVE = 504;
if (max == 1 && cards[0].Location == CardLocation.Deck
&& Util.GetLastChainCard() != null && Util.GetLastChainCard().IsCode(23002292) && Bot.GetRemainingCount(CardId.WakingtheDragon,1) > 0)
{
......@@ -2764,7 +2762,7 @@ namespace WindBot.Game.AI.Decks
Logger.DebugWriteLine("EvenlyMatched: min=" + min.ToString() + ", max=" + max.ToString());
}
else if (cards[0].Location == CardLocation.Hand && cards[cards.Count - 1].Location == CardLocation.Hand
&& (hint == 501 || hint == HIINT_TOGRAVE) && min == max)
&& (hint == HintMsg.Discard || hint == HintMsg.ToGrave) && min == max)
{
if (Duel.LastChainPlayer == 0 && Util.GetLastChainCard().IsCode(CardId.OneForOne)) return null;
Logger.DebugWriteLine("Hand drop except OneForOne");
......
......@@ -20,7 +20,7 @@ namespace WindBot.Game.AI.Decks
{
AddExecutor(ExecutorType.SpSummon);
AddExecutor(ExecutorType.Activate, DefaultDontChainMyself);
AddExecutor(ExecutorType.SummonOrSet);
AddExecutor(ExecutorType.SummonOrSet, DefaultMonsterSummon);
AddExecutor(ExecutorType.Repos, DefaultMonsterRepos);
AddExecutor(ExecutorType.SpellSet);
}
......
......@@ -83,18 +83,10 @@ namespace WindBot.Game.AI.Decks
private int m_swapFrogSummoned;
private int m_flipFlopFrogSummoned;
private int m_treebornFrogCount = 0;
public override void OnNewTurn()
{
m_treebornFrogCount = 0;
base.OnNewTurn();
}
private bool TreebornFrog()
{
m_treebornFrogCount++;
return m_treebornFrogCount <= 5;
return true;
}
private bool SwapFrogSummon()
......
......@@ -56,7 +56,7 @@ namespace WindBot.Game.AI.Decks
AddExecutor(ExecutorType.Activate, CardId.MonsterReborn, MonsterReborn);
AddExecutor(ExecutorType.Summon, CardId.WhiteNightDragon, WhiteNightDragon);
AddExecutor(ExecutorType.Summon, CardId.HorusTheBlackFlameDragonLv6, DefaultTributeSummon);
AddExecutor(ExecutorType.Summon, CardId.HorusTheBlackFlameDragonLv6, DefaultMonsterSummon);
AddExecutor(ExecutorType.Summon, CardId.AlexandriteDragon);
AddExecutor(ExecutorType.SummonOrSet, CardId.AxeDragonute);
AddExecutor(ExecutorType.SummonOrSet, CardId.DodgerDragon);
......@@ -157,7 +157,7 @@ namespace WindBot.Game.AI.Decks
if (card.IsCode(11224103))
return false;
return DefaultTributeSummon();
return DefaultMonsterSummon();
}
private bool HorusTheBlackFlameDragonLv8()
......
......@@ -184,7 +184,6 @@ namespace WindBot.Game.AI.Decks
private bool JetSynchronUsed = false;
private bool ScrapWyvernUsed = false;
private bool MaskedChameleonUsed = false;
private int ShootingRiserDragonCount = 0;
private int[] HandCosts = new[]
{
......@@ -218,7 +217,6 @@ namespace WindBot.Game.AI.Decks
JetSynchronUsed = false;
ScrapWyvernUsed = false;
MaskedChameleonUsed = false;
ShootingRiserDragonCount = 0;
}
public override void OnChainEnd()
......@@ -845,9 +843,8 @@ namespace WindBot.Game.AI.Decks
}
else
{
if (Duel.LastChainPlayer == 0 || ShootingRiserDragonCount >= 10)
if (Duel.LastChainPlayer == 0)
return false;
ShootingRiserDragonCount++;
AI.SelectCard(new[] {
CardId.BlackRoseMoonlightDragon,
CardId.ScrapDragon,
......
......@@ -230,7 +230,6 @@ namespace WindBot.Game.AI.Decks
}
int Ultimate_ss = 0;
int Enemy_atk = 0;
int TG_WonderMagician_count = 0;
bool Pillused = false;
bool CrystronNeedlefibereff_used = false;
bool OvertexCoatlseff_used = false;
......@@ -275,7 +274,6 @@ namespace WindBot.Game.AI.Decks
ShaddollSquamata_used = false;
ShaddollDragon_used = false;
ShaddollHedgehog_used = false;
TG_WonderMagician_count = 0;
}
private bool Luminasummon()
......@@ -576,8 +574,7 @@ namespace WindBot.Game.AI.Decks
private bool TG_WonderMagicianeff()
{
TG_WonderMagician_count++;
return TG_WonderMagician_count <= 10;
return true;
}
private bool AllureofDarkness()
{
......
This diff is collapsed.
......@@ -46,8 +46,8 @@ namespace WindBot.Game.AI.Decks
AddExecutor(ExecutorType.Activate, CardId.SwordsOfRevealingLight, SwordsOfRevealingLight);
AddExecutor(ExecutorType.Activate, CardId.DoubleSummon, DoubleSummon);
AddExecutor(ExecutorType.Summon, CardId.AncientGearGolem, DefaultTributeSummon);
AddExecutor(ExecutorType.Summon, CardId.Frostosaurus, DefaultTributeSummon);
AddExecutor(ExecutorType.Summon, CardId.AncientGearGolem, DefaultMonsterSummon);
AddExecutor(ExecutorType.Summon, CardId.Frostosaurus, DefaultMonsterSummon);
AddExecutor(ExecutorType.SummonOrSet, CardId.AlexandriteDragon);
AddExecutor(ExecutorType.SummonOrSet, CardId.GeneWarpedWarwolf);
AddExecutor(ExecutorType.MonsterSet, CardId.GearGolemTheMovingFortress);
......
......@@ -181,7 +181,6 @@ namespace WindBot.Game.AI.Decks
private bool CymbalSkeletonUsed = false;
private bool BorrelswordDragonUsed = false;
private ClientCard RustyBardicheTarget = null;
private int ShootingRiserDragonCount = 0;
private int[] HandCosts = new[]
{
......@@ -215,7 +214,6 @@ namespace WindBot.Game.AI.Decks
CymbalSkeletonUsed = false;
BorrelswordDragonUsed = false;
RustyBardicheTarget = null;
ShootingRiserDragonCount = 0;
}
public override void OnChainEnd()
......@@ -611,10 +609,7 @@ namespace WindBot.Game.AI.Decks
}
else
{
if (Duel.LastChainPlayer == 0)
return false;
ShootingRiserDragonCount++;
return ShootingRiserDragonCount <= 10;
return Duel.LastChainPlayer != 0;
}
}
......
......@@ -117,13 +117,11 @@ namespace WindBot.Game.AI.Decks
bool summon_used = false;
bool CardOfDemiseeff_used = false;
bool SeaStealthAttackeff_used = false;
int City_count = 0;
public override void OnNewTurn()
{
summon_used = false;
CardOfDemiseeff_used = false;
SeaStealthAttackeff_used = false;
City_count = 0;
base.OnNewTurn();
}
private bool PreventFeatherDustereff()
......@@ -356,9 +354,6 @@ namespace WindBot.Game.AI.Decks
}
else
{
if (City_count > 10)
return false;
ClientCard target = null;
foreach(ClientCard s in Bot.GetSpells())
{
......@@ -380,7 +375,6 @@ namespace WindBot.Game.AI.Decks
break;
}
}
City_count++;
AI.SelectPlace(Zones.z1 | Zones.z3);
AI.SelectCard(CardId.PhantasmSprialBattle);
return true;
......
......@@ -215,8 +215,7 @@ namespace WindBot.Game.AI.Decks
private bool Summon_used;
private bool Pilica_eff;
private bool plan_A;
private int SnowBell_count = 0;
//TODO: reset the flags when they should reset ( public override void OnNewTurn() )
public PureWindsExecutor(GameAI ai, Duel duel)
: base(ai, duel)
{
......@@ -302,7 +301,6 @@ namespace WindBot.Game.AI.Decks
Summon_used = false;
Pilica_eff = false;
plan_A = false;
SnowBell_count = 0;
base.OnNewTurn();
}
private bool windaset()
......@@ -770,7 +768,6 @@ namespace WindBot.Game.AI.Decks
private bool WindwitchSnowBellsp()
{
if (SnowBell_count >= 5) return false;
if ((Bot.HasInMonstersZone(CardId.CrystalWingSynchroDragon) ||
Bot.HasInMonstersZone(CardId.DaigustoSphreez) ||
Bot.HasInMonstersZone(CardId.MistWurm)) &&
......@@ -786,7 +783,6 @@ namespace WindBot.Game.AI.Decks
(Util.GetBotAvailZonesFromExtraDeck() == 0))
return false;
AI.SelectPosition(CardPosition.FaceUpDefence);
SnowBell_count++;
return true;
}
private bool DaigustoSphreezsp()
......
......@@ -73,7 +73,6 @@ namespace WindBot.Game.AI.Decks
bool snake_four_s = false;
bool tuner_eff_used = false;
bool crystal_eff_used = false;
int red_ss_count = 0;
bool white_eff_used = false;
bool lockbird_useful = false;
bool lockbird_used = false;
......@@ -758,7 +757,6 @@ namespace WindBot.Game.AI.Decks
public bool Red_ss()
{
if (red_ss_count >= 6) return false;
if ((Util.ChainContainsCard(CardId.DarkHole) || Util.ChainContainsCard(99330325) || Util.ChainContainsCard(53582587)) && Util.ChainContainsCard(CardId.Red)) return false;
if (Duel.LastChainPlayer == 0 && Util.GetLastChainCard().IsCode(CardId.Red))
{
......@@ -766,7 +764,6 @@ namespace WindBot.Game.AI.Decks
{
if (Util.IsChainTarget(m) && IsTrickstar(m.Id))
{
red_ss_count += 1;
AI.SelectCard(m);
Red_SelectPos();
return true;
......@@ -789,7 +786,6 @@ namespace WindBot.Game.AI.Decks
{
AI.SelectCard(c);
Red_SelectPos(c);
red_ss_count += 1;
return true;
}
if (c.IsCode(CardId.Pink)) return false;
......@@ -800,14 +796,12 @@ namespace WindBot.Game.AI.Decks
if (tosolve_enemy.Attack > 3200) AI.SelectPosition(CardPosition.FaceUpDefence);
AI.SelectCard(c);
Red_SelectPos(c);
red_ss_count += 1;
return true;
}
if (!Bot.HasInHand(CardId.White) && tosolve_enemy.Attack <= 3200 && c.IsCode(CardId.White))
{
AI.SelectCard(c);
Red_SelectPos(c);
red_ss_count += 1;
return true;
}
if (!Bot.HasInHand(CardId.White) && c.Attack < tosolve_enemy.Attack)
......@@ -824,7 +818,6 @@ namespace WindBot.Game.AI.Decks
if (tosolve_enemy.Attack > 1600) AI.SelectPosition(CardPosition.FaceUpDefence);
AI.SelectCard(c);
Red_SelectPos(c);
red_ss_count += 1;
return true;
}
}
......@@ -845,7 +838,6 @@ namespace WindBot.Game.AI.Decks
{
AI.SelectCard(card);
Red_SelectPos(card);
red_ss_count += 1;
return true;
}
}
......@@ -1710,7 +1702,6 @@ namespace WindBot.Game.AI.Decks
pink_ss = false;
snake_four_s = false;
crystal_eff_used = false;
red_ss_count = 0;
white_eff_used = false;
lockbird_useful = false;
lockbird_used = false;
......
......@@ -197,7 +197,6 @@ namespace WindBot.Game.AI.Decks
bool MagicianRightHand_used = false;
ClientCard MagiciansLeftHand_negate = null;
ClientCard MagicianRightHand_negate = null;
int PSYOmega_count = 0;
// go first
public override bool OnSelectHand()
......@@ -271,7 +270,6 @@ namespace WindBot.Game.AI.Decks
public override void OnNewTurn()
{
CrossoutDesignatorTarget = 0;
PSYOmega_count = 0;
MadameVerreGainedATK = false;
summoned = false;
enemy_activate_MaxxC = false;
......@@ -311,8 +309,8 @@ namespace WindBot.Game.AI.Decks
// overwrite OnSelectCard to act normally in SelectUnselect
public override IList<ClientCard> OnSelectCard(IList<ClientCard> cards, int min, int max, int hint, bool cancelable)
{
// Patronus HINTMSG_ATOHAND
if (hint == 506)
// Patronus
if (hint == HintMsg.AddToHand)
{
bool flag = true;
foreach(ClientCard card in cards)
......@@ -336,8 +334,8 @@ namespace WindBot.Game.AI.Decks
return selected;
}
}
// MaxxC HINTMSG_SPSUMMON
if (hint == 509 && enemy_activate_MaxxC)
// MaxxC solution
if (hint == HintMsg.SpSummon && enemy_activate_MaxxC)
{
// check whether SS from deck while using effect
bool flag = true;
......@@ -394,8 +392,8 @@ namespace WindBot.Game.AI.Decks
}
}
}
// MadameVerre HINTMSG_CONFIRM
if (hint == 526)
// MadameVerre
if (hint == HintMsg.Confirm)
{
Logger.DebugWriteLine("** min-max: " + min.ToString() + " / " + max.ToString());
foreach (ClientCard card in cards)
......@@ -2501,20 +2499,15 @@ namespace WindBot.Game.AI.Decks
// recycle from grave
if (Card.Location == CardLocation.Grave)
{
if (PSYOmega_count >= 5){
return false;
}
List<ClientCard> enemy_danger = CheckDangerousCardinEnemyGrave();
if (enemy_danger.Count > 0)
{
AI.SelectCard(enemy_danger);
PSYOmega_count ++;
return true;
}
if (!Bot.HasInHandOrInSpellZoneOrInGraveyard(CardId.Holiday) && Bot.HasInGraveyard(important_witchcraft))
{
AI.SelectCard(important_witchcraft);
PSYOmega_count ++;
return true;
}
if (CheckProblematicCards() == null)
......@@ -2523,7 +2516,6 @@ namespace WindBot.Game.AI.Decks
CardId.MaxxC, CardId.AshBlossom_JoyousSpring,
CardId.MagicianRightHand, CardId.MagiciansLeftHand, CardId.MagiciansRestage, CardId.Patronus,
CardId.LightningStorm, CardId.Reasoning);
PSYOmega_count ++;
return true;
}
}
......
......@@ -100,6 +100,7 @@ namespace WindBot.Game.AI.Decks
AddExecutor(ExecutorType.Summon, CardId.Goblindbergh);
AddExecutor(ExecutorType.Summon, CardId.TinGoldfish);
AddExecutor(ExecutorType.Summon, CardId.SummonerMonk);
AddExecutor(ExecutorType.Summon, CardId.Honest);
// Summons: Effects
AddExecutor(ExecutorType.Activate, CardId.Goblindbergh, GoblindberghEffect);
......@@ -122,13 +123,6 @@ namespace WindBot.Game.AI.Decks
AddExecutor(ExecutorType.Activate, CardId.SolemnStrike, DefaultSolemnStrike);
}
private int ZwCount = 0;
public override void OnNewTurn()
{
ZwCount = 0;
}
public override bool OnSelectHand()
{
return false;
......@@ -177,8 +171,7 @@ namespace WindBot.Game.AI.Decks
private bool ZwWeapon()
{
ZwCount++;
return ZwCount < 10;
return true;
}
private bool ReinforcementOfTheArmy()
......
......@@ -47,7 +47,6 @@ namespace WindBot.Game.AI.Decks
bool TigermortarSpsummoned = false;
bool ChakanineSpsummoned = false;
bool BroadbullSpsummoned = false;
int WhiptailEffectCount = 0;
public ZoodiacExecutor(GameAI ai, Duel duel)
: base(ai, duel)
......@@ -128,7 +127,6 @@ namespace WindBot.Game.AI.Decks
TigermortarSpsummoned = false;
ChakanineSpsummoned = false;
BroadbullSpsummoned = false;
WhiptailEffectCount = 0;
}
public override bool OnPreBattleBetween(ClientCard attacker, ClientCard defender)
......@@ -431,7 +429,7 @@ namespace WindBot.Game.AI.Decks
{
if (Duel.Phase == DuelPhase.Main1 || Duel.Phase == DuelPhase.Main2)
return false;
if (Card.IsDisabled() || WhiptailEffectCount >= 3)
if (Card.IsDisabled())
return false;
ClientCard target = null;
List<ClientCard> monsters = Bot.GetMonsters();
......@@ -461,7 +459,6 @@ namespace WindBot.Game.AI.Decks
CardId.Drident
});
}
WhiptailEffectCount++;
return true;
}
......
This diff is collapsed.
......@@ -59,7 +59,7 @@ namespace WindBot.Game.AI
_game = game;
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(DialogsData));
string dialogfilename = game.Dialog;
using (FileStream fs = File.OpenRead("Dialogs/" + dialogfilename + ".json"))
using (FileStream fs = Program.ReadFile("Dialogs", dialogfilename, "json"))
{
DialogsData data = (DialogsData)serializer.ReadObject(fs);
_welcome = data.welcome;
......
namespace WindBot.Game.AI.Enums
{
/// <summary>
/// Cards that are invincible to battle and should always attack to use effect.
/// </summary>
public enum InvincibleBotMonster
{
YubelTheUltimateNightmare = 31764700,
YubelTerrorIncarnate = 4779091,
SandaionTheTimelord = 33015627,
GabrionTheTimelord = 6616912,
MichionTheTimelord = 7733560,
ZaphionTheTimelord = 28929131,
HailonTheTimelord = 34137269,
RaphionTheTimelord = 60222213,
SadionTheTimelord = 65314286,
MetaionTheTimelord = 74530899,
KamionTheTimelord = 91712985,
LazionTheTimelord = 92435533,
TimelordProgenitorVorpgate = 67508932,
RocketWarrior = 30860696,
GoDDDDivineZeroKingRage = 40227329,
BloomDivaTheMelodiousChoir = 84988419,
BlackwingArmorMaster = 69031175,
DaigustoSphreez = 29552709,
Number92HearteartHDragon = 97403510,
NumberC96DarkStorm = 77205367,
Number54LionHeart = 54366836
}
/// <summary>
/// Cards that are invincible to battle.
/// </summary>
public enum InvincibleMonster
public enum InvincibleEnemyMonster
{
SpiritReaper = 23205979,
YubelTheUltimateNightmare = 31764700,
......
......@@ -73,13 +73,19 @@ namespace WindBot.Game.AI
public virtual BattlePhaseAction OnSelectAttackTarget(ClientCard attacker, IList<ClientCard> defenders)
{
// Overrided in DefalultExecutor
// Overrided in DefaultExecutor
return null;
}
public virtual bool OnPreBattleBetween(ClientCard attacker, ClientCard defender)
{
// Overrided in DefalultExecutor
// Overrided in DefaultExecutor
return true;
}
public virtual bool OnPreActivate(ClientCard card)
{
// Overrided in DefaultExecutor
return true;
}
......@@ -178,13 +184,23 @@ namespace WindBot.Game.AI
public virtual CardPosition OnSelectPosition(int cardId, IList<CardPosition> positions)
{
// Overrided in DefalultExecutor
// Overrided in DefaultExecutor
return 0;
}
public virtual bool OnSelectBattleReplay()
{
// Overrided in DefalultExecutor
// Overrided in DefaultExecutor
return false;
}
/// <summary>
/// Called when the executor type is SummonOrSet
/// </summary>
/// <returns>True if select to set the monster.</returns>
public virtual bool OnSelectMonsterSummonOrSet(ClientCard card)
{
// Overrided in DefaultExecutor
return false;
}
......
namespace WindBot.Game.AI
{
public static class HintMsg
{
public const int Release = 500,
Discard = 501,
Destroy = 502,
Remove = 503,
ToGrave = 504,
ReturnToHand = 505,
AddToHand = 506,
ToDeck = 507,
Summon = 508,
SpSummon = 509,
Set = 510,
FusionMaterial = 511,
SynchroMaterial = 512,
XyzMaterial = 513,
Faceup = 514,
Facedown = 515,
Attack = 516,
Defense = 517,
Equip = 518,
RemoveXyz = 519,
Control = 520,
DestroyReplace = 521,
FaceupAttack = 522,
FaceupDefense = 523,
FacedownAttack = 524,
FacedownDefense = 525,
Confirm = 526,
ToField = 527,
PosChange = 528,
Self = 529,
Oppo = 530,
Tribute = 531,
DeattachFrom = 532,
LinkMaterial = 533,
AttackTarget = 549,
Effect = 550,
Target = 551,
Coin = 552,
Dice = 553,
CardType = 554,
Option = 555,
ResolveEffect = 556,
Select = 560,
Position = 561,
Attribute = 562,
Race = 563,
Code = 564,
Number = 565,
LvRank = 567,
ResolveCard = 568,
Zone = 569,
DisableZone = 570,
ToZone = 571,
Counter = 572,
Disable = 573,
OperateCard = 574;
}
}
\ No newline at end of file
......@@ -32,7 +32,7 @@ namespace WindBot.Game
public int RealPower { get; set; }
public List<int> Overlays { get; private set; }
public int Owner { get; private set; }
public int Controller { get; private set; }
public int Controller { get; set; }
public int Disabled { get; private set; }
public int ProcCompleted { get; private set; }
public int SelectSeq { get; set; }
......
......@@ -43,7 +43,7 @@ namespace WindBot.Game
StreamReader reader = null;
try
{
reader = new StreamReader(new FileStream("Decks/" + name + ".ydk", FileMode.Open, FileAccess.Read));
reader = new StreamReader(Program.ReadFile("Decks", name, "ydk"));
Deck deck = new Deck();
bool side = false;
......
......@@ -96,30 +96,8 @@ namespace WindBot.Game
public void AddCard(CardLocation loc, int cardId, int player, int seq, int pos)
{
switch (loc)
{
case CardLocation.Hand:
Fields[player].Hand.Add(new ClientCard(cardId, loc, -1, pos));
break;
case CardLocation.Grave:
Fields[player].Graveyard.Add(new ClientCard(cardId, loc,-1, pos));
break;
case CardLocation.Removed:
Fields[player].Banished.Add(new ClientCard(cardId, loc, -1, pos));
break;
case CardLocation.MonsterZone:
Fields[player].MonsterZone[seq] = new ClientCard(cardId, loc, seq, pos);
break;
case CardLocation.SpellZone:
Fields[player].SpellZone[seq] = new ClientCard(cardId, loc, seq, pos);
break;
case CardLocation.Deck:
Fields[player].Deck.Add(new ClientCard(cardId, loc, -1, pos));
break;
case CardLocation.Extra:
Fields[player].ExtraDeck.Add(new ClientCard(cardId, loc, -1, pos));
break;
}
ClientCard card = new ClientCard(cardId, loc, seq, pos);
AddCard(loc, card, player, seq, pos, cardId);
}
public void AddCard(CardLocation loc, ClientCard card, int player, int seq, int pos, int id)
......@@ -127,6 +105,7 @@ namespace WindBot.Game
card.Location = loc;
card.Sequence = seq;
card.Position = pos;
card.Controller = player;
card.SetId(id);
switch (loc)
{
......
......@@ -13,12 +13,16 @@ namespace WindBot.Game
private Dialogs _dialogs;
// record activated count to prevent infinite actions
private Dictionary<int, int> _activatedCards;
public GameAI(GameClient game, Duel duel)
{
Game = game;
Duel = duel;
_dialogs = new Dialogs(game);
_activatedCards = new Dictionary<int, int>();
}
/// <summary>
......@@ -81,6 +85,7 @@ namespace WindBot.Game
/// </summary>
public void OnNewTurn()
{
_activatedCards.Clear();
Executor.OnNewTurn();
}
......@@ -190,13 +195,9 @@ namespace WindBot.Game
if (defenders.Count == 0)
{
// Attack with the monster with the lowest attack first
for (int i = attackers.Count - 1; i >= 0; --i)
{
ClientCard attacker = attackers[i];
if (attacker.Attack > 0)
ClientCard attacker = attackers[attackers.Count - 1];
return Attack(attacker, null);
}
}
else
{
for (int k = 0; k < attackers.Count; ++k)
......@@ -226,18 +227,12 @@ namespace WindBot.Game
/// <returns>A new list containing the selected cards.</returns>
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, hint, cancelable);
if (result != null)
return result;
if (hint == HINTMSG_SPSUMMON && min == 1 && max > min) // pendulum summon
if (hint == HintMsg.SpSummon && min == 1 && max > min) // pendulum summon
{
result = Executor.OnSelectPendulumSummon(cards, max);
if (result != null)
......@@ -245,7 +240,7 @@ namespace WindBot.Game
}
CardSelector selector = null;
if (hint == HINTMSG_FMATERIAL || hint == HINTMSG_SMATERIAL || hint == HINTMSG_XMATERIAL || hint == HINTMSG_LMATERIAL)
if (hint == HintMsg.FusionMaterial || hint == HintMsg.SynchroMaterial || hint == HintMsg.XyzMaterial || hint == HintMsg.LinkMaterial)
{
if (m_materialSelector != null)
{
......@@ -254,13 +249,13 @@ namespace WindBot.Game
}
else
{
if (hint == HINTMSG_FMATERIAL)
if (hint == HintMsg.FusionMaterial)
result = Executor.OnSelectFusionMaterial(cards, min, max);
if (hint == HINTMSG_SMATERIAL)
if (hint == HintMsg.SynchroMaterial)
result = Executor.OnSelectSynchroMaterial(cards, 0, min, max);
if (hint == HINTMSG_XMATERIAL)
if (hint == HintMsg.XyzMaterial)
result = Executor.OnSelectXyzMaterial(cards, min, max);
if (hint == HINTMSG_LMATERIAL)
if (hint == HintMsg.LinkMaterial)
result = Executor.OnSelectLinkMaterial(cards, min, max);
if (result != null)
......@@ -439,8 +434,7 @@ namespace WindBot.Game
}
if (ShouldExecute(exec, card, ExecutorType.SummonOrSet))
{
if (Executor.Util.IsAllEnemyBetter(true) && Executor.Util.IsAllEnemyBetterThanValue(card.Attack + 300, false) &&
main.MonsterSetableCards.Contains(card))
if (main.MonsterSetableCards.Contains(card) && Executor.OnSelectMonsterSummonOrSet(card))
{
_dialogs.SendSetMonster();
return new MainPhaseAction(MainPhaseAction.MainAction.SetMonster, card.ActionIndex);
......@@ -529,16 +523,13 @@ namespace WindBot.Game
/// <returns></returns>
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 (hint == HintMsg.Release || hint == HintMsg.SynchroMaterial)
{
if (m_materialSelector != null)
{
......@@ -548,10 +539,10 @@ namespace WindBot.Game
{
switch (hint)
{
case HINTMSG_SMATERIAL:
case HintMsg.SynchroMaterial:
selected = Executor.OnSelectSynchroMaterial(cards, sum, min, max);
break;
case HINTMSG_RELEASE:
case HintMsg.Release:
selected = Executor.OnSelectRitualTribute(cards, sum, min, max);
break;
}
......@@ -951,6 +942,11 @@ namespace WindBot.Game
m_materialSelector = null;
}
public bool HaveSelectedCards()
{
return m_selector.Count > 0 || m_materialSelector != null;
}
public CardSelector GetSelectedCards()
{
CardSelector selected = null;
......@@ -1102,11 +1098,30 @@ namespace WindBot.Game
private bool ShouldExecute(CardExecutor exec, ClientCard card, ExecutorType type, int desc = -1)
{
if (card.Id != 0 && type == ExecutorType.Activate)
{
if (_activatedCards.ContainsKey(card.Id) && _activatedCards[card.Id] >= 9)
return false;
if (!Executor.OnPreActivate(card))
return false;
}
Executor.SetCard(type, card, desc);
return card != null &&
exec.Type == type &&
bool result = card != null && exec.Type == type &&
(exec.CardId == -1 || exec.CardId == card.Id) &&
(exec.Func == null || exec.Func());
if (card.Id != 0 && type == ExecutorType.Activate && result)
{
int count = card.IsDisabled() ? 3 : 1;
if (!_activatedCards.ContainsKey(card.Id))
{
_activatedCards.Add(card.Id, count);
}
else
{
_activatedCards[card.Id] += count;
}
}
return result;
}
}
}
......@@ -44,7 +44,7 @@ namespace WindBot.Game
_ai = new GameAI(Game, _duel);
_ai.Executor = DecksManager.Instantiate(_ai, _duel);
Deck = Deck.Load(_ai.Executor.Deck);
Deck = Deck.Load(Game.DeckFile ?? _ai.Executor.Deck);
_select_hint = 0;
}
......@@ -1048,7 +1048,7 @@ namespace WindBot.Game
for (int i = 0; i < count; ++i)
{
packet.ReadByte(); // flag
packet.ReadInt32(); // card id
int id = packet.ReadInt32();
int con = GetLocalPlayer(packet.ReadByte());
int loc = packet.ReadByte();
int seq = packet.ReadByte();
......@@ -1059,7 +1059,12 @@ namespace WindBot.Game
{
desc = 0;
}
cards.Add(_duel.GetCard(con, loc, seq, sseq));
ClientCard card = _duel.GetCard(con, loc, seq, sseq);
if (card.Id == 0)
card.SetId(id);
cards.Add(card);
descs.Add(desc);
}
......
......@@ -13,6 +13,7 @@ namespace WindBot.Game
public YGOClient Connection { get; private set; }
public string Username;
public string Deck;
public string DeckFile;
public string Dialog;
public int Hand;
public bool Debug;
......@@ -29,6 +30,7 @@ namespace WindBot.Game
{
Username = Info.Name;
Deck = Info.Deck;
DeckFile = Info.DeckFile;
Dialog = Info.Dialog;
Hand = Info.Hand;
Debug = Info.Debug;
......
......@@ -68,6 +68,7 @@ namespace WindBot
WindBotInfo Info = new WindBotInfo();
Info.Name = Config.GetString("Name", Info.Name);
Info.Deck = Config.GetString("Deck", Info.Deck);
Info.DeckFile = Config.GetString("DeckFile", Info.DeckFile);
Info.Dialog = Config.GetString("Dialog", Info.Dialog);
Info.Host = Config.GetString("Host", Info.Host);
Info.Port = Config.GetInt("Port", Info.Port);
......@@ -104,6 +105,9 @@ namespace WindBot
string port = HttpUtility.ParseQueryString(RawUrl).Get("port");
if (port != null)
Info.Port = Int32.Parse(port);
string deckfile = HttpUtility.ParseQueryString(RawUrl).Get("deckfile");
if (deckfile != null)
Info.DeckFile = deckfile;
string dialog = HttpUtility.ParseQueryString(RawUrl).Get("dialog");
if (dialog != null)
Info.Dialog = dialog;
......@@ -193,5 +197,22 @@ namespace WindBot
}
#endif
}
public static FileStream ReadFile(string directory, string filename, string extension)
{
string tryfilename = filename + "." + extension;
string fullpath = Path.Combine(directory, tryfilename);
if (!File.Exists(fullpath))
fullpath = filename;
if (!File.Exists(fullpath))
fullpath = Path.Combine("../", filename);
if (!File.Exists(fullpath))
fullpath = Path.Combine("../deck/", filename);
if (!File.Exists(fullpath))
fullpath = Path.Combine("../", tryfilename);
if (!File.Exists(fullpath))
fullpath = Path.Combine("../deck/", tryfilename);
return new FileStream(fullpath, FileMode.Open, FileAccess.Read);
}
}
}
......@@ -20,6 +20,11 @@ The nickname for the bot.
`Deck`
The deck to be used by the bot. Available decks are listed below. Keep empty to use random deck.
`DeckFile`
The deck file (.ydk) to be used by the bot. Will be set by `Deck` automatically, but you can override it.
Note: Most cards not in the original deck are unknown to the bot, and won't be summoned or activated in the duel.
`Dialog`
The dialog texts to be used by the bot. See Dialogs folder for list.
......
......@@ -72,6 +72,7 @@
<Compile Include="Game\AI\Decks\AltergeistExecutor.cs" />
<Compile Include="Game\AI\Decks\FamiliarPossessedExecutor.cs" />
<Compile Include="Game\AI\Decks\BlackwingExecutor.cs" />
<Compile Include="Game\AI\Decks\LuckyExecutor.cs" />
<Compile Include="Game\AI\Decks\MathMechExecutor.cs" />
<Compile Include="Game\AI\Decks\PureWindsExecutor.cs" />
<Compile Include="Game\AI\Decks\DragunExecutor.cs" />
......@@ -124,6 +125,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\HintMsg.cs" />
<Compile Include="Game\AI\Opcodes.cs" />
<Compile Include="Game\AI\Zones.cs" />
<Compile Include="Game\AI\ExecutorType.cs" />
......
......@@ -6,6 +6,7 @@ namespace WindBot
{
public string Name { get; set; }
public string Deck { get; set; }
public string DeckFile { get; set; }
public string Dialog { get; set; }
public string Host { get; set; }
public int Port { get; set; }
......@@ -18,6 +19,7 @@ namespace WindBot
{
Name = "WindBot";
Deck = null;
DeckFile = null;
Dialog = "default";
Host = "127.0.0.1";
Port = 7911;
......
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