/// <summary> /// この左上 /// </summary> /// <param name="ms"></param> /// <param name="tb"></param> /// <returns></returns> static void TasuKonoHidariue(Piece km, Masu ms) { switch (Med_Koma.KomaToTaikyokusya(km)) { case Taikyokusya.T1: if (!BitboardsOmatome.YomiBitboardsOmatome.IsIntersect_UeHajiDan(ms) && !BitboardsOmatome.YomiBitboardsOmatome.IsIntersect_HidariHajiSuji(ms)) { Masu ms_tmp = ms - PureSettei.banYokoHaba - 1; if (Conv_Masu.IsBanjo(ms_tmp)) { BitboardsOmatome.KomanoUgokikataYk00.StandupElement(km, ms, ms_tmp); } } break; case Taikyokusya.T2: if (!BitboardsOmatome.YomiBitboardsOmatome.IsIntersect_SitaHajiDan(ms) && !BitboardsOmatome.YomiBitboardsOmatome.IsIntersect_MigiHajiSuji(ms)) { Masu ms_tmp = ms + PureSettei.banYokoHaba + 1; if (Conv_Masu.IsBanjo(ms_tmp)) { BitboardsOmatome.KomanoUgokikataYk00.StandupElement(km, ms, ms_tmp); } } break; default: break; } }
/// <summary> /// 桂馬跳び左 /// </summary> /// <param name="ms"></param> /// <param name="tb"></param> /// <returns></returns> static void TasuKeimatobiHidari(Piece km, Masu ms) { Taikyokusya tai = Med_Koma.KomaToTaikyokusya(km); if (!BitboardsOmatome.YomiBitboardsOmatome.IsIntersect_UsagigaHidariniToberu(tai, ms)) { switch (tai) { case Taikyokusya.T1: { Masu ms_tmp = ms - 2 * PureSettei.banYokoHaba - 1; if (Conv_Masu.IsBanjo(ms_tmp)) { BitboardsOmatome.KomanoUgokikataYk00.StandupElement(km, ms, ms_tmp); } } break; case Taikyokusya.T2: { Masu ms_tmp = ms + 2 * PureSettei.banYokoHaba + 1; if (Conv_Masu.IsBanjo(ms_tmp)) { BitboardsOmatome.KomanoUgokikataYk00.StandupElement(km, ms, ms_tmp); } } break; default: break; } } }
/// <summary> /// 2017-04-19 作成 /// /// パースに失敗してもエラーではない。 /// </summary> /// <param name="line"></param> /// <param name="caret"></param> /// <param name="out_ms"></param> /// <returns></returns> public static bool MatchMasu (string line, ref int caret, out Masu out_ms #if DEBUG , IDebugMojiretu dbg_reigai #endif ) { Match m = Itiran_FenParser.GetMasuPattern(PureSettei.fenSyurui).Match(line, caret); if (m.Success) { // キャレットを進める Util_String.SkipMatch(line, ref caret, m); int suji = LisInt.FenSuji_Int(PureSettei.fenSyurui, m.Groups[1].Value); int dan = LisInt.FenDan_Int(PureSettei.fenSyurui, m.Groups[2].Value); // 升を返す out_ms = Conv_Masu.ToMasu(suji, dan); return(true); } else { // 該当なし(エラーではない) out_ms = Conv_Masu.masu_error; return(false); } }
/// <summary> /// 対人表示用☆(^~^) /// </summary> /// <param name="ms"></param> /// <returns></returns> public static int ToDan_WithError(Masu ms) { if (Conv_Masu.IsBanjo(ms)) { return(((int)ms) / PureSettei.banYokoHaba + 1); } return(Conv_Masu.ERROR_DAN); }
/// <summary> /// 対人表示用☆(^~^) /// </summary> /// <param name="ms"></param> /// <returns></returns> public static int ToSuji_WithError(Masu ms) { if (Conv_Masu.IsBanjo(ms)) { return(((int)ms) % PureSettei.banYokoHaba + 1); } return(Conv_Masu.ERROR_SUJI); }
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; } }
public static Move TryFenMove2( FenSyurui f, string str1, string str2, string str3, string str4, string str5 ) { int dstSuji = LisInt.FenSuji_Int(f, str3); // 至筋 int dstDan = LisInt.FenDan_Int(f, str4); // 至段 // 取った駒を調べるぜ☆(^▽^) Masu dstMs = Conv_Masu.ToMasu(dstSuji, dstDan); //------------------------------ // 5 //------------------------------ bool natta = false; if ("+" == str5) { // 成りました natta = true; } //------------------------------ // 結果 //------------------------------ if ("*" == str2) { // 駒台から打ったぜ☆ return(AbstractConvMove.ToMove01cUtta( dstMs, Med_Parser.MojiToMotikomaSyurui(f, str1)//打った駒 )); } else { // 盤上の駒を動かしたぜ☆ if (natta) { return(AbstractConvMove.ToMove01bNariSasi(Med_Parser.FenSujiDan_Masu(f, str1, str2), dstMs)); } else { return(AbstractConvMove.ToMove01aNarazuSasi(Med_Parser.FenSujiDan_Masu(f, str1, str2), dstMs)); } } }
public static int GetNanameDan(Masu ms, TobikikiDirection kikiDir) { switch (kikiDir) { case TobikikiDirection.KY: case TobikikiDirection.None: // 横方向(0オリジン) return(Conv_Masu.ToDanO0_WithoutErrorCheck((int)ms)); case TobikikiDirection.KT: case TobikikiDirection.S: // 縦方向 return(massugudanD[(int)ms]); case TobikikiDirection.ZHa: case TobikikiDirection.ZHs: return(nanamedanD[(int)ms][Conv_TobikikiDirection.ToUgokikataArrayIndex(kikiDir)]); default: throw new Exception(string.Format("想定外の方向 dir={0}", kikiDir)); } }
/// <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) { #if DEBUG Debug.Assert(Conv_Masu.IsBanjoOrError(ms_src), $"ms_src=[{ms_src}] kymS.masuYososu=[{PureSettei.banHeimen}]"); Debug.Assert(Conv_Masu.IsBanjo(ms_dst), "盤外に指したぜ☆?"); #endif // バリュー int v = 0; // 筋と段☆(^▽^)盤外なら 0 だぜ☆(^▽^) SetSrcMasu_WithoutErrorCheck(ref v, ms_src); // 「打」のときは何もしないぜ☆(^▽^) SetDstMasu_WithoutErrorCheck(ref v, ms_dst); // 打った駒なし // 成らない☆(^▽^) return((Move)v); }
/// <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) { #if DEBUG Debug.Assert(Conv_Masu.IsBanjoOrError(ms_src), ""); Debug.Assert(Conv_Masu.IsBanjo(ms_dst), "盤外に指したぜ☆?"); #endif // バリュー 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 int GetDstDan_WithoutErrorCheck(int ss) { // (v & m) >> s + 1。 v:バリュー、m:マスク、s:シフト return(Conv_Masu.ToDanO1_WithoutErrorCheck((int)GetDstMasu_WithoutErrorCheck(ss))); // if (Move.Toryo == ss) { return Conv_Masu.ERROR_DAN; } // 解析不能☆ }
public static int GetDstSuji_WithoutErrorCheck(int ss) { // (v & m) >> s + 1。 v:バリュー、m:マスク、s:シフト return(Conv_Masu.ToSujiO1_WithoutErrorCheck((int)GetDstMasu_WithoutErrorCheck(ss))); // if (Move.Toryo == ss) { return Conv_Masu.ERROR_SUJI; } // エラーチェック付き }
public static int GetSrcDan_WithoutErrorCheck(int ss) { // (v & m) >> s + 1。 v:バリュー、m:マスク、s:シフト return(Conv_Masu.ToDanO1_WithoutErrorCheck((int)GetSrcMasu_WithoutErrorCheck(ss))); // if (Move.Toryo == ss || AbstractConvMove.IsUtta(ss)) { return Conv_Masu.ERROR_DAN; } // エラーチェック付き }
///// <summary> ///// ///// </summary> ///// <param name="out_restString"></param> ///// <param name="commandline">B3といった文字列☆</param> ///// <returns></returns> //public static bool TryParseMs( // string commandline, // Kyokumen ky, // ref int caret, // out Masu result //) //{ // //「B4」形式と想定 // // テキスト形式の符号「A4 …」の最初の1要素を、切り取ってトークンに分解します。 // //------------------------------------------------------------ // // リスト作成 // //------------------------------------------------------------ // Match m = Itiran_FenParser.GetMasuMovePattern(Option_Application.Optionlist.USI).Match(commandline, caret); // if (m.Success) // { // Util_String.SkipMatch(commandline, ref caret, m); // // 符号1「B4」を元に、Masu を作ります。 // // 盤上の駒を動かしたぜ☆ // result = Med_Parser.FenSujiDan_Masu( // Option_Application.Optionlist.USI, // m.Groups[1].Value, //ABCabc か、 ZKH // m.Groups[2].Value //1234 か、 * // ); // return true; // } // // 「B4B3」形式ではなかった☆(^△^)!? 次の一手が読めない☆ // result = ky.MASU_ERROR; // return false; //} /// <summary> /// A1 を 0 に。 /// </summary> /// <param name="f"></param> /// <param name="suji"></param> /// <param name="dan"></param> /// <returns></returns> public static Masu FenSujiDan_Masu(FenSyurui f, string suji, string dan) { return(Conv_Masu.ToMasu(LisInt.FenSuji_Int(f, suji), LisInt.FenDan_Int(f, dan))); }
/// <summary> /// 指したあとの、次の局面へと更新するぜ☆ /// ハッシュも差分変更するぜ☆ /// /// 手番を進める処理は、分けるぜ☆(^~^) /// </summary> /// <param name="ss">指し手☆</param> public static bool TryFailDoMoveAll( Move ss, MoveType ssType #if DEBUG , FenSyurui f , IDebugMojiretu reigai1 , bool isAssertYokusei // 駒の取り合いは呼び出し回数が多いので、アサートを抑制したいときに真 , string hint #endif ) { #if DEBUG isAssertYokusei = false;//FIXME: #endif // 投了なら、なにも更新せず終了☆(^▽^) if (Move.Toryo == ss) { PureMemory.dmv_ks_c = Komasyurui.Yososu; goto gt_EndMethod; } MoveGenAccessor.BunkaiMoveDmv(ss); Debug.Assert(Conv_Koma.IsOk(PureMemory.dmv_km_t0), string.Format("Do km_t0={0}", PureMemory.dmv_km_t0)); Debug.Assert(Conv_Koma.IsOk(PureMemory.dmv_km_t1), "Do"); Debug.Assert(Conv_Masu.IsBanjoOrError(PureMemory.dmv_ms_t1), ""); Debug.Assert(Conv_Koma.IsOkOrKuhaku(PureMemory.dmv_km_c), "Do"); if (AbstractConvMove.IsUtta(ss)) { // 打った場合☆(^~^) // 駒台から駒を減らすんだぜ☆(^~^) if (TryFail_DaiOff( PureMemory.dmv_ms_t0, // 打ち、の場合は使わないので、エラー値を入れておく PureMemory.dmv_km_t0, // 打つ駒 PureMemory.dmv_mk_t0, // 持駒 PureMemory.dmv_ms_t1 // 移動先升 #if DEBUG , f , reigai1 #endif )) { return(Pure.FailTrue("TryFail_Tejun3_IdomotoJibunnoKomaTorinozoku")); } } else { // 盤上の駒を動かした場合☆(^~^) // 移動先に駒があれば取る if (CanDstOff(PureMemory.dmv_km_c)) { if (TryFail_DstOff( PureMemory.dmv_ms_t1, // 移動先升 PureMemory.dmv_km_c, // あれば、移動先の相手の駒(取られる駒; capture) PureMemory.dmv_ks_c #if DEBUG , f , reigai1 #endif )) { return(Pure.FailTrue("TryFail_Tejun1_IdosakiNoKomaWoToru")); } // 取った駒が有れば駒台に増やすぜ☆(^~^) if (TryFail_DaiOn( PureMemory.dmv_km_c,// あれば、移動先の相手の駒(取られる駒; capture) PureMemory.dmv_ks_c, PureMemory.dmv_mk_c #if DEBUG , f , reigai1 #endif )) { return(Pure.FailTrue("TryFail_Tejun2_TottaKomaWoKomadainiOku")); } } // 移動元から自分の駒を取り除くぜ☆(^~^) if (TryFail_SrcOff( ss, PureMemory.dmv_ms_t0, PureMemory.dmv_km_t0, PureMemory.dmv_mk_t0, PureMemory.dmv_ms_t1 // 移動先升 #if DEBUG , f , reigai1 #endif )) { return(Pure.FailTrue("TryFail_Tejun3_IdomotoJibunnoKomaTorinozoku")); } } // 移動先に手番の駒を置くぜ☆(^~^) if (TryFail_DstOn( PureMemory.dmv_ms_t0, PureMemory.dmv_km_t1, PureMemory.dmv_ms_t1 // 移動先升 #if DEBUG , f , reigai1 #endif )) { return(Pure.FailTrue("TryFail_Tejun4_IdosakiNiTebanonKomawoOku")); } //──────────────────────────────────────── // 最後に診断 //──────────────────────────────────────── gt_EndMethod: return(Pure.SUCCESSFUL_FALSE); }
/// <summary> /// 初期局面としてセットするぜ☆(^▽^) /// </summary> public static bool TryFail_SetSyokiKyokumen_ByFen( FenSyurui f, string[] danMojiretu, // [0~3]1段目~4段目、[0~2]1筋目~3筋目 string motigoma, string tb_Mojis //手番 #if DEBUG , IDebugMojiretu dbg_reigai #endif ) { PureMemory.gky_ky.Tukurinaosi_ClearKyokumen(); // 持ち駒パース { //PureMemory.gky_ky.motigomaItiran.Clear(); if ("-" != motigoma)// '-' は持ち駒無し { int maisu = 0; for (int caret = 0; caret < motigoma.Length; caret++) { char ch = motigoma[caret]; int numeric; if (int.TryParse(ch.ToString(), out numeric)) { maisu = maisu * 10 + numeric; } else { Motigoma mk; if (!LisMotiKoma.TryParseFen(f, ch, out mk)) { return(Pure.FailTrue("TryParseFen")); } else { // 枚数の指定がなかったとき(=0)は、1。 PureMemory.gky_ky.motigomaItiran.Set(mk, maisu == 0 ? 1 : maisu); maisu = 0; } } } } } // 盤上の升(既にクリアされているものとするぜ☆) int suji; for (int dan = 1; dan <= danMojiretu.Length; dan++) // 1段目~N段目 の順に解析。 { // // "2z" のように、3列を 2桁 で表記しているので、タテ筋のループ・カウントの数え方には注意だぜ☆(^~^) // suji = 1; int ruikeiKuhakuSu = 0; //累計空白数 bool isPowerupKoma = false; //パワーアップ駒(成りゴマ) for (int caret = 0; //caret < 3 && caret < danMojiretu[dan - 1].Length // 可変長配列☆ ; caret++) { char moji = danMojiretu[dan - 1][caret]; int kuhaku; if ('+' == moji) { isPowerupKoma = true; } else if (int.TryParse(moji.ToString(), out kuhaku)) { // 数字は空き升の個数なので、筋を進めるぜ☆(^▽^) // とりあえず 1~9 まで対応できるだろうなんだぜ☆(^~^) //for (int i = 0; i < kuhaku; i++) //{ ruikeiKuhakuSu = ruikeiKuhakuSu * 10 + kuhaku; //} //Mojiretu reigai1 = new StringBuilder(); //reigai1.AppendLine($"未定義の空白の数 moji=[{moji}]"); //reigai1.AppendLine($"dan =[{dan}]"); //reigai1.AppendLine($"caret =[{caret}]"); //reigai1.AppendLine($"danMojiretu[dan-1] =[{danMojiretu[dan - 1]}]"); //throw new Exception(reigai1.ToContents()); } else { // 駒でした。 if (0 < ruikeiKuhakuSu) { // 空白は置かなくていいのでは? //Masu ms = Conv_Masu.ToMasu(suji, dan); //Koma km_actual = GetBanjoKoma(ms); //HerasuBanjoKoma(ms, km_actual, true); suji += ruikeiKuhakuSu; ruikeiKuhakuSu = 0; } Piece tmp; if (!LisKoma.Try_ParseFen(f, (isPowerupKoma ? $"+{moji}" : moji.ToString()), out tmp)) { #if DEBUG Pure.Sc.AddErr(string.Format("SetNaiyoで未定義の駒が指定されました。 fen moji=[{0}]", moji)); #endif return(Pure.FailTrue("Try_ParseFen")); } isPowerupKoma = false; if (PureMemory.gky_ky.shogiban.TryFail_OkuKoma(//SetNaiyo Conv_Masu.ToMasu(suji, dan), tmp, true #if DEBUG , dbg_reigai #endif )) { return(Pure.FailTrue("TryFail_Oku")); } // あとで適用 suji += 1; } } if (0 < ruikeiKuhakuSu) { // 空白は置かなくていいのでは? //Masu ms = Conv_Masu.ToMasu(suji, dan); //HerasuBanjoKoma(ms, GetBanjoKoma(ms), true); suji += ruikeiKuhakuSu; ruikeiKuhakuSu = 0; } } // 手番 { Taikyokusya syokikyokumenTai; if (!Med_Parser.Try_MojiToTaikyokusya(f, tb_Mojis, out syokikyokumenTai)) { #if DEBUG dbg_reigai.AppendLine(string.Format("SetNaiyoで未定義の手番が指定されたんだぜ☆ isSfen={0} 入力={1} 出力={2}", f, tb_Mojis, syokikyokumenTai )); //reigai1.AppendLine($"ky.Teban=[{PureMemory.gky_ky.yomiKy.teban}]"); //reigai1.AppendLine($"BanTateHaba=[{PureSettei.banTateHaba}]"); dbg_reigai.AppendLine(string.Format("持ち駒数一覧({0}件)", danMojiretu.Length)); foreach (Motigoma mk in Conv_Motigoma.itiran) { dbg_reigai.AppendLine(string.Format("{0}={1}", mk, PureMemory.gky_ky.motigomaItiran.yomiMotigomaItiran.Count(mk))); } #endif return(Pure.FailTrue("Try_Taikyokusya")); //throw new Exception($"対局者のパースエラー tb_Mojis=[{tb_Mojis}]{reigai1.ToContents()}"); } // 先手番始まりか、後手番始まりか、に合わせるぜ☆(^~^) PureMemory.ResetTebanArray(syokikyokumenTai); // 手番には 1 が入っていると思うんだが、無視して 0 スタートに固定するぜ☆(^~^) // PureMemory.ClearTeme(); } return(Pure.SUCCESSFUL_FALSE); }
/// <summary> /// トライできる先。 /// </summary> /// <param name="ky">局面</param> /// <param name="kikiBB">手番らいおんの利きビットボード</param> /// <param name="tb">手番</param> /// <param name="ms1">手番らいおんがいる升</param> /// <returns></returns> public static Bitboard GetTrySaki(Bitboard kikiBB, Masu ms1) { #if DEBUG Util_Test.AppendLine("テスト: トライルール", Pure.Sc.dbgMojiretu); #endif m_trySakiBB_.Clear(); // 自分はN段目にいる☆ int dan = Conv_Masu.ToDanO1_JibunSiten(PureMemory.kifu_teban, ms1); bool nidanme = 2 == dan; #if DEBUG Util_Test.AppendLine($"2段目にいるか☆?[{nidanme}] わたしは[{dan}]段目にいるぜ☆", Pure.Sc.dbgMojiretu); #endif if (!nidanme) { #if DEBUG Util_Test.AppendLine("むりだぜ☆", Pure.Sc.dbgMojiretu); //Util_Test.Flush(reigai1); #endif return(m_trySakiBB_); } // 1段目に移動できる升☆ m_trySakiBB_.Set(kikiBB); m_trySakiBB_.Siborikomi(BitboardsOmatome.bb_try[PureMemory.kifu_nTeban]); #if DEBUG Interproject.project.Dbg_TryRule1(kikiBB, m_trySakiBB_); #endif // 味方の駒がないところ☆ Bitboard spaceBB = new Bitboard(); spaceBB.Set(BitboardsOmatome.bb_boardArea); PureMemory.gky_ky.shogiban.ibashoBan_yk00.yomiIbashoBan.ToSitdown_KomaZenbu(PureMemory.kifu_teban, spaceBB); m_trySakiBB_.Siborikomi(spaceBB); #if DEBUG Interproject.project.Dbg_TryRule2(spaceBB, m_trySakiBB_); #endif if (m_trySakiBB_.IsEmpty()) { #if DEBUG Util_Test.AppendLine("むりだぜ☆", Pure.Sc.dbgMojiretu); //Util_Test.Flush(reigai1); #endif return(m_trySakiBB_); } // 相手の利きが届いていないところ☆ Bitboard safeBB = new Bitboard(); safeBB.Set(BitboardsOmatome.bb_boardArea); PureMemory.gky_ky.yomiKy.yomiShogiban.yomiKikiBan.ToSitdown_BBKikiZenbu(PureMemory.kifu_aiteban, safeBB); m_trySakiBB_.Siborikomi(safeBB); #if DEBUG Interproject.project.Dbg_TryRule3(safeBB, m_trySakiBB_); #endif if (m_trySakiBB_.IsEmpty()) { #if DEBUG Util_Test.AppendLine("むりだぜ☆", Pure.Sc.dbgMojiretu); //Util_Test.Flush(reigai1); #endif return(m_trySakiBB_); } #if DEBUG Util_Test.AppendLine("トライできるぜ☆", Pure.Sc.dbgMojiretu); //Util_Test.Flush(reigai1); #endif return(m_trySakiBB_); }
/// <summary> /// 盤のサイズが設定されたあとに呼び出すこと /// </summary> public static void Tukurinaosi( #if DEBUG string dbg_hint #endif ) { int tate = PureSettei.banTateHaba; int yoko = PureSettei.banYokoHaba; int heimen = PureSettei.banHeimen; int nanamedanDLen = PureSettei.banNanameDanLen; { //---------------------------------------- // ビットボードの作り直し(端チェックをするものを先に) //---------------------------------------- // 筋 { // o-- // o-- // o-- // o-- bb_sujiArray = new Bitboard[yoko]; // 左端列を立てる。 bb_sujiArray[0] = new Bitboard(); for (int iDan = 0; iDan < tate; iDan++) { bb_sujiArray[0].Standup((Masu)(iDan * yoko)); } // 1ビットずつ左シフトしていく。 for (int iSuji = 1; iSuji < yoko; iSuji++) { bb_sujiArray[iSuji] = new Bitboard(); bb_sujiArray[iSuji].Set(bb_sujiArray[iSuji - 1]); bb_sujiArray[iSuji].LeftShift(1); } } // 段 { bb_danArray = new Bitboard[tate]; // 1段目のビットは全て立てるぜ☆(^~^) bb_danArray[0] = new Bitboard(); for (int iSuji = 0; iSuji < yoko; iSuji++) { bb_danArray[0].Standup((Masu)iSuji);// 1段目は筋も升も同じ番号。 } // 2段目以降は、左ビットシフト☆(^~^) for (int iDan = 1; iDan < tate; iDan++) { bb_danArray[iDan] = new Bitboard(); bb_danArray[iDan].Set(bb_danArray[iDan - 1]); bb_danArray[iDan].LeftShift(yoko); //#if DEBUG // Util_Machine.Syuturyoku.AppendLine($"iDan=[{ iDan }] KyokumenImpl.BB_DanArray[iDan]=[{ KyokumenImpl.BB_DanArray[iDan].Value }] Option_Application.Optionlist.BanTateHaba=[{ Option_Application.Optionlist.BanTateHaba }] Option_Application.Optionlist.BanYokoHaba=[{ Option_Application.Optionlist.BanYokoHaba }]"); // Util_Machine.Flush(Util_Machine.Syuturyoku); //#endif } } //──────────────────── // トライ用ビットボード //──────────────────── bb_try = new Bitboard[Conv_Taikyokusya.itiran.Length]; bb_try[(int)Taikyokusya.T1] = bb_danArray[0]; bb_try[(int)Taikyokusya.T2] = bb_danArray[PureSettei.banTateHaba - 1]; // トライ段 { bb_try[(int)Taikyokusya.T1] = bb_danArray[0]; bb_try[(int)Taikyokusya.T2] = bb_danArray[tate - 1]; } //──────────────────── // 成り用ビットボード //──────────────────── bb_nareruZone = new Bitboard[Conv_Taikyokusya.itiran.Length]; if (PureSettei.gameRule == GameRule.HonShogi) { // 9x9マス盤を想定☆(^~^) bb_nareruZone[(int)Taikyokusya.T1] = bb_danArray[0].Clone(); bb_nareruZone[(int)Taikyokusya.T1].Standup(bb_danArray[1]); bb_nareruZone[(int)Taikyokusya.T1].Standup(bb_danArray[2]); bb_nareruZone[(int)Taikyokusya.T2] = bb_danArray[PureSettei.banTateHaba - 1].Clone(); bb_nareruZone[(int)Taikyokusya.T2].Standup(bb_danArray[PureSettei.banTateHaba - 2]); bb_nareruZone[(int)Taikyokusya.T2].Standup(bb_danArray[PureSettei.banTateHaba - 3]); } else { bb_nareruZone[(int)Taikyokusya.T1] = bb_danArray[0].Clone(); bb_nareruZone[(int)Taikyokusya.T2] = bb_danArray[PureSettei.banTateHaba - 1].Clone(); } //──────────────────── // ビットボードのうち、ゲームに使っているビット //──────────────────── bb_boardArea_ = new Bitboard(); // ビットを立てていく。 if (0 < PureSettei.banHeimen) { bb_boardArea.Set(1); for (int i = 1; i < PureSettei.banHeimen; i++) { bb_boardArea.LeftShift(1); bb_boardArea.Standup((Masu)0); } } else { bb_boardArea.Clear(); } //──────────────────── // うさぎが飛べる升ビットボード //──────────────────── bb_usagigaMiginiToberu = new Bitboard[Conv_Taikyokusya.itiran.Length]; bb_usagigaHidariniToberu = new Bitboard[Conv_Taikyokusya.itiran.Length]; foreach (Taikyokusya tai in Conv_Taikyokusya.itiran) { bb_usagigaMiginiToberu[(int)tai] = new Bitboard(); bb_usagigaHidariniToberu[(int)tai] = new Bitboard(); bb_usagigaMiginiToberu[(int)tai].Set(bb_boardArea); bb_usagigaHidariniToberu[(int)tai].Set(bb_boardArea); // 1段目と2段目を省く for (int iDanO0 = 0; iDanO0 < 2; iDanO0++) { bb_usagigaMiginiToberu[(int)tai].Sitdown(bb_danArray[Conv_Masu.ToDanO0_JibunSiten_ByDanO0(tai, iDanO0)]); bb_usagigaHidariniToberu[(int)tai].Sitdown(bb_danArray[Conv_Masu.ToDanO0_JibunSiten_ByDanO0(tai, iDanO0)]); } // 右跳びは 9筋 を省く bb_usagigaMiginiToberu[(int)tai].Sitdown(bb_sujiArray[Conv_Masu.ToSujiO0_JibunSiten_BySujiO0(tai, PureSettei.banYokoHaba - 1)]); // 左跳びは 1筋 を省く bb_usagigaHidariniToberu[(int)tai].Sitdown(bb_sujiArray[Conv_Masu.ToSujiO0_JibunSiten_BySujiO0(tai, 0)]); } } //──────────────────── // 筋一列ビットボード //──────────────────── // o-- // o-- // o-- // o-- bb_sujiArray = new Bitboard[PureSettei.banYokoHaba]; bb_sujiArray[0] = new Bitboard(); //// 0x249 → 10 0100 1001(2進数) //BB_SujiArray[0].Set(0x249); // 筋一列を立てます for (int iDan = 0; iDan < PureSettei.banTateHaba; iDan++) { bb_sujiArray[0].Standup((Masu)(iDan * PureSettei.banYokoHaba)); } // 2筋目以降 for (int iSuji = 1; iSuji < PureSettei.banYokoHaba; iSuji++) { bb_sujiArray[iSuji] = new Bitboard(); bb_sujiArray[iSuji].Set(bb_sujiArray[iSuji - 1]); bb_sujiArray[iSuji].LeftShift(1); } //──────────────────── // 段一列ビットボード //──────────────────── // ooo // --- // --- // --- bb_danArray = new Bitboard[PureSettei.banTateHaba]; bb_danArray[0] = new Bitboard(); //// 0x07 → 111(2進数) //BB_DanArray[0].Set(0x07); // 段一列を立てます for (int iSuji = 0; iSuji < PureSettei.banYokoHaba; iSuji++) { bb_danArray[0].Standup((Masu)iSuji); } // 2段目以降 for (int iDan = 1; iDan < PureSettei.banTateHaba; iDan++) { bb_danArray[iDan] = new Bitboard(); bb_danArray[iDan].Set(bb_danArray[iDan - 1]); bb_danArray[iDan].LeftShift(PureSettei.banYokoHaba); } //──────────────────── // ローテート・ビットボードの置換表 //──────────────────── RotateChikanhyo.Tukurinaosi(); //──────────────────── // 左上がり筋一列ビットボード //──────────────────── // o--- // -o-- // --o- // ---o { bb_hidariAgariSujiArray = new Bitboard[PureSettei.banNanameDanLen]; int preDiagonals = -1; ScanHidariAgariSuji((int diagonals, Masu ms) => { if (preDiagonals != diagonals) { bb_hidariAgariSujiArray[diagonals] = new Bitboard(); preDiagonals = diagonals; } bb_hidariAgariSujiArray[diagonals].Standup(ms); }); } //──────────────────── // 左下がり筋一列ビットボード //──────────────────── // ---o // --o- // -o-- // o--- { bb_hidariSagariSujiArray = new Bitboard[PureSettei.banNanameDanLen]; int preDiagonals = -1; ScanHidariSagariSuji((int diagonals, Masu ms) => { if (preDiagonals != diagonals) { bb_hidariSagariSujiArray[diagonals] = new Bitboard(); preDiagonals = diagonals; } bb_hidariSagariSujiArray[diagonals].Standup(ms); }); } //──────────────────── // 持駒を進める(打てる)ゾーン //──────────────────── // 駒の行き所のない段に打つのを防止 // 段配列をセットしたあとで { bb_uteruZone = new Bitboard[Conv_Koma.itiran.Length]; foreach (Piece km in Conv_Koma.itiran) { // まず、盤面全体に打てるとするぜ☆(^~^) bb_uteruZone[(int)km] = bb_boardArea.Clone(); // 次に個別に、打てない場所を除外しろだぜ☆(^~^) if (PureSettei.gameRule == GameRule.HonShogi) { switch (km) { // ひよこ、いのしし case Piece.P1: case Piece.L1: bb_uteruZone[(int)km].Sitdown(bb_danArray[0]); break; case Piece.P2: case Piece.L2: bb_uteruZone[(int)km].Sitdown(bb_danArray[tate - 1]); break; // うさぎ case Piece.N1: bb_uteruZone[(int)km].Sitdown(bb_danArray[0]); bb_uteruZone[(int)km].Sitdown(bb_danArray[1]); break; case Piece.N2: bb_uteruZone[(int)km].Sitdown(bb_danArray[tate - 1]); bb_uteruZone[(int)km].Sitdown(bb_danArray[tate - 2]); break; default: break; } } } } //──────────────────── // 駒の動き方 //──────────────────── KomanoUgokikataYk00.Tukurinaosi( #if DEBUG dbg_hint #endif ); }
static void ToStandup_ByElement(Piece km, Masu ms, Bitboard bb_update) { Debug.Assert(Conv_Masu.IsBanjo(ms)); bb_update.Standup(TonarikikiElement.ugokikataTon[(int)km][(int)ms]); }
/// <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()); // がない場合、詰み☆ ; }
public static bool CanDoMove(Move ss, out MoveMatigaiRiyu reason) { if (Move.Toryo == ss) { reason = MoveMatigaiRiyu.Karappo; return(true); } // 投了はOKだぜ☆(^~^) // 打つ駒調べ MotigomaSyurui mksUtta = AbstractConvMove.GetUttaKomasyurui(ss);// 打った駒の種類 bool utta = MotigomaSyurui.Yososu != mksUtta; if (utta) { // 「打」の場合、持ち駒チェック☆ if (!PureMemory.gky_ky.yomiKy.yomiMotigomaItiran.HasMotigoma(Med_Koma.MotiKomasyuruiAndTaikyokusyaToMotiKoma(mksUtta, PureMemory.kifu_teban))) { // 持駒が無いのに打とうとしたぜ☆(>_<) reason = MoveMatigaiRiyu.NaiMotiKomaUti; return(false); } } // 移動先、打つ先 調べ☆ Masu ms_dst = AbstractConvMove.GetDstMasu_WithoutErrorCheck((int)ss); // 移動先升 if (!Conv_Masu.IsBanjo(ms_dst)) { // 盤外に移動しようとしたぜ☆(^~^) reason = MoveMatigaiRiyu.BangaiIdo; return(false); } Piece km_dst = PureMemory.gky_ky.yomiKy.yomiShogiban.yomiIbashoBan.GetBanjoKoma(ms_dst); Taikyokusya tai_dstKm = Med_Koma.KomaToTaikyokusya(km_dst); if (km_dst != Piece.Kuhaku && PureMemory.kifu_teban == tai_dstKm) { // 自分の駒を取ろうとするのは、イリーガル・ムーブだぜ☆(^▽^) reason = MoveMatigaiRiyu.TebanKomaNoTokoroheIdo; return(false); } else if (utta && km_dst != Piece.Kuhaku) { // 駒があるところに打ち込んではいけないぜ☆(^▽^) reason = MoveMatigaiRiyu.KomaGaAruTokoroheUti; return(false); } // 移動元調べ☆ Piece km_src; if (utta) { // 「打」のときは ここ。 km_src = Med_Koma.MotiKomasyuruiAndTaikyokusyaToKoma(mksUtta, PureMemory.kifu_teban); } else { Masu ms_src = AbstractConvMove.GetSrcMasu_WithoutErrorCheck((int)ss); // 移動先升 km_src = PureMemory.gky_ky.yomiKy.yomiShogiban.yomiIbashoBan.GetBanjoKoma(ms_src); Taikyokusya tai_srcKm = Med_Koma.KomaToTaikyokusya(km_src); if (km_src == Piece.Kuhaku) { // 空き升に駒があると思って動かそうとするのは、イリーガル・ムーブだぜ☆(^▽^) reason = MoveMatigaiRiyu.KuhakuWoIdo; return(false); } else if (tai_srcKm != PureMemory.kifu_teban) { // 相手の駒を動かそうとするのは、イリーガル・ムーブだぜ☆(^▽^) reason = MoveMatigaiRiyu.AiteNoKomaIdo; return(false); } // 移動方向調べ if (!BitboardsOmatome.KomanoUgokikataYk00.IsIntersect( km_src, ms_src, //この2つのマスが交わっているか ms_dst //この2つのマスが交わっているか )) { // その駒の種類からは、ありえない動きをしたぜ☆(^▽^) //#if DEBUG // throw new Exception($"その駒の種類からは、ありえない動きをしたぜ☆(^▽^) ms1=[{ ms_src }] ms2=[{ ms_dst }]"); //#else reason = MoveMatigaiRiyu.SonoKomasyuruiKarahaArienaiUgoki; return(false); //#endif } } // 成り調べ if (AbstractConvMove.IsNatta(ss))//成りを指示した場合 { switch (PureSettei.gameRule) { case GameRule.DobutuShogi: { if (Med_Koma.KomaToKomasyurui(km_src) != Komasyurui.H) { // ひよこ以外が、にわとりになろうとしました☆ reason = MoveMatigaiRiyu.NarenaiNari; return(false); } } break; case GameRule.HonShogi: { switch (Med_Koma.KomaToKomasyurui(km_src)) { case Komasyurui.H: case Komasyurui.K: case Komasyurui.N: case Komasyurui.S: case Komasyurui.U: case Komasyurui.Z: // セーフ break; case Komasyurui.I: case Komasyurui.PH: case Komasyurui.PK: case Komasyurui.PN: case Komasyurui.PS: case Komasyurui.PU: case Komasyurui.PZ: case Komasyurui.R: case Komasyurui.Yososu: //FIXME: default: { // 成れる駒以外が、成ろうとしました☆ reason = MoveMatigaiRiyu.NarenaiNari; return(false); } } } break; } } reason = MoveMatigaiRiyu.Karappo; return(true); }