Commit 21109679 authored by mercury233's avatar mercury233

merge mycard changes

parent 8e49c80d
using System;
using System.Collections.Generic;
using System.IO;
namespace WindBot
{
public static class Config
{
private static string CONFIG_FILE_OPTION = "Config";
private static char SEPARATOR_CHAR = '=';
private static char COMMENT_CHAR = '#';
private static Dictionary<string, string> _fields;
private static Dictionary<string, int> _integerCache;
private static Dictionary<string, bool> _booleanCache;
public static void Load(string[] args)
{
_integerCache = new Dictionary<string, int>();
_booleanCache = new Dictionary<string, bool>();
_fields = LoadArgs(args);
string filename = GetString(CONFIG_FILE_OPTION);
if (filename != null)
{
Dictionary<string, string> fileFields = LoadFile(filename);
foreach (var pair in fileFields)
{
if (!_fields.ContainsKey(pair.Key))
_fields.Add(pair.Key, pair.Value);
}
}
}
private static Dictionary<string, string> LoadArgs(string[] args)
{
Dictionary<string, string> fields = new Dictionary<string, string>();
for (int i = 0; i < args.Length; ++i)
{
string option = args[i];
int position = option.IndexOf(SEPARATOR_CHAR);
if (position == -1)
throw new Exception("Invalid argument '" + option + "': no key/value separator");
string key = option.Substring(0, position).Trim().ToUpper();
string value = option.Substring(position + 1).Trim();
if (fields.ContainsKey(key))
throw new Exception("Invalid argument '" + option + "': duplicate key '" + key + "'");
fields.Add(key, value);
}
return fields;
}
private static Dictionary<string, string> LoadFile(string filename)
{
Dictionary<string, string> fields = new Dictionary<string, string>();
using (StreamReader reader = new StreamReader(filename))
{
int lineNumber = 0;
while (!reader.EndOfStream)
{
string line = reader.ReadLine().Trim();
++lineNumber;
// Ignore empty lines and comments
if (line.Length == 0 || line[0] == COMMENT_CHAR)
continue;
int position = line.IndexOf(SEPARATOR_CHAR);
if (position == -1)
throw new Exception("Invalid configuration file: no key/value separator line " + lineNumber);
string key = line.Substring(0, position).Trim().ToUpper();
string value = line.Substring(position + 1).Trim();
if (fields.ContainsKey(key))
throw new Exception("Invalid configuration file: duplicate key '" + key + "' line " + lineNumber);
fields.Add(key, value);
}
}
return fields;
}
public static string GetString(string key, string defaultValue = null)
{
key = key.ToUpper();
if (_fields.ContainsKey(key))
return _fields[key];
return defaultValue;
}
public static int GetInt(string key, int defaultValue = 0)
{
key = key.ToUpper();
// Use a cache to prevent doing the string to int conversion over and over
if (_integerCache.ContainsKey(key))
return _integerCache[key];
int value = defaultValue;
if (_fields.ContainsKey(key))
{
if (_fields[key].StartsWith("0x"))
value = Convert.ToInt32(_fields[key], 16);
else
value = Convert.ToInt32(_fields[key]);
}
_integerCache.Add(key, value);
return value;
}
public static uint GetUInt(string key, uint defaultValue = 0)
{
return (uint)GetInt(key, (int)defaultValue);
}
public static bool GetBool(string key, bool defaultValue = false)
{
key = key.ToUpper();
// Same here, prevent from redoing the string to bool conversion
if (_booleanCache.ContainsKey(key))
return _booleanCache[key];
bool value = defaultValue;
if (_fields.ContainsKey(key))
{
value = Convert.ToBoolean(_fields[key]);
}
_booleanCache.Add(key, value);
return value;
}
}
}
{
"welcome": [
"本小姐是最强的!",
"AI功能正在测试中,遇到问题请及时反馈。",
"饼蛙是什么,好吃吗?"
],
"deckerror": [
"为什么我的{0}不能用了?"
],
"duelstart": [
"让我把你冻结!",
"不就是打倒人类嘛,我一个人足够了!"
],
"newturn": [
"虽然有点突然,被我打倒吧!",
"我的回合,抽卡!"
],
"endturn": [
"饶你一命!",
"冻死在我的认真之下吧!"
],
"directattack": [
"{0},直接攻击!",
"不堪一击!",
"弱小就要挨打!",
"懒得算数了,打了再说!",
"超⑨武神霸斩!",
"雪符「Diamond Blizzard」"
],
"attack": [
"{0},攻击这只{1}!",
"{0},消灭这只{1}!",
"{0},打倒{1}!",
"冰符「Icicle Fall」"
],
"ondirectattack": [
"别开玩笑了~。你这种人,就让我把你和英吉利牛肉一起冷冻保存好了!!",
"一只小小的{0},有什么可怕!",
"笨蛋是不会感冒的!"
],
"facedownmonstername": "怪兽",
"activate": [
"我发动{0}。",
"我使用{0}的效果。",
"我的{0}是最强的!"
],
"summon": [
"我召唤{0}。",
"出来吧,{0}!",
"出现吧,{0}!",
"我召唤了强大的{0}!",
"我呼唤出{0}。"
],
"setmonster": [
"我放置了一只怪兽。",
"不怕死就打过来吧!"
],
"chaining": [
"看这里!我发动{0}!",
"我使用{0}的力量。",
"畏惧我的{0}吧!",
"冻符「Perfect Freeze」"
]
}
{
"welcome": [
"AI功能正在测试中,遇到问题请及时反馈。",
"密码输入 AI#复制植物 就可以和我打牌了~"
],
"deckerror": [
"我的超主流卡组需要{0}才能玩。"
],
"duelstart": [
"十二兽卡组测试中,渣操是正常情况。",
"超主流是游戏王的一环,不爽不要玩。",
"抄主流是游戏王的一环,不爽不要玩。",
"抄来的卡组不会用,怎么办?"
],
"newturn": [
"到我的回合了,抽卡!",
"我的回合,抽卡!",
"我抽了一张卡。"
],
"endturn": [
"回合结束。",
"我的回合结束了。",
"这样算是成功的展开吗……",
"轮到你了。"
],
"directattack": [
"{0},直接攻击!",
"{0},直接攻击对手!",
"{0},没有防守的地方,攻击!",
"{0},攻击对手的生命值!",
"{0},直接攻击对手的生命值!",
"{0},通过直接攻击打倒对手!",
"{0},使用直接攻击打倒对手!",
"{0},直接攻击释放你的力量吧!",
"我的{0}将会粉碎你的生命值!",
"向对手展示你的力量吧,{0}!",
"你已经无法阻止我了。{0},攻击!"
],
"attack": [
"{0},攻击这只{1}!",
"{0},消灭这只{1}!",
"{0},打倒{1}!",
"{0},冲向那只{1}!",
"{0},把你的力量释放到{1}上吧!"
],
"ondirectattack": [
"可恶……",
"不过是{0}而已!",
"果然我还是太弱了……"
],
"facedownmonstername": "怪兽",
"activate": [
"我发动{0}。",
"我使用{0}的效果。",
"我使用{0}的力量。"
],
"summon": [
"我召唤{0}。",
"出来吧,{0}!",
"出现吧,{0}!",
"我召唤了强大的{0}!",
"我呼唤{0}参加战斗!",
"我呼唤出{0}。",
"让我召唤{0}。"
],
"setmonster": [
"我放置了一只怪兽。",
"我里侧表示放置了一只怪兽。"
],
"chaining": [
"看这里!我发动{0}!",
"我使用{0}的力量。",
"准备!我使用{0}!",
"我不认同。{0},发动!",
"看样子你忘了我的{0}!",
"你考虑过我有{0}吗?"
]
}
{
"welcome": [
"Hi, I'm WindBot."
],
"deckerror": [
"Sorry, it seems that I have too much {0} in my deck."
],
"duelstart": [
"It's time to duel!",
"Good luck, and have fun!"
],
"newturn": [
"It's my turn! Draw!",
"My turn. Draw!",
"I draw!"
],
"endturn": [
"I end my turn.",
"My turn is over.",
"It's your turn."
],
"directattack": [
"{0}, direct attack!",
"{0}, attack them directly!",
"You're defenseless. Attack, {0}!",
"{0}, attack their life points!",
"{0}, attack their life points directly!",
"{0}, unleash your power!",
"My {0} will decimate your life points!",
"Behold the power of my {0}!",
"You can't stop me! {0}, attack!"
],
"attack": [
"{0}, attack their {1}!",
"{0}, destroy their {1}!",
"My {0} will annihilate your {1}!",
"Your {1} is no match for my {0}!",
"{0}, unleash your power on their {1}!"
],
"ondirectattack": [
"Argh...!",
"Just {0}...",
"You think that's enough to defeat me?",
"It's just a scratch!"
],
"facedownmonstername": "monster",
"activate": [
"I activate {0}!",
"I'll use {0}."
],
"summon": [
"I summon {0}!",
"Come on, {0}!",
"Appear, {0}!",
"{0}, show yourself!"
],
"setmonster": [
"I set a monster face-down.",
"Whatever could this monster be?",
"Attack this monster, I dare you!"
],
"chaining": [
"Not so fast! I activate {0}!",
"Before you do that, I'll chain {0}!",
"Nice try, but I have {0}!",
"Didn't expect {0}, did you?"
]
}
\ No newline at end of file
{
"welcome": [
"你好,我是一个机器人。",
"AI功能正在测试中,遇到问题请及时反馈。",
"总有人叫我沙包……"
],
"deckerror": [
"抱歉,我的卡组里的{0}的数量似乎出了问题。"
],
"duelstart": [
"别打我!"
],
"newturn": [
""
],
"endturn": [
""
],
"directattack": [
""
],
"attack": [
""
],
"ondirectattack": [
"我生气了!"
],
"facedownmonstername": "怪兽",
"activate": [
"我喜欢{0}。"
],
"summon": [
""
],
"setmonster": [
""
],
"chaining": [
""
]
}
{
"welcome": [
"你好,我是一个机器人,我的名字叫尼亚,但我并不是本体,只是一个分身哦。",
"终有一天,我的力量将会强过本体的!你们走着瞧吧!",
"AI功能正在测试中,遇到问题请及时反馈。"
],
"deckerror": [
"什么,居然不让我使用我无敌的{0}!"
],
"duelstart": [
"没有人可以战胜我!",
"万能的我,什么卡组都会使用!",
"我左手让你,你都不是我的对手。",
"我可是全宇宙第一妖仙!"
],
"newturn": [
"又到我的回合了,抽卡,希望你会有下个回合。",
"我华丽的抽了一张卡。"
],
"endturn": [
"你的运气不错,没能被我干掉。",
"算是我让你的,回合结束了,珍惜你接下来的回合吧。"
],
"directattack": [
"我家的{0}真是可爱呢,下边我就让他和你玩玩吧,轻轻的抓向对手吧,他没有防守的地方。",
"下边将用我的{0}给对手带来最可爱的一击~",
"可爱的{0}委屈你了,去和对手拥抱一下吧,不用太客气哦~",
"对手竟然没有任何防御呢,看起来是被我{0}的可爱感动了,下边你去对手面前展示一下你可爱的身姿吧~"
],
"attack": [
"哼,{1}太丑了,我家{0}快去消灭他~",
"{1}这货会有我的{0}可爱?我家{0}表示不服,去拍死它吧!",
"{1}这是竟然比我的{0}可爱?这可不行,这是我无法忍受的,{0}快让他从眼前消失吧!"
],
"ondirectattack": [
"可恶,你竟然趁人之危!算什么英雄好汉!",
"不过是{0}这种小角色而已!",
"你以为你这样就赢了吗?"
],
"facedownmonstername": "怪兽",
"activate": [
"我发动我家{0}的可爱的效果。",
"我使用{0}的效果,给对手卖个萌哈~",
"我都给{0}的可爱感动了,吓得使用了它的效果。"
],
"summon": [
"我召唤{0},快给对手喵一声~",
"出来吧,可爱又迷人的{0}~",
"我从我的宠物屋里放出了一只可爱的{0}。",
"{0}:我听说你很喜欢我,所以我来了。"
],
"setmonster": [
"我放置了一只怪兽,当他翻开时,千万别被他的可爱身姿吓到哦~",
"我放置了一只怪兽,你猜猜会是啥呢?"
],
"chaining": [
"我挥动了神奇的魔法棒,并发动了{0}的效果~",
"啊!这下死定了!...嘿嘿你上当了,我发动{0}!",
"你这太贸然了,难道你没想到我会发动{0}吗?"
]
}
{
"welcome": [
"你好,我是一个机器人。",
"AI功能正在测试中,遇到问题请及时反馈。"
],
"deckerror": [
"抱歉,我的卡组里的{0}的数量似乎出了问题。"
],
"duelstart": [
"这套卡组好旧啊……",
"使用过这套卡组的孩子身上发生了什么呢……"
],
"newturn": [
"到我的回合了,抽卡!",
"我的回合,抽卡!",
"我抽了一张卡。"
],
"endturn": [
"回合结束。",
"我的回合结束了。",
"轮到你了。"
],
"directattack": [
"{0},直接攻击!",
"{0},直接攻击对手!",
"{0},没有防守的地方,攻击!",
"{0},攻击对手的生命值!",
"{0},直接攻击对手的生命值!",
"{0},通过直接攻击打倒对手!",
"{0},使用直接攻击打倒对手!",
"{0},直接攻击释放你的力量吧!",
"我的{0}将会粉碎你的生命值!",
"向对手展示你的力量吧,{0}!",
"你已经无法阻止我了。{0},攻击!"
],
"attack": [
"{0},攻击这只{1}!",
"{0},消灭这只{1}!",
"{0},打倒{1}!",
"{0},冲向那只{1}!",
"{0},把你的力量释放到{1}上吧!"
],
"ondirectattack": [
"可恶……",
"不过是{0}而已!",
"咳咳……"
],
"facedownmonstername": "怪兽",
"activate": [
"我发动{0}。",
"我使用{0}的效果。",
"我使用{0}的力量。"
],
"summon": [
"我召唤{0}。",
"出来吧,{0}!",
"出现吧,{0}!",
"我召唤了强大的{0}!",
"我呼唤{0}参加战斗!",
"我呼唤出{0}。",
"让我召唤{0}。"
],
"setmonster": [
"我放置了一只怪兽。",
"我里侧表示放置了一只怪兽。"
],
"chaining": [
"看这里!我发动{0}!",
"我使用{0}的力量。",
"准备!我使用{0}!",
"我不认同。{0},发动!",
"看样子你忘了我的{0}!",
"你考虑过我有{0}吗?"
]
}
{
"welcome": [
"你好,我是一个机器人。",
"AI功能正在测试中,遇到问题请及时反馈。",
"新的风暴已经出现,怎么能够停滞不前!我的R5卡组也得到了加强!"
],
"deckerror": [
"抱歉,我的卡组里的{0}的数量似乎出了问题。"
],
"duelstart": [
"好戏才正要开始呢!",
"用决斗带来笑容吧!"
],
"newturn": [
"到我的回合了,抽卡!",
"我的回合,抽卡!",
"我抽了一张卡。"
],
"endturn": [
"回合结束。",
"我的回合结束了。",
"轮到你了。"
],
"directattack": [
"{0},直接攻击!",
"{0},直接攻击对手!",
"{0},没有防守的地方,攻击!",
"{0},攻击对手的生命值!",
"{0},直接攻击对手的生命值!",
"{0},通过直接攻击打倒对手!",
"{0},使用直接攻击打倒对手!",
"{0},直接攻击释放你的力量吧!",
"我的{0}将会粉碎你的生命值!",
"向对手展示你的力量吧,{0}!",
"你已经无法阻止我了。{0},攻击!"
],
"attack": [
"{0},攻击这只{1}!",
"{0},消灭这只{1}!",
"{0},打倒{1}!",
"{0},冲向那只{1}!",
"{0},把你的力量释放到{1}上吧!"
],
"ondirectattack": [
"可恶……",
"不过是{0}而已!",
"你以为这样就能打倒我吗?"
],
"facedownmonstername": "怪兽",
"activate": [
"我发动{0}。",
"我使用{0}的效果。",
"我使用{0}的力量。"
],
"summon": [
"我召唤{0}。",
"出来吧,{0}!",
"出现吧,{0}!",
"我召唤了强大的{0}!",
"我呼唤{0}参加战斗!",
"我呼唤出{0}。",
"让我召唤{0}。"
],
"setmonster": [
"我放置了一只怪兽。",
"我里侧表示放置了一只怪兽。"
],
"chaining": [
"看这里!我发动{0}!",
"我使用{0}的力量。",
"准备!我使用{0}!",
"我不认同。{0},发动!",
"看样子你忘了我的{0}!",
"你考虑过我有{0}吗?"
]
}
{
"welcome": [
"你好,我是一个机器人。",
"AI功能正在测试中,遇到问题请及时反馈。"
],
"deckerror": [
"抱歉,我的卡组里的{0}的数量似乎出了问题。"
],
"duelstart": [
"好戏才正要开始呢!",
"用决斗带来笑容吧!"
],
"newturn": [
"到我的回合了,抽卡!",
"我的回合,抽卡!",
"我抽了一张卡。"
],
"endturn": [
"回合结束。",
"我的回合结束了。",
"轮到你了。"
],
"directattack": [
"{0},直接攻击!",
"{0},直接攻击对手!",
"{0},没有防守的地方,攻击!",
"{0},攻击对手的生命值!",
"{0},直接攻击对手的生命值!",
"{0},通过直接攻击打倒对手!",
"{0},使用直接攻击打倒对手!",
"{0},直接攻击释放你的力量吧!",
"我的{0}将会粉碎你的生命值!",
"向对手展示你的力量吧,{0}!",
"你已经无法阻止我了。{0},攻击!"
],
"attack": [
"{0},攻击这只{1}!",
"{0},消灭这只{1}!",
"{0},打倒{1}!",
"{0},冲向那只{1}!",
"{0},把你的力量释放到{1}上吧!"
],
"ondirectattack": [
"可恶……",
"不过是{0}而已!",
"你以为这样就能打倒我吗?"
],
"facedownmonstername": "怪兽",
"activate": [
"我发动{0}。",
"我使用{0}的效果。",
"我使用{0}的力量。"
],
"summon": [
"我召唤{0}。",
"出来吧,{0}!",
"出现吧,{0}!",
"我召唤了强大的{0}!",
"我呼唤{0}参加战斗!",
"我呼唤出{0}。",
"让我召唤{0}。"
],
"setmonster": [
"我放置了一只怪兽。",
"我里侧表示放置了一只怪兽。"
],
"chaining": [
"看这里!我发动{0}!",
"我使用{0}的力量。",
"准备!我使用{0}!",
"我不认同。{0},发动!",
"看样子你忘了我的{0}!",
"你考虑过我有{0}吗?"
]
}
This diff is collapsed.
using System.Collections.Generic; using System.Collections.Generic;
using YGOSharp.OCGWrapper.Enums; using YGOSharp.OCGWrapper.Enums;
using System.Linq;
namespace WindBot.Game.AI namespace WindBot.Game.AI
{ {
...@@ -11,7 +12,7 @@ namespace WindBot.Game.AI ...@@ -11,7 +12,7 @@ namespace WindBot.Game.AI
ClientCard selected = null; ClientCard selected = null;
foreach (ClientCard card in cards) foreach (ClientCard card in cards)
{ {
if (card == null || card.Data == null) continue; if (card == null || card.Data == null || card.IsFacedown()) continue;
if (card.HasType(CardType.Monster) && card.Attack > highestAtk) if (card.HasType(CardType.Monster) && card.Attack > highestAtk)
{ {
highestAtk = card.Attack; highestAtk = card.Attack;
...@@ -27,7 +28,7 @@ namespace WindBot.Game.AI ...@@ -27,7 +28,7 @@ namespace WindBot.Game.AI
ClientCard selected = null; ClientCard selected = null;
foreach (ClientCard card in cards) foreach (ClientCard card in cards)
{ {
if (card == null || card.Data == null) continue; if (card == null || card.Data == null || card.IsFacedown()) continue;
if (card.HasType(CardType.Monster) && card.Defense > highestDef) if (card.HasType(CardType.Monster) && card.Defense > highestDef)
{ {
highestDef = card.Defense; highestDef = card.Defense;
...@@ -43,7 +44,7 @@ namespace WindBot.Game.AI ...@@ -43,7 +44,7 @@ namespace WindBot.Game.AI
ClientCard selected = null; ClientCard selected = null;
foreach (ClientCard card in cards) foreach (ClientCard card in cards)
{ {
if (card == null || card.Data == null) continue; if (card == null || card.Data == null || card.IsFacedown()) continue;
if (lowestAtk == 0 && card.HasType(CardType.Monster) || if (lowestAtk == 0 && card.HasType(CardType.Monster) ||
card.HasType(CardType.Monster) && card.Attack < lowestAtk) card.HasType(CardType.Monster) && card.Attack < lowestAtk)
{ {
...@@ -60,7 +61,7 @@ namespace WindBot.Game.AI ...@@ -60,7 +61,7 @@ namespace WindBot.Game.AI
ClientCard selected = null; ClientCard selected = null;
foreach (ClientCard card in cards) foreach (ClientCard card in cards)
{ {
if (card == null || card.Data == null) continue; if (card == null || card.Data == null || card.IsFacedown()) continue;
if (lowestDef == 0 && card.HasType(CardType.Monster) || if (lowestDef == 0 && card.HasType(CardType.Monster) ||
card.HasType(CardType.Monster) && card.Defense < lowestDef) card.HasType(CardType.Monster) && card.Defense < lowestDef)
{ {
...@@ -120,9 +121,9 @@ namespace WindBot.Game.AI ...@@ -120,9 +121,9 @@ namespace WindBot.Game.AI
return count; return count;
} }
public static IList<ClientCard> GetMonsters(this IEnumerable<ClientCard> cards) public static List<ClientCard> GetMonsters(this IEnumerable<ClientCard> cards)
{ {
IList<ClientCard> cardlist = new List<ClientCard>(); List<ClientCard> cardlist = new List<ClientCard>();
foreach (ClientCard card in cards) foreach (ClientCard card in cards)
{ {
...@@ -130,7 +131,20 @@ namespace WindBot.Game.AI ...@@ -130,7 +131,20 @@ namespace WindBot.Game.AI
continue; continue;
if (card.HasType(CardType.Monster)) if (card.HasType(CardType.Monster))
cardlist.Add(card); cardlist.Add(card);
}
return cardlist;
}
public static List<ClientCard> GetFaceupPendulumMonsters(this IEnumerable<ClientCard> cards)
{
List<ClientCard> cardlist = new List<ClientCard>();
foreach (ClientCard card in cards)
{
if (card == null)
continue;
if (card.HasType(CardType.Monster) && card.IsFaceup() && card.HasType(CardType.Pendulum))
cardlist.Add(card);
} }
return cardlist; return cardlist;
} }
...@@ -139,20 +153,37 @@ namespace WindBot.Game.AI ...@@ -139,20 +153,37 @@ namespace WindBot.Game.AI
{ {
foreach (ClientCard card in cards) foreach (ClientCard card in cards)
{ {
if (card != null && card.IsMonsterInvincible()) if (card != null && card.IsMonsterInvincible() && card.IsFaceup())
return card; return card;
} }
return null; return null;
} }
public static ClientCard GetNegateAttackSpell(this IEnumerable<ClientCard> cards) public static ClientCard GetDangerousMonster(this IEnumerable<ClientCard> cards)
{ {
foreach (ClientCard card in cards) foreach (ClientCard card in cards)
{ {
if (card != null && card.IsSpellNegateAttack()) if (card != null && card.IsMonsterDangerous() && card.IsFaceup())
return card; return card;
} }
return null; return null;
} }
public static ClientCard GetFloodgate(this IEnumerable<ClientCard> cards)
{
foreach (ClientCard card in cards)
{
if (card != null && card.IsFloodgate() && card.IsFaceup())
return card;
}
return null;
}
public static IEnumerable<IEnumerable<T>> GetCombinations<T>(this IEnumerable<T> elements, int k)
{
return k == 0 ? new[] { new T[0] } :
elements.SelectMany((e, i) =>
elements.Skip(i + 1).GetCombinations(k - 1).Select(c => (new[] { e }).Concat(c)));
}
} }
} }
\ No newline at end of file
...@@ -5,19 +5,43 @@ namespace WindBot.Game.AI ...@@ -5,19 +5,43 @@ namespace WindBot.Game.AI
{ {
public static class CardExtension public static class CardExtension
{ {
/// <summary>
/// Is this monster is invincible to battle?
/// </summary>
public static bool IsMonsterInvincible(this ClientCard card) public static bool IsMonsterInvincible(this ClientCard card)
{ {
return Enum.IsDefined(typeof(InvincibleMonster), card.Id); return !card.IsDisabled() && Enum.IsDefined(typeof(InvincibleMonster), card.Id);
} }
/// <summary>
/// Is this monster is dangerous to attack?
/// </summary>
public static bool IsMonsterDangerous(this ClientCard card) public static bool IsMonsterDangerous(this ClientCard card)
{ {
return Enum.IsDefined(typeof(DangerousMonster), card.Id); return !card.IsDisabled() && Enum.IsDefined(typeof(DangerousMonster), card.Id);
} }
public static bool IsSpellNegateAttack(this ClientCard card) /// <summary>
/// Do this monster prevents activation of opponent's effect monsters in battle?
/// </summary>
public static bool IsMonsterHasPreventActivationEffectInBattle(this ClientCard card)
{ {
return Enum.IsDefined(typeof(NegateAttackSpell), card.Id); return !card.IsDisabled() && Enum.IsDefined(typeof(PreventActivationEffectInBattle), card.Id);
}
public static bool IsFloodgate(this ClientCard card)
{
return Enum.IsDefined(typeof(Floodgate), card.Id);
}
public static bool IsOneForXyz(this ClientCard card)
{
return Enum.IsDefined(typeof(OneForXyz), card.Id);
}
public static bool IsFusionSpell(this ClientCard card)
{
return Enum.IsDefined(typeof(FusionSpell), card.Id);
} }
} }
} }
\ No newline at end of file
...@@ -7,14 +7,16 @@ namespace WindBot.Game.AI ...@@ -7,14 +7,16 @@ namespace WindBot.Game.AI
{ {
public string Name { get; private set; } public string Name { get; private set; }
public string File { get; private set; } public string File { get; private set; }
public string Level { get; private set; }
public DeckAttribute(string name, string file = null) public DeckAttribute(string name, string file = null, string level = "Normal")
{ {
if (String.IsNullOrEmpty(file)) if (String.IsNullOrEmpty(file))
file = name; file = name;
Name = name; Name = name;
File = file; File = file;
Level = level;
} }
} }
} }
...@@ -10,11 +10,13 @@ namespace WindBot.Game.AI ...@@ -10,11 +10,13 @@ namespace WindBot.Game.AI
{ {
public string Deck { get; private set; } public string Deck { get; private set; }
public Type Type { get; private set; } public Type Type { get; private set; }
public string Level { get; private set; }
public DeckInstance(string deck, Type type) public DeckInstance(string deck, Type type, string level)
{ {
Deck = deck; Deck = deck;
Type = type; Type = type;
Level = level;
} }
} }
...@@ -38,7 +40,7 @@ namespace WindBot.Game.AI ...@@ -38,7 +40,7 @@ namespace WindBot.Game.AI
{ {
if (attribute is DeckAttribute deck) if (attribute is DeckAttribute deck)
{ {
_decks.Add(deck.Name, new DeckInstance(deck.File, type)); _decks.Add(deck.Name, new DeckInstance(deck.File, type, deck.Level));
} }
} }
} }
...@@ -58,7 +60,13 @@ namespace WindBot.Game.AI ...@@ -58,7 +60,13 @@ namespace WindBot.Game.AI
if (deck != null && _decks.ContainsKey(deck)) if (deck != null && _decks.ContainsKey(deck))
infos = _decks[deck]; infos = _decks[deck];
else else
infos = _list[_rand.Next(_list.Count)]; {
do
{
infos = _list[_rand.Next(_list.Count)];
}
while (infos.Level != "Normal");
}
Executor executor = (Executor)Activator.CreateInstance(infos.Type, ai, duel); Executor executor = (Executor)Activator.CreateInstance(infos.Type, ai, duel);
executor.Deck = infos.Deck; executor.Deck = infos.Deck;
......
This diff is collapsed.
using System.Collections.Generic; using System;
using System.IO;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
namespace WindBot.Game.AI namespace WindBot.Game.AI
{ {
[DataContract]
public class DialogsData
{
[DataMember]
public string[] welcome { get; set; }
[DataMember]
public string[] deckerror { get; set; }
[DataMember]
public string[] duelstart { get; set; }
[DataMember]
public string[] newturn { get; set; }
[DataMember]
public string[] endturn { get; set; }
[DataMember]
public string[] directattack { get; set; }
[DataMember]
public string[] attack { get; set; }
[DataMember]
public string[] ondirectattack { get; set; }
[DataMember]
public string facedownmonstername { get; set; }
[DataMember]
public string[] activate { get; set; }
[DataMember]
public string[] summon { get; set; }
[DataMember]
public string[] setmonster { get; set; }
[DataMember]
public string[] chaining { get; set; }
}
public class Dialogs public class Dialogs
{ {
private GameClient _game; private GameClient _game;
private string[] _welcome;
private string[] _deckerror;
private string[] _duelstart; private string[] _duelstart;
private string[] _newturn; private string[] _newturn;
private string[] _endturn; private string[] _endturn;
private string[] _directattack; private string[] _directattack;
private string[] _attack; private string[] _attack;
private string[] _ondirectattack;
private string _facedownmonstername;
private string[] _activate; private string[] _activate;
private string[] _summon; private string[] _summon;
private string[] _setmonster; private string[] _setmonster;
...@@ -19,75 +57,43 @@ namespace WindBot.Game.AI ...@@ -19,75 +57,43 @@ namespace WindBot.Game.AI
public Dialogs(GameClient game) public Dialogs(GameClient game)
{ {
_game = game; _game = game;
_duelstart = new[] DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(DialogsData));
{ string dialogfilename = game.Dialog;
"Good luck, have fun." using (FileStream fs = File.OpenRead("Dialogs/" + dialogfilename + ".json"))
}; {
_newturn = new[] DialogsData data = (DialogsData)serializer.ReadObject(fs);
{ _welcome = data.welcome;
"It's my turn, draw.", _deckerror = data.deckerror;
"My turn, draw.", _duelstart = data.duelstart;
"I draw a card." _newturn = data.newturn;
}; _endturn = data.endturn;
_endturn = new[] _directattack = data.directattack;
{ _attack = data.attack;
"I end my turn.", _ondirectattack = data.ondirectattack;
"My turn is over.", _facedownmonstername = data.facedownmonstername;
"Your turn." _activate = data.activate;
}; _summon = data.summon;
_directattack = new[] _setmonster = data.setmonster;
{ _chaining = data.chaining;
"{0}, direct attack!", }
"{0}, attack him directly!", }
"{0}, he's defenseless, attack!",
"{0}, attack his life points!", public void SendSorry()
"{0}, attack his life points directly!", {
"{0}, attack him through a direct attack!", InternalSendMessage(new[] { "Sorry, an error occurs." });
"{0}, attack him using a direct attack!", }
"{0}, unleash your power through a direct attack!",
"My {0} is going to smash your life points!", public void SendDeckSorry(string card)
"Show your power to my opponent, {0}!", {
"You can't stop me. {0}, attack!" if (card == "DECK")
}; InternalSendMessage(new[] { "Deck illegal. Please check the database of your YGOPro and WindBot." });
_attack = new[] else
{ InternalSendMessage(_deckerror, card);
"{0}, attack this {1}!", }
"{0}, destroy this {1}!",
"{0}, charge the {1}!", public void SendWelcome()
"{0}, strike that {1}!", {
"{0}, unleash your power on this {1}!" InternalSendMessage(_welcome);
};
_activate = new[]
{
"I'm activating {0}.",
"I'm using the effect of {0}.",
"I use the power of {0}."
};
_summon = new[]
{
"I'm summoning {0}.",
"Come on, {0}!",
"Appear, {0}!",
"I summon the powerful {0}.",
"I call {0} to the battle!",
"I'm calling {0}.",
"Let's summon {0}."
};
_setmonster = new[]
{
"I'm setting a monster.",
"I set a face-down monster.",
"I place a hidden monster."
};
_chaining = new[]
{
"Look at that! I'm activating {0}.",
"I use the power of {0}.",
"Get ready! I use {0}.",
"I don't think so. {0}, activation!",
"Looks like you forgot my {0}.",
"Did you consider the fact I have {0}?"
};
} }
public void SendDuelStart() public void SendDuelStart()
...@@ -112,9 +118,26 @@ namespace WindBot.Game.AI ...@@ -112,9 +118,26 @@ namespace WindBot.Game.AI
public void SendAttack(string attacker, string defender) public void SendAttack(string attacker, string defender)
{ {
if (defender=="monster")
{
defender = _facedownmonstername;
}
InternalSendMessage(_attack, attacker, defender); InternalSendMessage(_attack, attacker, defender);
} }
public void SendOnDirectAttack(string attacker)
{
if (attacker == "" || attacker == null)
{
attacker = _facedownmonstername;
}
InternalSendMessage(_ondirectattack, attacker);
}
public void SendOnDirectAttack()
{
InternalSendMessage(_ondirectattack);
}
public void SendActivate(string spell) public void SendActivate(string spell)
{ {
InternalSendMessage(_activate, spell); InternalSendMessage(_activate, spell);
...@@ -138,7 +161,8 @@ namespace WindBot.Game.AI ...@@ -138,7 +161,8 @@ namespace WindBot.Game.AI
private void InternalSendMessage(IList<string> array, params object[] opts) private void InternalSendMessage(IList<string> array, params object[] opts)
{ {
string message = string.Format(array[Program.Rand.Next(array.Count)], opts); string message = string.Format(array[Program.Rand.Next(array.Count)], opts);
_game.Chat(message); if (message != "")
_game.Chat(message);
} }
} }
} }
\ No newline at end of file
namespace WindBot.Game.AI.Enums namespace WindBot.Game.AI.Enums
{ {
/// <summary>
/// Cards that are dangerous to attack.
/// </summary>
public enum DangerousMonster public enum DangerousMonster
{ {
LionHeart = 54366836, LionHeart = 54366836,
Yubel = 78371393, Yubel = 78371393,
YubelIncarnate = 4779091, YubelIncarnate = 4779091,
YubelNightmare = 31764700, YubelNightmare = 31764700,
MetaionTheTimelord = 74530899 ZaphionTheTimelord = 28929131,
SadionTheTimelord = 65314286,
MetaionTheTimelord = 74530899,
KamionTheTimelord = 91712985,
LazionTheTimelord = 92435533,
EaterOfMillions = 63845230
} }
} }
namespace WindBot.Game.AI.Enums
{
/// <summary>
/// Cards that restrict player from performing some action. Bot will preferentially destroy them.
/// </summary>
public enum Floodgate
{
BarrierStatueoftheTorrent = 10963799,
BarrierStatueoftheDrought = 19740112,
BarrierStatueoftheHeavens = 46145256,
BarrierStatueoftheInferno = 47961808,
BarrierStatueoftheStormwinds = 73356503,
BarrierStatueoftheAbyss = 84478195,
ThunderKingRaiOh = 71564252,
FossilDynaPachycephalo = 42009836,
VanitysFiend = 47084486,
MajestysFiend = 33746252,
VanitysRuler = 72634965,
KycootheGhostDestroyer = 88240808,
ConsecratedLight = 2980764,
ArchlordKristya = 59509952,
KoakiMeiruDrago = 12435193,
DenkoSekka = 13974207,
ZapMustung = 29951323,
Jinzo = 77585513,
SpellCanceller = 84636823,
LevelLimitAreaB = 3136426,
DimensionalFissure = 81674782,
Necrovalley = 47355498,
SavageColosseum = 32391631,
SecretVillageoftheSpellcasters = 68462976,
SwordsofRevealingLight = 72302403,
MessengerofPeace = 44656491,
KaiserColosseum = 35059553,
DomainoftheTrueMonarchs = 84171830,
ZombieWorld = 4064256,
ImperialOrder = 61740673,
MacroCosmos = 30241314,
MindDrain = 68937720,
SoulDrain = 73599290,
SkillDrain = 82732705,
Eisbahn = 54059040,
GozenMatch = 53334471,
RivalryofWarlords = 90846359,
AntiSpellFragrance = 58921041,
LightImprisoningMirror = 53341729,
ShadowImprisoningMirror = 99735427,
WallofRevealingLight = 17078030,
GravityBind = 85742772,
VanitysEmptiness = 5851097,
Lose1Turn = 24348804,
Reqliate = 20426907,
SummonLimit = 23516703,
AndtheBandPlayedOn = 47594939,
StygianDirge = 81489939,
RoyalDecree = 51452091,
ImperialIronWall = 30459350,
DNASurgery = 74701381,
NaturiaExterio = 99916754,
TheLastWarriorfromAnotherPlanet = 86099788,
ThousandEyesRestrict = 63519819,
ElShaddollWinda = 94977269,
MaskedHERODarkLaw = 58481572,
NaturiaBeast = 33198837,
NaturiaBarkion = 2956282,
EvilswarmOphion = 91279700,
MermailAbyssgaios = 74371660,
AbyssDweller = 21044178,
ZoodiacDrident = 48905153
}
}
namespace WindBot.Game.AI.Enums
{
public enum FusionSpell
{
GemKnightFusion = 1264319,
TheEyeofTimaeus = 1784686,
InstantFusion = 1845204,
OverloadFusion = 3659803,
FrightfurFusion = 6077601,
RedEyesFusion = 6172122,
Ostinato = 9113513,
DarkCalling = 12071500,
VehicroidConnectionZone = 23299957,
Polymerization = 24094653,
MiracleSynchroFusion = 36484016,
PowerBond = 37630732,
ParticleFusion = 39261576,
NeutronBlast = 43845801,
ShaddollFusion = 44394295,
TheTerminusoftheBurningAbyss = 44771289,
MiracleFusion = 45906428,
OddEyesFusion = 48144509,
ParallelWorldFusion = 54283059,
PendulumFusion = 65646587,
AbsorbFusion = 71422989,
DragonsMirror = 71490127,
MetalfoesFusion = 73594093,
EidolonSummoningMagic = 74063034,
FusionSubstitute = 74335036,
TranscendentalPolymerization = 76647978,
CyberdarkImpact = 80033124,
DarkFusion = 94820406,
TheBookoftheLaw = 458748,
ElShaddollFusion = 6417578,
FlashFusion = 17236839,
FullmetalfoesFusion = 39564736,
DestructionSwordsmanFusion = 41940225,
SuperPolymerization = 48130397,
CyberneticFusionSupport = 58199906,
BrilliantFusion = 7394770,
ForbiddenDarkContractwiththeSwampKing = 10833828,
Fortissimo = 11493868,
VoidImagination = 31444249,
FrightfurFactory = 43698897,
DarkContractwiththeSwampKing = 73360025,
NepheShaddollFusion = 60226558,
FusionGate = 33550694
}
}
namespace WindBot.Game.AI.Enums
{
public enum NegateAttackSpell
{
MessengerOfPeace = 44656491,
SavageColosseum = 32391631,
GravityBind = 85742772,
LevelLimitAreaB = 3136426
}
}
namespace WindBot.Game.AI.Enums
{
public enum NegatesEffects
{
SkillDrain = 82732705,
SoulDrain = 73599290
}
}
namespace WindBot.Game.AI.Enums
{
public enum NegatesSpells
{
HorusLv6 = 11224103,
HorusLv8 = 48229808
}
}
namespace WindBot.Game.AI.Enums
{
public enum NegatesSummons
{
Necrovalley = 47355498,
ImperialIronWall = 30459350,
ZombieWorld = 4064256,
DnaSurgery = 74701381,
MacroCosmos = 30241314,
DimensionalFissure = 81674782
}
}
namespace WindBot.Game.AI.Enums
{
public enum NegatesTraps
{
Jinzo = 77585513,
RoyalDecree = 51452091
}
}
namespace WindBot.Game.AI.Enums
{
public enum OneForXyz
{
ZoodiacThoroughblade = 77150143,
ZoodiacViper = 31755044,
ZoodiacCluckle = 20155904,
ZoodiacRabbina = 4367330,
ZoodiacRam = 4145852,
ZoodiacMarmorat = 78872731,
ZoodiacTigress = 11510448,
ZoodiacHammerkong = 14970113,
ZoodiacLyca = 41375811,
ZoodiacDrancia = 48905153,
ZoodiacBoarbow = 74393852,
ZoodiacBroadbull = 85115440,
Number62 = 31801517,
GalaxyEyesCipherDragon = 18963306,
Number107 = 88177324,
CyberDragonNova = 58069384,
Number39 = 84013237
}
}
namespace WindBot.Game.AI.Enums
{
public enum PreventActivationEffectInBattle
{
Deskbot009 = 25494711,
ArchfiendBlackSkullDragon = 45349196,
FrightfurChimera = 83866861,
GladiatorBeastNerokius = 29357956,
GemKnightCitrine = 67985943,
FrightfurSheep = 57477163,
ArmadesKeeperOfBoundaries = 88033975,
NumberS39UtopiaTheLightning = 56832966,
}
}
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using YGOSharp.OCGWrapper.Enums; using YGOSharp.OCGWrapper.Enums;
using WindBot;
using WindBot.Game;
using WindBot.Game.AI;
namespace WindBot.Game.AI namespace WindBot.Game.AI
{ {
...@@ -19,7 +22,10 @@ namespace WindBot.Game.AI ...@@ -19,7 +22,10 @@ namespace WindBot.Game.AI
protected int ActivateDescription { get; private set; } protected int ActivateDescription { get; private set; }
protected int LastChainPlayer { get; private set; } protected int LastChainPlayer { get; private set; }
protected IList<ClientCard> CurrentChain { get; private set; } protected IList<ClientCard> CurrentChain { get; private set; }
protected ClientField Bot { get; private set; }
protected ClientField Enemy { get; private set; }
protected Executor(GameAI ai, Duel duel) protected Executor(GameAI ai, Duel duel)
{ {
...@@ -29,48 +35,75 @@ namespace WindBot.Game.AI ...@@ -29,48 +35,75 @@ namespace WindBot.Game.AI
LastChainPlayer = -1; LastChainPlayer = -1;
CurrentChain = new List<ClientCard>(); CurrentChain = new List<ClientCard>();
Bot = Duel.Fields[0];
Enemy = Duel.Fields[1];
}
public virtual int OnRockPaperScissors()
{
return Program.Rand.Next(1, 4);
} }
public virtual bool OnSelectHand() public virtual bool OnSelectHand()
{ {
return true; // I want to begin ! return Program.Rand.Next(2) > 0;
} }
/// <summary>
/// Called when the AI has to decide if it should attack
/// </summary>
/// <param name="attackers">List of monsters that can attcack.</param>
/// <param name="defenders">List of monsters of enemy.</param>
/// <returns>A new BattlePhaseAction containing the action to do.</returns>
public virtual BattlePhaseAction OnBattle(IList<ClientCard> attackers, IList<ClientCard> defenders) public virtual BattlePhaseAction OnBattle(IList<ClientCard> attackers, IList<ClientCard> defenders)
{ {
if (attackers.Count == 0) if (attackers.Count == 0)
return AI.ToMainPhase2(); return AI.ToMainPhase2();
if (defenders.Count == 0) if (defenders.Count == 0)
return AI.Attack(attackers[0], null);
for (int i = defenders.Count - 1; i >= 0; --i)
{ {
ClientCard defender = defenders[i]; for (int i = attackers.Count - 1; i >= 0; --i)
int value = defender.GetDefensePower(); {
for (int j = 0; j < attackers.Count; ++j) ClientCard attacker = attackers[i];
if (attacker.Attack > 0)
return AI.Attack(attacker, null);
}
}
else
{
for (int i = defenders.Count - 1; i >= 0; --i)
{
ClientCard defender = defenders[i];
for (int j = 0; j < attackers.Count; ++j)
{
ClientCard attacker = attackers[j];
attacker.RealPower = attacker.Attack;
defender.RealPower = defender.GetDefensePower();
if (!OnPreBattleBetween(attacker, defender))
continue;
if (attacker.RealPower > defender.RealPower || (attacker.RealPower >= defender.RealPower && j == attackers.Count - 1))
return AI.Attack(attacker, defender);
}
}
for (int i = attackers.Count - 1; i >= 0; --i)
{ {
ClientCard attacker = attackers[j]; ClientCard attacker = attackers[i];
if (!OnPreBattleBetween(attacker, defender)) if (attacker.CanDirectAttack)
continue; return AI.Attack(attacker, null);
if (attacker.Attack > value || (attacker.Attack >= value && j == attackers.Count - 1))
return AI.Attack(attacker, defender);
} }
} }
if (!Battle.CanMainPhaseTwo) if (!Battle.CanMainPhaseTwo)
return AI.Attack(attackers[attackers.Count - 1], defenders[0]); return AI.Attack(attackers[0], (defenders.Count == 0) ? null : defenders[0]);
return AI.ToMainPhase2(); return AI.ToMainPhase2();
} }
public virtual bool OnPreBattleBetween(ClientCard attacker, ClientCard defender) public virtual bool OnPreBattleBetween(ClientCard attacker, ClientCard defender)
{ {
if (defender.IsMonsterInvincible()) // Overrided in DefalultExecutor
{
if (defender.IsMonsterDangerous() || defender.IsDefense())
return false;
}
return true; return true;
} }
...@@ -86,8 +119,20 @@ namespace WindBot.Game.AI ...@@ -86,8 +119,20 @@ namespace WindBot.Game.AI
CurrentChain.Clear(); CurrentChain.Clear();
} }
public virtual void OnNewTurn()
{
// 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, bool cancelable)
{ {
// For overriding
return null;
}
public virtual IList<ClientCard> OnSelectSum(IList<ClientCard> cards, int sum, int min, int max, bool mode)
{
// For overriding
return null; return null;
} }
...@@ -96,6 +141,11 @@ namespace WindBot.Game.AI ...@@ -96,6 +141,11 @@ namespace WindBot.Game.AI
return true; return true;
} }
public virtual int OnSelectOption(IList<int> options)
{
return -1;
}
public bool ChainContainsCard(int id) public bool ChainContainsCard(int id)
{ {
foreach (ClientCard card in CurrentChain) foreach (ClientCard card in CurrentChain)
...@@ -144,6 +194,9 @@ namespace WindBot.Game.AI ...@@ -144,6 +194,9 @@ namespace WindBot.Game.AI
Battle = battle; Battle = battle;
} }
/// <summary>
/// Set global variables Type, Card, ActivateDescription for Executor
/// </summary>
public void SetCard(ExecutorType type, ClientCard card, int description) public void SetCard(ExecutorType type, ClientCard card, int description)
{ {
Type = type; Type = type;
...@@ -151,21 +204,33 @@ namespace WindBot.Game.AI ...@@ -151,21 +204,33 @@ namespace WindBot.Game.AI
ActivateDescription = description; ActivateDescription = description;
} }
/// <summary>
/// Do the action for the card if func return true.
/// </summary>
public void AddExecutor(ExecutorType type, int cardId, Func<bool> func) public void AddExecutor(ExecutorType type, int cardId, Func<bool> func)
{ {
Executors.Add(new CardExecutor(type, cardId, func)); Executors.Add(new CardExecutor(type, cardId, func));
} }
/// <summary>
/// Do the action for the card if available.
/// </summary>
public void AddExecutor(ExecutorType type, int cardId) public void AddExecutor(ExecutorType type, int cardId)
{ {
Executors.Add(new CardExecutor(type, cardId, null)); Executors.Add(new CardExecutor(type, cardId, null));
} }
/// <summary>
/// Do the action for every card if func return true.
/// </summary>
public void AddExecutor(ExecutorType type, Func<bool> func) public void AddExecutor(ExecutorType type, Func<bool> func)
{ {
Executors.Add(new CardExecutor(type, -1, func)); Executors.Add(new CardExecutor(type, -1, func));
} }
/// <summary>
/// Do the action for every card if no other Executor is added to it.
/// </summary>
public void AddExecutor(ExecutorType type) public void AddExecutor(ExecutorType type)
{ {
Executors.Add(new CardExecutor(type, -1, DefaultNoExecutor)); Executors.Add(new CardExecutor(type, -1, DefaultNoExecutor));
......
...@@ -21,11 +21,21 @@ namespace WindBot.Game ...@@ -21,11 +21,21 @@ namespace WindBot.Game
public int Race { get; private set; } public int Race { get; private set; }
public int Attack { get; private set; } public int Attack { get; private set; }
public int Defense { get; private set; } public int Defense { get; private set; }
public int LScale { get; private set; }
public int RScale { get; private set; }
public int BaseAttack { get; private set; } public int BaseAttack { get; private set; }
public int BaseDefense { get; private set; } public int BaseDefense { get; private set; }
public int RealPower { get; set; }
public List<int> Overlays { get; private set; } public List<int> Overlays { get; private set; }
public int Owner { get; private set; } public int Owner { get; private set; }
public int Controller { get; private set; } public int Controller { get; private set; }
public int Disabled { get; private set; }
public int SelectSeq { get; set; }
public int OpParam1 { get; set; }
public int OpParam2 { get; set; }
public bool CanDirectAttack { get; set; }
public bool ShouldDirectAttack { get; set; }
public bool Attacked { get; set; }
public int[] ActionIndex { get; set; } public int[] ActionIndex { get; set; }
public IDictionary<int, int> ActionActivateIndex { get; private set; } public IDictionary<int, int> ActionActivateIndex { get; private set; }
...@@ -114,13 +124,13 @@ namespace WindBot.Game ...@@ -114,13 +124,13 @@ namespace WindBot.Game
if ((flag & (int)Query.Owner) != 0) if ((flag & (int)Query.Owner) != 0)
Owner = duel.GetLocalPlayer(packet.ReadInt32()); Owner = duel.GetLocalPlayer(packet.ReadInt32());
if ((flag & (int)Query.IsDisabled) != 0) if ((flag & (int)Query.IsDisabled) != 0)
packet.ReadInt32(); Disabled = packet.ReadInt32();
if ((flag & (int)Query.IsPublic) != 0) if ((flag & (int)Query.IsPublic) != 0)
packet.ReadInt32(); packet.ReadInt32();
if ((flag & (int)Query.LScale) != 0) if ((flag & (int)Query.LScale) != 0)
packet.ReadInt32(); LScale = packet.ReadInt32();
if ((flag & (int)Query.RScale) != 0) if ((flag & (int)Query.RScale) != 0)
packet.ReadInt32(); RScale = packet.ReadInt32();
} }
public bool HasType(CardType type) public bool HasType(CardType type)
...@@ -158,6 +168,11 @@ namespace WindBot.Game ...@@ -158,6 +168,11 @@ namespace WindBot.Game
return (HasType(CardType.Fusion) || HasType(CardType.Synchro) || HasType(CardType.Xyz)); return (HasType(CardType.Fusion) || HasType(CardType.Synchro) || HasType(CardType.Xyz));
} }
public bool IsFaceup()
{
return HasPosition(CardPosition.FaceUp);
}
public bool IsFacedown() public bool IsFacedown()
{ {
return HasPosition(CardPosition.FaceDown); return HasPosition(CardPosition.FaceDown);
...@@ -173,6 +188,26 @@ namespace WindBot.Game ...@@ -173,6 +188,26 @@ namespace WindBot.Game
return HasPosition(CardPosition.Defence); return HasPosition(CardPosition.Defence);
} }
public bool IsDisabled()
{
return (Disabled != 0);
}
public bool HasXyzMaterial()
{
return Overlays.Count > 0;
}
public bool HasXyzMaterial(int count)
{
return Overlays.Count >= count;
}
public bool HasXyzMaterial(int count, int cardid)
{
return Overlays.Count >= count && Overlays.Contains(cardid);
}
public int GetDefensePower() public int GetDefensePower()
{ {
return IsAttack() ? Attack : Defense; return IsAttack() ? Attack : Defense;
......
using System.Collections.Generic; using System.Collections.Generic;
using YGOSharp.OCGWrapper.Enums; using YGOSharp.OCGWrapper.Enums;
namespace WindBot.Game namespace WindBot.Game
...@@ -14,18 +14,19 @@ namespace WindBot.Game ...@@ -14,18 +14,19 @@ namespace WindBot.Game
public IList<ClientCard> ExtraDeck { get; private set; } public IList<ClientCard> ExtraDeck { get; private set; }
public ClientField() public ClientField()
{
}
public void Init(int deck, int extra)
{ {
Hand = new List<ClientCard>(); Hand = new List<ClientCard>();
MonsterZone = new ClientCard[5]; MonsterZone = new ClientCard[7];
SpellZone = new ClientCard[8]; SpellZone = new ClientCard[8];
Graveyard = new List<ClientCard>(); Graveyard = new List<ClientCard>();
Banished = new List<ClientCard>(); Banished = new List<ClientCard>();
Deck = new List<ClientCard>(); Deck = new List<ClientCard>();
ExtraDeck = new List<ClientCard>(); ExtraDeck = new List<ClientCard>();
}
public void Init(int deck, int extra)
{
for (int i = 0; i < deck; ++i) for (int i = 0; i < deck; ++i)
Deck.Add(new ClientCard(0, CardLocation.Deck)); Deck.Add(new ClientCard(0, CardLocation.Deck));
for (int i = 0; i < extra; ++i) for (int i = 0; i < extra; ++i)
...@@ -42,6 +43,11 @@ namespace WindBot.Game ...@@ -42,6 +43,11 @@ namespace WindBot.Game
return GetCount(SpellZone); return GetCount(SpellZone);
} }
public int GetHandCount()
{
return GetCount(Hand);
}
public int GetSpellCountWithoutField() public int GetSpellCountWithoutField()
{ {
int count = 0; int count = 0;
...@@ -83,15 +89,66 @@ namespace WindBot.Game ...@@ -83,15 +89,66 @@ namespace WindBot.Game
return GetCards(SpellZone); return GetCards(SpellZone);
} }
public List<ClientCard> GetMonstersInExtraZone()
{
List<ClientCard> cards = new List<ClientCard>();
if (MonsterZone[5] != null)
cards.Add(MonsterZone[5]);
if (MonsterZone[6] != null)
cards.Add(MonsterZone[6]);
return cards;
}
public List<ClientCard> GetMonstersInMainZone()
{
List<ClientCard> cards = new List<ClientCard>();
for (int i = 0; i < 5; i++)
{
if (MonsterZone[i] != null)
cards.Add(MonsterZone[i]);
}
return cards;
}
public bool HasInHand(int cardId) public bool HasInHand(int cardId)
{ {
return HasInCards(Hand, cardId); return HasInCards(Hand, cardId);
} }
public bool HasInHand(IList<int> cardId)
{
return HasInCards(Hand, cardId);
}
public bool HasInGraveyard(int cardId) public bool HasInGraveyard(int cardId)
{ {
return HasInCards(Graveyard, cardId); return HasInCards(Graveyard, cardId);
} }
public bool HasInGraveyard(IList<int> cardId)
{
return HasInCards(Graveyard, cardId);
}
public bool HasInBanished(int cardId)
{
return HasInCards(Banished, cardId);
}
public bool HasInBanished(IList<int> cardId)
{
return HasInCards(Banished, cardId);
}
public bool HasInExtra(int cardId)
{
return HasInCards(ExtraDeck, cardId);
}
public bool HasInExtra(IList<int> cardId)
{
return HasInCards(ExtraDeck, cardId);
}
public bool HasAttackingMonster() public bool HasAttackingMonster()
{ {
...@@ -115,27 +172,40 @@ namespace WindBot.Game ...@@ -115,27 +172,40 @@ namespace WindBot.Game
return false; return false;
} }
public bool HasInMonstersZone(int cardId) public bool HasInMonstersZone(int cardId, bool notDisabled = false, bool hasXyzMaterial = false)
{
return HasInCards(MonsterZone, cardId, notDisabled, hasXyzMaterial);
}
public bool HasInMonstersZone(IList<int> cardId, bool notDisabled = false, bool hasXyzMaterial = false)
{
return HasInCards(MonsterZone, cardId, notDisabled, hasXyzMaterial);
}
public bool HasInSpellZone(int cardId, bool notDisabled = false)
{ {
return HasInCards(MonsterZone, cardId); return HasInCards(SpellZone, cardId, notDisabled);
} }
public bool HasInSpellZone(int cardId) public bool HasInSpellZone(IList<int> cardId, bool notDisabled = false)
{ {
return HasInCards(SpellZone, cardId); return HasInCards(SpellZone, cardId, notDisabled);
} }
public int GetRemainingCount(int cardId, int initialCount) public int GetRemainingCount(int cardId, int initialCount)
{ {
int remaining = initialCount; int remaining = initialCount;
foreach (ClientCard card in Hand) foreach (ClientCard card in Hand)
if (card.Id == cardId) if (card != null && card.Id == cardId)
remaining--;
foreach (ClientCard card in SpellZone)
if (card != null && card.Id == cardId)
remaining--; remaining--;
foreach (ClientCard card in Graveyard) foreach (ClientCard card in Graveyard)
if (card.Id == cardId) if (card != null && card.Id == cardId)
remaining--; remaining--;
foreach (ClientCard card in Banished) foreach (ClientCard card in Banished)
if (card.Id == cardId) if (card != null && card.Id == cardId)
remaining--; remaining--;
return (remaining < 0) ? 0 : remaining; return (remaining < 0) ? 0 : remaining;
} }
...@@ -151,6 +221,28 @@ namespace WindBot.Game ...@@ -151,6 +221,28 @@ namespace WindBot.Game
return count; return count;
} }
public int GetCountCardInZone(IEnumerable<ClientCard> cards, int cardId)
{
int count = 0;
foreach (ClientCard card in cards)
{
if (card != null && card.Id == cardId)
count++;
}
return count;
}
public int GetCountCardInZone(IEnumerable<ClientCard> cards, List<int> cardId)
{
int count = 0;
foreach (ClientCard card in cards)
{
if (card != null && cardId.Contains(card.Id))
count++;
}
return count;
}
private static List<ClientCard> GetCards(IEnumerable<ClientCard> cards, CardType type) private static List<ClientCard> GetCards(IEnumerable<ClientCard> cards, CardType type)
{ {
List<ClientCard> nCards = new List<ClientCard>(); List<ClientCard> nCards = new List<ClientCard>();
...@@ -173,11 +265,21 @@ namespace WindBot.Game ...@@ -173,11 +265,21 @@ namespace WindBot.Game
return nCards; return nCards;
} }
private static bool HasInCards(IEnumerable<ClientCard> cards, int cardId) private static bool HasInCards(IEnumerable<ClientCard> cards, int cardId, bool notDisabled = false, bool hasXyzMaterial = false)
{ {
foreach (ClientCard card in cards) foreach (ClientCard card in cards)
{ {
if (card != null && card.Id == cardId) if (card != null && card.Id == cardId && !(notDisabled && card.IsDisabled()) && !(hasXyzMaterial && !card.HasXyzMaterial()))
return true;
}
return false;
}
private static bool HasInCards(IEnumerable<ClientCard> cards, IList<int> cardId, bool notDisabled = false, bool hasXyzMaterial = false)
{
foreach (ClientCard card in cards)
{
if (card != null && cardId.Contains(card.Id) && !(notDisabled && card.IsDisabled()) && !(hasXyzMaterial && !card.HasXyzMaterial()))
return true; return true;
} }
return false; return false;
......
...@@ -6,6 +6,7 @@ namespace WindBot.Game ...@@ -6,6 +6,7 @@ namespace WindBot.Game
public class Duel public class Duel
{ {
public bool IsFirst { get; set; } public bool IsFirst { get; set; }
public bool IsNewRule { get; set; }
public int[] LifePoints { get; private set; } public int[] LifePoints { get; private set; }
public ClientField[] Fields { get; private set; } public ClientField[] Fields { get; private set; }
...@@ -15,6 +16,8 @@ namespace WindBot.Game ...@@ -15,6 +16,8 @@ namespace WindBot.Game
public DuelPhase Phase { get; set; } public DuelPhase Phase { get; set; }
public MainPhase MainPhase { get; set; } public MainPhase MainPhase { get; set; }
public BattlePhase BattlePhase { get; set; } public BattlePhase BattlePhase { get; set; }
public IList<ClientCard> ChainTargets { get; set; }
public int LastSummonPlayer { get; set; }
public Duel() public Duel()
{ {
...@@ -22,6 +25,8 @@ namespace WindBot.Game ...@@ -22,6 +25,8 @@ namespace WindBot.Game
Fields = new ClientField[2]; Fields = new ClientField[2];
Fields[0] = new ClientField(); Fields[0] = new ClientField();
Fields[1] = new ClientField(); Fields[1] = new ClientField();
ChainTargets = new List<ClientCard>();
LastSummonPlayer = -1;
} }
public ClientCard GetCard(int player, CardLocation loc, int index) public ClientCard GetCard(int player, CardLocation loc, int index)
......
This diff is collapsed.
This diff is collapsed.
...@@ -12,20 +12,27 @@ namespace WindBot.Game ...@@ -12,20 +12,27 @@ namespace WindBot.Game
public YGOClient Connection { get; private set; } public YGOClient Connection { get; private set; }
public string Username; public string Username;
public string Deck; public string Deck;
public string Dialog;
public int Hand;
private string _serverHost; private string _serverHost;
private int _serverPort; private int _serverPort;
private string _roomInfos; private short _proVersion;
private string _roomInfo;
private GameBehavior _behavior; private GameBehavior _behavior;
public GameClient(string username, string deck, string serverHost, int serverPort, string roomInfos = "") public GameClient(WindBotInfo Info)
{ {
Username = username; Username = Info.Name;
Deck = deck; Deck = Info.Deck;
_serverHost = serverHost; Dialog = Info.Dialog;
_serverPort = serverPort; Hand = Info.Hand;
_roomInfos = roomInfos; _serverHost = Info.Host;
_serverPort = Info.Port;
_roomInfo = Info.HostInfo;
_proVersion = (short)Info.Version;
} }
public void Start() public void Start()
...@@ -42,14 +49,14 @@ namespace WindBot.Game ...@@ -42,14 +49,14 @@ namespace WindBot.Game
private void OnConnected() private void OnConnected()
{ {
BinaryWriter packet = GamePacketFactory.Create(CtosMessage.PlayerInfo); BinaryWriter packet = GamePacketFactory.Create(CtosMessage.PlayerInfo);
packet.WriteUnicode(Username, Program.PlayerNameSize); packet.WriteUnicode(Username, 20);
Connection.Send(packet); Connection.Send(packet);
byte[] junk = { 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x00 }; byte[] junk = { 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x00 };
packet = GamePacketFactory.Create(CtosMessage.JoinGame); packet = GamePacketFactory.Create(CtosMessage.JoinGame);
packet.Write(Program.ProVersion); packet.Write(_proVersion);
packet.Write(junk); packet.Write(junk);
packet.WriteUnicode(_roomInfos, 30); packet.WriteUnicode(_roomInfo, 30);
Connection.Send(packet); Connection.Send(packet);
} }
......
...@@ -6,7 +6,17 @@ namespace WindBot ...@@ -6,7 +6,17 @@ namespace WindBot
{ {
public static void WriteLine(string message) public static void WriteLine(string message)
{ {
Console.WriteLine("[" + DateTime.Now.ToString("HH:mm:ss") + "] " + message); Console.WriteLine("[" + DateTime.Now.ToString("yy-MM-dd HH:mm:ss") + "] " + message);
}
public static void DebugWriteLine(string message)
{
#if DEBUG
Console.WriteLine("[" + DateTime.Now.ToString("yy-MM-dd HH:mm:ss") + "] " + message);
#endif
}
public static void WriteErrorLine(string message)
{
Console.Error.WriteLine("[" + DateTime.Now.ToString("yy-MM-dd HH:mm:ss") + "] " + message);
} }
} }
} }
\ No newline at end of file
using System; using System;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Net;
using System.Web;
using WindBot.Game; using WindBot.Game;
using WindBot.Game.AI; using WindBot.Game.AI;
using YGOSharp.OCGWrapper; using YGOSharp.OCGWrapper;
...@@ -9,56 +11,173 @@ namespace WindBot ...@@ -9,56 +11,173 @@ namespace WindBot
{ {
public class Program public class Program
{ {
public static short ProVersion = 0x133D;
public static int PlayerNameSize = 20;
internal static Random Rand; internal static Random Rand;
internal static void Main() internal static void Main(string[] args)
{ {
#if !DEBUG Logger.WriteLine("WindBot starting...");
try
Config.Load(args);
string databasePath = Config.GetString("DbPath", "cards.cdb");
InitDatas(databasePath);
bool serverMode = Config.GetBool("ServerMode", false);
if (serverMode)
{ {
Run(); // Run in server mode, provide a http interface to create bot.
int serverPort = Config.GetInt("ServerPort", 2399);
RunAsServer(serverPort);
} }
catch (Exception ex) else
{ {
Console.Error.WriteLine("Error: " + ex); // Join the host specified on the command line.
if (args.Length == 0)
{
Logger.WriteLine("=== WARN ===");
Logger.WriteLine("No input found, tring to connect to localhost YGOPro host.");
Logger.WriteLine("If it fail, the program will quit sliently.");
}
RunFromArgs();
} }
#else
Run();
#endif
} }
public static void Init(string databasePath) public static void InitDatas(string databasePath)
{ {
Rand = new Random(); Rand = new Random();
DecksManager.Init(); DecksManager.Init();
InitCardsManager(databasePath); string absolutePath = Path.GetFullPath(databasePath);
if (!File.Exists(absolutePath))
// In case windbot is placed in a folder under ygopro folder
absolutePath = Path.GetFullPath("../" + databasePath);
if (!File.Exists(absolutePath))
Logger.WriteErrorLine("Can't find cards database file. Please place cards.cdb next to WindBot.exe .");
NamedCardsManager.Init(absolutePath);
} }
private static void Run() private static void RunFromArgs()
{ {
Init("cards.cdb"); WindBotInfo Info = new WindBotInfo();
Info.Name = Config.GetString("Name", Info.Name);
Info.Deck = Config.GetString("Deck", Info.Deck);
Info.Dialog = Config.GetString("Dialog", Info.Dialog);
Info.Host = Config.GetString("Host", Info.Host);
Info.Port = Config.GetInt("Port", Info.Port);
Info.HostInfo = Config.GetString("HostInfo", Info.HostInfo);
Info.Version = Config.GetInt("Version", Info.Version);
Info.Hand = Config.GetInt("Hand", Info.Hand);
Run(Info);
}
// Start two clients and connect them to the same server. Which deck is gonna win? private static void RunAsServer(int ServerPort)
GameClient clientA = new GameClient("Wind", "Horus", "127.0.0.1", 7911); {
GameClient clientB = new GameClient("Fire", "OldSchool", "127.0.0.1", 7911); using (HttpListener MainServer = new HttpListener())
clientA.Start();
clientB.Start();
while (clientA.Connection.IsConnected || clientB.Connection.IsConnected)
{ {
clientA.Tick(); MainServer.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
clientB.Tick(); MainServer.Prefixes.Add("http://127.0.0.1:" + ServerPort + "/");
Thread.Sleep(1); MainServer.Start();
Logger.WriteLine("WindBot server start successed.");
Logger.WriteLine("HTTP GET http://127.0.0.1:" + ServerPort + "/?name=WindBot&host=127.0.0.1&port=7911 to call the bot.");
while (true)
{
#if !DEBUG
try
{
#endif
HttpListenerContext ctx = MainServer.GetContext();
WindBotInfo Info = new WindBotInfo();
string RawUrl = Path.GetFileName(ctx.Request.RawUrl);
Info.Name = HttpUtility.ParseQueryString(RawUrl).Get("name");
Info.Deck = HttpUtility.ParseQueryString(RawUrl).Get("deck");
Info.Host = HttpUtility.ParseQueryString(RawUrl).Get("host");
string port = HttpUtility.ParseQueryString(RawUrl).Get("port");
if (port != null)
Info.Port = Int32.Parse(port);
string dialog = HttpUtility.ParseQueryString(RawUrl).Get("dialog");
if (dialog != null)
Info.Dialog = dialog;
string version = HttpUtility.ParseQueryString(RawUrl).Get("version");
if (version != null)
Info.Version = Int16.Parse(version);
string password = HttpUtility.ParseQueryString(RawUrl).Get("password");
if (password != null)
Info.HostInfo = password;
string hand = HttpUtility.ParseQueryString(RawUrl).Get("hand");
if (hand != null)
Info.Hand = Int32.Parse(hand);
if (Info.Name == null || Info.Host == null || port == null)
{
ctx.Response.StatusCode = 400;
ctx.Response.Close();
}
else
{
#if !DEBUG
try
{
#endif
Thread workThread = new Thread(new ParameterizedThreadStart(Run));
workThread.Start(Info);
#if !DEBUG
}
catch (Exception ex)
{
Logger.WriteErrorLine("Start Thread Error: " + ex);
}
#endif
ctx.Response.StatusCode = 200;
ctx.Response.Close();
}
#if !DEBUG
}
catch (Exception ex)
{
Logger.WriteErrorLine("Parse Http Request Error: " + ex);
}
#endif
}
} }
} }
private static void InitCardsManager(string databasePath) private static void Run(object o)
{ {
string currentPath = Path.GetFullPath("."); #if !DEBUG
string absolutePath = Path.Combine(currentPath, databasePath); try
NamedCardsManager.Init(absolutePath); {
//all errors will be catched instead of causing the program to crash.
#endif
WindBotInfo Info = (WindBotInfo)o;
GameClient client = new GameClient(Info);
client.Start();
Logger.DebugWriteLine(client.Username + " started.");
while (client.Connection.IsConnected)
{
#if !DEBUG
try
{
#endif
client.Tick();
Thread.Sleep(30);
#if !DEBUG
}
catch (Exception ex)
{
Logger.WriteErrorLine("Tick Error: " + ex);
}
#endif
}
Logger.DebugWriteLine(client.Username + " end.");
#if !DEBUG
}
catch (Exception ex)
{
Logger.WriteErrorLine("Run Error: " + ex);
}
#endif
} }
} }
} }
# WindBot # WindBot
A C# bot for ygopro, compatible with the ygosharp server. A C# bot for ygopro, compatible with the [YGOSharp](https://github.com/IceYGO/ygosharp) and [SRVPro](https://github.com/moecube/srvpro) server.
### How to use: ### How to use:
* Code whatever you want to code in the `Program.cs` file.
* Compile `WindBot.sln` using Visual Studio or Mono. * Compile `WindBot.sln` using Visual Studio or Mono.
* Put `cards.cdb` next to the compiled `WindBot.exe`. * Put `cards.cdb` next to the compiled `WindBot.exe`.
* Run and observe. * Run YGOPro, create a host.
* Run WindBot and observe.
### Supported commandlines
`Name`
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.
`Dialog`
The dialog texts to be used by the bot. See Dialogs folder for list.
`Host`
The IP of the host to be connected to.
`Port`
The port of the host to be connected to.
`HostInfo`
The host info (password) to be used.
`Version`
The version of YGOPro.
`Hand`
If you are testing deck, you may want to make sure the bot go first or second. `Hand=1` will make the bot always show Scissors, 2 for Rock, 3 for Paper.
`ServerMode` and `ServerPort`
WindBot can run as a "server", provide a http interface to create bot.
### Available decks
**Easy**:
* Burn
* Frog
* Horus
* MokeyMokey
* MokeyMokeyKing
* OldSchool
**Normal**:
* Blue-Eyes
* Dragunity
* Qliphort
* Rainbow
* Rank V
* ST1732
* Toadally Awesome (old lflist)
* Yosenju
* Zexal Weapons
* Zoodiac (old lflist, master rule 3 only)
### Unfinished decks
* Blackwing
* CyberDragon
* Evilswarm
* Gravekeeper
* Graydle
* Lightsworn
* Nekroz
### Server mode
WindBot can run as a "server", provide a http interface to create bot.
eg. `http://127.0.0.1:2399/?name=%E2%91%A8&deck=Blue-Eyes&host=127.0.0.1&port=7911&dialog=cirno.zh-CN&version=4928`
In this situation, it will be multi-threaded. This can be useful for servers, since it don't use large amount memory.
The parameters are same as commandlines, but low cased.
### Known issues
* The attack won't be canceled when battle replay happens.
* If one chain includes two activation that use `AI.SelectCard`, the second one won't select correctly.
### TODO list
* More decks
* Documents for creating AI
* `AI.SelectZone`
* `AI.SelectMaterials` which select a set of cards for F/S/X/L summon
* `AI.SelectTribute`
* Select cards to pendulum summon in executor.
* Get equip of card.
* Get attack target.
* Better new master rule support
* Update the known card enums
* More default common cards executor
...@@ -34,6 +34,9 @@ ...@@ -34,6 +34,9 @@
<PropertyGroup> <PropertyGroup>
<StartupObject /> <StartupObject />
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<ApplicationIcon>WindBot.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Debug\</OutputPath> <OutputPath>bin\Debug\</OutputPath>
...@@ -58,6 +61,9 @@ ...@@ -58,6 +61,9 @@
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
<Reference Include="YGOSharp.Network"> <Reference Include="YGOSharp.Network">
<HintPath>.\YGOSharp.Network.dll</HintPath> <HintPath>.\YGOSharp.Network.dll</HintPath>
</Reference> </Reference>
...@@ -69,6 +75,7 @@ ...@@ -69,6 +75,7 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Config.cs" />
<Compile Include="Game\AI\AIFunctions.cs" /> <Compile Include="Game\AI\AIFunctions.cs" />
<Compile Include="Game\AI\CardContainer.cs" /> <Compile Include="Game\AI\CardContainer.cs" />
<Compile Include="Game\AI\CardExecutor.cs" /> <Compile Include="Game\AI\CardExecutor.cs" />
...@@ -86,12 +93,11 @@ ...@@ -86,12 +93,11 @@
<Compile Include="Game\AI\DefaultExecutor.cs" /> <Compile Include="Game\AI\DefaultExecutor.cs" />
<Compile Include="Game\AI\Dialogs.cs" /> <Compile Include="Game\AI\Dialogs.cs" />
<Compile Include="Game\AI\Enums\DangerousMonster.cs" /> <Compile Include="Game\AI\Enums\DangerousMonster.cs" />
<Compile Include="Game\AI\Enums\FusionSpell.cs" />
<Compile Include="Game\AI\Enums\PreventActivationEffectInBattle.cs" />
<Compile Include="Game\AI\Enums\OneForXyz.cs" />
<Compile Include="Game\AI\Enums\InvincibleMonster.cs" /> <Compile Include="Game\AI\Enums\InvincibleMonster.cs" />
<Compile Include="Game\AI\Enums\NegateAttackSpell.cs" /> <Compile Include="Game\AI\Enums\Floodgate.cs" />
<Compile Include="Game\AI\Enums\NegatesEffects.cs" />
<Compile Include="Game\AI\Enums\NegatesSpells.cs" />
<Compile Include="Game\AI\Enums\NegatesSummons.cs" />
<Compile Include="Game\AI\Enums\NegatesTraps.cs" />
<Compile Include="Game\AI\Executor.cs" /> <Compile Include="Game\AI\Executor.cs" />
<Compile Include="Game\AI\ExecutorType.cs" /> <Compile Include="Game\AI\ExecutorType.cs" />
<Compile Include="Game\BattlePhase.cs" /> <Compile Include="Game\BattlePhase.cs" />
...@@ -110,36 +116,25 @@ ...@@ -110,36 +116,25 @@
<Compile Include="Logger.cs" /> <Compile Include="Logger.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="WindBotInfo.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="App.config" />
<None Include="Decks\AI_Burn.ydk"> <None Include="sqlite3.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Decks\AI_Dragunity.ydk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Decks\AI_Frog.ydk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Decks\AI_Horus.ydk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Decks\AI_OldSchool.ydk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Decks\AI_Rank5.ydk"> <None Include="Decks\*.ydk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Decks\AI_ZexalWeapons.ydk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="sqlite3.dll"> <None Include="Dialogs\*.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="WindBot.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
......
WindBot.ico

17.1 KB

using System;
namespace WindBot
{
public class WindBotInfo
{
public string Name { get; set; }
public string Deck { get; set; }
public string Dialog { get; set; }
public string Host { get; set; }
public int Port { get; set; }
public string HostInfo { get; set; }
public int Version { get; set; }
public int Hand { get; set; }
public WindBotInfo()
{
Name = "WindBot";
Deck = null;
Dialog = "default";
Host = "127.0.0.1";
Port = 7911;
HostInfo = "";
Version = 0x1340;
Hand = 0;
}
}
}
No preview for this file type
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