public static void Kiki(bool isSfen, string commandline, Kyokumen ky, out Masu out_ms, out Bitboard out_kikiBB) { //KomanoUgokikata komanoUgokikata, // うしろに続く文字は☆(^▽^) int caret = 0; Util_String.TobasuTangoToMatubiKuhaku(commandline, ref caret, "kiki "); string line = commandline.Substring(caret).TrimEnd(); if (line.Length == 2)// kiki b3 { out_kikiBB = null; // 升を返すぜ☆ if (!Med_Parser.TryParseMs(isSfen, commandline, ky, ref caret, out out_ms)) { throw new Exception("パースエラー102"); } } else// kiki b3 R 1 { out_ms = ky.MASU_ERROR; // 盤面表示を返すぜ☆ string moji1 = ""; string moji2 = ""; string moji3 = ""; string moji4 = ""; Match m = Itiran_FenParser.GetKikiCommandPattern(Option_Application.Optionlist.USI).Match(commandline, caret); if (m.Success) { Util_String.SkipMatch(commandline, ref caret, m); moji1 = m.Groups[1].Value; moji2 = m.Groups[2].Value; moji3 = m.Groups[3].Value; moji4 = m.Groups[4].Value; if (!Med_Parser.TryTaikyokusya(Option_Application.Optionlist.USI, moji4, out Option <Phase> phase)) { throw new Exception($"対局者のパースエラー moji4=[{ moji4 }]"); } out_kikiBB = Util_Application.Kiki_BB(Med_Koma.KomasyuruiAndTaikyokusyaToKoma(Med_Parser.Moji_Komasyurui(Option_Application.Optionlist.USI, moji3), phase), Med_Parser.FenSujiDan_Masu(Option_Application.Optionlist.USI, moji1, moji2), ky.Shogiban);// komanoUgokikata } else { out_kikiBB = null; } } }
/// <summary> /// 2017-04-19 作成 /// </summary> /// <param name="commandline"></param> /// <param name="caret"></param> /// <param name="out_ms"></param> /// <returns></returns> public static bool TryParseMs(bool isSfen, string commandline, Kyokumen ky, ref int caret, out Masu out_ms) { Match m = Itiran_FenParser.GetMasuPattern(isSfen).Match(commandline, caret); if (m.Success) { Util_String.SkipMatch(commandline, ref caret, m); int suji = FenSuji_Int(isSfen, m.Groups[1].Value); int dan = FenDan_Int(isSfen, m.Groups[2].Value); out_ms = Conv_Masu.ToMasu(suji, dan); return(true); } else { out_ms = ky.MASU_ERROR; return(false); } }
/// <summary> /// 定跡ファイルの解析☆(^~^) /// </summary> /// <param name="lines"></param> public void Parse(bool isSfen, string[] lines, StringBuilder syuturyoku) { this.Clear(); Kyokumen ky_forJoseki = new Kyokumen();//使いまわすぜ☆(^▽^) JosekiKyokumen josekiKy = null; JosekiMove josekiSs; Match m; string commandline; for (int iGyoBango = 0; iGyoBango < lines.Length; iGyoBango++) { commandline = lines[iGyoBango]; if (commandline.Length < 1) { // 空行は無視☆ // 半角空白とか、全角空白とか、タブとか 入れてるやつは考慮しないぜ☆(^~^)! } else if ('f' == commandline[0])// fen で始まれば局面データ☆(^▽^)// caret == commandline.IndexOf("fen ", caret) { // キャレットは進めずに続行だぜ☆(^▽^) m = Itiran_FenParser.GetJosekiKyPattern(Option_Application.Optionlist.USI).Match(commandline);//, caret if (!m.Success) { StringBuilder reigai1 = new StringBuilder(); reigai1.AppendLine($@"パースに失敗だぜ☆(^~^)! #寿 定跡ファイル解析失敗 commandline=[{ commandline }]"); #if DEBUG reigai1.Append(" ["); reigai1.Append(iGyoBango.ToString()); reigai1.Append("]行目"); #endif syuturyoku.AppendLine(reigai1.ToString()); var msg = syuturyoku.ToString(); Logger.Flush(msg); syuturyoku.Clear(); throw new Exception(msg); } // .Value は、該当しないときは空文字列か☆ // .Value は、該当しないときは空文字列か☆ if (Itiran_FenParser.STARTPOS_LABEL == m.Groups[1].Value) { DanStrings = Itiran_FenParser.GetStartpos(Option_Application.Optionlist.USI).Split('/'); } else { DanStrings = m.Groups[1].Value.Split('/'); // N段目 } ky_forJoseki.SetNaiyo( isSfen, true, //適用 false, Joseki.DanStrings, //1~N 段目 m.Groups[2].Value, m.Groups[3].Value, //手番 syuturyoku ); /* #if DEBUG * { * Kyokumen ky3 = new KyokumenImpl(); * int caret = 0; * ky3.ParseFen(commandline, ref caret, false, syuturyoku); * ulong newHash = ky3.CreateKyokumenHash(); * if (newHash != ky2.KyokumenHash) * { * StringBuilder reigai1 = new StringBuilder(); * reigai1.Append("局面ハッシュが異なるぜ☆(^~^)! commandline=["); * reigai1.Append(commandline); * reigai1.Append("] ky3.AppendFenTo=["); * ky3.AppendFenTo(reigai1); * reigai1.Append("] dan1["); * reigai1.Append(JosekiImpl.DanStrings[0]); * reigai1.Append("] dan2["); * reigai1.Append(JosekiImpl.DanStrings[1]); * reigai1.Append("] dan3["); * reigai1.Append(JosekiImpl.DanStrings[2]); * reigai1.Append("] dan4["); * reigai1.Append(JosekiImpl.DanStrings[3]); * reigai1.Append("] newHash=["); * reigai1.Append(newHash.ToString()); * reigai1.Append("] ky2.KyokumenHash=["); * reigai1.Append(ky2.KyokumenHash.ToString()); * reigai1.Append("]"); * syuturyoku.AppendLine(reigai1.ToString()); * Logger.Flush(syuturyoku); * throw new Exception(reigai1.ToString()); * } * } #endif */ josekiKy = this.ParseKyokumenLine(commandline, ky_forJoseki.KyokumenHash.Value, ky_forJoseki.CurrentOptionalPhase, syuturyoku); } else { // それ以外は手筋☆(^▽^) if (null == josekiKy) { throw new Exception("定跡ファイル解析失敗 定跡局面の指定なし☆"); } // 指し手、指し手、数字、数字、数字 と並んでいるぜ☆(^▽^) m = Itiran_FenParser.GetJosekiSsPattern(Option_Application.Optionlist.USI).Match(commandline); if (!m.Success) { //* // FIXME: syuturyoku.AppendLine($"パースに失敗だぜ☆(^~^)! #鮪 commandline=[{ commandline }]"); var msg = syuturyoku.ToString(); syuturyoku.Clear(); Logger.Flush(msg); throw new Exception(msg); // */ } // 高速化のために、ローカル変数を減らして、詰め込んだコードにしているぜ☆(>_<) // 第1引数 B1C1 や toryo のような指し手の解析。 josekiSs = new JosekiMove( // 1列目:指し手☆ (1:グループ,2:指し手全体,3~7:指し手各部,8:投了) m.Groups[8].Success ? Move.Toryo : // "toryo" が入っている場合☆ Med_Parser.TryFenMove2(Option_Application.Optionlist.USI, ky_forJoseki.Sindan, m.Groups[3].Value, m.Groups[4].Value, m.Groups[5].Value, m.Groups[6].Value, m.Groups[7].Value ), // 2列目:応手☆ none とか。(9:グループ,10:none,11:指し手全体,12~16:指し手各部,17:投了) m.Groups[10].Success || m.Groups[17].Success ? Move.Toryo :// [10]"none" または[17]"toryo" が入っている場合☆ FIXME: none と toryo を区別してないぜ☆(^~^) Med_Parser.TryFenMove2(Option_Application.Optionlist.USI, ky_forJoseki.Sindan, m.Groups[12].Value, m.Groups[13].Value, m.Groups[14].Value, m.Groups[15].Value, m.Groups[16].Value ), (Hyokati)int.Parse(m.Groups[18].Value), //hyokati (18) 解析はokなはず☆ int.Parse(m.Groups[19].Value), //fukasa (19) 解析はokなはず☆ int.Parse(m.Groups[20].Value), //version (20) 解析はokなはず☆(旧版ではバージョンは無いこともある☆) josekiKy ); // 定跡ファイルの局面には、重複指し手データがないようにしてくれだぜ☆(^~^)チェックは省くぜ☆ /* * if (josekiKy.SsItems.ContainsKey(josekiSs.Move)) * { * // FIXME: * String2 str = new String2Impl(); * str.Append("局面データに重複の指し手があるぜ☆(^~^)! 局面=["); * str.Append(josekiKy.Fen); * str.Append("] 指し手=["); * ConvMove.Setumei(josekiSs.Move,str); * str.Append("]"); * Util_Machine.AppendLine(str.ToString()); * Logger.Flush(); * throw new Exception(str.ToString()); * } * else * { * // */ // 新規 //#if DEBUG // // 指し手の整合性をチェックしておきたいぜ☆(^▽^) // { // Kyokumen ky2 = new KyokumenImpl(); // if (!ky2.ParseFen(ky.ToFen(), false)) // { // string msg = "新規: パースに失敗だぜ☆(^~^)!"; // Face_Application.MessageLine(msg); // Face_Application.Write(); // throw new Exception(msg); // } // Move bestMove; // int caret_test = 0; // ConvMove.TryParse(commandline, ref caret_test, ky2, out bestMove); // MoveError reason; // if (!ky2.CanDoMove( bestMove, out reason)) // { // throw new Exception($"新規: 指せない指し手を定跡に登録しようとしたぜ☆(^~^)!:{ConvMove.Setumei(reason)}"); // } // } //#endif josekiKy.SsItems.Add(josekiSs.Move, josekiSs); this.Edited = true; //} } } }
/// <summary> /// /// </summary> /// <param name="commandline">B4B3、または toryo といった文字列を含む行☆</param> /// <param name="caret">文字カーソルの位置</param> /// <param name="ky">取られた駒を調べるために使う☆</param> /// <param name="out_sasite"></param> /// <returns></returns> public static bool TryFenMove( bool isSfen, string commandline, ref int caret, Kyokumen.Sindanyo kys, out Move out_sasite ) { if ('n' == commandline[caret]) { if (caret == commandline.IndexOf("none", caret))//定跡ファイルの応手が無いときに利用☆ { Util_String.TobasuTangoToMatubiKuhaku(commandline, ref caret, "none"); out_sasite = Move.Toryo; return(true); } } else //if ('t' == commandline[caret]) //{ if (caret == commandline.IndexOf(Itiran_FenParser.GetToryo(isSfen), caret)) { Util_String.TobasuTangoToMatubiKuhaku(commandline, ref caret, Itiran_FenParser.GetToryo(isSfen)); out_sasite = Move.Toryo; return(true); } //} // 「toryo」でも「none」でもなければ、「B4B3」形式と想定して、1手だけ読込み // テキスト形式の符号「A4A3 C1C2 …」の最初の1要素を、切り取ってトークンに分解します。 Match m = Itiran_FenParser.GetMovePattern(isSfen).Match(commandline, caret); if (!m.Success) { //// 「B4B3」形式ではなかった☆(^△^)!? 次の一手が読めない☆ //string msg = $"指し手のパースに失敗だぜ☆(^~^)! commandline=[{ commandline }] caret=[{ caret }] m.Groups.Count=[{ m.Groups.Count }]"; //Util_Machine.AppendLine(msg); //Logger.Flush(); //throw new Exception(msg); out_sasite = Move.Toryo; return(false); } // m.Groups[1].Value : ABCabc か、 ZKH // m.Groups[2].Value : 1234 か、 * // m.Groups[3].Value : ABCabc // m.Groups[4].Value : 1234 // m.Groups[5].Value : + // カーソルを進めるぜ☆(^~^) Util_String.SkipMatch(commandline, ref caret, m); // 符号1「B4B3」を元に、move を作ります。 out_sasite = TryFenMove2( isSfen, kys, m.Groups[1].Value, m.Groups[2].Value, m.Groups[3].Value, m.Groups[4].Value, m.Groups[5].Value ); Debug.Assert((int)out_sasite != -1, ""); return(true); }
/// <summary> /// 改造FEN符号表記 /// </summary> /// <returns></returns> public static void AppendFenTo(bool isSfen, Move ss, StringBuilder syuturyoku) { if (Move.Toryo == ss) { syuturyoku.Append(Itiran_FenParser.GetToryo(isSfen)); return; } int v = (int)ss;//バリュー(ビットフィールド) // 打った駒の種類(取り出すのは難しいので関数を使う☆) MotiKomasyurui mksUtta = GetUttaKomasyurui(ss); if (MotiKomasyurui.Yososu != mksUtta)//指定があれば { // 打でした。 // (自)筋・(自)段は書かずに、「P*」といった表記で埋めます。 Conv_MotiKomasyurui.AppendFenTo(isSfen, mksUtta, syuturyoku); syuturyoku.Append("*"); } else { //------------------------------------------------------------ // (自)筋 //------------------------------------------------------------ if (Option_Application.Optionlist.USI) { syuturyoku.Append(Option_Application.Optionlist.BanYokoHaba + 1 - GetSrcSuji_WithoutErrorCheck(v)); } else { syuturyoku.Append(Conv_Kihon.ToAlphabetLarge(GetSrcSuji_WithoutErrorCheck(v))); } //------------------------------------------------------------ // (自)段 //------------------------------------------------------------ if (Option_Application.Optionlist.USI) { syuturyoku.Append(Conv_Kihon.ToAlphabetSmall(GetSrcDan_WithoutErrorCheck(v))); } else { syuturyoku.Append(GetSrcDan_WithoutErrorCheck(v).ToString()); } } //------------------------------------------------------------ // (至)筋 //------------------------------------------------------------ if (Option_Application.Optionlist.USI) { syuturyoku.Append(Option_Application.Optionlist.BanYokoHaba + 1 - GetDstSuji_WithoutErrorCheck(v)); } else { syuturyoku.Append(Conv_Kihon.ToAlphabetLarge(GetDstSuji_WithoutErrorCheck(v))); } //------------------------------------------------------------ // (至)段 //------------------------------------------------------------ if (Option_Application.Optionlist.USI) { syuturyoku.Append(Conv_Kihon.ToAlphabetSmall(GetDstDan_WithoutErrorCheck(v))); } else { syuturyoku.Append(GetDstDan_WithoutErrorCheck(v).ToString()); } //------------------------------------------------------------ // 成 //------------------------------------------------------------ int natta; { // (v & m) >> s + 1。 v:バリュー、m:マスク、s:シフト natta = (v & (int)MoveMask.Natta) >> (int)MoveShift.Natta; } if (1 == natta) { syuturyoku.Append("+"); } }