Commit 53eaabb4 authored by mercury233's avatar mercury233

update command line and readme

parent 35cd5e6d
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;
}
}
}
...@@ -23,34 +23,28 @@ namespace WindBot ...@@ -23,34 +23,28 @@ namespace WindBot
{ {
Logger.WriteLine("WindBot starting..."); Logger.WriteLine("WindBot starting...");
InitDatas("cards.cdb"); Config.Load(args);
int argc = args.Length; string databasePath = Config.GetString("DbPath", "cards.cdb");
// Only one parameter will make Windbot run as a server, use the parameter as port InitDatas(databasePath);
// 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
if (argc == 1)
{
RunAsServer(Int32.Parse(args[0]));
}
// Use all five parameters to run Windbot bool serverMode = Config.GetBool("ServerMode", false);
// The parameters should be name, deck, server ip, server port, password
// eg. WindBot.exe "My Bot" "Zexal Weapons" 127.0.0.1 7911 "" if (serverMode)
else if (argc == 5)
{ {
RunFromArgs(args); int serverPort = Config.GetInt("ServerPort", 2399);
RunAsServer(serverPort);
} }
// Else, tell the user to run it correctly
else else
{ {
Logger.WriteLine(""); if (args.Length == 0)
Logger.WriteLine("See the readme for how to run WindBot!"); {
Logger.WriteLine("Press any key to quit..."); Logger.WriteLine("=== WARN ===");
Logger.WriteLine(""); Logger.WriteLine("No input found, tring to connect to localhost YGOPro host.");
Console.ReadKey(); Logger.WriteLine("If it fail, the program will quit sliently.");
}
RunFromArgs();
} }
} }
...@@ -61,17 +55,22 @@ namespace WindBot ...@@ -61,17 +55,22 @@ namespace WindBot
string absolutePath = Path.GetFullPath(databasePath); string absolutePath = Path.GetFullPath(databasePath);
if (!File.Exists(absolutePath)) if (!File.Exists(absolutePath))
absolutePath = Path.GetFullPath("../" + databasePath); 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); NamedCardsManager.Init(absolutePath);
} }
private static void RunFromArgs(string[] args) private static void RunFromArgs()
{ {
WindBotInfo Info = new WindBotInfo(); WindBotInfo Info = new WindBotInfo();
Info.Name = args[0]; Info.Name = Config.GetString("Name", Info.Name);
Info.Deck = args[1]; Info.Deck = Config.GetString("Deck", Info.Deck);
Info.Host = args[2]; Info.Dialog = Config.GetString("Dialog", Info.Dialog);
Info.Port = Int32.Parse(args[3]); Info.Host = Config.GetString("Host", Info.Host);
Info.HostInfo = args[4]; 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); Run(Info);
} }
......
# WindBot # WindBot
A C# bot for ygopro, compatible with the ygosharp server. A C# bot for ygopro, compatible with the ygosharp and 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
* Blue-Eyes
* Burn
* Dragunity
* Frog
* Horus
* MokeyMokey
* MokeyMokeyKing
* OldSchool
* Qliphort
* Rainbow
* Rank V
* ST1732
* Toadally Awesome
* Yosenju
* Zexal Weapons
* Zoodiac
### 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.
\ No newline at end of file
...@@ -75,6 +75,7 @@ ...@@ -75,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" />
......
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