public static void Setumei_Discovered(Masu ms_removed, Kyokumen.Sindanyo kys, StringBuilder syuturyoku) { kys.TryInControl(ms_removed, out Koma[] kmHairetu_control); Bitboard bb_relative = new Bitboard();//関連のある飛び利き駒 // 飛び利きを計算し直す foreach (Koma km in kmHairetu_control) { if (Koma.PieceNum == km) { break; } // 駒の居場所 Bitboard bb_ibasho = new Bitboard(); kys.ToSetIbasho(km, bb_ibasho); while (bb_ibasho.Ref_PopNTZ(out Masu ms_ibasho)) { bb_relative.Standup(ms_ibasho); } } Setumei_1Bitboard("関連する飛び利き駒", bb_relative, syuturyoku); }
public static void Assert_Sabun_Komawari(string message, Kyokumen.Sindanyo kys, StringBuilder syuturyoku) { KomawariHyokatiSabunItiran saikeisan = new KomawariHyokatiSabunItiran(); saikeisan.Tukurinaosi(kys); Hyokati hyokati1 = kys.GetKomawari(OptionalPhase.Black); Hyokati hyokati2 = kys.GetKomawari(OptionalPhase.White); bool safe = hyokati1 == saikeisan.Get(OptionalPhase.Black) && hyokati2 == saikeisan.Get(OptionalPhase.White) ; string msg = $@"{message}#河馬 診断 駒割り評価値 P1差分 =[{hyokati1}] 再計算=[{saikeisan.Get(OptionalPhase.Black)}] P2差分 =[{hyokati2}] 再計算=[{saikeisan.Get(OptionalPhase.White)}] "; if (!safe) { syuturyoku.AppendLine(msg); { var msg2 = syuturyoku.ToString(); syuturyoku.Clear(); Logger.Flush(msg2); } } Debug.Assert(safe, msg); }
/// <summary> /// /// </summary> /// <returns></returns> public static ulong GetTaikyokusyaKey(Option <Phase> optionalPhase, Kyokumen.Sindanyo kys) { if (Util_ZobristHashing.Dirty) { Util_ZobristHashing.Tukurinaosi(kys); } return(Util_ZobristHashing.m_tbTaikyokusya_[OptionalPhase.IndexOf(optionalPhase)]); }
/// <summary> /// /// </summary> /// <returns></returns> public static ulong GetMotiKey(Kyokumen.Sindanyo kys, MotiKoma mk) { if (Util_ZobristHashing.Dirty) { Util_ZobristHashing.Tukurinaosi(kys); } return(Util_ZobristHashing.m_motiKeys_[(int)mk][kys.CountMotikoma(mk)]); }
/// <summary> /// 下側に自分の陣地がある視点の段番号だぜ☆(^▽^) /// 例:対局者1でも2でも、トライルールは らいおん が1段目に入ったときだぜ☆(^▽^) /// </summary> /// <param name="ms"></param> /// <returns></returns> public static int ToDan_JibunSiten(Option <Phase> optionalPhase, Masu ms, Kyokumen.Sindanyo kys) { var phase = optionalPhase.Unwrap(); if (phase == Phase.Black) { return(Conv_Masu.ToDan_WithoutErrorCheck((int)ms)); } return(Conv_Masu.ToDan_WithoutErrorCheck(kys.MASU_YOSOSU - 1 - (int)ms)); }
public static Move TryFenMove2( bool isSfen, Kyokumen.Sindanyo kys, string str1, string str2, string str3, string str4, string str5 ) { int dstSuji = FenSuji_Int(isSfen, str3); // 至筋 int dstDan = FenDan_Int(isSfen, str4); // 至段 // 取った駒を調べるぜ☆(^▽^) Masu dstMs = Conv_Masu.ToMasu(dstSuji, dstDan); //------------------------------ // 5 //------------------------------ bool natta = false; if ("+" == str5) { // 成りました natta = true; } //------------------------------ // 結果 //------------------------------ if ("*" == str2) { // 駒台から打ったぜ☆ return(ConvMove.ToMove01cUtta( dstMs, Med_Parser.Moji_MotikomaSyurui(isSfen, str1)//打った駒 )); } else { // 盤上の駒を動かしたぜ☆ if (natta) { return(ConvMove.ToMove01bNariSasi(Med_Parser.FenSujiDan_Masu(isSfen, str1, str2), dstMs, kys)); } else { return(ConvMove.ToMove01aNarazuSasi(Med_Parser.FenSujiDan_Masu(isSfen, str1, str2), dstMs, kys)); } } }
public static void Assert_Sabun_Kiki(string message, Kyokumen.Sindanyo kys) { // 駒の利き☆ bool safe = true; // 再計算 Recalculate Shogiban saikeisan = new Shogiban(kys); saikeisan.Tukurinaosi_1_Clear_KikiKomabetu(); saikeisan.Tukurinaosi_2_Input_KikiKomabetu(kys); foreach (var optionalPhase in Conv_Taikyokusya.AllOptionalPhaseList) // 対局者1、対局者2 { int iKm = 0; //どの駒でエラーがあったか foreach (Koma km in Conv_Koma.ItiranTai[OptionalPhase.IndexOf(optionalPhase)]) { if (!kys.EqualsKiki(km, saikeisan))//現行版と、再計算版の比較 { safe = false; break; } iKm++; } // ダイアログボックスに収まるように分けるぜ☆ if (!safe) { StringBuilder sindan1 = new StringBuilder(); //// 参考:駒の居場所 //{ // sindan1.Append(message); // sindan1.AppendLine("参考:駒の居場所"); // Util_Information.HyojiKomanoIbasho(ky.BB_KomaZenbu, ky.BB_Koma, sindan1); // sindan1.AppendLine($"Util_Tansaku.TansakuTyakusyuEdas=[{Util_Tansaku.TansakuTyakusyuEdas}]"); //} sindan1.Append(message); sindan1.Append("【エラー】"); Conv_Taikyokusya.Setumei_Name(optionalPhase, sindan1); sindan1.AppendLine(); sindan1.AppendLine($"iKm=[{iKm}]"); sindan1.AppendLine("利き:(再計算)"); Util_Information.Setumei_Bitboards(Med_Koma.GetKomasyuruiNamaeItiran(optionalPhase), saikeisan.WhereBBKiki(optionalPhase), sindan1); kys.Setumei_GenkoKiki(optionalPhase, sindan1); // 利き:(現行) var msg = sindan1.ToString(); sindan1.Clear(); Logger.Flush(msg); Debug.Assert(safe, msg); } } }
/// <summary> /// moves 以降の符号を指定しろだぜ☆(^~^) /// </summary> /// <param name="moves"></param> public void AddMoves(bool isSfen, string moves, Kyokumen.Sindanyo kys) { string[] fugoItiran = moves.Split(' '); foreach (string fugo in fugoItiran) { int caret = 0; if (!Med_Parser.TryFenMove(isSfen, fugo, ref caret, kys, out Move move)) { throw new System.Exception($"指し手のパースエラー fugo=[{ fugo }]"); } SsList.Add(move); } }
/// <summary> /// 手番と、 /// 駒の種類と、その升、 /// この3つを指定すると、利きを表にして返すぜ☆(^▽^) /// </summary> /// <param name="tai"></param> /// <param name="targetMs"></param> /// <param name="ks"></param> /// <param name="attackerMs"></param> /// <returns></returns> public static bool[] Kiki(Koma km, Masu attackerMs, Kyokumen.Sindanyo kys, Shogiban shogiban)//KomanoUgokikata komanoUgokikata { bool[] kiki = new bool[kys.MASU_YOSOSU]; // 盤上 for (int iDan = 0; iDan < Option_Application.Optionlist.BanTateHaba; iDan++) { for (int iSuji = 0; iSuji < Option_Application.Optionlist.BanYokoHaba; iSuji++) { kiki[iDan * Option_Application.Optionlist.BanYokoHaba + iSuji] = Util_HiouteCase.IsLegalMove(km, (Masu)(iDan * Option_Application.Optionlist.BanYokoHaba + iSuji), attackerMs, shogiban); } } return(kiki); }
/// <summary> /// 局面に点数を付けるぜ☆(^▽^) /// /// どちらの対局者でも、自分に有利と思っていれば正の数の方向に点数が付くぜ☆(^▽^) /// </summary> /// <param name="ky_base"></param> /// <returns></returns> public void Tukurinaosi(Kyokumen.Sindanyo kys) { Hyokati[] hyokati = new Hyokati[] { Hyokati.Hyokati_Rei, Hyokati.Hyokati_Rei , Hyokati.Hyokati_Rei // 空白は手番なしで ここに入れるぜ☆(^~^) }; // 盤上 Bitboard komaBB = new Bitboard(); for (int iTai = 0; iTai < Conv_Taikyokusya.AllOptionalPhaseList.Length; iTai++) { var optionalPhase = Conv_Taikyokusya.AllOptionalPhaseList[iTai]; for (int iKs = 0; iKs < Conv_Komasyurui.Itiran.Length; iKs++) { Komasyurui ks = Conv_Komasyurui.Itiran[iKs]; kys.ToSetIbasho(Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, optionalPhase), komaBB); while (komaBB.Ref_PopNTZ(out Masu ms_jissai)) { hyokati[iTai] += Conv_Koma.BanjoKomaHyokatiNumber[(int)Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, optionalPhase)]; } } } // 持ち駒 foreach (MotiKoma mk in Conv_MotiKoma.Itiran) { var optionalPhase = Med_Koma.MotiKomaToPhase(mk); var phaseIndex = OptionalPhase.IndexOf(optionalPhase); MotiKomasyurui mks = Med_Koma.MotiKomaToMotiKomasyrui(mk); Hyokati komaHyokati = Conv_Hyokati.KomaHyokati[(int)Med_Koma.MotiKomasyuruiAndPhaseToKoma(mks, optionalPhase)]; hyokati[phaseIndex] += (int)komaHyokati * kys.CountMotikoma(mk); } // 手番 - 相手番 Hyokati hyokatiP1 = hyokati[(int)Phase.Black]; hyokati[(int)Phase.Black] -= hyokati[(int)Phase.White]; hyokati[(int)Phase.White] -= hyokatiP1; KomawariHyokati_Sabun = hyokati; }
/// <summary> /// 盤上の駒を指したぜ☆(^▽^)(打つ以外の指し手☆) /// /// 指し手に、取った駒を記録するのは止めるぜ☆(^~^)局面データの方に入れておこう☆(^▽^) /// </summary> /// <param name="ms_src"></param> /// <param name="ms_dst"></param> /// <param name="natta"></param> /// <returns></returns> public static Move ToMove01aNarazuSasi(Masu ms_src, Masu ms_dst, Kyokumen.Sindanyo kys) { Debug.Assert(kys.IsBanjoOrError(ms_src), $"ms_src=[{ms_src}] kys.MASUS=[{kys.MASU_YOSOSU}]"); Debug.Assert(kys.IsBanjo(ms_dst), "盤外に指したぜ☆?"); // バリュー int v = 0; // 筋と段☆(^▽^)盤外なら 0 だぜ☆(^▽^) SetSrcMasu_WithoutErrorCheck(ref v, ms_src); // 「打」のときは何もしないぜ☆(^▽^) SetDstMasu_WithoutErrorCheck(ref v, ms_dst); // 打った駒なし // 成らない☆(^▽^) return((Move)v); }
/// <summary> /// 現局面の盤上、駒台に置いてある駒を 駒の種類別に数え、 /// 片方の対局者の駒台に全部乗れるよう、拡張する。 /// </summary> public static void Tukurinaosi(Kyokumen.Sindanyo kys) { // 盤上 m_banjoKeys_ = new ulong[kys.MASU_YOSOSU, Conv_Koma.Itiran.Length]; for (int iMs = 0; iMs < kys.MASU_YOSOSU; iMs++) { foreach (Komasyurui ks in Conv_Komasyurui.Itiran) { // 対局者1 m_banjoKeys_[iMs, (int)Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, OptionalPhase.Black)] = (ulong)(Option_Application.Random.NextDouble() * ulong.MaxValue); // 対局者2 m_banjoKeys_[iMs, (int)Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, OptionalPhase.White)] = (ulong)(Option_Application.Random.NextDouble() * ulong.MaxValue); } } // 持ち駒 { m_motiKeys_ = new ulong[Conv_MotiKoma.Itiran.Length][]; int[] counts = kys.CountMotikomaHashSize(); foreach (MotiKoma mk in Conv_MotiKoma.Itiran) { MotiKomasyurui mks = Med_Koma.MotiKomaToMotiKomasyrui(mk); m_motiKeys_[(int)mk] = new ulong[counts[(int)mks]]; for (int iCount = 0; iCount < counts[(int)mks]; iCount++) { m_motiKeys_[(int)mk][iCount] = (ulong)(Option_Application.Random.NextDouble() * ulong.MaxValue); } } } // 手番 m_tbTaikyokusya_ = new ulong[Conv_Taikyokusya.AllOptionalPhaseList.Length]; foreach (var optionalPhase78 in Conv_Taikyokusya.AllOptionalPhaseList) { m_tbTaikyokusya_[OptionalPhase.IndexOf(optionalPhase78)] = (ulong)(Option_Application.Random.NextDouble() * ulong.MaxValue); } Dirty = false; }
/// <summary> /// 盤上の駒を指したぜ☆(^▽^)(打つ以外の指し手☆) /// /// 指し手に、取った駒を記録するのは止めるぜ☆(^~^)局面データの方に入れておこう☆(^▽^) /// </summary> /// <param name="ms_src"></param> /// <param name="ms_dst"></param> /// <param name="natta"></param> /// <returns></returns> public static Move ToMove01bNariSasi(Masu ms_src, Masu ms_dst, Kyokumen.Sindanyo kys) { Debug.Assert(kys.IsBanjoOrError(ms_src), ""); Debug.Assert(kys.IsBanjo(ms_dst), "盤外に指したぜ☆?"); // バリュー int v = 0; // 筋と段☆(^▽^)盤外なら 0 だぜ☆(^▽^) SetSrcMasu_WithoutErrorCheck(ref v, ms_src); // 「打」のときは何もしないぜ☆(^▽^) SetDstMasu_WithoutErrorCheck(ref v, ms_dst); // 打った駒なし // 成った☆(^▽^) v |= 1 << MoveShift.Natta; return((Move)v); }
public static bool MoveCmd(string commandline, Kyokumen.Sindanyo kys, out Move out_sasite) { // うしろに続く文字は☆(^▽^) int caret = 0; Util_String.TobasuTangoToMatubiKuhaku(commandline, ref caret, "move "); string line = commandline.Substring(caret).Trim(); // move 912 といった数字かどうか☆(^~^) if (int.TryParse(line, out int ssSuji)) { out_sasite = (Move)ssSuji; return(true); } // 数字でなければ、 move B2B3 といった文字列か☆(^~^) if (Med_Parser.TryFenMove(Option_Application.Optionlist.USI, commandline, ref caret, kys, out out_sasite)) { return(true); } out_sasite = Move.Toryo; return(false); }
/// <summary> /// /// </summary> /// <param name="ms">どの(0~80)升に</param> /// <param name="km">先後付きの駒</param> /// <returns></returns> public static ulong GetBanjoKey(Masu ms, Koma km, Kyokumen.Sindanyo kys) { var optionalPiece = OptionalPiece.From(km); Debug.Assert(Conv_Koma.IsOk(optionalPiece), ""); if (Dirty) { Tukurinaosi(kys); } if (!Conv_Koma.IsOk(optionalPiece)) { throw new Exception("エラー☆(>_<) 盤上の駒じゃないぜ☆"); } else if (kys.IsBanjo(ms)) { return(m_banjoKeys_[(int)ms, (int)km]); } else { throw new Exception("エラー☆(>_<) 盤上のどこに置いてある駒なんだぜ☆"); } }
/// <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); }