// 成れない駒(X Koma) 捨て王手指し public static void GenerateNx_SuteOteZasi() { // 王手に限る☆ GenerateMove03.SiborikomiOte(); // 紐を付けない☆ GenerateMove03.KesuHimoduke(); while (PureMemory.ssss_bbVar_idosaki_narazu.Ref_PopNTZ(out PureMemory.ssss_ugoki_ms_dst)) // 立っているビットを降ろすぜ☆ { if (GenerateMove03.TadasuteNoUgoki()) // タダ捨ての動きに限る☆ { PureMemory.SetSsssGenk( Tume1Hantei.CheckBegin_Tume1_BanjoKoma(),// 一手詰めルーチン☆ false, NigemitiWatasuKansyu.IsNigemitiWoAkeru() ); MoveGenAccessor.AddMoveNarazuGoodXorBad(); if (Tume1Hantei.CheckEnd_Tume1()) { break; } //終了☆ } } }
// らいおん 駒を取る手 public static void GenerateRaion_KomaWoToruTe() { // トライ は除外するぜ☆(^▽^) GenerateMove03.KesuTry(); // らいおん が自分から 相手の利きに飛び込むのを防ぐぜ☆(^▽^)www GenerateMove03.KesuRaionJisatusyu(); while (PureMemory.ssss_bbVar_idosaki_narazu.Ref_PopNTZ(out PureMemory.ssss_ugoki_ms_dst)) { // 駒を取るような全ての手は、選択肢に入れるぜ☆(^~^) PureMemory.SetSsssGenk( Tume1Hantei.CheckBegin_Tume1_BanjoKoma(),// 一手詰めルーチン☆ false, NigemitiWatasuKansyu.IsNigemitiWoAkeru() ); MoveGenAccessor.AddMoveNarazuGoodXorBad(); if (Tume1Hantei.CheckEnd_Tume1()) { break; } //終了☆ } }
// 成れる駒(Nareru Koma) 捨て緩慢指し(タダ捨て指し) public static void GenerateNk_SuteKanmanZasi() { // 王手も除外するぜ☆(^▽^) GenerateMove03.KesuOte(); // 成れる場合 while (PureMemory.ssss_bbVar_idosaki_nari.Ref_PopNTZ(out PureMemory.ssss_ugoki_ms_dst)) // 立っているビットを降ろすぜ☆ { if (GenerateMove03.TadasuteNoUgoki()) // 相手の利きがあって、自分を除いた味方の利きがない升 に限るぜ☆(^▽^)www { PureMemory.SetSsssGenk( false, // タダ捨てに、一手詰めは無いだろう☆(*^~^*) GenerateMove03.IsMisuteruUgoki(), false //逃げ道を開けて逃がすかどうかは判定しないぜ☆(^~^) ); MoveGenAccessor.AddMoveNariGood(); } } while (PureMemory.ssss_bbVar_idosaki_narazu.Ref_PopNTZ(out PureMemory.ssss_ugoki_ms_dst)) // 立っているビットを降ろすぜ☆ { if (GenerateMove03.TadasuteNoUgoki()) // 相手の利きがあって、自分を除いた味方の利きがない升 に限るぜ☆(^▽^)www { PureMemory.SetSsssGenk( false, // タダ捨てに、一手詰めは無いだろう☆(*^~^*) GenerateMove03.IsMisuteruUgoki(), false //逃げ道を開けて逃がすかどうかは判定しないぜ☆(^~^) ); MoveGenAccessor.AddMoveNarazuGoodXorBad(); } } }
// らいおん 逼迫返討手 public static void GenerateRaion_HippakuKaeriutiTe() { if (PureMemory.hot_isNigerarenaiCheckerAr[PureMemory.kifu_nTeban]) { // 逃げられない状況で、王手が掛かけられていれば☆(^~^) // らいおん が自分から利きに飛び込むのを防ぐぜ☆(^▽^)www GenerateMove03.KesuRaionJisatusyu(); while (PureMemory.ssss_bbVar_idosaki_narazu.Ref_PopNTZ(out PureMemory.ssss_ugoki_ms_dst)) { PureMemory.SetSsssGenk( Tume1Hantei.CheckBegin_Tume1_BanjoKoma(),// 一手詰めルーチン☆ false, false ); // チェッカーを取るような全ての手は、選択肢に入れるぜ☆(^~^) MoveGenAccessor.AddMoveNarazuGood(); if (Tume1Hantei.CheckEnd_Tume1()) { break; } //終了☆ } } }
// ぼっち緩慢指 | 紐付緩慢指 public static void Generate02NiwatoriNado_BottiKanmanZasi_HimodukiKanmanZasi() { // 王手も除外するぜ☆(^▽^) GenerateMove03.KesuOte(); while (PureMemory.ssss_bbVar_idosaki_narazu.Ref_PopNTZ(out PureMemory.ssss_ugoki_ms_dst)) // 立っているビットを降ろすぜ☆ { if (!GenerateMove03.TadasuteNoUgoki()) // タダ捨てではない動きに限るぜ☆(^▽^) { // 一手詰めルーチン☆ PureMemory.SetSsssGenk( Tume1Hantei.CheckBegin_Tume1_BanjoKoma(), GenerateMove03.IsMisuteruUgoki(), false//逃げ道を開けて逃がすかどうかは判定しないぜ☆(^~^) ); MoveGenAccessor.AddMoveNarazuGoodXorBad(); if (Tume1Hantei.CheckEnd_Tume1()) { break; } //終了☆ } } }
/// <summary> /// グローバル変数に結果を入れるぜ☆(^~^) /// </summary> /// <param name="out_list"></param> /// <param name="hyoji"></param> /// <returns></returns> public static bool TryFailMoveCmd1(StringBuilder hyoji) { //グローバル変数に指し手がセットされるぜ☆(^▽^) PureMemory.SetTnskFukasa(PureMemory.FUKASA_MANUAL); MoveGenAccessor.DoMovePickerBegin(MoveType.N21_All); MovePicker01.MovePickerN01(MoveType.N21_All, true); return(Pure.SUCCESSFUL_FALSE); }
/// <summary> /// カーソル位置を最初に戻すだけだぜ☆(^~^) /// </summary> public static void BackTemeToFirst_AndClearTeme() { PureMemory.ClearTeme(); // 最初の要素をリセットするぜ☆(^~^) PureMemory.kifu_moveArray[PureMemory.kifu_endTeme] = Move.Toryo; PureMemory.kifu_moveTypeArray[PureMemory.kifu_endTeme] = MoveType.N00_Karappo; PureMemory.kifu_toraretaKsAr[PureMemory.kifu_endTeme] = Komasyurui.Yososu; }
public static bool CheckEnd_Tume1() { if (PureSettei.ittedumeTukau && PureMemory.ssss_genk_tume1) { PureMemory.SetTansakuUtikiri(TansakuUtikiri.RaionTukamaeta); return(true); } return(false); }
public static bool Try_SetumeiTebanAll(StringBuilder hyoji) { hyoji.AppendLine("手番、最初の数件:"); for (int iTeme = 0; iTeme < 10 && iTeme < PureMemory.KIFU_SIZE; iTeme++) { hyoji.AppendLine(PureMemory.ToString_KifuCursor(iTeme)); } return(true); }
public static bool Try_Rnd( #if DEBUG IDebugMojiretu dbg_reigai #endif ) { //グローバル変数に指し手がセットされるぜ☆(^▽^) PureMemory.SetTnskFukasa(PureMemory.FUKASA_MANUAL); MoveGenAccessor.DoMovePickerBegin(MoveType.N21_All); MovePicker01.MovePickerN01(MoveType.N21_All, true); if (PureMemory.ssss_moveList[PureMemory.FUKASA_MANUAL].listCount < 1) { Move ss = Move.Toryo; MoveType ssType = MoveType.N00_Karappo; if (DoMoveOpe.TryFailDoMoveAll(ss, ssType #if DEBUG , PureSettei.fenSyurui , dbg_reigai , false , "Try_Rnd(1)" #endif )) { return(false); } // 手番を進めるぜ☆(^~^) MoveGenAccessor.AddKifu(ss, ssType, PureMemory.dmv_ks_c); //#if DEBUG // Util_Tansaku.Snapshot("Rndコマンド", dbg_reigai); //#endif } else { Move ss = PureMemory.ssss_moveList[PureMemory.FUKASA_MANUAL].moveList[PureSettei.random.Next(PureMemory.ssss_moveList[PureMemory.FUKASA_MANUAL].listCount)]; MoveType ssType = MoveType.N00_Karappo; if (DoMoveOpe.TryFailDoMoveAll(ss, ssType #if DEBUG , PureSettei.fenSyurui , dbg_reigai , false , "Try_Rnd(2)" #endif )) { return(false); } // 手番を進めるぜ☆(^~^) MoveGenAccessor.AddKifu(ss, ssType, PureMemory.dmv_ks_c); //#if DEBUG // Util_Tansaku.Snapshot("Rnd(2)", dbg_reigai); //#endif } return(true); }
/// <summary> /// カーソル位置に挿入。 /// カーソルは1進み、エンドは進んだカーソル位置に合わせるぜ☆(^~^) /// </summary> /// <param name="ss"></param> /// <param name="ssType"></param> public static void AddKifu(Move ss, MoveType ssType, Komasyurui toraretaKs) { PureMemory.kifu_moveArray[PureMemory.kifu_endTeme] = ss; PureMemory.kifu_moveTypeArray[PureMemory.kifu_endTeme] = ssType; // 取った駒の種類を覚えておくぜ☆(^▽^) PureMemory.kifu_toraretaKsAr[PureMemory.kifu_endTeme] = toraretaKs; // 棋譜を進めるぜ☆(^~^) PureMemory.AddTeme(); }
/// <summary> /// グローバル変数 Util_MoveSeisei.Movelist[fukasa] に、指し手が追加されていくぜ☆(^▽^) /// 捨て緩慢打(タダ捨て打) /// </summary> /// <param name="mks"></param> /// <param name="mk"></param> /// <param name="ks"></param> public static void GenerateMotigoma_SuteDa() { while (PureMemory.ssss_bbVar_idosaki_narazu.Ref_PopNTZ(out PureMemory.ssss_ugoki_ms_dst)) // 立っているビットを降ろすぜ☆ { if (GenerateMove03.TadasuteNoUgoki()) // タダ捨ての動きに限る☆ { PureMemory.SetSsssGenk( false, // タダ捨てに、一手詰めは無いだろう☆(*^~^*) false, // 持ち駒を打つのに、見捨てる動きも無いだろう☆(^~^) false // 持ち駒を打つのに、逃げ道を開けて逃がす動きも無いだろう☆(^~^) ); MoveGenAccessor.AddMoveUttaGood(); } } }
// らいおん トライ public static void GenerateRaion_Try() { // らいおん が自分から 相手の利きに飛び込むのを防ぐぜ☆(^▽^)www GenerateMove03.KesuRaionJisatusyu(); Pure.Sc.Push("トライ", PureMemory.tnsk_hyoji); Bitboard trysakiBB = Util_TryRule.GetTrySaki(PureMemory.ssss_bbVar_idosaki_narazu, PureMemory.ssss_ugoki_ms_src); Pure.Sc.Pop(); if (trysakiBB.GetNTZ(out PureMemory.ssss_ugoki_ms_dst))// トライはどこか1つ行けばいい { MoveGenAccessor.AddMoveNarazuGood(); PureMemory.SetTansakuUtikiri(TansakuUtikiri.Try); } }
/// <summary> /// グローバル変数 Util_MoveSeisei.Movelist[fukasa] に、指し手が追加されていくぜ☆(^▽^) /// 紐付王手打 /// </summary> /// <param name="mks"></param> /// <param name="mk"></param> /// <param name="ks"></param> public static void GenerateMotigoma_NormalDa() { while (PureMemory.ssss_bbVar_idosaki_narazu.Ref_PopNTZ(out PureMemory.ssss_ugoki_ms_dst))// 立っているビットを降ろすぜ☆ { PureMemory.SetSsssGenk( Tume1Hantei.CheckBegin_Ittedume_MotiKoma(), // 一手詰めルーチン☆ false, // 持ち駒を打つのに、見捨てる動きも無いだろう☆(^~^) false // 持ち駒を打つのに、逃げ道を開けて逃がす動きも無いだろう☆(^~^) ); MoveGenAccessor.AddMoveUttaGood(); if (Tume1Hantei.CheckEnd_Tume1()) { break; } //終了☆ } }
// 成れる駒(Nareru Koma) 余裕返討手 public static void GenerateNk_YoyuKaeriutiTe() { if (!PureMemory.hot_isNigerarenaiCheckerAr[PureMemory.kifu_nTeban]) { // 逃げられない状況で、王手が掛かけられている……、というわけでもなければ☆(^~^) // 成れる場合 while (PureMemory.ssss_bbVar_idosaki_nari.Ref_PopNTZ(out PureMemory.ssss_ugoki_ms_dst)) { PureMemory.SetSsssGenk( Tume1Hantei.CheckBegin_Tume1_BanjoKoma(),// 一手詰めルーチン☆ false, false ); // チェッカーを取るような全ての手は、選択肢に入れるぜ☆(^~^) MoveGenAccessor.AddMoveNariGood(); if (Tume1Hantei.CheckEnd_Tume1()) { break; } //終了☆ } while (PureMemory.ssss_bbVar_idosaki_narazu.Ref_PopNTZ(out PureMemory.ssss_ugoki_ms_dst)) { PureMemory.SetSsssGenk( Tume1Hantei.CheckBegin_Tume1_BanjoKoma(),// 一手詰めルーチン☆ false, false ); // チェッカーを取るような全ての手は、選択肢に入れるぜ☆(^~^) MoveGenAccessor.AddMoveNarazuGood(); if (Tume1Hantei.CheckEnd_Tume1()) { break; } //終了☆ } } }
/// <summary> /// Go する前に☆(^~^) /// </summary> public static void PreGo() { PureMemory.tnsk_itibanFukaiNekkoKaranoFukasa_JohoNoTameni = 0; // 読み筋情報に表示するための、読み終わった、一番深い根っこからの深さを覚えておくものだぜ☆(^▽^) // カウンターをクリアだぜ☆(^▽^) PureMemory.tnsk_tyakusyuEdas = 0; PureMemory.tnsk_kohoMove = Move.Toryo; // ストップウォッチ ComSettei.timeManager.RestartStopwatch_Tansaku(); ComSettei.timeManager.lastJohoTime = 0; // ループに入ると探索開始時にセットするんだが、最初の1回はループに入るために、何か設定しておく必要があるぜ☆(*^~^*) ComSettei.SetSikoJikan_KonkaiNoTansaku(); PureMemory.InitTansaku(); #if DEBUG PureMemory.tnsk_syuryoRiyu = TansakuSyuryoRiyu.Kaisi; #endif }
// らいおん、成れない駒(X Koma) 駒を取る手 public static void GenerateXk_KomaWoToruTe() { while (PureMemory.ssss_bbVar_idosaki_narazu.Ref_PopNTZ(out PureMemory.ssss_ugoki_ms_dst)) { // 駒を取るような全ての手は、選択肢に入れるぜ☆(^~^) PureMemory.SetSsssGenk( Tume1Hantei.CheckBegin_Tume1_BanjoKoma(),// 一手詰めルーチン☆ false, NigemitiWatasuKansyu.IsNigemitiWoAkeru() ); MoveGenAccessor.AddMoveNarazuGoodXorBad(); if (Tume1Hantei.CheckEnd_Tume1()) { break; } //終了☆ } }
// 成れる駒(Nareru Koma) らいおんキャッチ調査 | らいおんキャッチ public static void GenerateNk_RaionCatch() { // 成れる場合 if (PureMemory.ssss_bbVar_idosaki_nari.GetNTZ(out PureMemory.ssss_ugoki_ms_dst)) { // らいおんをキャッチする手は、1つ見つければOKだぜ☆(^~^) if (MoveType.N17_RaionCatchChosa == PureMemory.ssss_ugoki_kakuteiSsType) { // 調査するだけ☆ らいおんキャッチできることが分かったので終了☆(^~^) PureMemory.hot_raionCatchChosaAr[PureMemory.kifu_nTeban] = true; return; } MoveGenAccessor.AddMoveNariGood(); PureMemory.SetTansakuUtikiri(TansakuUtikiri.RaionTukamaeta); } if (PureMemory.ssss_bbVar_idosaki_narazu.GetNTZ(out PureMemory.ssss_ugoki_ms_dst)) { // らいおんをキャッチする手は、1つ見つければOKだぜ☆(^~^) if (MoveType.N17_RaionCatchChosa == PureMemory.ssss_ugoki_kakuteiSsType) { // 調査するだけ☆ らいおんキャッチできることが分かったので終了☆(^~^) PureMemory.hot_raionCatchChosaAr[PureMemory.kifu_nTeban] = true; return; } PureMemory.SetSsssGenk( false, false, NigemitiWatasuKansyu.IsNigemitiWoAkeru() ); MoveGenAccessor.AddMoveNarazuGoodXorBad(); PureMemory.SetTansakuUtikiri(TansakuUtikiri.RaionTukamaeta); } }
// 仲間を見捨てる動きは Badへ☆(^~^) // らいおん ぼっち緩慢指 | 紐付き緩慢指 (らいおんは 捨て緩慢指し をやらないぜ☆) public static void GenerateRaion_BottiKanmanZasi_HimodukiKanmanZasi() { // トライ は除外するぜ☆(^▽^) GenerateMove03.KesuTry(); // らいおん が自分から 相手の利きに飛び込むのを防ぐぜ☆(^▽^)www GenerateMove03.KesuRaionJisatusyu(); while (PureMemory.ssss_bbVar_idosaki_narazu.Ref_PopNTZ(out PureMemory.ssss_ugoki_ms_dst))// 立っているビットを降ろすぜ☆ { PureMemory.SetSsssGenk( Tume1Hantei.CheckBegin_Tume1_BanjoKoma(), // 一手詰めルーチン☆ GenerateMove03.IsMisuteruUgoki(), false //逃げ道を開けて逃がすかどうかは判定しないぜ☆(^~^) ); MoveGenAccessor.AddMoveNarazuGoodXorBad(); if (Tume1Hantei.CheckEnd_Tume1()) { break; } //終了☆ } }
/// <summary> /// 指定した指し手をやりなおす動きをするぜ☆(^▽^) /// </summary> /// <param name="ss"></param> public static bool TryFailUndoMove( #if DEBUG FenSyurui dbg_f , IDebugMojiretu dbg_reigai #endif ) { //──────────────────────────────────────── // 手番 //──────────────────────────────────────── // 事前に戻すぜ☆(^▽^) PureMemory.RemoveTeme(); //──────────────────────────────────────── // まず最初に整合性を確認だぜ☆(^~^) //──────────────────────────────────────── //──────────────────────────────────────── // グローバル変数に、結果を入れておくぜ☆(^~^) //──────────────────────────────────────── MoveGenAccessor.BunkaiMoveUmv(); if (Move.Toryo == PureMemory.umv_ss) { goto gt_EndMethod; } // なにも更新せず終了☆(^▽^) if (TryFail_Tejun1_IdosakiNoTebanNoKomaWoTorinozoku( #if DEBUG dbg_f , dbg_reigai #endif )) { return(Pure.FailTrue("TryFail_Tejun1_IdosakiNoTebanNoKomaWoTorinozoku")); } if (AbstractConvMove.IsUtta(PureMemory.umv_ss)) { // 打つ if (TryFail_Tejun2Utu_IdomotoniTebannoKomawoModosu( #if DEBUG dbg_f , dbg_reigai #endif )) { return(Pure.FailTrue("TryFail_Tejun2_IdomotoniTebannoKomawoModosu")); } } else { // 指す if (TryFail_Tejun2Sasu_IdomotoniTebannoKomawoModosu( #if DEBUG dbg_f , dbg_reigai #endif )) { return(Pure.FailTrue("TryFail_Tejun2_IdomotoniTebannoKomawoModosu")); } } if (TryFail_Tejun3_KomadaiKaraTottakomawoJogai( #if DEBUG dbg_f , dbg_reigai #endif )) { return(Pure.FailTrue("TryFail_Tejun3_KomadaiKaraTottakomawoJogai")); } if (TryFail_Tejun4_IdosakiniTottakomawoModosu( #if DEBUG dbg_f , dbg_reigai #endif )) { return(Pure.FailTrue("TryFail_Tejun4_IdosakiniTottakomawoModosu")); } //──────────────────────────────────────── // 最後に一括更新 //──────────────────────────────────────── gt_EndMethod: //──────────────────────────────────────── // 最後に整合性を確認だぜ☆(^~^) //──────────────────────────────────────── return(Pure.SUCCESSFUL_FALSE); }
public static void AddMoveNariGoodXorBad() { Move ss = AbstractConvMove.ToMove01bNariSasi(PureMemory.ssss_ugoki_ms_src, PureMemory.ssss_ugoki_ms_dst); if (PureMemory.ssss_genk_tume1) { MoveGenAccessor.ClearMoveList(); } //他の指し手を消し飛ばすぜ☆(^▽^) Debug.Assert(Move.Toryo != ss, ""); if (PureMemory.IsAkusyu_Ssss) { PureMemory.ssss_moveListBad[PureMemory.tnsk_fukasa].AddList(ss, PureMemory.ssss_ugoki_kakuteiSsType | PureMemory.GetAkusyuType_Ssss()); } else { PureMemory.ssss_moveList[PureMemory.tnsk_fukasa].AddList(ss, PureMemory.ssss_ugoki_kakuteiSsType); } }
/// <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="ky"></param> /// <param name="alpha"></param> /// <param name="fukasa">カウントダウン式の数字☆(^▽^) 反復深化探索の1週目の初期値は 1、2週目の初期値は 2 だぜ☆(^▽^) /// これがどんどんカウントダウンしていくぜ☆(^▽^) 0 で呼び出されたときは葉にしてすぐ処理を終われよ☆(^▽^)www</param> /// <param name="out_yomisujiToBack"></param> /// <param name="out_bestHyokatiAb1">手番から見た指し手の評価値だぜ☆(^~^)</param> /// <param name="out_edaBest_Komawari_JohoNoTame">内訳の目視確認用に使うだけの項目。</param> /// <param name="out_edaBest__Okimari_JohoNoTame">内訳の目視確認用に使うだけの項目。</param> /// <param name="out_edaBest_____Riyu_JohoNoTame">内訳の目視確認用に使うだけの項目。</param> /// <param name="dlgt_CreateJoho"></param> /// <returns></returns> private static void Tansaku_( out Move out_bestMove, out Hyokati out_bestHyokasu // 手番側の指し手の評価値だぜ☆(^~^) ) { Debug.Assert(0 <= PureMemory.tnsk_fukasa && PureMemory.tnsk_fukasa < PureMemory.ssss_moveList.Length, ""); out_bestMove = Move.Toryo; out_bestHyokasu = null; //──────────────────────────────────────── // 時間切れ判定 //──────────────────────────────────────── if (ComSettei.timeManager.IsTimeOver_TansakuChu()) { out_bestMove = Move.Toryo; out_bestHyokasu = new Hyokati( Conv_Hyokati.Hyokati_Rei, Conv_Tumesu.Stalemate, true // 今回の探索の結果は破棄するぜ☆(^~^) #if DEBUG , Conv_Hyokati.Hyokati_Rei , Conv_Hyokati.Hyokati_Rei , Conv_Hyokati.Hyokati_Rei , HyokaRiyu.JikanGire , "" #endif ); #if DEBUG Util_Tansaku.Snapshot("時間切れだぜ☆(^~^)", out_bestMove); #endif return; } //──────────────────────────────────────── // 葉 //──────────────────────────────────────── #region 葉 if ( // 深さ0 で呼び出されたときは、葉にしろということだぜ☆(^▽^)www PureMemory.tnsk_fukasa == 0 ) { // 深さ(根っこからの深さ)は 1 以上で始まるから、ループの1週目は、スルーされるはずだぜ☆(^▽^) // 1手指して 枝を伸ばしたとき、相手の手番の局面になっているな☆(^▽^)そのとき ここを通る可能性があるぜ☆ // // 末端局面で評価値を作らないぜ☆(^~^)! // 指し手を、指したときに作るんだぜ☆(^~^)! // PureMemory.tnsk_happaTeme = PureMemory.kifu_endTeme; // 「手目」カーソルは DoMove で1つ進んでいるはずなので、戻すんだぜ☆(^~^) out_bestMove = PureMemory.kifu_moveArray[PureMemory.kifu_endTeme - 1]; out_bestHyokasu = new Hyokati(PureMemory.gky_hyokati); // 葉で情報表示 Util_Joho.JohoMatome( PureMemory.tnsk_fukasa + 1, out_bestHyokasu, PureMemory.tnsk_hyoji #if DEBUG , out_bestHyokasu.dbg_riyu.ToString() #endif ); #if DEBUG Util_Tansaku.Snapshot("葉だぜ☆(^~^)", out_bestMove); #endif return;//枝を戻る(正常終了) } #endregion //──────────────────────────────────────── // 指し手生成 //──────────────────────────────────────── // グローバル変数 Util_MoveSeisei.Sslist に指し手がセットされるぜ☆(^▽^) MoveGenAccessor.DoMovePickerBegin(MoveType.N21_All); MovePicker01.MovePickerN01(MoveType.N21_All, true); #region ステイルメイト //──────────────────────────────────────── // ステイル・メイト //──────────────────────────────────────── if (PureMemory.ssss_moveList[PureMemory.tnsk_fukasa].listCount < 1) { // 詰んでるぜ☆(^~^) out_bestMove = Move.Toryo; out_bestHyokasu = new Hyokati( Conv_Hyokati.Hyokati_Rei, Conv_Tumesu.Stalemate, false #if DEBUG , Conv_Hyokati.Hyokati_Rei , Conv_Hyokati.Hyokati_Rei , Conv_Hyokati.Hyokati_Rei , HyokaRiyu.Stalemate , "" #endif ); // ステイルメイトで情報表示 Util_Joho.JohoMatome( PureMemory.tnsk_fukasa + 1,// 深さは 0 になっているので、Tansaku していない状態(=+1 して)に戻すぜ☆ out_bestHyokasu, PureMemory.tnsk_hyoji #if DEBUG , "Stalemate" #endif ); #if DEBUG Util_Tansaku.Snapshot("ステイルメイトだぜ☆(^~^)", out_bestMove); MoveSeiseiAccessor.DumpMoveSeisei(PureMemory.tnsk_hyoji); #endif return;//枝を戻る(正常終了) } #endregion for (int iSs = 0; iSs < PureMemory.ssss_moveList[PureMemory.tnsk_fukasa].listCount; iSs++) { // 枝☆ 適当にここらへんでカウントアップするかだぜ☆(^~^) PureMemory.tnsk_tyakusyuEdas++; //──────────────────────────────────────── // 指す //──────────────────────────────────────── //#if DEBUG // Util_Tansaku.Snapshot("ドゥ前", hyoji); //#endif Move ss_jibun = PureMemory.ssss_moveList[PureMemory.tnsk_fukasa].moveList[iSs]; MoveType ssType_jibun = PureMemory.ssss_moveList[PureMemory.tnsk_fukasa].moveTypeList[iSs]; if (DoMoveOpe.TryFailDoMoveAll( ss_jibun, ssType_jibun #if DEBUG , PureSettei.fenSyurui , (IDebugMojiretu)PureMemory.tnsk_hyoji , false , "TryFail_Tansaku_(1)" #endif )) { // 探索時にエラーが起こった場合は強制終了☆(^~^) throw new Exception(PureMemory.tnsk_hyoji.ToString()); } // 手番を進めるぜ☆(^~^) MoveGenAccessor.AddKifu( ss_jibun, ssType_jibun, PureMemory.dmv_ks_c); #if DEBUG Util_Tansaku.Snapshot("ドゥ後・探索前", out_bestMove); #endif Move ss_aite; //MoveType eda_moveType; // goto文で飛ぶと未割当になるので、ヌルでも入れておくぜ☆(^~^) Hyokati hyokasu_aiteToJibun = null; // この指し手が、駒を取った手かどうか☆ PureMemory.SetTnskHyoji(PureMemory.tnsk_hyoji); // 探索者がプラスでスタートして、 // 探索者の反対側はマイナスになり、 // 探索者の反対側の反対側はプラスに戻るぜ☆(^▽^) PureMemory.DecreaseTnskFukasa(); Tansaku_( out ss_aite, out hyokasu_aiteToJibun // 相手番の指し手の評価値が入ってくるぜ☆(^~^) ); PureMemory.IncreaseTnskFukasa(); //#if DEBUG // Util_Tansaku.Snapshot("探索後・アンドゥ前", hyoji); //#endif //──────────────────────────────────────── // 詰みを発見していれば、打ち切りフラグを立てるぜ☆(*^~^*) //──────────────────────────────────────── bool undoAndBreak = false; if (hyokasu_aiteToJibun.tumeSu == Conv_Tumesu.CatchRaion) { out_bestMove = ss_jibun; out_bestHyokasu = new Hyokati( Conv_Hyokati.Hyokati_Rei, Conv_Tumesu.CatchRaion,// この枝にこれるようなら、勝ち宣言だぜ☆(^▽^) false #if DEBUG , Conv_Hyokati.Hyokati_Rei , Conv_Hyokati.Hyokati_Rei , Conv_Hyokati.Hyokati_Rei , HyokaRiyu.TansakuRaionCatch , "" #endif ); // 打ち切りで情報表示 Util_Joho.JohoMatome( PureMemory.tnsk_fukasa, out_bestHyokasu, PureMemory.tnsk_hyoji #if DEBUG , "TansakuRaionCatch" #endif ); // 詰みではなく、らいおんきゃっち または トライかを 調べるぜ☆(^~^) // この手番は、 // この指し手を選べば、勝てるという理屈だが……☆ undoAndBreak = true; #if DEBUG Util_Tansaku.Snapshot("らいおんキャッチだぜ☆(^~^)", out_bestMove); #endif } // 探索で先の枝から戻ってきたときは、評価の符号を反転し、詰め手数のカウントもアップするぜ☆(^~^) hyokasu_aiteToJibun.CountUpTume(); hyokasu_aiteToJibun.ToHanten(); if (UndoMoveOpe.TryFailUndoMove( #if DEBUG PureSettei.fenSyurui , (IDebugMojiretu)PureMemory.tnsk_hyoji #endif )) { // 探索時にエラーが起こった場合は強制終了☆(^~^) throw new Exception(PureMemory.tnsk_hyoji.ToString()); } #if DEBUG Util_Tansaku.Snapshot("アンドゥ後", out_bestMove); #endif //──────────────────────────────────────── // これ以上 弟要素を探索するのを止め、枝を戻るかどうか☆(^~^) //──────────────────────────────────────── #region 打ち切り各種 if (undoAndBreak) { // (1)千日手の権利を相手に渡すために低点数付け<それ以降の手は読まない> // (2)らいおん を捕獲した // (3)トライ した #if DEBUG Util_Tansaku.Snapshot("アンドゥ後ブレイクだぜ☆(^~^)", out_bestMove); #endif break;//枝を戻る(正常終了) } #endregion //──────────────────────────────────────── // アップデート・枝ベスト //──────────────────────────────────────── #region アップデート・枝ベスト // 点数が付かないことがあって、その場合 ベスト指し手 を1度も選ばない // 「<=」にすると同点だったら、指し手のオーダリングの低いのを選ぶが☆(^~^) if (null == out_bestHyokasu) { out_bestMove = ss_jibun; out_bestHyokasu = hyokasu_aiteToJibun;// new HyokaSu(eda_hyokasu);//ここで新規作成 #if DEBUG Util_Tansaku.Snapshot("アップデート枝ベスト1回目だぜ☆(^~^)", out_bestMove); #endif } else if (out_bestHyokasu.hyokaTen < hyokasu_aiteToJibun.hyokaTen) { out_bestMove = ss_jibun; out_bestHyokasu.ToSet(hyokasu_aiteToJibun); // 兄弟の中で一番の読み筋だぜ☆(^▽^) // ↓ // TODO: ここで情報を表示したいが……☆(^~^) #if DEBUG Util_Tansaku.Snapshot("アップデート枝ベストだぜ☆(^~^)", out_bestMove); #endif } #endregion }//指し手ループ //; // このノードでの最大評価を返すんだぜ☆(^▽^) // ここでアルファを返してしまうと、アルファが1回も更新されなかったときに、このノードの最大評価ではないものを返してしまうので不具合になるぜ☆(^~^) if (null == out_bestHyokasu) { out_bestMove = Move.Toryo; out_bestHyokasu = new Hyokati( Conv_Hyokati.Hyokati_Rei, Conv_Tumesu.None, false #if DEBUG , Conv_Hyokati.Hyokati_Rei , Conv_Hyokati.Hyokati_Rei , Conv_Hyokati.Hyokati_Rei , HyokaRiyu.Fumei , "ループ抜け" #endif ); // ステイルメイトで情報表示 Util_Joho.JohoMatome( PureMemory.tnsk_fukasa, out_bestHyokasu, PureMemory.tnsk_hyoji #if DEBUG , "LoopOut" #endif ); #if DEBUG Util_Tansaku.Snapshot("評価の決まらない、ループ抜けだぜ☆(^~^)", out_bestMove); #endif return;//枝を戻る(正常終了) } }
/// <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> /// <returns></returns> static void Setumei_Hanyo( DLGT_dataBu dlgt_dataBu, int banYokoHaba_tmp, int banTateHaba_tmp, int teme, StringBuilder hyoji ) { #region 盤の上の方 // 2行目 { // 何手目 hyoji.Append(string.Format("図は{0,3}手まで ", teme)); // 手番 SpkTaikyokusya.AppendSetumeiName(PureMemory.GetTebanByTeme(teme), hyoji); hyoji.Append("の番"); hyoji.AppendLine(); } // 3行目 後手の持ち駒 { // 後手の持ち駒の数 foreach (MotigomaSyurui mks in Conv_MotigomaSyurui.itiran) { Motigoma mk = Med_Koma.MotiKomasyuruiAndTaikyokusyaToMotiKoma(mks, Taikyokusya.T2); if (PureMemory.gky_ky.yomiKy.yomiMotigomaItiran.HasMotigoma(mk)) { hyoji.Append(Conv_MotigomaSyurui.GetHyojiName(mks)); hyoji.Append(PureMemory.gky_ky.yomiKy.yomiMotigomaItiran.Count(mk).ToString()); } } hyoji.AppendLine(); } // 4行目 { // A B C D とか hyoji.Append(" "); SpkBanWaku.AppendLine_SujiFugo(banYokoHaba_tmp, hyoji); } // 5行目 { hyoji.Append(" "); SpkBanWaku.AppendLine_TopBar(1, PureSettei.banYokoHaba, hyoji); // ┌──┬──┬──┐ } #endregion // 5行目~13行目 // 盤上 for (int dan = 0; dan < PureSettei.banTateHaba; dan++) { // 6,8,10,12行目 hyoji.Append(Conv_Kihon.ToZenkakuInteger(dan + 1)); SpkBanWaku.AppendLine_Record_Cell4Hankakus2( (Masu ms) => { return(dlgt_dataBu(dan, ms)); }, dan, banYokoHaba_tmp, hyoji); if (dan + 1 < PureSettei.banTateHaba) { // 7,9,11行目 hyoji.Append(" "); SpkBanWaku.AppendLine_MiddleBar(1, PureSettei.banYokoHaba, hyoji);//├──┼──┼──┤ } } #region 盤の下の方 // 13行目 { hyoji.Append(" "); SpkBanWaku.AppendLine_BottomBar(1, PureSettei.banYokoHaba, hyoji);//└──┴──┴──┘ } // 先手の持ち駒の数 { foreach (MotigomaSyurui mks in Conv_MotigomaSyurui.itiran) { Motigoma mk = Med_Koma.MotiKomasyuruiAndTaikyokusyaToMotiKoma(mks, Taikyokusya.T1); if (PureMemory.gky_ky.yomiKy.yomiMotigomaItiran.HasMotigoma(mk)) { hyoji.Append(Conv_MotigomaSyurui.GetHyojiName(mks)); hyoji.Append(PureMemory.gky_ky.yomiKy.yomiMotigomaItiran.Count(mk).ToString()); } } hyoji.AppendLine(); } #endregion }