Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/hakubishin-private/master'
Browse files Browse the repository at this point in the history
# Conflicts:
#	TanukiColiseum/Cli.cs
#	TanukiColiseum/Coliseum.cs
#	TanukiColiseum/Engine.cs
#	TanukiColiseum/Gui.cs
#	TanukiColiseum/Options.cs
#	TanukiColiseum/Status.cs
#	source/engine/2017-early-engine/2017-early-search.cpp
#	tools/tools.pyproj
  • Loading branch information
nodchip committed Nov 13, 2017
2 parents bd221fd + db21691 commit 19adf50
Show file tree
Hide file tree
Showing 157 changed files with 4,540,217 additions and 8,671 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -44,6 +44,7 @@ bld/

# Visual Studio 2015 cache/options directory
.vs/
enc_temp_folder

# MSTest test Results
[Tt]est[Rr]esult*/
Expand Down
80 changes: 53 additions & 27 deletions README.md
@@ -1,42 +1,68 @@
# About this project

"The Minstrel's Ballad: Tanuki's Reign" (tanuki-wcsc27 ver) is a shogi engine (AI player) based on YaneuraOu. The development concept is "easily and for fun!".
YaneuraOu mini is a shogi engine(AI player), stronger than Bonanza6 , educational and tiny code(about 2500 lines) , USI compliant engine , capable of being compiled by VC++2017

蒼天幻想ナイツ・オブ・タヌキ(tanuki-第27回世界コンピュータ将棋選手権バージョン)はやねうら王から派生したコンピューター将棋エンジンです。開発コンセプトは「楽に!楽しく!」です
やねうら王miniは、将棋の思考エンジンで、Bonanza6より強く、教育的で短いコード(2500行程度)で書かれたUSIプロトコル準拠の思考エンジンで、VC++2017でコンパイル可能です

