public static void Assert_Genkou_Bitboard(string message, Kyokumen ky) { bool safe = ky.Shogiban.Assert(); if (!safe) { StringBuilder sindan1 = new StringBuilder(); sindan1.Append(message); sindan1.AppendLine(" ビットボード診断"); Util_Information.HyojiKomanoIbasho(ky.Shogiban, sindan1); sindan1.AppendLine($"Util_Tansaku.TansakuTyakusyuEdas=[{Util_Tansaku.TansakuTyakusyuEdas}]"); var msg = sindan1.ToString(); sindan1.Clear(); Logger.Flush(msg); Debug.Fail(msg); } }
/// <summary> /// 一手詰めの局面かどうか調べるぜ☆(^▽^) /// /// 盤上の駒を動かすのか、駒台の駒を打つのかによって、利き の形が異なるぜ☆(^~^) /// /// 自分が一手詰めを掛けられるから、この指し手は作らないでおこう、といった使い方がされるぜ☆(^▽^) /// /// FIXME: 成りを考慮してない /// </summary> /// <param name="ky"></param> /// <param name="jibun"></param> /// <param name="ms_t0">移動元。持ち駒の場合、エラー値</param> /// <param name="ms_t1">移動先</param> /// <param name="jibunHioute"></param> /// <returns></returns> public static bool Ittedume_BanjoKoma(Kyokumen ky, Option <Phase> phase, Masu ms_t0, Masu ms_t1, HiouteJoho jibunHioute, HiouteJoho aiteHioute) { Debug.Assert(ky.Sindan.IsBanjo(ms_t1), "升エラー"); var optionalOpponent = Conv_Taikyokusya.Reverse(phase); // 動かす駒 if (!ky.Shogiban.ExistsBBKoma(phase, ms_t0, out Komasyurui ks_t0)) { StringBuilder reigai1 = new StringBuilder(); reigai1.AppendLine($"盤上の駒じゃないじゃないか☆(^▽^)www phase=[{ phase }] ms_src=[{ ms_t0 }] ks_jibun=[{ ks_t0 }]"); Util_Information.HyojiKomanoIbasho(ky.Shogiban, reigai1); var msg = reigai1.ToString(); Logger.Flush(msg); throw new Exception(msg); } Koma km_t0 = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks_t0, phase); Koma km_t1 = km_t0; // FIXME: 成りを考慮していないぜ☆(>_<) // A B C // ┌──┬──┬──┐ //1│ │▽ら│ │ // ├──┼──┼──┤ //2│▲き│ │▲き│ // ├──┼──┼──┤ //3│ │▲に│▲ら│ // ├──┼──┼──┤ //4│▲ぞ│▲ひ│▲ぞ│ // └──┴──┴──┘ // 動かしたばかりの駒を 取り返されるようでは、一手詰めは成功しないぜ☆(^~^)(ステイルメイト除く) if (1 < ky.Shogiban.CountKikisuZenbu(optionalOpponent, ms_t1)) { // 移動先升は、相手らいおん の利きも 1つ あるはず。 // 移動先升に 相手の利きが2つあれば、駒を取り返される☆ return(false); } if (!ky.Shogiban.GetBBKoma(aiteHioute.KmRaion).IsIntersect( // 相手のらいおん ky.Shogiban.GetKomanoUgokikata(km_t0, ms_t1) // 移動先での駒の利き )) // 相手らいおん が、移動先での駒の利きの中に居ないんだったら、一手詰め にはならないぜ☆(^~^) { // FIXME: ステイルメイトは考えてないぜ☆(>_<) return(false); } Bitboard bb_idogoKikiNew = new Bitboard();// 移動後の、利き { // 盤上の重ね利きの数を差分更新するぜ☆(^▽^) { ky.Shogiban.N100_HerasuKiki(km_t0, ky.Sindan.CloneKomanoUgoki(km_t0, ms_t0), ky.Sindan); // 移動元の駒の利きを消すぜ☆(^▽^) ky.Shogiban.N100_FuyasuKiki(km_t1, ky.Sindan.CloneKomanoUgoki(km_t1, ms_t1), ky.Sindan); // 移動先の駒の利きを増やすぜ☆(^▽^) } // 移動後の利きを作り直し bb_idogoKikiNew = ky.Shogiban.ToBitboard_KikisuZenbuPositiveNumber(phase, ky.Sindan); // 盤上の重ね利きの数の差分更新を元に戻すぜ☆(^▽^) { //ky.BB_KikiZenbu ky.Shogiban.N100_HerasuKiki(km_t1, ky.Sindan.CloneKomanoUgoki(km_t1, ms_t1), ky.Sindan); // 移動先の駒の利きを減らすぜ☆(^▽^) ky.Shogiban.N100_FuyasuKiki(km_t0, ky.Sindan.CloneKomanoUgoki(km_t0, ms_t0), ky.Sindan); // 移動元の駒の利きを増やすぜ☆(^▽^) } } return (aiteHioute.FriendRaion8KinboBB.Clone() // 相手らいおん が逃げれる、相手らいおんの周りの空白 .Sitdown(ky.Shogiban.GetBBKomaZenbu(optionalOpponent)) // 相手の駒がない升 .Sitdown(bb_idogoKikiNew) // こっちの利きがない升 .IsEmpty()); // がない場合、詰み☆ ; }