/// <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); }
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> /// 探索だぜ☆(^▽^) /// </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;//枝を戻る(正常終了) } }