[やねうら王mini 公式サイト (解説記事、開発者向け情報等)](http://yaneuraou.yaneu.com/YaneuraOu_Mini/)

[やねうら王公式 ](http://yaneuraou.yaneu.com/)

# Using tanuki- with WinBoard 4.8.0
Please follow the steps below.
## やねうら王シリーズの遊び方

1. Install WinBoard 4.8.0. The installation path is "C:\WinBoard-4.8.0".
2. Download "tanuki-sdt4-2016-10-09.7z" from https://github.com/nodchip/hakubishin-/releases, and extract to "C:\WinBoard-4.8.0\tanuki-sdt4-2016-10-09".
3. Start "C:\WinBoard-4.8.0\WinBoard\winboard.exe".
4. Check "Advanced options", and set -uxiAdapter {UCI2WB -%variant "%fcp" "%fd"). Please refer #8 (comment) about this step.
5. Add "tanuki-sdt4" with the following settings:
Engine (.exe or .jar): C:\WinBoard-4.8.0\tanuki-sdt4-2016-10-09\tanuki-sdt4.exe
command-line parameters: empty
Special WinBoard options: empty
directory: empty
UCCI/USI [uses specified /uxiAdapter]: on
6. Engine > Engine #1 Settings... > Set "Minimum_Thinking_Time" to "0".
[このプロジェクトのexeフォルダ](https://github.com/yaneurao/YaneuraOu/tree/master/exe)の対象フォルダ配下にある、XXX-readme.txtをご覧ください。

The steps will be changed in future versions.
- 質問等は以下の記事のコメント欄でお願いします。Twitterでの個別質問にはお答え出来ません。
- [やねうら王セットアップ質問スレッド](http://yaneuraou.yaneu.com/2017/05/04/%E3%82%84%E3%81%AD%E3%81%86%E3%82%89%E7%8E%8B-%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97%E8%B3%AA%E5%95%8F%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89/)

# Q & A
Q. Do you plan to create an all-in-one package with WinBoard and tanuki-?
A. There are no plans for it.
# 現在進行中のサブプロジェクト

Q. Do you plan to support WB/CECP-protocol in the next tanuki- edition? http://hgm.nubati.net/CECP.html v2 - http://home.hccnet.nl/h.g.muller/engine-intf.html v1
A. There are no plans for it.
## やねうら王2017 Early

Q. Do you plan to add any logos to tanuki-?
A. There are no plans for it.
2017年5月5日完成。この思考エンジンを用いたelmoがWCSC27で優勝しました。elmo(WCSC27)や蒼天幻想ナイツ・オブ・タヌキ(WCSC27出場)の評価関数を用いるとXeon 24コアでR4000程度の模様。

Q. Why tanuki- uses up all its time with 1 min + 0 sec/move?
A. Start "C:\WinBoard-4.8.0\WinBoard\winboard.exe", check "Advanced options", and set `-uxiAdapter {UCI2WB -%variant "%fcp" "%fd")`.
## やねうら王2017 GOKU

Q. Why tanuki- uses up all its time in 27-36 moves with 1 min + 0 sec/move?
A. Engine > Engine #1 Settings... > Set "Minimum_Thinking_Time" to "0".
《開発計画中》

## やねうら王詰め将棋solver

《tanuki-さんが開発中》

長手数の詰将棋が解けるsolverです。


# 過去のサブプロジェクト

過去のサブプロジェクトである、やねうら王nano , mini , classic、王手将棋、取る一手将棋、協力詰めsolver、連続自己対戦フレームワークなどはこちらからどうぞ。

- [過去のサブプロジェクト](/docs/README2017.md)

## やねうら王評価関数ファイル

やねうら王2016Mid用/2016Late用/2017Early用

- [真やねうら王の評価関数ファイル](https://drive.google.com/open?id=0ByIGrGAuSfHHVVh0bEhxRHNpcGc) (Apery20161007の評価関数から追加学習させたものです。) 詳しい情報は[こちら。](http://yaneuraou.yaneu.com/2016/10/17/%E7%9C%9F%E3%82%84%E3%81%AD%E3%81%86%E3%82%89%E7%8E%8B%E3%81%AE%E8%A9%95%E4%BE%A1%E9%96%A2%E6%95%B0%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/)
- [やねうら王で使える評価関数ファイル28バリエーション公開しました](http://yaneuraou.yaneu.com/2016/07/22/%E3%82%84%E3%81%AD%E3%81%86%E3%82%89%E7%8E%8B%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B%E8%A9%95%E4%BE%A1%E9%96%A2%E6%95%B0%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB28%E3%83%90%E3%83%AA%E3%82%A8%E3%83%BC%E3%82%B7/)
- また、Apery(WCSC26)、Apery(SDT4)=「浮かむ瀬」の評価関数バイナリがそのまま使えます。

## 定跡集

やねうら王2016Mid以降で使える、各種定跡集。
ダウンロードしたあと、zipファイルになっているのでそれを解凍して、やねうら王の実行ファイルを配置しているフォルダ配下のbookフォルダに放り込んでください。

コンセプトおよび定跡フォーマットについて : [やねうら大定跡はじめました](http://yaneuraou.yaneu.com/2016/07/10/%E3%82%84%E3%81%AD%E3%81%86%E3%82%89%E5%A4%A7%E5%AE%9A%E8%B7%A1%E3%81%AF%E3%81%98%E3%82%81%E3%81%BE%E3%81%97%E3%81%9F/)

-[やねうら大定跡V1.01](https://drive.google.com/open?id=0Bzbi5rbfN85NbWxfazMzamFVZm8)
-[真やねうら定跡](https://drive.google.com/open?id=0ByIGrGAuSfHHcXRrc2FmdHVmRzA)

## 世界コンピュータ将棋選手権および2017年に開催される第5回将棋電王トーナメントに参加される開発者の方へ

やねうら王をライブラリとして用いて参加される場合、このやねうら王のGitHub上にあるすべてのファイルおよび、このトップページから直リンしているファイルすべてが使えます。
ただし、真やねうら王の評価関数ファイルを用いる場合は、Aperyライブラリの申請が必要かも知れません。詳しくは大会のルールを参照してください。

## ライセンス

やねうら王プロジェクトのソースコードはStockfishをそのまま用いている部分が多々あり、Apery/SilentMajorityを参考にしている部分もありますので、やねうら王プロジェクトは、それらのプロジェクトのライセンス(GPLv3)に従うものとします。

また、「真やねうら王の評価関数ファイル」は、Aperyの評価関数バイナリから追加学習させたものですので、その著作権は、Aperyの開発者の平岡拓也氏に帰属し、ライセンスや取扱いは元のライセンスに従うものとします。また、やねうら王プロジェクト側はこのファイルの著作権を主張しません。
7 changes: 5 additions & 2 deletions TanukiColiseum/Cli.cs
Expand Up @@ -18,6 +18,8 @@ private void ShowResult(Status status)
int draw = status.NumDraw;
int blackWin = status.Win[0, 0] + status.Win[1, 0];
int whiteWin = status.Win[0, 1] + status.Win[1, 1];
int engine1DeclarationWin = status.DeclarationWin[0];
int engine2DeclarationWin = status.DeclarationWin[1];

// T1,b10000,433 - 54 - 503(46.26% R-26.03) win black : white = 52.42% : 47.58%
double winRate = engine1Win / (double)(engine1Win + engine2Win);
Expand All @@ -28,8 +30,9 @@ private void ShowResult(Status status)
}
double black = blackWin / (double)(blackWin + whiteWin);
double white = whiteWin / (double)(blackWin + whiteWin);
Console.WriteLine("T1,b{0},{1} - {2} - {3}({4:0.00%} R{5:0.00}) win black: white = {6:0.00%} : {7:0.00%}",
status.TimeMs, engine1Win, draw, engine2Win, winRate, rating, black, white);
Console.WriteLine("T1,b{0},{1} - {2} - {3}({4:0.00%} R{5:0.00}) win black: white = {6:0.00%} : {7:0.00%} declaration win engine1={8} engine2={9}",
status.TimeMs, engine1Win, draw, engine2Win, winRate, rating, black, white,
engine1DeclarationWin, engine2DeclarationWin);
Console.Out.Flush();
}
}
Expand Down
74 changes: 46 additions & 28 deletions TanukiColiseum/Coliseum.cs
Expand Up @@ -3,6 +3,7 @@
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace TanukiColiseum
{
Expand All @@ -29,50 +30,62 @@ public void Run(Options options)
Console.WriteLine("Initializing engines...");
Console.Out.Flush();

List<Task> startAsyncTasks = new List<Task>();

for (int gameIndex = 0; gameIndex < options.NumConcurrentGames; ++gameIndex)
{
int numaNode = gameIndex * options.NumNumaNodes / options.NumConcurrentGames;

// エンジン1初期化
var options1 = new List<string>();
options1.Add("setoption name Threads value 1");
options1.Add("setoption name EvalDir value " + options.Eval1FolderPath);
options1.Add("setoption name Hash value " + options.HashMb);
options1.Add("setoption name BookFile value no_book");
options1.Add("setoption MinimumThinkingTime value 1000");
options1.Add("setoption name NetworkDelay value 0");
options1.Add("setoption name NetworkDelay2 value 0");
options1.Add("setoption name EvalShare value true");
options1.Add("setoption name BookMoves value " + options.NumBookMoves1);
options1.Add("setoption name BookFile value " + options.BookFileName1);
Dictionary<string, string> overriddenOptions1 = new Dictionary<string, string>(){
{"EvalDir", options.Eval1FolderPath},
{"Hash", options.HashMb.ToString()},
{"MinimumThinkingTime", "1000"},
{"NetworkDelay", "0"},
{"NetworkDelay2", "0"},
{"EvalShare", "true"},
{"BookMoves", options.NumBookMoves1.ToString()},
{"BookFile", options.BookFileName1},
{"Threads", options.NumThreads1.ToString()},
{"BookEvalDiff1", options.BookEvalDiff1.ToString()},
{"ConsiderBookMoveCount1", options.ConsiderBookMoveCount1},
};
Console.WriteLine("Starting the engine process " + (gameIndex * 2));
Console.Out.Flush();
var engine1 = new Engine(options.Engine1FilePath, options1, this, gameIndex * 2, gameIndex, 0, numaNode);
engine1.StartAsync().Wait();
var engine1 = new Engine(options.Engine1FilePath, this, gameIndex * 2, gameIndex, 0, numaNode, overriddenOptions1);
startAsyncTasks.Add(engine1.StartAsync());

// エンジン2初期化
var options2 = new List<string>();
options2.Add("setoption name Threads value 1");
options2.Add("setoption name EvalDir value " + options.Eval2FolderPath);
options2.Add("setoption name Hash value " + options.HashMb);
options2.Add("setoption name BookFile value no_book");
options2.Add("setoption MinimumThinkingTime value 1000");
options2.Add("setoption name NetworkDelay value 0");
options2.Add("setoption name NetworkDelay2 value 0");
options2.Add("setoption name EvalShare value true");
options2.Add("setoption name BookMoves value " + options.NumBookMoves2);
options2.Add("setoption name BookFile value " + options.BookFileName2);
Dictionary<string, string> overriddenOptions2 = new Dictionary<string, string>()
{
{"EvalDir", options.Eval2FolderPath},
{"Hash", options.HashMb.ToString()},
{"MinimumThinkingTime", "1000"},
{"NetworkDelay", "0"},
{"NetworkDelay2", "0"},
{"EvalShare", "true"},
{"BookMoves", options.NumBookMoves2.ToString()},
{"BookFile", options.BookFileName2},
{"Threads", options.NumThreads2.ToString()},
{"BookEvalDiff2", options.BookEvalDiff2.ToString()},
{"ConsiderBookMoveCount2", options.ConsiderBookMoveCount2},
};
Console.WriteLine("Starting the engine process " + (gameIndex * 2 + 1));
Console.Out.Flush();
var engine2 = new Engine(options.Engine2FilePath, options2, this, gameIndex * 2 + 1, gameIndex, 1, numaNode);
engine2.StartAsync().Wait();
var engine2 = new Engine(options.Engine2FilePath, this, gameIndex * 2 + 1, gameIndex, 1, numaNode, overriddenOptions2);
startAsyncTasks.Add(engine2.StartAsync());

// ゲーム初期化
// 偶数番目はengine1が先手、奇数番目はengine2が先手
Games.Add(new Game(gameIndex & 1, options.TimeMs, engine1, engine2,
options.NumBookMoves, openings));
}

foreach (var startAsyncTask in startAsyncTasks)
{
startAsyncTask.Wait();
}

Console.WriteLine("Initialized engines...");
Console.WriteLine("Started games...");
Console.Out.Flush();
Expand Down Expand Up @@ -108,17 +121,22 @@ public void Run(Options options)
OnStatusChanged(new Status(Status));
}

public void OnGameFinished(int enginWin, int blackWhiteWin, bool draw)
public void OnGameFinished(int engineWin, int blackWhiteWin, bool draw, bool declarationWin)
{
if (!draw)
{
Interlocked.Increment(ref Status.Win[enginWin, blackWhiteWin]);
Interlocked.Increment(ref Status.Win[engineWin, blackWhiteWin]);
}
else
{
Interlocked.Increment(ref Status.NumDraw);
}

if (declarationWin)
{
Interlocked.Increment(ref Status.DeclarationWin[engineWin]);
}

if (LastOutput.AddMilliseconds(ProgressIntervalMs) <= DateTime.Now)
{
OnStatusChanged(new Status(Status));
Expand Down
56 changes: 41 additions & 15 deletions TanukiColiseum/Engine.cs
Expand Up @@ -11,13 +11,13 @@ class Engine
private const int MaxMoves = 256;
private Process Process = new Process();
private Coliseum Coliseum;
private List<string> Options;
private SemaphoreSlim ReadyokSemaphoreSlim = new SemaphoreSlim(0);
private int ProcessIndex;
private int GameIndex;
private int EngineIndex;
private Dictionary<string, string> OverriddenOptions;

public Engine(string fileName, List<string> options, Coliseum coliseum, int processIndex, int gameIndex, int engineIndex, int numaNode)
public Engine(string fileName, Coliseum coliseum, int processIndex, int gameIndex, int engineIndex, int numaNode, Dictionary<string, string> overriddenOptions)
{
this.Process.StartInfo.FileName = "cmd.exe";
if (Path.IsPathRooted(fileName))
Expand All @@ -32,17 +32,17 @@ public Engine(string fileName, List<string> options, Coliseum coliseum, int proc
this.Process.OutputDataReceived += HandleStdout;
this.Process.ErrorDataReceived += HandleStderr;
this.Coliseum = coliseum;
this.Options = options;
this.ProcessIndex = processIndex;
this.GameIndex = gameIndex;
this.EngineIndex = engineIndex;
this.OverriddenOptions = overriddenOptions;
}

/// <summary>
/// 思考エンジンを開始し、isreadyを送信し、readyokが返るのを待つ
/// </summary>
/// <returns></returns>
public async Task StartAsync()
public Task StartAsync()
{
//BeginOutputReadLine()/BeginErrorReadLine()が呼び出されたあと
//読み込みスレッドが動かないので
Expand All @@ -52,12 +52,7 @@ public async Task StartAsync()
Process.BeginOutputReadLine();
Process.BeginErrorReadLine();
Send("usi");
foreach (var option in Options)
{
Send(option);
}
Send("isready");
await ReadyokSemaphoreSlim.WaitAsync().ConfigureAwait(false);
return ReadyokSemaphoreSlim.WaitAsync();
}

public void Finish()
Expand Down Expand Up @@ -93,7 +88,15 @@ private void HandleStdout(object sender, DataReceivedEventArgs e)
//Debug.WriteLine(" < [{0}] {1}", ProcessIndex, e.Data);

List<string> command = Util.Split(e.Data);
if (command.Contains("readyok"))
if (command.Contains("usiok"))
{
HandleUsiok(command);
}
else if (command.Contains("option"))
{
HandleOption(command);
}
else if (command.Contains("readyok"))
{
HandleReadyok(command);
}
Expand All @@ -113,6 +116,29 @@ private void HandleStderr(object sender, DataReceivedEventArgs e)
Debug.WriteLine(" ! [{0}] {1}", ProcessIndex, e.Data);
}

private void HandleUsiok(List<string> command)
{
Send("isready");
}
private void HandleOption(List<string> command)
{
int nameIndex = command.IndexOf("name");
int defaultIndex = command.IndexOf("default");
if (nameIndex == -1 || nameIndex + 1 >= command.Count ||
defaultIndex == -1 || defaultIndex + 1 >= command.Count)
{
return;
}

string name = command[nameIndex + 1];
string value = command[defaultIndex + 1];
if (OverriddenOptions.ContainsKey(name))
{
value = OverriddenOptions[name];
}
Send(string.Format("setoption name {0} value {1}", name, value));
}

private void HandleReadyok(List<string> command)
{
// readyokが返ってきたのでセマフォを開放してStart()関数から抜けさせる
Expand All @@ -126,20 +152,20 @@ private void HandleBestmove(List<string> command)
{
int engineWin;
int blackWhiteWin;
bool draw;
bool draw = false;
bool declaration = false;
if (command[1] == "resign")
{
// 相手側の勝数を上げる
engineWin = game.Turn ^ 1;
blackWhiteWin = (game.Moves.Count + 1) & 1;
draw = false;
}
else if (command[1] == "win")
{
// 自分側の勝数を上げる
engineWin = game.Turn;
blackWhiteWin = game.Moves.Count & 1;
draw = false;
declaration = true;
}
else
{
Expand All @@ -152,7 +178,7 @@ private void HandleBestmove(List<string> command)
// 次の対局を開始する
// 先にGame.OnGameFinished()を読んでゲームの状態を停止状態に移行する
game.OnGameFinished();
Coliseum.OnGameFinished(engineWin, blackWhiteWin, draw);
Coliseum.OnGameFinished(engineWin, blackWhiteWin, draw, declaration);
}
else
{
Expand Down

0 comments on commit 19adf50

Please sign in to comment.