public void ReadyOk() { //------------------------------------------------------------ // それでは定刻になりましたので…… //------------------------------------------------------------ // // 図. // // log.txt // ┌──────────────────────────────────────── // ~ // │2014/08/02 1:31:35> isready // │ // // // 対局開始前に、将棋所から送られてくる文字が isready です。 //------------------------------------------------------------ // 将棋エンジン「おっおっ、設定を終わらせておかなければ(汗、汗…)」 //------------------------------------------------------------ #if DEBUG Logger.Trace("┏━━━━━設定━━━━━┓"); foreach (KeyValuePair <string, string> pair in this.SetoptionDictionary) { // ここで将棋エンジンの設定を済ませておいてください。 Logger.Trace($"{pair.Key}={pair.Value}"); } Logger.Trace("┗━━━━━━━━━━━━┛"); #endif //------------------------------------------------------------ // よろしくお願いします(^▽^)! //------------------------------------------------------------ // // 図. // // log.txt // ┌──────────────────────────────────────── // ~ // │2014/08/02 2:03:33< readyok // │ // // // いつでも対局する準備が整っていましたら、 readyok を送り返します。 Playing.Send("readyok"); }
public void Stop() { //------------------------------------------------------------ // あなたの手番です (すぐ指してください!) //------------------------------------------------------------ // // 図. // // log.txt // ┌──────────────────────────────────────── // ~ // │2014/08/02 2:03:35> stop // │ // // 何らかの理由で すぐ指してほしいときに、将棋所から送られてくる文字が stop です。 // // 理由は2つ考えることができます。 // (1)1手前に、将棋エンジンが 将棋所に向かって「予想手」付きで指し手を伝えたのだが、 // 相手の応手が「予想手」とは違ったので、予想手にもとづく思考を 今すぐ変えて欲しいとき。 // // (2)「急いで指すボタン」が押されたときなどに送られてくるようです? // // stop するのは思考です。 stop を受け取ったら すぐに最善手を指してください。 if (this.Game.GoPonderNow) { //------------------------------------------------------------ // 将棋エンジン「(予想手が間違っていたって?) △9二香 を指そうと思っていたんだが」 //------------------------------------------------------------ // // 図. // // log.txt // ┌──────────────────────────────────────── // ~ // │2014/08/02 2:36:21< bestmove 9a9b // │ // // // 1手前の指し手で、将棋エンジンが「bestmove ★ ponder ★」という形で 予想手付きで将棋所にメッセージを送っていたとき、 // その予想手が外れていたならば、将棋所は「stop」を返してきます。 // このとき 思考を打ち切って最善手の指し手をすぐに返信するわけですが、将棋所はこの返信を無視します☆w // (この指し手は、外れていた予想手について考えていた“最善手”ですからゴミのように捨てられます) // その後、将棋所から「position」「go」が再送されてくるのだと思います。 // // 将棋エンジン「bestmove ★ ponder ★」 // ↓ // 将棋所 「stop」 // ↓ // 将棋エンジン「うその指し手返信」(無視されます)←今ここ // ↓ // 将棋所 「position」「go」 // ↓ // 将棋エンジン「本当の指し手」 // // という流れと思います。 // この指し手は、無視されます。(無視されますが、送る必要があります) Playing.Send("bestmove 9a9b"); } else { //------------------------------------------------------------ // じゃあ、△9二香で //------------------------------------------------------------ // // 図. // // log.txt // ┌──────────────────────────────────────── // ~ // │2014/08/02 2:36:21< bestmove 9a9b // │ // // // 特に何もなく、すぐ指せというのですから、今考えている最善手をすぐに指します。 Playing.Send("bestmove 9a9b"); } }
public void Go(string btime, string wtime, string byoyomi, string binc, string winc) { //------------------------------------------------------------ // あなたの手番です //------------------------------------------------------------ // // 図. // // log.txt // ┌──────────────────────────────────────── // ~ // │2014/08/02 2:36:19> go btime 599000 wtime 600000 byoyomi 60000 // │ // // もう指していいときに、将棋所から送られてくる文字が go です。 // //------------------------------------------------------------ // 先手 3:00 後手 0:00 記録係「50秒ぉ~」 //------------------------------------------------------------ // // 上図のメッセージのままだと使いにくいので、 // あとで使いやすいように Key と Value の表に分けて持ち直します。 // // 図. // // goDictionary // ┌──────┬──────┐ // │Key │Value │ // ┝━━━━━━┿━━━━━━┥ // │btime │599000 │ // ├──────┼──────┤ // │wtime │600000 │ // ├──────┼──────┤ // │byoyomi │60000 │ // └──────┴──────┘ // 単位はミリ秒ですので、599000 は 59.9秒 です。 // //---------------------------------------- // 棋譜ツリー、局面データは、position コマンドで先に与えられているものとします。 //---------------------------------------- // ┏━━━━プログラム━━━━┓ int latestTemezumi = this.Game.Kifu.CurNode.Value.KyokumenConst.Temezumi; //現・手目済 SkyConst src_Sky = this.Game.Kifu.NodeAt(latestTemezumi).Value.KyokumenConst; //現局面 //Logger.Trace($"将棋サーバー「{latestTemezumi}手目、きふわらべ さんの手番ですよ!」 {line}"); //---------------------------------------- // 王の状態を調べます。 //---------------------------------------- Result_KingState result_kingState; { result_kingState = Result_KingState.Empty; RO_Star king1p = Util_Starlightable.AsKoma(src_Sky.StarlightIndexOf(Finger_Honshogi.SenteOh).Now); RO_Star king2p = Util_Starlightable.AsKoma(src_Sky.StarlightIndexOf(Finger_Honshogi.GoteOh).Now); //Logger.Trace("将棋サーバー「ではここで、王さまがどこにいるか確認してみましょう」"); //Logger.Trace($"▲王の置き場={Conv_SyElement.Masu_ToOkiba(koma1.Masu)}"); //Logger.Trace($"△王の置き場={Conv_SyElement.Masu_ToOkiba(koma2.Masu)}"); if (Conv_SyElement.ToOkiba(king1p.Masu) != Okiba.ShogiBan) { // 先手の王さまが将棋盤上にいないとき☆ result_kingState = Result_KingState.Lost_SenteOh; } else if (Conv_SyElement.ToOkiba(king2p.Masu) != Okiba.ShogiBan) { // または、後手の王さまが将棋盤上にいないとき☆ result_kingState = Result_KingState.Lost_GoteOh; } else { result_kingState = Result_KingState.Empty; } } //------------------------------------------------------------ // わたしの手番のとき、王様が 将棋盤上からいなくなっていれば、投了します。 //------------------------------------------------------------ // // 将棋GUI『きふならべ』用☆ 将棋盤上に王さまがいないときに、本将棋で go コマンドが送られてくることは無いのでは☆? // switch (result_kingState) { case Result_KingState.Lost_SenteOh: // 先手の王さまが将棋盤上にいないとき☆ case Result_KingState.Lost_GoteOh: // または、後手の王さまが将棋盤上にいないとき☆ { //------------------------------------------------------------ // 投了 //------------------------------------------------------------ // // 図. // // log.txt // ┌──────────────────────────────────────── // ~ // │2014/08/02 2:36:21< bestmove resign // │ // // この将棋エンジンは、後手とします。 // 20手目、投了 を決め打ちで返します。 Playing.Send("bestmove resign"); //投了 } break; default: // どちらの王さまも、まだまだ健在だぜ☆! { List <KifuNode> bestKifuNodeList = new List <KifuNode>(); //------------------------------------------------------------ // 指し手のチョイス //------------------------------------------------------------ bool isHonshogi = true; //------------------------------------------------------------ // MultiPV のテスト中☆ //------------------------------------------------------------ // // 指し手を決めます。 // TODO: その指し手の評価値がいくらだったのか調べたい。 // // FIXME: ログがMultiPV別になっていないので、混ざって、同じ手を2度指しているみたいに見えてしまう☆ // int multiPV_Count = 1; // 2; { // 最善手、次善手、三次善手、四次善手、五次善手 for (int iMultiPV = 0; iMultiPV < multiPV_Count; iMultiPV++) { bestKifuNodeList.Add(this.WA_Bestmove( isHonshogi, this.Game.Kifu) ); } #if DEBUG //// 内容をログ出力 //// 最善手、次善手、三次善手、四次善手、五次善手 //StringBuilder sb = new StringBuilder(); //for (int iMultiPV = 0; iMultiPV < 5; iMultiPV++) //{ // string sfenText = Util_Sky.ToSfenMoveText(bestMoveList[iMultiPV]); // sb.AppendLine($"[{iMultiPV}]{sfenText}"); //} //System.Windows.Forms.MessageBox.Show(sb.ToString()); #endif } KifuNode bestKifuNode = null; // 最善手、次善手、三次善手、四次善手、五次善手 float bestScore = float.MinValue; for (int iMultiPV = 0; iMultiPV < bestKifuNodeList.Count; iMultiPV++) { KifuNode node = bestKifuNodeList[iMultiPV]; if (null != node && null != node.KyHyokaSheet_Mutable && bestScore <= node.Score) { bestScore = node.Score; bestKifuNode = node; } } IMove bestMove2; if (null == bestKifuNode) { // 投了 bestMove2 = Util_Sky258A.NullObjectMove; } else { bestMove2 = bestKifuNode.Key; } if (Util_Sky_BoolQuery.isEnableSfen(bestMove2)) { string sfenText = ConvMoveStrSfen.ToMoveStrSfen(bestMove2); // ログが重過ぎる☆! //Logger.Trace($"(Warabe)指し手のチョイス: bestmove=[{sfenText}] 棋譜={KirokuGakari.ToJsaKifuText(this.Kifu)}"); //---------------------------------------- // スコア 試し //---------------------------------------- { //int hyojiScore = (int)(bestScore / 100.0d);//FIXME:適当に調整した。 int hyojiScore = (int)bestScore; if (this.Game.Kifu.CurNode.Value.KyokumenConst.KaisiPside == Playerside.P2) { // 符号を逆転 hyojiScore = -hyojiScore; } Playing.Send($"info time 1 depth 1 nodes 1 score cp {hyojiScore.ToString()} pv "); //FIXME: //+ " pv 3a3b L*4h 4c4d" } //---------------------------------------- // 指し手を送ります。 //---------------------------------------- Playing.Send($"bestmove {sfenText}"); } else // 指し手がないときは、SFENが書けない☆ 投了だぜ☆ { // ログが重過ぎる☆! //Logger.Trace($"(Warabe)指し手のチョイス: 指し手がないときは、SFENが書けない☆ 投了だぜ☆ww(>_<) 棋譜={KirokuGakari.ToJsaKifuText(this.Kifu)}"); //---------------------------------------- // 投了w! //---------------------------------------- Playing.Send("bestmove resign"); } //------------------------------------------------------------ // 以前の手カッター //------------------------------------------------------------ UtilKifuTree282.IzennoHenkaCutter(this.Game.Kifu); } break; } // ┗━━━━プログラム━━━━┛ // Logger.Trace(); //throw new Exception("デバッグだぜ☆! エラーはキャッチできたかな~☆?(^▽^)"); }
public void UsiOk(string engineName, string engineAuthor) { //------------------------------------------------------------ // あなたは USI ですか? //------------------------------------------------------------ // // 図. // // log.txt // ┌──────────────────────────────────────── // ~ // │2014/08/02 1:31:35> usi // │ // // // 将棋所で [対局(G)]-[エンジン管理...]-[追加...] でファイルを選んだときに、 // 送られてくる文字が usi です。 //------------------------------------------------------------ // エンジン設定ダイアログボックスを作ります //------------------------------------------------------------ // // 図. // // log.txt // ┌──────────────────────────────────────── // ~ // │2014/08/02 23:40:15< option name 子 type check default true // │2014/08/02 23:40:15< option name USI type spin default 2 min 1 max 13 // │2014/08/02 23:40:15< option name 寅 type combo default tiger var マウス var うし var tiger var ウー var 龍 var へび var 馬 var ひつじ var モンキー var バード var ドッグ var うりぼー // │2014/08/02 23:40:15< option name 卯 type button default うさぎ // │2014/08/02 23:40:15< option name 辰 type string default DRAGON // │2014/08/02 23:40:15< option name 巳 type filename default スネーク.html // │ // // // 将棋所で [エンジン設定] ボタンを押したときに出てくるダイアログボックスに、 // ・チェックボックス // ・スピン // ・コンボボックス // ・ボタン // ・テキストボックス // ・ファイル選択テキストボックス // を置くことができます。 // //------------------------------------------------------------ // USI です!! //------------------------------------------------------------ // // 図. // // log.txt // ┌──────────────────────────────────────── // ~ // │2014/08/02 2:03:33< id name fugafuga 1.00.0 // │2014/08/02 2:03:33< id author hogehoge // │2014/08/02 2:03:33< usiok // │ // // プログラム名と、作者名を送り返す必要があります。 // オプションも送り返せば、受け取ってくれます。 // usi を受け取ってから、5秒以内に usiok を送り返して完了です。 Playing.Send($@"option name 子 type check default true option name USI type spin default 2 min 1 max 13 option name 寅 type combo default tiger var マウス var うし var tiger var ウー var 龍 var へび var 馬 var ひつじ var モンキー var バード var ドッグ var うりぼー option name 卯 type button default うさぎ option name 辰 type string default DRAGON option name 巳 type filename default スネーク.html id name {engineName} id author {engineAuthor} usiok"); }