public static string BoardFileLog_ToJsonStr(GraphicalLog_File boardFileLog1) { StringBuilder sb_json_boardsLog = new StringBuilder(); foreach (GraphicalLog_Board boardLog1 in boardFileLog1.boards) { // 指し手。分かれば。 string moveStr = Converter04.MoveToStringForLog(boardLog1.moveOrNull, boardLog1.GenTeban); //string oldCaption = boardLog1.Caption; //boardLog1.Caption += "_" + moveStr; sb_json_boardsLog.Append(boardLog1.ToJsonStr()); //boardLog1.Caption = oldCaption; } return(sb_json_boardsLog.ToString()); }
/// <summary> /// ハブノードの次手番の局面のうち、王手がかかった局面は取り除きます。 /// </summary> public static void LAA_RemoveNextNode_IfMate( Node <ShootingStarlightable, KyokumenWrapper> hubNode, bool enableLog, int yomuDeep, //脳内読み手数 int tesumi_yomiGenTeban_forLog, //読み進めている現在の手目 Playerside pside_genTeban, GraphicalLog_File logF_kiki ) { // Node<,>の形で。 Dictionary <string, Node <ShootingStarlightable, KyokumenWrapper> > newNextNodes = new Dictionary <string, Node <ShootingStarlightable, KyokumenWrapper> >(); hubNode.Foreach_NextNodes((string key, Node <ShootingStarlightable, KyokumenWrapper> node, ref bool toBreak) => { System.Diagnostics.Debug.Assert(node.Key != null);//指し手がヌルなはず無いはず。 // 王様が利きに飛び込んだか? bool kingSuicide = Util_LegalMove.LAAA_KingSuicide( enableLog, node.Value.ToKyokumenConst, yomuDeep, tesumi_yomiGenTeban_forLog, pside_genTeban,//現手番=攻め手視点 logF_kiki, node.Key ); if (!kingSuicide) { // 王様が利きに飛び込んでいない局面だけ、残します。 if (newNextNodes.ContainsKey(key)) { newNextNodes[key] = node; } else { newNextNodes.Add(key, node); } } }); // 入替え hubNode.Set_NextNodes(newNextNodes); }
/// <summary> /// 指定された局面で、指定された手番の駒の、利きマスを算出します。 /// 持ち駒は盤上にないので、利きを調べる必要はありません。 /// /// 「手目」は判定できません。 /// /// </summary> /// <param name="kouho"></param> /// <param name="sbGohosyu"></param> /// <param name="logger"></param> public static List_OneAndMulti <Finger, SySet <SyElement> > LAAAA_GetEffect( bool enableLog, bool isHonshogi, SkyConst src_Sky, Playerside pside_genTeban3, bool isAiteban, GraphicalLog_File logF_kiki, string logBrd_caption, int yomuDeep_forLog,//脳内読み手数 int tesumi_yomiCur_forLog, ShootingStarlightable move_forLog ) { GraphicalLog_Board logBrd_kiki = new GraphicalLog_Board(); logBrd_kiki.Caption = logBrd_caption;// "利き_" logBrd_kiki.Tesumi = tesumi_yomiCur_forLog; logBrd_kiki.NounaiYomiDeep = yomuDeep_forLog; //logBrd_kiki.Score = 0.0d; logBrd_kiki.GenTeban = pside_genTeban3;// 現手番 logF_kiki.boards.Add(logBrd_kiki); // 《1》 List_OneAndMulti <Finger, SySet <SyElement> > sMs_effect = new List_OneAndMulti <Finger, SySet <SyElement> >();//盤上の駒の利き { // 《1.1》 Playerside tebanSeme; //手番(利きを調べる側) Playerside tebanKurau; //手番(喰らう側) { if (isAiteban) { tebanSeme = Converter04.AlternatePside(pside_genTeban3); tebanKurau = pside_genTeban3; } else { tebanSeme = pside_genTeban3; tebanKurau = Converter04.AlternatePside(pside_genTeban3); } if (Playerside.P1 == tebanSeme) { logBrd_kiki.NounaiSeme = Gkl_NounaiSeme.Sente; } else if (Playerside.P2 == tebanSeme) { logBrd_kiki.NounaiSeme = Gkl_NounaiSeme.Gote; } } // 《1.2》 Fingers fingers_seme_IKUSA; //戦駒(利きを調べる側) Fingers fingers_kurau_IKUSA; //戦駒(喰らう側) Fingers dust1; Fingers dust2; Util_Things.AAABAAAA_SplitGroup( out fingers_seme_IKUSA, out fingers_kurau_IKUSA, out dust1, out dust2, src_Sky, tebanSeme, tebanKurau ); // 攻め手の駒の位置 GraphicalLog_Board boardLog_clone = new GraphicalLog_Board(logBrd_kiki); foreach (Finger finger in fingers_seme_IKUSA.Items) { RO_Star_Koma koma = Util_Koma.AsKoma(src_Sky.StarlightIndexOf(finger).Now); Gkl_KomaMasu km = new Gkl_KomaMasu( Util_GraphicalLog.PsideKs14_ToString(tebanSeme, Haiyaku184Array.Syurui(koma.Haiyaku), ""), Util_Masu.AsMasuNumber(koma.Masu) ); boardLog_clone.KomaMasu1.Add(km); } foreach (Finger finger in fingers_kurau_IKUSA.Items) { RO_Star_Koma koma = Util_Koma.AsKoma(src_Sky.StarlightIndexOf(finger).Now); logBrd_kiki.KomaMasu2.Add(new Gkl_KomaMasu( Util_GraphicalLog.PsideKs14_ToString(tebanKurau, Haiyaku184Array.Syurui(koma.Haiyaku), ""), Util_Masu.AsMasuNumber(koma.Masu) )); } logBrd_kiki = boardLog_clone; // 《1.3》 SySet <SyElement> masus_seme_IKUSA = Converter04.Fingers_ToMasus(fingers_seme_IKUSA, src_Sky); // 盤上のマス(利きを調べる側の駒) SySet <SyElement> masus_kurau_IKUSA = Converter04.Fingers_ToMasus(fingers_kurau_IKUSA, src_Sky); // 盤上のマス(喰らう側の駒) // 駒のマスの位置は、特にログに取らない。 // 《1.4》 Maps_OneAndOne <Finger, SySet <SyElement> > kmEffect_seme_IKUSA = Util_Things.Get_KmEffect_seme_IKUSA( fingers_seme_IKUSA,//この中身がおかしい。 masus_seme_IKUSA, masus_kurau_IKUSA, src_Sky, enableLog, Converter04.MoveToStringForLog(move_forLog, pside_genTeban3) );// 利きを調べる側の利き(戦駒) // 戦駒の利き logBrd_kiki = new GraphicalLog_Board(logBrd_kiki); kmEffect_seme_IKUSA.Foreach_Entry((Finger key, SySet <SyElement> value, ref bool toBreak) => { RO_Star_Koma koma = Util_Koma.AsKoma(src_Sky.StarlightIndexOf(key).Now); string komaImg = Util_GraphicalLog.PsideKs14_ToString(tebanSeme, Haiyaku184Array.Syurui(koma.Haiyaku), ""); foreach (Basho masu in value.Elements) { boardLog_clone.Masu_theEffect.Add((int)masu.MasuNumber); } }); logBrd_kiki = boardLog_clone; // 《1》 = 《1.4》の戦駒+持駒 sMs_effect.AddRange_New(kmEffect_seme_IKUSA); } return(sMs_effect); }
/// <summary> /// 指定された手の中から、王手局面を除外します。 /// /// 王手回避漏れを防ぎたいんだぜ☆ /// </summary> /// <param name="km_available">自軍の各駒の移動できる升セット</param> /// <param name="sbGohosyu"></param> /// <param name="logTag"></param> public static KifuNode LA_RemoveMate( bool isHonshogi, Maps_OneAndMulti <Finger, ShootingStarlightable> genTeban_komabetuAllMove1, // 現手番の、どの駒が、どんな手を指すことができるか int yomuDeep, //脳内読み手数 int tesumi_yomiGenTeban, Playerside pside_yomiGenTeban, KifuNode siteiNode_yomiGenTeban, bool enableLog, GraphicalLog_File logF_kiki, string hint) { Node <ShootingStarlightable, KyokumenWrapper> hubNode = UtilKomabetuMove.ToNextNodes_AsHubNode( genTeban_komabetuAllMove1, siteiNode_yomiGenTeban, pside_yomiGenTeban ); // ハブ・ノード自身はダミーノードなんだが、子ノードに、次のノードが入っている。 Converter04.AssertNariMove(hubNode, "#LA_RemoveMate(1)"); //ここはok Util_LegalMove.Log1(hubNode, enableLog, tesumi_yomiGenTeban, hint); if (isHonshogi) { // 王手が掛かっている局面を除きます。 Util_LegalMove.LAA_RemoveNextNode_IfMate( hubNode, enableLog, yomuDeep, tesumi_yomiGenTeban, pside_yomiGenTeban, logF_kiki); } Converter04.AssertNariMove(hubNode, "#LA_RemoveMate(2)王手局面削除直後");//ここはok // 「指し手一覧」を、「駒別の全指し手」に分けます。 Maps_OneAndMulti <Finger, ShootingStarlightable> komabetuAllMoves2 = siteiNode_yomiGenTeban.SplitMoveByKoma(hubNode); Converter04.AssertNariMove(komabetuAllMoves2, "#LA_RemoveMate(3)更に変換後");//ここはok // // 「駒別の指し手一覧」を、「駒別の進むマス一覧」になるよう、データ構造を変換します。 // Maps_OneAndOne <Finger, SySet <SyElement> > komabetuSusumuMasus = new Maps_OneAndOne <Finger, SySet <SyElement> >();// 「どの駒を、どこに進める」の一覧 foreach (KeyValuePair <Finger, List <ShootingStarlightable> > entry in komabetuAllMoves2.Items) { Finger finger = entry.Key; List <ShootingStarlightable> teList = entry.Value; // ポテンシャル・ムーブを調べます。 SySet <SyElement> masus_PotentialMove = new SySet_Default <SyElement>("ポテンシャルムーブ"); foreach (ShootingStarlightable te in teList) { RO_Star_Koma koma = Util_Koma.AsKoma(te.Now); masus_PotentialMove.AddElement(koma.Masu); } if (!masus_PotentialMove.IsEmptySet()) { // 空でないなら Util_KomabetuMasus.AddOverwrite(komabetuSusumuMasus, finger, masus_PotentialMove); } } // まず、ディクショナリー構造へ変換。 Dictionary <ShootingStarlightable, KyokumenWrapper> movebetuSky = Converter04.KomabetuMasus_ToMovebetuSky( komabetuSusumuMasus, siteiNode_yomiGenTeban.Value.ToKyokumenConst, pside_yomiGenTeban); // 棋譜ノード構造へ変換。 return(Converter04.MovebetuSky_ToHubNode(movebetuSky, KifuNodeImpl.GetReverseTebanside(pside_yomiGenTeban))); }
/// <summary> /// 利きに飛び込んでいないか(王手されていないか)、調べます。 /// /// GetAvailableMove()の中では使わないでください。循環してしまいます。 /// </summary> public static bool LAAA_KingSuicide( bool enableLog, SkyConst src_Sky, //調べたい局面 int yomuDeep, //脳内読み手数 int tesumi_yomiCur_forLog, //読み進めている現在の手目 Playerside pside_genTeban, //現手番側 GraphicalLog_File logF_kiki, ShootingStarlightable move_forLog ) { bool isHonshogi = true; System.Diagnostics.Debug.Assert(src_Sky.Count == Masu_Honshogi.HONSHOGI_KOMAS); // 「相手の駒を動かしたときの利き」リスト // 持ち駒はどう考える?「駒を置けば、思い出王手だってある」 List_OneAndMulti <Finger, SySet <SyElement> > sMs_effect_aiTeban = Util_LegalMove.LAAAA_GetEffect( enableLog, isHonshogi, src_Sky, pside_genTeban, true,// 相手盤の利きを調べます。 logF_kiki, "玉自殺チェック", yomuDeep, tesumi_yomiCur_forLog, move_forLog); // 現手番側が受け手に回ったとします。現手番の、王の座標 SyElement genTeban_kingMasu; if (Playerside.P2 == pside_genTeban) { // 現手番は、後手 RO_Star_Koma koma = Util_Koma.AsKoma(src_Sky.StarlightIndexOf(Finger_Honshogi.GoteOh).Now); genTeban_kingMasu = koma.Masu; } else { // 現手番は、先手 RO_Star_Koma koma = Util_Koma.AsKoma(src_Sky.StarlightIndexOf(Finger_Honshogi.SenteOh).Now); genTeban_kingMasu = koma.Masu; } // 相手の利きに、自分の王がいるかどうか確認します。 bool mate = false; sMs_effect_aiTeban.Foreach_Entry((Finger koma, SySet <SyElement> kikis, ref bool toBreak) => { foreach (Basho kiki in kikis.Elements) { if (Util_Masu.AsMasuNumber(genTeban_kingMasu) == (int)kiki.MasuNumber) { mate = true; toBreak = true; } } }); return(mate); }
/// <summary> /// 読む。 /// /// 棋譜ツリーを作成します。 /// </summary> /// <param name="kifu">この棋譜ツリーの現局面に、次局面をぶら下げて行きます。</param> /// <param name="enableLog"></param> /// <param name="isHonshogi"></param> /// <param name="logTag"></param> /// <returns></returns> public static void WAA_Yomu_Start( KifuTree kifu, bool isHonshogi, SsssLogGenjo log ) { //------------------------------------------------------------ // (>_<)次の1手の合法手の中からランダムに選ぶぜ☆! //------------------------------------------------------------ // // バグ探し: // ①次の1手の合法手のリスト作成 // ②ランダムに1手選ぶ // // の2つしかやっていないんだが、合法手ではない手を返してくるんだぜ☆ #if DEBUG_STOPPABLE MessageBox.Show("ここでブレイク☆!", "デバッグ"); System.Diagnostics.Debugger.Break(); //throw new Exception("デバッグだぜ☆! エラーはキャッチできたかな~☆?(^▽^)"); #endif KifuNode node_yomiNext = (KifuNode)kifu.CurNode;// このノードに、ツリーをぶら下げていきます。 int yomuIndex = 0; // TODO:ここではログを出力せずに、ツリーの先端で出力したい。 GraphicalLog_File logF_moveKiki = new GraphicalLog_File(); // TODO:「読む」と、ツリー構造が作成されます。 //int[] yomuLimitter = new int[]{ // 600, // 読みの1手目の横幅 // 王手回避漏れのために、合法手全読み(約600)は必要です。 // 100, // 読みの2手目の横幅 // 100, // 読みの3手目の横幅 // //2, // 読みの4手目の横幅 // //1 // 読みの5手目の横幅 //}; //// ↓これなら1手1秒で指せる☆ //int[] yomuLimitter = new int[]{ // 600, // 読みの1手目の横幅 // 王手回避漏れのために、合法手全読み(約600)は必要です。 // 150, // 読みの2手目の横幅 // 150, // 読みの3手目の横幅 // //2 // 読みの4手目の横幅 // //1 // 読みの5手目の横幅 //}; //int[] yomuLimitter = new int[]{ // 600, // 読みの1手目の横幅 // 王手回避漏れのために、合法手全読み(約600)は必要です。 // 600, // 読みの2手目の横幅 // 600, // 読みの3手目の横幅 //}; //ok //int[] yomuLimitter = new int[]{ // 0, // 現局面は無視します。 // 600, // 読みの1手目の横幅 // 王手回避漏れのために、合法手全読み(約600)は必要です。 // 600, // 読みの2手目の横幅 //}; int[] yomuLimitter = new int[] { 0, // 現局面は無視します。 600, // 読みの1手目の横幅 // 王手回避漏れのために、1手目は、合法手全読み(約600)は必要です。 600, // 読みの2手目の横幅 //600, // 読みの3手目の横幅 }; #if DEBUG // ログの出力数を減らすために、読みを弱くします。 //yomuLimitter = new int[]{ // 0, // 現局面は無視します。 // 600, // 読みの1手目の横幅 // 王手回避漏れのために、合法手全読み(約600)は必要です。 // 100, // 読みの2手目の横幅 // 100 // 読みの3手目の横幅 //}; yomuLimitter = new int[] { 0, // 現局面は無視します。 600, // 読みの1手目の横幅 // 王手回避漏れのために、1手目は、合法手全読み(約600)は必要です。 600, // 読みの2手目の横幅 //600 // 読みの3手目の横幅 }; //yomuLimitter = new int[]{ // 600, // 読みの1手目の横幅 // 王手回避漏れのために、合法手全読み(約600)は必要です。 // 600, // 読みの2手目の横幅 // 600, // 読みの3手目の横幅 // 100, // 100 //}; #endif MoveGenArgs yomiArgs = new MoveGenArgsImpl(isHonshogi, yomuLimitter, logF_moveKiki); MoveGenGenjo yomiGenjo = new MoveGenGenjoImpl(yomiArgs, yomuIndex + 1, kifu.CurrentTesumi(), kifu.CountPside(node_yomiNext)); MoveGenRoutine.WAAA_Yomu_Loop(node_yomiNext, yomiGenjo, log); if (0 < logF_moveKiki.boards.Count)//ログが残っているなら { // // ログの書き出し // Util_GraphicalLog.Log( true,//enableLog, "MoveRoutine#Yomi_NextNodes(00)新ログ", "[" + Util_GraphicalLog.BoardFileLog_ToJsonStr(logF_moveKiki) + "]" ); // 書き出した分はクリアーします。 logF_moveKiki.boards.Clear(); } }