/// <summary> /// 駒の利き数☆(^~^) /// 対局者別と、駒別 /// </summary> /// <returns></returns> public static void HyojiKomanoKikiSu(KikiBan.YomiKikiBan yomiKikiBan, StringBuilder hyoji) { hyoji.AppendLine("重ね利き数全部"); hyoji.AppendLine(string.Format("差分更新トータル ▲{0} △{1}", yomiKikiBan.CountKikisuTotalZenbu(Taikyokusya.T1), yomiKikiBan.CountKikisuTotalZenbu(Taikyokusya.T2))); // 対局者別 全部 { // 見出し SpkBanWaku.Setumei_Headers(Conv_Taikyokusya.namaeItiran, hyoji); SpkBanWaku.AppendLine_TopBar(Conv_Taikyokusya.itiran.Length, PureSettei.banYokoHaba, hyoji); // ┌──┬──┬──┐みたいな線☆ for (int dan = 0; dan < PureSettei.banTateHaba; dan++) { // データ表示 SpkBanWaku.AppendLine_Record_Cell4Hankakus1( (Taikyokusya tai, Masu ms) => { int kikisuZenbu = yomiKikiBan.CountKikisuZenbu(tai, ms); return(0 < kikisuZenbu ? string.Format(" {0,2} ", kikisuZenbu) : " "); }, dan, hyoji ); if (dan + 1 < PureSettei.banTateHaba) { SpkBanWaku.AppendLine_MiddleBar(Conv_Taikyokusya.itiran.Length, PureSettei.banYokoHaba, hyoji); // ├──┼──┼──┤みたいな線☆ } } SpkBanWaku.AppendLine_BottomBar(Conv_Taikyokusya.itiran.Length, PureSettei.banYokoHaba, hyoji); // └──┴──┴──┘みたいな線☆ } // 駒別 foreach (Taikyokusya tai in Conv_Taikyokusya.itiran) // 対局者1、対局者2 { foreach (Piece km_tai in Conv_Koma.itiranTai[(int)tai]) { hyoji.Append(SpkBanWaku.CutHeaderBanWidthZenkaku(Conv_Koma.GetName(km_tai))); } hyoji.AppendLine(); SpkBanWaku.AppendLine_TopBar(Conv_Komasyurui.itiran.Length, PureSettei.banYokoHaba, hyoji); for (int dan = 0; dan < PureSettei.banTateHaba; dan++) { SpkBanWaku.AppendLine_Record_Cell4Hankakus3( (Taikyokusya tai1, Komasyurui ks, Masu ms) => { int kikisuKomabetu = yomiKikiBan.CountKikisuKomabetu(Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, tai1), ms); return(0 < kikisuKomabetu ? string.Format(" {0,2} ", kikisuKomabetu) : " "); }, tai, dan, hyoji); if (dan + 1 < PureSettei.banTateHaba) { SpkBanWaku.AppendLine_MiddleBar(Conv_Komasyurui.itiran.Length, PureSettei.banYokoHaba, hyoji); } } SpkBanWaku.AppendLine_BottomBar(Conv_Komasyurui.itiran.Length, PureSettei.banYokoHaba, hyoji); } }
public static void BunkaiMoveUmv() { PureMemory.umv_ss = PureMemory.kifu_moveArray[PureMemory.kifu_endTeme]; // 駒がないところを指していることがないか? PureMemory.umv_ms_t1 = AbstractConvMove.GetDstMasu_WithoutErrorCheck((int)PureMemory.umv_ss); PureMemory.umv_km_t1 = PureMemory.gky_ky.yomiKy.yomiShogiban.yomiIbashoBan.GetBanjoKoma(PureMemory.umv_ms_t1); PureMemory.umv_ks_t1 = Med_Koma.KomaToKomasyurui(PureMemory.umv_km_t1);// 成っているかもしれない☆ Debug.Assert(Conv_Masu.IsBanjoOrError(PureMemory.umv_ms_t1), "error Undo-Begin-6"); Debug.Assert(Conv_Koma.IsOk(PureMemory.umv_km_t1), "error Undo-Begin-7"); if (!AbstractConvMove.IsUtta(PureMemory.umv_ss)) // 指す { PureMemory.umv_ms_t0 = AbstractConvMove.GetSrcMasu_WithoutErrorCheck((int)PureMemory.umv_ss); // 戻し先。 Debug.Assert(Conv_Masu.IsBanjo(PureMemory.umv_ms_t0), "error Undo-Begin-21 #金魚 戻し先が盤上でない?"); PureMemory.umv_mk_t0 = Motigoma.Yososu; if (AbstractConvMove.IsNatta(PureMemory.umv_ss)) // 成っていたとき { PureMemory.umv_ks_t0 = Conv_Komasyurui.ToNarazuCase(PureMemory.umv_ks_t1); // 成る前 } else { PureMemory.umv_ks_t0 = PureMemory.umv_ks_t1;// 成る前、あるいは、成っていない、あるいは もともと にわとり☆ } PureMemory.umv_km_t0 = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(PureMemory.umv_ks_t0, PureMemory.kifu_teban); Debug.Assert(Conv_Koma.IsOk(PureMemory.umv_km_t0), "error Undo-Begin-9 #羊"); Debug.Assert(Conv_Masu.IsBanjoOrError(PureMemory.umv_ms_t0), "error Undo-Begin-8 #颪"); } else// 打つ { PureMemory.umv_ms_t0 = Conv_Masu.masu_error; PureMemory.umv_km_t0 = Piece.Yososu; PureMemory.umv_ks_t0 = Komasyurui.Yososu; PureMemory.umv_mk_t0 = Med_Koma.KomasyuruiAndTaikyokusyaToMotiKoma(PureMemory.umv_ks_t1, PureMemory.kifu_teban); } PureMemory.umv_ks_c = PureMemory.kifu_toraretaKsAr[PureMemory.kifu_endTeme]; if (Komasyurui.Yososu != PureMemory.umv_ks_c) { PureMemory.umv_km_c = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(PureMemory.umv_ks_c, PureMemory.kifu_aiteban); PureMemory.umv_mk_c = Med_Koma.BanjoKomaToMotiKoma(PureMemory.umv_km_c); Debug.Assert(Conv_Koma.IsOk(PureMemory.umv_km_c), "error Undo-Begin-10 #竜巻"); } else { PureMemory.umv_km_c = Piece.Yososu; PureMemory.umv_mk_c = Motigoma.Yososu; } }
/// <summary> /// トライしていれば真☆ /// </summary> /// <returns></returns> public static bool IsTried(Taikyokusya ts) { Piece km = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(Komasyurui.R, ts); switch (ts) { case Taikyokusya.T1: return(PureMemory.gky_ky.yomiKy.yomiShogiban.yomiIbashoBan.ToIsIntersect_Koma(km, BitboardsOmatome.bb_danArray[0])); case Taikyokusya.T2: return(PureMemory.gky_ky.yomiKy.yomiShogiban.yomiIbashoBan.ToIsIntersect_Koma(km, BitboardsOmatome.bb_danArray[PureSettei.banTateHaba - 1])); default: throw new Exception("未定義の手番"); } }
/// <summary> /// 二歩防止 /// </summary> public static void SiborikomiByNifu() { bbTmp_nifu.Clear(); Piece hiyoko = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(Komasyurui.H, PureMemory.kifu_teban); for (int iSuji = 0; iSuji < PureSettei.banYokoHaba; iSuji++) { PureMemory.gky_ky.shogiban.yomiIbashoBan_yoko.ToSet_Koma(hiyoko, bbTmp_nifu); //自分の歩 bbTmp_nifu.Siborikomi(BitboardsOmatome.bb_sujiArray[iSuji]); //調べる筋だけ残す if (!bbTmp_nifu.IsEmpty()) { PureMemory.ssss_bbVar_idosaki_narazu.Sitdown(BitboardsOmatome.bb_sujiArray[iSuji]); } } }
/// <summary> /// タダ捨ての動き /// </summary> /// <param name="ky2"></param> /// <param name="tai1"></param> /// <param name="ms_src"></param> /// <param name="ms_dst"></param> /// <param name="da">打の場合</param> /// <returns></returns> public static bool TadasuteNoUgoki() { // 主なケース // ・移動先の升には、味方の利き(動かす駒の利き除く)がない。 // ・敵の利きに指す、打ち込む // タダ捨ての特殊なケース // // ・移動先の升は 空白☆ // ・移動先の升には、手番らいおん の利きがある☆(味方の利きはあるが、それが らいおん だった場合☆) // ・移動先の升には、相手番の駒の 重ね利きが 2つ以上ある☆ // // これはタダ捨てになる☆ らいおんでは取り返せないので☆ // 「らいおんの利きを除いた利きビットボード」とかあれば便利だろうか☆(>_<)? // if (PureMemory.gky_ky.shogiban.kikiBan.yomiKikiBan.ExistsKikiZenbu(PureMemory.kifu_aiteban, PureMemory.ssss_ugoki_ms_dst)) // 相手の利きがあるところに放り込む { // 移動先の升の、味方の重ね利き の数(これから動かす駒を除く) int kiki_ts1 = PureMemory.gky_ky.shogiban.kikiBan.yomiKikiBan.CountKikisuZenbu(PureMemory.kifu_teban, PureMemory.ssss_ugoki_ms_dst); if (!PureMemory.ssss_ugoki_kakuteiDa) { // 「指」だと、自分の利きの数はカウントしないぜ☆(^▽^)wwwこれから動くからな☆(^▽^)wwww // 「打」だと、数字を-1してはいけないぜ☆ kiki_ts1--; } int kiki_ts2 = PureMemory.gky_ky.shogiban.kikiBan.yomiKikiBan.CountKikisuZenbu(PureMemory.kifu_aiteban, PureMemory.ssss_ugoki_ms_dst); if (0 == kiki_ts1 && 0 < kiki_ts2)//味方の利きがなくて、敵の利きがあれば、タダ捨てだぜ☆(^▽^)www { return(true); } if (1 == kiki_ts1 && 1 < kiki_ts2//味方の利きがあり、敵の利きが2以上あり、 && //その味方はらいおんだった場合、タダ捨てだぜ☆(^▽^)www PureMemory.gky_ky.shogiban.kikiBan.yomiKikiBan.ExistsBBKiki(Med_Koma.KomasyuruiAndTaikyokusyaToKoma(Komasyurui.R, PureMemory.kifu_teban), PureMemory.ssss_ugoki_ms_dst) ) { return(true); } } return(false); }
/// <summary> /// 手番の駒 の8近傍を調べて、利きに飛び込んでいたら真顔で真だぜ☆(^▽^) /// </summary> /// <param name="gky"></param> /// <param name="ms_attacker">相手の攻撃駒の居場所</param> /// <param name="ms_target">狙っている升</param> /// <returns></returns> public static bool IsTobikondaKiki(Taikyokusya irekaeAiteban, Masu ms_attacker, Masu ms_target) { if (PureMemory.gky_ky.yomiKy.yomiShogiban.yomiIbashoBan.ExistsKomaZenbu(irekaeAiteban, ms_attacker)) // 攻撃を仕掛けてくるだろう場所(attackerMs)に相手の駒があることを確認 { Komasyurui ks; if (PureMemory.gky_ky.yomiKy.yomiShogiban.yomiIbashoBan.ExistsKoma(irekaeAiteban, ms_attacker, out ks))// 駒があれば、その駒の種類を確認 { Piece km_attacker = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, irekaeAiteban); // 相手の攻撃駒の利き // ここで飛び利きを判定できるか? return(BitboardsOmatome.KomanoUgokikataYk00.IsIntersect( km_attacker, // 王手してくる駒 ms_attacker, // その駒がいる升 ms_target // 調べている升(王手されている升) )); } } return(false); }
/// <summary> /// 駒の動き☆ /// </summary> /// <param name="komanoUgokikata"></param> /// <param name="hyoji"></param> public static void HyojiKomanoUgoki(KikiBan.YomiKikiBan yomiKikiBan, int masuYososu, StringBuilder hyoji) { for (int ms = 0; ms < masuYososu; ms++) { hyoji.AppendLine($"ます{ ms}"); foreach (Taikyokusya tai in Conv_Taikyokusya.itiran) { // 盤上 YomiBitboard[] bbHairetu = new YomiBitboard[Conv_Komasyurui.itiran.Length]; foreach (Komasyurui ks in Conv_Komasyurui.itiran) { bbHairetu[(int)ks] = new YomiBitboard(BitboardsOmatome.KomanoUgokikataYk00.Clone_Merge( Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, tai), (Masu)ms)); } SpkBan_MultiColumn.Setumei_Bitboard(Med_Koma.GetKomasyuruiNamaeItiran(tai), bbHairetu, " + ", " ", hyoji); hyoji.AppendLine(); } } }
/// <summary> /// 指定の升にいる駒を除く、味方全部の利き☆ /// /// 盤上の駒を指す場合、自分自身が動いてしまうので利きが変わってしまうので、 /// 全部の利きを合成したBBが使えないので、代わりにこの関数を使うんだぜ☆(^~^) /// </summary> /// <param name="ky"></param> /// <param name="ms_nozoku">除きたい駒がいる升</param> /// <returns></returns> public static Bitboard CreateBBTebanKikiZenbu_1KomaNozoku(Masu ms_nozoku) { Bitboard kikiZenbuBB = new Bitboard(); // 味方の駒(変数使いまわし) Bitboard mikataBB = new Bitboard(); foreach (Komasyurui ks in Conv_Komasyurui.itiran) { Piece km_teban = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, PureMemory.kifu_teban); PureMemory.gky_ky.shogiban.yomiIbashoBan_yoko.ToSet_Koma(km_teban, mikataBB); Masu ms; while (mikataBB.Ref_PopNTZ(out ms)) { if (ms_nozoku != ms)//この駒を除く { BitboardsOmatome.KomanoUgokikataYk00.ToStandup_Merge(km_teban, ms, kikiZenbuBB); } } } return(kikiZenbuBB); }
/// <summary> /// 局面(駒の配置)の一致判定だぜ☆(^▽^) /// /// 重い処理がある☆ 探索で使うような内容じゃないぜ☆(^~^)開発中用だぜ☆(^▽^) /// </summary> /// <param name="motiKomas1"></param> /// <returns></returns> public static bool Equals_ForDevelop(Shogiban shogiban_hikaku, int[] motiKomas1) { Debug.Assert(PureMemory.gky_ky.yomiKy.yomiMotigomaItiran.GetArrayLength() == motiKomas1.Length, "局面の一致判定"); // 盤上の一致判定 for (int iTai = 0; iTai < Conv_Taikyokusya.itiran.Length; iTai++) { Taikyokusya tai = (Taikyokusya)iTai; if (!PureMemory.gky_ky.shogiban.ibashoBan_yk00.yomiIbashoBan.Equals_KomaZenbu_ForDevelop(tai, shogiban_hikaku.ibashoBan_yk00.yomiIbashoBan)) { return(false); } for (int iKs = 0; iKs < Conv_Komasyurui.itiran.Length; iKs++) { Komasyurui ks = Conv_Komasyurui.itiran[iKs]; Piece km = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, tai); if (!PureMemory.gky_ky.shogiban.ibashoBan_yk00.yomiIbashoBan.Equals_Koma_ForDevelop(km, shogiban_hikaku.ibashoBan_yk00.yomiIbashoBan)) { return(false); } } } // 持ち駒の一致判定 for (int iMk = 0; iMk < Conv_Motigoma.itiran.Length; iMk++) { if (PureMemory.gky_ky.yomiKy.yomiMotigomaItiran.Count((Motigoma)iMk) != motiKomas1[iMk]) { return(false); } } return(true); }
/// <summary> /// 勝負なし調査☆ /// 指し次いではいけない局面なら真だぜ☆(^~^) /// (A)自分のらいおんがいない☆ /// (B)相手のらいおんがいない☆ /// (C)自分のらいおんがトライしている☆ /// (D)相手のらいおんがトライしている☆ /// </summary> /// <returns></returns> public static bool IsSyobuNasi() { Piece raionJibun = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(Komasyurui.R, PureMemory.kifu_teban); Piece raionAite = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(Komasyurui.R, PureMemory.kifu_aiteban); // (A)自分のらいおんがいない☆ if (PureMemory.gky_ky.shogiban.ibashoBan_yk00.yomiIbashoBan.IsEmptyKoma(raionJibun)) { return(true); } // (B)相手のらいおんがいない☆ if (PureMemory.gky_ky.shogiban.ibashoBan_yk00.yomiIbashoBan.IsEmptyKoma(raionAite)) { return(true); } // (C)自分のらいおんがトライしている☆ Bitboard bbTmp = new Bitboard(); bbTmp.Set(BitboardsOmatome.bb_try[PureMemory.kifu_nTeban]); PureMemory.gky_ky.yomiKy.yomiShogiban.yomiIbashoBan.ToSelect_Koma(raionJibun, bbTmp); if (!bbTmp.IsEmpty()) { return(true); } // (D)相手のらいおんがトライしている☆ bbTmp.Set(BitboardsOmatome.bb_try[PureMemory.kifu_nAiteban]); PureMemory.gky_ky.yomiKy.yomiShogiban.yomiIbashoBan.ToSelect_Koma(raionAite, bbTmp); if (!bbTmp.IsEmpty()) { return(true); } return(false); }
/// <summary> /// コンピューターの思考の開始だぜ☆(^▽^) /// ここが入り口だぜ☆(^~^) /// /// 最善手は yomisuji[0] に入っているぜ☆(^▽^) /// </summary> /// <returns></returns> public static bool TryFail_Go(StringBuilder hyoji) { tmp_bestHyokaSu.Clear(); if (PureMemory.gky_ky.shogiban.yomiIbashoBan_yoko.IsEmpty(Med_Koma.KomasyuruiAndTaikyokusyaToKoma(Komasyurui.R, PureMemory.kifu_teban))) { // 自分のらいおんがいない局面の場合、投了☆ #if DEBUG PureMemory.tnsk_syuryoRiyu = TansakuSyuryoRiyu.JibunRaionInai; PureMemory.tnsk_kohoMove = Move.Toryo; tmp_bestHyokaSu.tumeSu = Conv_Tumesu.Stalemate; #endif } else { //──────────────────────────────────────── // 反復深化ループ☆(^~^) //──────────────────────────────────────── Move currMove = Move.Toryo; tmp_currHyokaSu.Clear(); for (HanpukuSinka.happaenoFukasa = 1; // まだ思考に時間を使っていい !ComSettei.timeManager.IsTimeOver_IterationDeeping() ; HanpukuSinka.happaenoFukasa++) { Debug.Assert(0 <= HanpukuSinka.happaenoFukasa && HanpukuSinka.happaenoFukasa < PureMemory.ssss_moveList.Length, ""); if (ComSettei.saidaiFukasa < HanpukuSinka.happaenoFukasa) { // 最大深さを超えた場合 Util_Joho.JohoMatome( HanpukuSinka.happaenoFukasa, tmp_bestHyokaSu, hyoji #if DEBUG , "SaidaiFukasaGoe" #endif ); break; } // ここでは現在の局面に盤面を戻してあると思えだぜ☆(^~^) Debug.Assert(1 <= HanpukuSinka.happaenoFukasa && HanpukuSinka.happaenoFukasa < PureMemory.ssss_moveList.Length, ""); ComSettei.SetSikoJikan_KonkaiNoTansaku();//思考時間(ランダム込み)を確定させるぜ☆(^~^) PureMemory.SetTnskHyoji(hyoji); //カウントダウン式の数字☆(^▽^) 反復深化探索の1週目は 1、2週目は 2 だぜ☆(^▽^) PureMemory.SetTnskFukasa(HanpukuSinka.happaenoFukasa); Tansaku_( out currMove, out tmp_currHyokaSu// 相手番の指し手の評価値が入ってくるぜ☆(^~^) ); // TODO: 1手も読めていなければ、さっさと投了したいぜ☆(^~^) if (tmp_currHyokaSu.isHaki) { // 時間切れ等の中途半端探索のとき☆ // この計算結果は、無視するぜ☆(^~^) // ここに来るときは探索終了だぜ☆(^~^) break;// 読みを終了しようなんだぜ☆ } else { // 更新☆(^▽^) PureMemory.tnsk_itibanFukaiNekkoKaranoFukasa_JohoNoTameni = HanpukuSinka.happaenoFukasa; PureMemory.tnsk_kohoMove = currMove; tmp_bestHyokaSu.ToSet(tmp_currHyokaSu); if (Conv_Tumesu.CatchRaion == tmp_bestHyokaSu.tumeSu) { // 「0手詰められ」が返ってきているなら、負けました、をいう場面だぜ☆ #if DEBUG PureMemory.tnsk_syuryoRiyu = TansakuSyuryoRiyu.Minus2TeTumerare; #endif break;// 読みを終了しようなんだぜ☆ } } }//ループ // ストップウォッチ ComSettei.timeManager.stopwatch_Tansaku.Stop(); } //──────────────────────────────────────── // 詰め、詰められ //──────────────────────────────────────── { Util_Taikyoku.Update( tmp_bestHyokaSu, PureMemory.kifu_teban ); } //──────────────────────────────────────── // 指し手は決まった☆(^~^) // 指して、局面を進めておくぜ☆(^~^) //──────────────────────────────────────── // 何これ if (DoMoveOpe.TryFailDoMoveAll( PureMemory.tnsk_kohoMove, MoveType.N00_Karappo #if DEBUG , PureSettei.fenSyurui , (IDebugMojiretu)hyoji , true//アサート抑制 , "TryFail_Go(1)" #endif )) { return(Pure.FailTrue("GenkyokuOpe.Try_DoMove(1)")); } // 手番を進めるぜ☆(^~^) MoveGenAccessor.AddKifu(PureMemory.tnsk_kohoMove, MoveType.N00_Karappo, PureMemory.dmv_ks_c); #if DEBUG Util_Tansaku.Snapshot("Go(1)確定指し", PureMemory.tnsk_kohoMove); #endif // 指し手が決まったときにも、強制情報表示 { if (0 == PureMemory.tnsk_itibanFukaiNekkoKaranoFukasa_JohoNoTameni) { #if DEBUG hyoji.AppendLine($@"0手投了してないかだぜ☆?(^~^) tansakuSyuryoRiyu=[{PureMemory.tnsk_syuryoRiyu}] Option_Application.Optionlist.SaidaiFukasa=[{ComSettei.saidaiFukasa}] Option_Application.Optionlist.SikoJikan_KonkaiNoTansaku=[{ComSettei.sikoJikan_KonkaiNoTansaku}] Option_Application.Optionlist.SikoJikan=[{ComSettei.sikoJikan}] Option_Application.Optionlist.SikoJikanRandom=[{ComSettei.sikoJikanRandom}] "); return(Pure.FailTrue("0手投了")); #endif } } #if DEBUG hyoji.AppendLine(string.Format("bestMove: [{0}] ss={1}", PureMemory.tnsk_kaisiTeme, SpkMove.ToString_Fen(PureSettei.fenSyurui, PureMemory.tnsk_kohoMove) )); #endif return(Pure.SUCCESSFUL_FALSE); }
/// <summary> /// 被王手されている情報を調べるぜ☆(^~^) /// 手番側を設定するんだぜ☆(^~^) /// </summary> /// <param name="gky"></param> /// <param name="isHouimouCheck">包囲網チェック</param> /// <returns></returns> public static void Tukurinaosi_1( Taikyokusya irekaeTeban, // 入れ替える Taikyokusya irekaeAiteban, // 入れ替える bool isHouimouCheck ) { bbVar_nigemiti.Clear(); PureMemory.hot_bb_checkerAr[(int)irekaeTeban].Clear(); PureMemory.hot_bb_nigereruAr[(int)irekaeTeban].Clear(); PureMemory.hot_outeKomasCountAr[(int)irekaeTeban] = 0; PureMemory.hot_isNigerarenaiCheckerAr[(int)irekaeTeban] = false; PureMemory.hot_bb_nigemitiWoFusaideiruAiteNoKomaAr[(int)irekaeTeban].Clear(); //らいおんが盤上にいないこともあるぜ☆(^▽^) if (Conv_Masu.masu_error != PureMemory.hot_ms_raionAr[(int)irekaeTeban]) { // 手番らいおんの8近傍の升☆(^▽^) Debug.Assert((int)Komasyurui.R < Conv_Komasyurui.itiran.Length, ""); Debug.Assert((int)irekaeTeban < Conv_Taikyokusya.itiran.Length, ""); Debug.Assert((int)irekaeAiteban < Conv_Taikyokusya.itiran.Length, ""); Debug.Assert((int)PureMemory.hot_ms_raionAr[(int)irekaeTeban] < PureSettei.banHeimen, ""); // らいおんが逃げれる8近傍の升☆(^▽^) // <編集> PureMemory.hot_bb_nigereruAr[(int)irekaeTeban].Set(PureMemory.hot_bb_raion8KinboAr[(int)irekaeTeban]); // <影響> PureMemory.gky_ky.yomiKy.yomiShogiban.yomiIbashoBan.ToSitdown_KomaZenbu(irekaeTeban, PureMemory.hot_bb_nigereruAr[(int)irekaeTeban]); PureMemory.gky_ky.yomiKy.yomiShogiban.yomiKikiBan.ToSitdown_BBKikiZenbu(irekaeAiteban, PureMemory.hot_bb_nigereruAr[(int)irekaeTeban]); // 手番の らいおん の // - 8近傍 // - タテ筋 // - ヨコ筋 // - 左上がり筋 // - 左下がり筋 // を調べて、王手をかけている駒を一覧するぜ☆(^▽^) Masu ms_checker; bbVar_checker.Set(PureMemory.hot_bb_raion8KinboAr[(int)irekaeTeban]); // きりんとぞうは、先後同形☆(^~^) BitboardsOmatome.KomanoUgokikataYk00.ToStandup_Merge(Piece.R1, PureMemory.hot_ms_raionAr[(int)irekaeTeban], bbVar_checker); BitboardsOmatome.KomanoUgokikataYk00.ToStandup_Merge(Piece.B1, PureMemory.hot_ms_raionAr[(int)irekaeTeban], bbVar_checker); // いのししは先後別☆(^~^) switch (irekaeAiteban) { case Taikyokusya.T1: BitboardsOmatome.KomanoUgokikataYk00.ToStandup_Merge(Piece.L1, PureMemory.hot_ms_raionAr[(int)irekaeTeban], bbVar_checker); break; case Taikyokusya.T2: BitboardsOmatome.KomanoUgokikataYk00.ToStandup_Merge(Piece.L2, PureMemory.hot_ms_raionAr[(int)irekaeTeban], bbVar_checker); break; } while (bbVar_checker.Ref_PopNTZ(out ms_checker))// 立っているビットを降ろすぜ☆ { if (IsTobikondaKiki(irekaeAiteban, ms_checker, PureMemory.hot_ms_raionAr[(int)irekaeTeban])) { // <編集> PureMemory.hot_bb_checkerAr[(int)irekaeTeban].Standup(ms_checker); PureMemory.hot_outeKomasCountAr[(int)irekaeTeban]++; } } // 8方向に逃げ場がない場合は、王手を掛けてきている駒(チェッカー)を、 // ~~~~~~~~~~~~~~~~~~~~~~~~ // 必ず取り返して、その場にいようぜ☆ PureMemory.hot_isNigerarenaiCheckerAr[(int)irekaeTeban] = (0 < PureMemory.hot_outeKomasCountAr[(int)irekaeTeban] && PureMemory.hot_bb_nigereruAr[(int)irekaeTeban].IsEmpty()); if (isHouimouCheck) { // 編集 // らいおんが逃げようとする8マス☆(^~^) bbVar_nigemiti.Set(PureMemory.hot_bb_raion8KinboAr[(int)irekaeTeban]); // 影響 // 相手の利きで塞がれているところを消す☆(^~^) PureMemory.gky_ky.yomiKy.yomiShogiban.yomiKikiBan.ToSelect_BBKikiZenbu(irekaeAiteban, bbVar_nigemiti); // 自分の駒があるところを消す☆(^~^) PureMemory.gky_ky.shogiban.ibashoBan_yk00.yomiIbashoBan.ToSitdown_KomaZenbu(irekaeTeban, bbVar_nigemiti); Masu ms_fusagiMiti; while (bbVar_nigemiti.Ref_PopNTZ(out ms_fusagiMiti)) { // 塞がれている升の8近傍に、塞いでいる駒がいるだろう☆ foreach (Komasyurui ks_fusagi8Kinbo in Conv_Komasyurui.itiran) { // <編集> // 8近傍のそれぞれのマスについて、 // 相手の駒がそこに利きを利かしているかどうかを調べるには、 // 8近傍に自分の駒を置いて利きを調べれば、 // そこに利かしている相手の駒の場所が分かるぜ☆(^▽^) BitboardsOmatome.KomanoUgokikataYk00.ToSet_Merge( Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks_fusagi8Kinbo, irekaeTeban), ms_fusagiMiti, bbVar_kikasiteiruKoma ); // <影響> PureMemory.gky_ky.shogiban.ibashoBan_yk00.yomiIbashoBan.ToSelect_Koma(Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks_fusagi8Kinbo, irekaeAiteban), bbVar_kikasiteiruKoma); Masu ms_fusagi8KinboKoma; while (bbVar_kikasiteiruKoma.Ref_PopNTZ(out ms_fusagi8KinboKoma)) { PureMemory.hot_bb_nigemitiWoFusaideiruAiteNoKomaAr[(int)irekaeTeban].Standup(ms_fusagi8KinboKoma); } } } } } // 王手を掛けている駒を数えるぜ☆(^~^) if (PureMemory.hot_outeKomasCountAr[(int)irekaeTeban] < 1) { // 王手を掛けられていないか、 // 王手は掛けられているが逃げれる場合は、 // クリアー PureMemory.hot_bb_nigeroAr[(int)irekaeTeban].Clear(); } }
/// <summary> /// 改造Fen /// 例: fen kr1/1h1/1H1/1R1 K2z 1 /// 盤上の駒配置、持ち駒の数、手番の対局者 /// </summary> public static void AppendFenTo( FenSyurui f, StringBuilder syuturyoku) { syuturyoku.Append(f == FenSyurui.sfe_n ? "sfen " : "fen "); // 盤上 { int space = 0; for (int iDan = 0; iDan < PureSettei.banTateHaba; iDan++) { for (int iSuji = 0; iSuji < PureSettei.banYokoHaba; iSuji++) { Masu ms = (Masu)(iDan * PureSettei.banYokoHaba + iSuji); Taikyokusya tai; if (PureMemory.gky_ky.yomiKy.yomiShogiban.yomiIbashoBan.ExistsKomaZenbu(ms, out tai)) { if (0 < space) { syuturyoku.Append(space.ToString()); space = 0; } Komasyurui ks; PureMemory.gky_ky.yomiKy.yomiShogiban.yomiIbashoBan.ExistsKoma(tai, ms, out ks); SpkKoma.AppendFenTo(f, Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, tai), syuturyoku); } else { space++; } } if (0 < space) { syuturyoku.Append(space.ToString()); space = 0; } if (iDan + 1 < PureSettei.banTateHaba) { syuturyoku.Append("/"); } } } syuturyoku.Append(" "); // 持駒 if (PureMemory.gky_ky.yomiKy.yomiMotigomaItiran.IsEmpty()) { syuturyoku.Append("-"); } else { for (int iMk = 0; iMk < Conv_Motigoma.itiran.Length; iMk++) { int cnt = PureMemory.gky_ky.yomiKy.yomiMotigomaItiran.Count((Motigoma)iMk); if (0 < cnt) { syuturyoku.Append( cnt == 1 ? SpkMotiKoma.GetFen(f, (Motigoma)iMk)// 1個の時は数字は付かないぜ☆(^~^) : cnt.ToString() + SpkMotiKoma.GetFen(f, (Motigoma)iMk) ); } } } // 手番 syuturyoku.Append(" "); syuturyoku.Append(SpkTaikyokusya.ToFen(f, PureMemory.kifu_teban)); //// moves //if (syuturyokuMoves) //{ //} }
/// <summary> /// 駒の利き /// </summary> /// <param name="bbItiran_kikiZenbu"></param> /// <param name="bbItiran_kikiKomabetu"></param> /// <param name="hyoji"></param> public static void HyojiKomanoKiki(KikiBan.YomiKikiBan yomiKikiBan, StringBuilder hyoji) { Debug.Assert(yomiKikiBan.IsActiveBBKiki(), ""); // 対局者別 { hyoji.AppendLine("利き(対局者別)"); YomiBitboard[] bbHairetu = new YomiBitboard[Conv_Taikyokusya.itiran.Length]; foreach (Taikyokusya tai in Conv_Taikyokusya.itiran) { bbHairetu[(int)tai] = new YomiBitboard(yomiKikiBan.CloneBBKikiZenbu(tai)); } SpkBan_MultiColumn.Setumei_Bitboard(Conv_Taikyokusya.namaeItiran, bbHairetu, " + ", " ", hyoji); } // 駒別 { hyoji.AppendLine("利き(駒別)"); foreach (Taikyokusya tai in Conv_Taikyokusya.itiran)// 対局者1、対局者2 { // 盤上 YomiBitboard[] bbHairetu = new YomiBitboard[Conv_Komasyurui.itiran.Length]; foreach (Komasyurui ks in Conv_Komasyurui.itiran) { bbHairetu[(int)ks] = new YomiBitboard(yomiKikiBan.CloneBBKiki(Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, tai))); } SpkBan_MultiColumn.Setumei_Bitboard(Med_Koma.GetKomasyuruiNamaeItiran(tai), bbHairetu, " + ", " ", hyoji); } } }
/// <summary> /// 仲間を支えていた駒が離れたら真だぜ☆(^▽^)www /// /// 利きテーブルをいじっているが、更新したいわけではないので、使い終わったら元に戻すぜ☆(^~^) /// </summary> /// <param name="out_ret"></param> /// <param name="ms_t0">移動元</param> /// <param name="ms_t1">移動先</param> /// <returns></returns> public static bool IsMisuteruUgoki() { // 升にある駒種類 Komasyurui ks_t0; if (PureMemory.gky_ky.shogiban.ibashoBan_yk00.yomiIbashoBan.ExistsKoma(PureMemory.kifu_teban, PureMemory.ssss_ugoki_ms_src, out ks_t0)) { } Piece km_t0 = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks_t0, PureMemory.kifu_teban); Piece km_t1 = km_t0; //FIXME:成りを考慮してないぜ☆(>_<) int sasaeBeforeMove = 0; // 移動前に、動こうとしている駒を支えている味方の数 int sasaeAfterMove = 0; // 移動後の、動いた駒を支えている味方の数 // 移動前の駒の動き(2個作っておく) Bitboard bbConst_kiki0 = BitboardsOmatome.KomanoUgokikataYk00.Clone_Merge(km_t0, PureMemory.ssss_ugoki_ms_src); Bitboard bbVar_kiki = bbConst_kiki0.Clone(); if (!bbConst_kiki0.IsEmpty()) { // 移動する前の、利き先の 利きの数を数えておこうぜ☆(^▽^) Masu ms_kiki; while (bbVar_kiki.Ref_PopNTZ(out ms_kiki)) { // 0以上なら駒の取り合いで勝つぜ☆(^▽^) // 利き重ね = 自分の利き数 - 相手の利き数 int kasaneGake = PureMemory.gky_ky.shogiban.kikiBan.yomiKikiBan.CountKikisuZenbu(PureMemory.kifu_teban, ms_kiki) - PureMemory.gky_ky.shogiban.kikiBan.yomiKikiBan.CountKikisuZenbu(PureMemory.kifu_aiteban, ms_kiki); if (0 < kasaneGake) { sasaeBeforeMove++; } } //──────────────────────────────────────── // 駒は動かさず、移動前の利きを消す(減らす)ぜ☆(^▽^) //──────────────────────────────────────── bbVar_kiki.Set(bbConst_kiki0); //ビットボード使い回し PureMemory.gky_ky.shogiban.kikiBan.TorinozokuKiki(km_t0, bbVar_kiki); } // 移動先での駒の動き Bitboard bbConst_kiki1 = BitboardsOmatome.KomanoUgokikataYk00.Clone_Merge(km_t1, PureMemory.ssss_ugoki_ms_dst); if (!bbConst_kiki1.IsEmpty()) { // 駒を移動させた想定で、利きの数を増やすぜ☆(^▽^) bbVar_kiki.Set(bbConst_kiki1); //ビットボード使い回し PureMemory.gky_ky.shogiban.kikiBan.OkuKiki(km_t1, bbVar_kiki); // 移動した後の、利き先の 利きの数を数えておこうぜ☆(^▽^) bbVar_kiki.Set(bbConst_kiki1); Masu ms_kiki; while (bbVar_kiki.Ref_PopNTZ(out ms_kiki)) { // 0以上なら駒の取り合いで勝つぜ☆(^▽^) // 利き重ね = 自分の利き数 - 相手の利き数 int kasaneGake = PureMemory.gky_ky.shogiban.kikiBan.yomiKikiBan.CountKikisuZenbu(PureMemory.kifu_teban, ms_kiki) - PureMemory.gky_ky.shogiban.kikiBan.yomiKikiBan.CountKikisuZenbu(PureMemory.kifu_aiteban, ms_kiki); if (0 < kasaneGake) { sasaeAfterMove++; } } } //──────────────────────────────────────── // 利き数表をいじったんで、元に戻しておこうぜ☆(^▽^) //──────────────────────────────────────── { bbVar_kiki.Set(bbConst_kiki1); if (!bbVar_kiki.IsEmpty()) { // 増やした分の重ね利きを減らして、元に戻すぜ☆(^▽^) //ビットボード使い回し PureMemory.gky_ky.shogiban.kikiBan.TorinozokuKiki(km_t1, bbVar_kiki); } } { bbVar_kiki.Set(bbConst_kiki0); // 減らした分の重ね利きを増やして、元に戻すぜ☆(^▽^) //ビットボード使い回し PureMemory.gky_ky.shogiban.kikiBan.OkuKiki(km_t0, bbVar_kiki); } return(sasaeBeforeMove - sasaeAfterMove < 0); }
/// <summary> /// 指し手情報を分解するぜ☆(^~^) /// 駒を動かす方を手番、相手を相手番と考えるぜ☆(^~^) /// </summary> public static void BunkaiMoveDmv(Move ss) { // // 動かす駒を t0 と呼ぶとする。 // 移動元を t0、移動先を t1 と呼ぶとする。 // 取られる駒を c と呼ぶとする。 // 取られる駒の元位置は t1 、駒台は 3 と呼ぶとする。 // // 変数をグローバルに一時退避 // 移動先升 PureMemory.dmv_ms_t1 = AbstractConvMove.GetDstMasu_WithoutErrorCheck((int)ss); // あれば、移動先の相手の駒(取られる駒; capture) PureMemory.dmv_km_c = PureMemory.gky_ky.yomiKy.yomiShogiban.yomiIbashoBan.GetBanjoKoma(PureMemory.kifu_aiteban, PureMemory.dmv_ms_t1); PureMemory.dmv_ks_c = Med_Koma.KomaToKomasyurui(PureMemory.dmv_km_c); PureMemory.dmv_mk_c = Med_Koma.BanjoKomaToMotiKoma(PureMemory.dmv_km_c); if (AbstractConvMove.IsUtta(ss)) { // 打 PureMemory.dmv_ms_t0 = Conv_Masu.masu_error; // 指し手から「持駒」を判別 PureMemory.dmv_mks_t0 = AbstractConvMove.GetUttaKomasyurui(ss); PureMemory.dmv_mk_t0 = Med_Koma.MotiKomasyuruiAndTaikyokusyaToMotiKoma(PureMemory.dmv_mks_t0, PureMemory.kifu_teban); // 「持駒」から「駒」へ変換 PureMemory.dmv_km_t0 = Med_Koma.MotiKomasyuruiAndTaikyokusyaToKoma(PureMemory.dmv_mks_t0, PureMemory.kifu_teban); // 持ち駒は t0 も t1 も同じ。 PureMemory.dmv_km_t1 = PureMemory.dmv_km_t0; PureMemory.dmv_ks_t0 = Med_Koma.MotiKomasyuruiToKomasyrui(PureMemory.dmv_mks_t0); //おまとめ☆(^~^) PureMemory.dmv_ks_t1 = PureMemory.dmv_ks_t0; //追加 //#if DEBUG // if (!gky.ky.motiKomas.sindanMK.HasMotiKoma(mk_t0)) // { // CommandK.Ky(isSfen, "ky", gky, syuturyoku); // Util_Machine.Flush(syuturyoku); // } //#endif Debug.Assert(PureMemory.gky_ky.motigomaItiran.yomiMotigomaItiran.HasMotigoma(PureMemory.dmv_mk_t0), $"持っていない駒を打つのか☆(^~^)!? mks_src=[{ PureMemory.dmv_mks_t0 }] mk_utu=[{ PureMemory.dmv_mk_t0 }]"); } else { // 指し PureMemory.dmv_ms_t0 = AbstractConvMove.GetSrcMasu_WithoutErrorCheck((int)ss); PureMemory.dmv_km_t0 = PureMemory.gky_ky.yomiKy.yomiShogiban.yomiIbashoBan.GetBanjoKoma(PureMemory.dmv_ms_t0); PureMemory.dmv_ks_t0 = Med_Koma.KomaToKomasyurui(PureMemory.dmv_km_t0);//移動元の駒の種類 PureMemory.dmv_mks_t0 = MotigomaSyurui.Yososu; PureMemory.dmv_mk_t0 = Motigoma.Yososu; if (AbstractConvMove.IsNatta(ss)) // 駒が成るケース { PureMemory.dmv_ks_t1 = Conv_Komasyurui.ToNariCase(PureMemory.dmv_ks_t0); PureMemory.dmv_km_t1 = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(PureMemory.dmv_ks_t1, PureMemory.kifu_teban); } else // 駒が成らないケース { PureMemory.dmv_km_t1 = PureMemory.gky_ky.yomiKy.yomiShogiban.yomiIbashoBan.GetBanjoKoma(PureMemory.dmv_ms_t0); PureMemory.dmv_ks_t1 = PureMemory.dmv_ks_t0; } } }
public static void SetSsssUgokiKm(Piece km) { ssss_ugoki_km_ = km; ssss_ugoki_ks_ = Med_Koma.KomaToKomasyurui(km); ssss_ugoki_sakasaKm_ = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ssss_ugoki_ks_, kifu_aiteban); }
/// <summary> /// 一手詰めの局面かどうか調べるぜ☆(^▽^) /// /// 盤上の駒を動かすのか、駒台の駒を打つのかによって、利き の形が異なるぜ☆(^~^) /// /// 自分が一手詰めを掛けられるから、この指し手は作らないでおこう、といった使い方がされるぜ☆(^▽^) /// /// FIXME: 成りを考慮してない /// </summary> /// <param name="ky2"></param> /// <param name="ms_t0">移動元。持ち駒の場合、エラー値</param> /// <param name="ms_t1">移動先</param> /// <param name="tebanHioute"></param> /// <returns></returns> public static bool CheckBegin_Tume1_BanjoKoma() { Debug.Assert(Conv_Masu.IsBanjo(PureMemory.ssss_ugoki_ms_dst), "升エラー"); if (!PureSettei.ittedumeTukau) { return(false); } // 動かす駒 Komasyurui ks_t0; if (!PureMemory.gky_ky.yomiKy.yomiShogiban.yomiIbashoBan.ExistsKoma(PureMemory.kifu_teban, PureMemory.ssss_ugoki_ms_src, out ks_t0)) { // エラー。盤上の駒ではないのかも☆(^~^) throw new Exception(Interproject.project.Owata("TryFail_Ittedume_BanjoKoma gky.ky.shogiban.ibashoBan.ExistsBBKoma(1)", PureMemory.tnsk_hyoji)); } Piece km_t0 = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks_t0, PureMemory.kifu_teban); Piece km_t1 = km_t0; // FIXME: 成りを考慮していないぜ☆(>_<) // A B C // ┌──┬──┬──┐ //1│ │▽ら│ │ // ├──┼──┼──┤ //2│▲き│ │▲き│ // ├──┼──┼──┤ //3│ │▲に│▲ら│ // ├──┼──┼──┤ //4│▲ぞ│▲ひ│▲ぞ│ // └──┴──┴──┘ // 動かしたばかりの駒を 取り返されるようでは、一手詰めは成功しないぜ☆(^~^)(ステイルメイト除く) if (1 < PureMemory.gky_ky.shogiban.kikiBan.yomiKikiBan.CountKikisuZenbu(PureMemory.kifu_aiteban, PureMemory.ssss_ugoki_ms_dst)) { // 移動先升は、相手らいおん の利きも 1つ あるはず。 // 移動先升に 相手の利きが2つあれば、駒を取り返される☆ return(false); } if (!PureMemory.gky_ky.shogiban.yomiIbashoBan_yoko.IsIntersect(Med_Koma.ToRaion(PureMemory.kifu_aiteban), // 相手のらいおん BitboardsOmatome.KomanoUgokikataYk00.Clone_Merge(km_t0, PureMemory.ssss_ugoki_ms_dst) // 移動先での駒の利き )) // 相手らいおん が、移動先での駒の利きの中に居ないんだったら、一手詰め にはならないぜ☆(^~^) { // FIXME: ステイルメイトは考えてないぜ☆(>_<) return(false); } Bitboard bb_idogoKikiNew = new Bitboard();// 移動後の、利き { // 盤上の重ね利きの数を差分更新するぜ☆(^▽^) // 移動元の駒の利きを消すぜ☆(^▽^) PureMemory.gky_ky.shogiban.kikiBan.TorinozokuKiki(km_t0, PureMemory.ssss_ugoki_ms_src); // 現局面より 利き が減っているのが正しい // 移動先の駒の利きを増やすぜ☆(^▽^) PureMemory.gky_ky.shogiban.kikiBan.OkuKiki(km_t1, PureMemory.ssss_ugoki_ms_dst); // ここで、現行の利きは変更されているぜ☆(^~^)駒は移動していないので、再計算の駒配置は 現行の利きと異なるぜ☆(^~^) // 移動後の利きを作り直し bb_idogoKikiNew = PureMemory.gky_ky.shogiban.kikiBan.RefBB_FromKikisuZenbuPositiveNumber(PureMemory.kifu_teban); // 盤上の重ね利きの数の差分更新を元に戻すぜ☆(^▽^) { // 移動先の駒の利きを減らすぜ☆(^▽^) PureMemory.gky_ky.shogiban.kikiBan.TorinozokuKiki(km_t1, PureMemory.ssss_ugoki_ms_dst); // 駒の利きを減らしているぜ☆(^~^) 駒は減っていないので、再計算すると結果が異なるぜ☆(^~^) // 移動元の駒の利きを増やすぜ☆(^▽^) PureMemory.gky_ky.shogiban.kikiBan.OkuKiki(km_t0, PureMemory.ssss_ugoki_ms_src); } } Bitboard bb1 = PureMemory.hot_bb_raion8KinboAr[PureMemory.kifu_nAiteban].Clone(); // 相手らいおん が逃げれる、相手らいおんの周りの空白 PureMemory.gky_ky.shogiban.ibashoBan_yk00.yomiIbashoBan.ToSitdown_KomaZenbu(PureMemory.kifu_aiteban, bb1); // 相手の駒がない升 return (bb1.Sitdown(bb_idogoKikiNew) // こっちの利きがない升 .IsEmpty()); // がない場合、詰み☆ ; }
/// <summary> /// 相手番らいおん の逃げ道を開けてしまう、手番側の悪手かどうか調べるぜ☆(^▽^) /// </summary> /// <returns></returns> public static bool IsNigemitiWoAkeru() { if (PureMemory.hot_bb_nigemitiWoFusaideiruAiteNoKomaAr[PureMemory.kifu_nAiteban].IsOff(PureMemory.ssss_ugoki_ms_src)) { // 逃げ道を塞いでいる駒ではないのなら、スルーするぜ☆(^▽^) return(false);//正常 } // 手番らいおん の8近傍 のどこかに、重ね利きの数 0 が出来ていれば、 // 逃げ道を開けると判定するぜ☆(^▽^) bool akeru = false; Piece km0_teban = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(PureMemory.ssss_ugoki_ks, PureMemory.kifu_teban); Piece km1_teban = km0_teban;// FIXME: 成りを考慮していない //──────────────────────────────────────── // (1)利き表をいじる前☆(^▽^) //──────────────────────────────────────── // 2回以上使う Bitboard bbConst_kiki0 = BitboardsOmatome.KomanoUgokikataYk00.Clone_Merge(km0_teban, PureMemory.ssss_ugoki_ms_src); Bitboard bbVar_kiki = bbConst_kiki0.Clone(); if (!bbVar_kiki.IsEmpty()) { //──────────────────────────────────────── // (2)動く前の、駒の利きを、利き表から減らすぜ☆(^▽^) //──────────────────────────────────────── //ビットボード使い回し PureMemory.gky_ky.shogiban.kikiBan.TorinozokuKiki(km0_teban, bbVar_kiki); // FIXME: ここで 利きの数が減っている必要がある } Bitboard kikiBB1_const = BitboardsOmatome.KomanoUgokikataYk00.Clone_Merge(km1_teban, PureMemory.ssss_ugoki_ms_dst); if (!kikiBB1_const.IsEmpty()) { bbVar_kiki.Set(kikiBB1_const); //──────────────────────────────────────── // (3)動いた後の、駒の動きを、利き表へ足すぜ☆(^▽^) //──────────────────────────────────────── //ビットボード使い回し PureMemory.gky_ky.shogiban.kikiBan.OkuKiki(km1_teban, bbVar_kiki); } // 動いたことで、らいおんの逃げ道を塞いでいた駒が、らいおんの逃げ道を空けてしまうか☆(^~^) Bitboard nigemitiBB = new Bitboard(); nigemitiBB.Set(PureMemory.hot_bb_raion8KinboAr[PureMemory.kifu_nAiteban]); PureMemory.gky_ky.shogiban.ibashoBan_yk00.yomiIbashoBan.ToSitdown_KomaZenbu(PureMemory.kifu_aiteban, nigemitiBB); Masu ms_nigemiti; while (nigemitiBB.Ref_PopNTZ(out ms_nigemiti)) { // 手番の利きが無くなったか☆(^▽^) if (0 == PureMemory.gky_ky.yomiKy.yomiShogiban.yomiKikiBan.CountKikisuZenbu(PureMemory.kifu_teban, ms_nigemiti)) { akeru = true; // (^▽^)相手らいおんの逃げ道が開いたぜ☆! goto gt_EndLoop; } } gt_EndLoop: ; bbVar_kiki.Set(kikiBB1_const); if (!bbVar_kiki.IsEmpty()) { //──────────────────────────────────────── // (4)増やした重ね利きの数を減らして、元に戻すぜ☆(^▽^) //──────────────────────────────────────── //ビットボード使い回し PureMemory.gky_ky.shogiban.kikiBan.TorinozokuKiki(km1_teban, bbVar_kiki); } // 利き数は、まだ戻している途中 bbVar_kiki.Set(bbConst_kiki0); if (!bbVar_kiki.IsEmpty()) { //──────────────────────────────────────── // (5)減らした重ね利きの数を増やして、元に戻すぜ☆(^▽^) //──────────────────────────────────────── //ビットボード使い回し PureMemory.gky_ky.shogiban.kikiBan.OkuKiki(km0_teban, bbVar_kiki); } //──────────────────────────────────────── // ここで、利きの数は現局面と合ってるはずだぜ☆(^~^) //──────────────────────────────────────── return(akeru); }