/// <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; //} } } }