/// <summary> /// 局面ハッシュを再計算するぜ☆(^▽^) /// </summary> /// <returns></returns> public void Tukurinaosi(Kyokumen ky) { ulong hash = 0; // 盤上 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]; Koma km = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, optionalPhase); ky.Shogiban.ToSet_BBKoma(km, komaBB); while (komaBB.Ref_PopNTZ(out Masu ms)) { hash ^= Util_ZobristHashing.GetBanjoKey(ms, km, ky.Sindan); } } } // 持ち駒 foreach (MotiKoma mk in Conv_MotiKoma.Itiran) { hash ^= Util_ZobristHashing.GetMotiKey(ky.Sindan, mk); } // 手番 hash ^= Util_ZobristHashing.GetTaikyokusyaKey(ky.CurrentOptionalPhase, ky.Sindan); Value = hash; }
/// <summary> /// 駒の利き /// </summary> /// <param name="bbItiran_kikiZenbu"></param> /// <param name="bbItiran_kikiKomabetu"></param> /// <param name="syuturyoku"></param> public static void HyojiKomanoKiki(Shogiban shogiban, StringBuilder syuturyoku) { Debug.Assert(shogiban.IsActiveBBKiki(), ""); // 利き全部 { syuturyoku.AppendLine("利き(全部)"); Bitboard[] bbHairetu = new Bitboard[Conv_Taikyokusya.AllOptionalPhaseList.Length]; foreach (var optionalPhase65 in Conv_Taikyokusya.AllOptionalPhaseList) { bbHairetu[OptionalPhase.IndexOf(optionalPhase65)] = shogiban.GetBBKikiZenbu(optionalPhase65); } Setumei_Bitboards(Conv_Taikyokusya.NamaeItiran, bbHairetu, syuturyoku); } // 駒別 { syuturyoku.AppendLine("利き(駒別)"); foreach (var optionalPhase74 in Conv_Taikyokusya.AllOptionalPhaseList)// 対局者1、対局者2 { // 盤上 Bitboard[] bbHairetu = new Bitboard[Conv_Komasyurui.Itiran.Length]; foreach (Komasyurui ks in Conv_Komasyurui.Itiran) { bbHairetu[(int)ks] = shogiban.GetBBKiki(Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, optionalPhase74)); } Setumei_Bitboards(Med_Koma.GetKomasyuruiNamaeItiran(optionalPhase74), bbHairetu, syuturyoku); } } }
public static void Setumei_Kiki(Kyokumen ky, Masu attackerMs, StringBuilder syuturyoku) { var(exists, optionalPhase) = ky.Shogiban.ExistsBBKomaZenbu(attackerMs); if (exists) { ky.Shogiban.ExistsBBKoma(optionalPhase, attackerMs, out Komasyurui ks); Util_Information.Setumei_1Bitboard("利き", Util_Application.Kiki_BB(Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, optionalPhase), attackerMs, ky.Shogiban)//利き , syuturyoku); } }
/// <summary> /// 一手詰めの局面かどうか調べるぜ☆(^▽^) /// /// 自分が一手詰めを掛けられるから、この指し手は作らないでおこう、といった使い方がされるぜ☆(^▽^) /// /// FIXME: 持ち駒の打ちにも使えないか☆(^~^)? /// </summary> /// <param name="fukasa"></param> /// <param name="ky"></param> /// <param name="jibun"></param> /// <param name="ms_src">持ち駒の場合、エラー値</param> /// <param name="mks">持ち駒の場合、持駒の種類</param> /// <param name="ms_t1"></param> /// <param name="jibunHioute"></param> /// <returns></returns> public static bool Ittedume_MotiKoma(int fukasa, Kyokumen ky, MotiKoma mk, Masu ms_t1, HiouteJoho jibunHioute, HiouteJoho aiteHioute) { if (!Conv_MotiKoma.IsOk(mk)) { throw new Exception("持ち駒じゃないじゃないか☆(^▽^)www"); } // A B C // ┌──┬──┬──┐ //1│ │▽ら│ │ // ├──┼──┼──┤ //2│▲き│ │▲き│ // ├──┼──┼──┤ //3│ │▲に│▲ら│ // ├──┼──┼──┤ //4│▲ぞ│▲ひ│▲ぞ│ // └──┴──┴──┘ // 盤上の駒を動かすのか、駒台の駒を打つのかによって、利き の形が異なるぜ☆(^~^) Bitboard bb_kiki_t1 = ky.Shogiban.GetKomanoUgokikata(Med_Koma.MotiKomaToKoma(mk), ms_t1); if (!ky.Shogiban.GetBBKoma(aiteHioute.KmRaion).IsIntersect( // 相手らいおんの場所☆ bb_kiki_t1)) // 相手らいおん が、動かした駒の、利きの中に居ないんだったら、一手詰め にはならないぜ☆(^~^) { // FIXME: ステイルメイトは考えてないぜ☆(>_<) return(false); } Koma km_t1 = Med_Koma.MotiKomaToKoma(mk);//t0も同じ // FIXME: ↓駒移動後の、利きを取る必要がある Bitboard bb_jibunKikiNew = new Bitboard(); { // 打による、重ね利きの数を差分更新するぜ☆(^▽^) //, ky.BB_KikiZenbu ky.Shogiban.N100_FuyasuKiki(km_t1, ky.Sindan.CloneKomanoUgoki(km_t1, ms_t1), ky.Sindan);// 移動先の駒の利きを増やすぜ☆(^▽^) // こっちの利きを作り直し bb_jibunKikiNew = ky.Shogiban.ToBitboard_KikisuZenbuPositiveNumber(Med_Koma.MotiKomaToPhase(mk), ky.Sindan); // 打による、重ね利きの数の差分更新を元に戻すぜ☆(^▽^) // , ky.BB_KikiZenbu ky.Shogiban.N100_HerasuKiki(km_t1, ky.Sindan.CloneKomanoUgoki(km_t1, ms_t1), ky.Sindan);// 移動先の駒の利きを減らすぜ☆(^▽^) } // 相手らいおんが逃げようとしていて。 return(aiteHioute.FriendRaion8KinboBB.Clone() // 相手らいおんの8近傍 .Sitdown(ky.Shogiban.GetBBKomaZenbu(aiteHioute.CurrentOptionalPhase)) // 相手の駒がない升 .Sitdown(bb_jibunKikiNew) // こっちの利きがない升 .IsEmpty()); // 相手らいおん が逃げれる升がない場合、詰み☆ }
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); } } }
public static void Kiki(bool isSfen, string commandline, Kyokumen ky, out Masu out_ms, out Bitboard out_kikiBB) { //KomanoUgokikata komanoUgokikata, // うしろに続く文字は☆(^▽^) int caret = 0; Util_String.TobasuTangoToMatubiKuhaku(commandline, ref caret, "kiki "); string line = commandline.Substring(caret).TrimEnd(); if (line.Length == 2)// kiki b3 { out_kikiBB = null; // 升を返すぜ☆ if (!Med_Parser.TryParseMs(isSfen, commandline, ky, ref caret, out out_ms)) { throw new Exception("パースエラー102"); } } else// kiki b3 R 1 { out_ms = ky.MASU_ERROR; // 盤面表示を返すぜ☆ string moji1 = ""; string moji2 = ""; string moji3 = ""; string moji4 = ""; Match m = Itiran_FenParser.GetKikiCommandPattern(Option_Application.Optionlist.USI).Match(commandline, caret); if (m.Success) { Util_String.SkipMatch(commandline, ref caret, m); moji1 = m.Groups[1].Value; moji2 = m.Groups[2].Value; moji3 = m.Groups[3].Value; moji4 = m.Groups[4].Value; if (!Med_Parser.TryTaikyokusya(Option_Application.Optionlist.USI, moji4, out Option <Phase> phase)) { throw new Exception($"対局者のパースエラー moji4=[{ moji4 }]"); } out_kikiBB = Util_Application.Kiki_BB(Med_Koma.KomasyuruiAndTaikyokusyaToKoma(Med_Parser.Moji_Komasyurui(Option_Application.Optionlist.USI, moji3), phase), Med_Parser.FenSujiDan_Masu(Option_Application.Optionlist.USI, moji1, moji2), ky.Shogiban);// komanoUgokikata } else { out_kikiBB = null; } } }
public static void AppendLine_Data_Countboard(Option <Phase> optionalPhase, Shogiban sg, int ms_hidariHasi, StringBuilder syuturyoku) { for (int iKs = 0; iKs < Conv_Komasyurui.Itiran.Length; iKs++) { syuturyoku.Append("│"); for (int iMs_offset = 0; iMs_offset < Option_Application.Optionlist.BanYokoHaba; iMs_offset++) { int kikisuKomabetu = sg.CountKikisuKomabetu(Med_Koma.KomasyuruiAndTaikyokusyaToKoma((Komasyurui)iKs, optionalPhase), (Masu)(ms_hidariHasi + iMs_offset)); syuturyoku.Append(0 < kikisuKomabetu ? string.Format(" {0,2} ", kikisuKomabetu) : " "); syuturyoku.Append("│"); } } syuturyoku.AppendLine(); }
/// <summary> /// 手番の駒 の8近傍を調べて、利きに飛び込んでいたら真顔で真だぜ☆(^▽^) /// </summary> /// <param name="ky"></param> /// <param name="attackerMs">相手の攻撃駒の居場所</param> /// <param name="targetMs">狙っている升</param> /// <returns></returns> public static bool InKiki(Kyokumen ky, Masu attackerMs, Masu targetMs) { var optionalOpponent = Conv_Taikyokusya.Reverse(ky.CurrentOptionalPhase); if (ky.Shogiban.ExistsBBKomaZenbu(optionalOpponent, attackerMs)) // 指定の場所に相手の駒があることを確認 { if (ky.Shogiban.ExistsBBKoma(optionalOpponent, attackerMs, out Komasyurui ks)) // 攻撃側の駒の種類 { return(ky.Shogiban.GetKomanoUgokikata(Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, optionalOpponent), attackerMs).IsIntersect( //相手の攻撃駒の利き targetMs //調べる升 )); } } return(false); }
/// <summary> /// 駒の動き☆ /// </summary> /// <param name="komanoUgokikata"></param> /// <param name="syuturyoku"></param> public static void HyojiKomanoUgoki(Shogiban shogiban, int masuYososu, StringBuilder syuturyoku) { // KomanoUgokikata komanoUgokikata for (int ms = 0; ms < masuYososu; ms++) { syuturyoku.AppendLine($"ます{ms}"); foreach (var optionalPhase in Conv_Taikyokusya.AllOptionalPhaseList) { // 盤上 Bitboard[] bbHairetu = new Bitboard[Conv_Komasyurui.Itiran.Length]; foreach (Komasyurui ks in Conv_Komasyurui.Itiran) { bbHairetu[(int)ks] = shogiban.GetKomanoUgokikata(Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, optionalPhase), (Masu)ms); } Util_Information.Setumei_Bitboards(Med_Koma.GetKomasyuruiNamaeItiran(optionalPhase), bbHairetu, syuturyoku); syuturyoku.AppendLine(); } } }
/// <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> /// 指定の升にいる駒を除く、味方全部の利き☆ /// /// 盤上の駒を指す場合、自分自身が動いてしまうので利きが変わってしまうので、 /// 全部の利きを合成したBBが使えないので、代わりにこの関数を使うんだぜ☆(^~^) /// </summary> /// <param name="ky"></param> /// <param name="ms_nozoku">除きたい駒がいる升</param> /// <returns></returns> public static Bitboard CreateKikiZenbuBB_1KomaNozoku(Kyokumen ky, Option <Phase> phase, Masu ms_nozoku) { Bitboard kikiZenbuBB = new Bitboard(); // 味方の駒(変数使いまわし) Bitboard mikataBB = new Bitboard(); foreach (Komasyurui ks in Conv_Komasyurui.Itiran) { Koma km = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, phase); ky.Shogiban.ToSet_BBKoma(km, mikataBB); while (mikataBB.Ref_PopNTZ(out Masu ms)) { if (ms_nozoku != ms)//この駒を除く { ky.Shogiban.ToStandup_KomanoUgokikata(km, ms, kikiZenbuBB); } } } return(kikiZenbuBB); }
/// <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> /// <returns></returns> public bool IsNigemitiWoAkeru(Kyokumen ky, Komasyurui ks_aite, Masu ms_t0, Masu ms_t1) { if (NigemitiWoFusaideiruAiteNoKomaBB.IsOff(ms_t0)) { // 逃げ道を塞いでいる駒ではないのなら、スルーするぜ☆(^▽^) return(false); } // 手番らいおん の8近傍 のどこかに、重ね利きの数 0 が出来ていれば、 // 逃げ道を開けると判定するぜ☆(^▽^) bool akeru = false; Koma km_t0 = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks_aite, CurrentOptionalPhase); Koma km_t1 = km_t0;// FIXME: 成りを考慮していない // 重ね利きの数を差分更新するぜ☆(^▽^) 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); Bitboard nigemitiBB = new Bitboard(); nigemitiBB.Set(FriendRaion8KinboBB); nigemitiBB.Sitdown(FriendKomaBB); while (nigemitiBB.Ref_PopNTZ(out Masu ms_nigemiti)) { if (0 == ky.Shogiban.CountKikisuZenbu(Conv_Taikyokusya.Reverse(CurrentOptionalPhase), ms_nigemiti)) // 相手番の利きが無くなったか☆(^▽^) { akeru = true; // (^▽^)逃げ道が開いたぜ☆! goto gt_EndLoop; } } gt_EndLoop: ; // 重ね利きの数の差分更新を、元に戻すぜ☆(^▽^) 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(akeru); }
/// <summary> /// 駒の居場所 /// </summary> /// <param name="syuturyoku"></param> public static void HyojiKomanoIbasho(Shogiban shogiban, StringBuilder syuturyoku) { //IbasyoKomabetuBitboardItiran bb_koma, // KomaZenbuIbasyoBitboardItiran bb_komaZenbu syuturyoku.AppendLine("駒の居場所"); // 駒全部☆ { Setumei_Bitboards(new string[] { "対局者1", "対局者2" }, new Bitboard[] { shogiban.GetBBKomaZenbu(OptionalPhase.Black), shogiban.GetBBKomaZenbu(OptionalPhase.White) }, syuturyoku); syuturyoku.AppendLine(); } foreach (var optionalPhase81 in Conv_Taikyokusya.AllOptionalPhaseList)// 対局者1、対局者2 { // 見出し foreach (Koma km in Conv_Koma.ItiranTai[OptionalPhase.IndexOf(optionalPhase81)]) { syuturyoku.Append(FormatBanWidthZenkaku(Conv_Koma.GetName(km))); } syuturyoku.AppendLine(); // 盤 Bitboard[] bbHairetu = new Bitboard[Conv_Komasyurui.Itiran.Length]; int i = 0; foreach (Komasyurui ks in Conv_Komasyurui.Itiran) { bbHairetu[i] = shogiban.GetBBKoma(Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, optionalPhase81)); i++; } Setumei_Bitboards(bbHairetu, syuturyoku); } }
//private static Option<T> Option<T>(T white) //{ // throw new NotImplementedException(); //} /// <summary> /// 将棋盤をコンソールへ出力するぜ☆(^▽^) /// コンソールでゲームするのに向いた表示☆ /// </summary> /// <returns></returns> public static void Setumei_NingenGameYo(Kyokumen ky, StringBuilder syuturyoku) { // 1行目 { // 千日手 int sennitite = ky.Konoteme.GetSennititeCount(); if (Const_Game.SENNITITE_COUNT == sennitite) { Conv_Taikyokusya.Setumei_Name(Conv_Taikyokusya.Reverse(ky.CurrentOptionalPhase), syuturyoku); syuturyoku.Append("の着手にて 千日手"); syuturyoku.AppendLine(); } else if (1 < sennitite) { syuturyoku.Append("同一局面反復 "); syuturyoku.Append(sennitite.ToString()); syuturyoku.AppendLine(" 回目"); } else { syuturyoku.AppendLine(); } } // 2行目 { // 何手目 syuturyoku.Append("図は"); syuturyoku.Append(string.Format("{0,3}", ky.Konoteme.ScanNantemadeBango())); syuturyoku.Append("手まで "); // 手番 Conv_Taikyokusya.Setumei_Name(ky.CurrentOptionalPhase, syuturyoku); syuturyoku.Append("の番"); // #仲ルール if (Option_Application.Optionlist.SagareruHiyoko) { syuturyoku.Append(" #仲"); } syuturyoku.AppendLine(); } // 3行目 後手の持ち駒の数 { foreach (MotiKomasyurui mks in Conv_MotiKomasyurui.Itiran) { MotiKoma mk = Med_Koma.MotiKomasyuruiAndPhaseToMotiKoma(mks, OptionalPhase.White); if (ky.MotiKomas.HasMotiKoma(mk)) { syuturyoku.Append(Conv_MotiKomasyurui.GetHyojiName(mks)); syuturyoku.Append(ky.MotiKomas.Get(mk).ToString()); } } syuturyoku.AppendLine(); } // 4行目 { syuturyoku.Append(" "); AppendLine_SujiFugo_Kyokumen(syuturyoku); //syuturyoku.AppendLine(" A B C "); } // 5行目~13行目 // 盤上 { // 5行目 syuturyoku.Append(" "); Util_Information.AppendLine_Top_Kyokumen(1, syuturyoku); // ┌──┬──┬──┐ for (int dan = 0; dan < Option_Application.Optionlist.BanTateHaba; dan++) { // 6,8,10,12行目 syuturyoku.Append(Conv_Kihon.ToZenkakuInteger(dan + 1)); AppendLine_Data_Kyokumen(ky, dan, syuturyoku); if (dan + 1 < Option_Application.Optionlist.BanTateHaba) { // 7,9,11行目 syuturyoku.Append(" "); AppendLine_Middle(1, syuturyoku);//├──┼──┼──┤ } } // 13行目 syuturyoku.Append(" "); AppendLine_Bottom(1, syuturyoku);//└──┴──┴──┘ } // 14行目 { // 先手の持ち駒の数 foreach (MotiKomasyurui mks in Conv_MotiKomasyurui.Itiran) { MotiKoma mk = Med_Koma.MotiKomasyuruiAndPhaseToMotiKoma(mks, OptionalPhase.Black); if (ky.MotiKomas.HasMotiKoma(mk)) { syuturyoku.Append(Conv_MotiKomasyurui.GetHyojiName(mks)); syuturyoku.Append(ky.MotiKomas.Get(mk).ToString()); } } syuturyoku.AppendLine(); } }
/// <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()); // がない場合、詰み☆ ; }
/// <summary> /// トライしていれば真☆ /// </summary> /// <returns></returns> public static bool IsTried(Kyokumen ky, Option <Phase> phase) { switch (phase.Unwrap()) { case Phase.Black: return(ky.BB_DanArray[0].IsIntersect(ky.Shogiban.GetBBKoma(Med_Koma.KomasyuruiAndTaikyokusyaToKoma(Komasyurui.R, phase)))); case Phase.White: return(ky.BB_DanArray[Option_Application.Optionlist.BanTateHaba - 1].IsIntersect(ky.Shogiban.GetBBKoma(Med_Koma.KomasyuruiAndTaikyokusyaToKoma(Komasyurui.R, phase)))); default: throw new Exception("未定義の手番"); } }