/// <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="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="enableLog"></param> /// <param name="isHonshogi"></param> /// <param name="yomuDeep"></param> /// <param name="tesumi_yomiCur"></param> /// <param name="pside_yomiCur"></param> /// <param name="node_yomiCur"></param> /// <param name="logF_moveKiki"></param> /// <param name="logTag"></param> /// <returns>複数のノードを持つハブ・ノード</returns> private static KifuNode WAAAA_CreateNextNodes( MoveGenGenjo genjo, KifuNode node_yomiCur, SsssLogGenjo log ) { // 利きから、被王手の局面を除いたハブノード // このハブ・ノード自身は空っぽで、ハブ・ノードの次ノードが、次局面のリストになっています。 KifuNode hubNode; { // ①現手番の駒の移動可能場所_被王手含む List_OneAndMulti <Finger, SySet <SyElement> > komaBETUSusumeruMasus; { GraphicalLog_Board logBrd_move1 = new GraphicalLog_Board();// 盤1個分のログの準備 Util_MovableMove.LA_Get_KomaBETUSusumeruMasus( out komaBETUSusumeruMasus, //進めるマス new MmGenjo_MovableMasuImpl( genjo.Args.IsHonshogi, //本将棋か node_yomiCur.Value.ToKyokumenConst, //現在の局面 genjo.Pside_teban, //手番 false //相手番か ), new MmLogGenjoImpl( log.EnableLog, //ログを出力するかfalse, logBrd_move1, //ログ? genjo.YomuDeep, //読みの深さ genjo.Tesumi_yomiCur, //手済み node_yomiCur.Key //指し手 ) ); MoveGenRoutine.Log1(genjo, node_yomiCur, logBrd_move1);//ログ試し } // ②利きから、被王手の局面を除いたハブノード if (genjo.Args.IsHonshogi) { Maps_OneAndMulti <Finger, ShootingStarlightable> komaBETUAllMoves = Converter04.KomaBETUSusumeruMasusToKomaBETUAllMoves(komaBETUSusumeruMasus, node_yomiCur); Converter04.AssertNariMove(komaBETUAllMoves, "#WAAAA_CreateNextNodes(1)"); // 本将棋の場合、王手されている局面は削除します。 hubNode = Util_LegalMove.LA_RemoveMate( genjo.Args.IsHonshogi, komaBETUAllMoves, genjo.YomuDeep, genjo.Tesumi_yomiCur, genjo.Pside_teban, node_yomiCur, log.EnableLog, genjo.Args.LogF_moveKiki,//利き用 "読みNextルーチン"); Converter04.AddNariMove(node_yomiCur, hubNode); Converter04.AssertNariMove(hubNode, "#WAAAA_CreateNextNodes(2)");//ここで消えていた☆ } else { //そのまま変換 Dictionary <ShootingStarlightable, KyokumenWrapper> ss = Converter04.KomabetuMasusToMovebetuSky( komaBETUSusumeruMasus, node_yomiCur.Value.ToKyokumenConst, genjo.Pside_teban); hubNode = Converter04.MovebetuSky_ToHubNode(ss, KifuNodeImpl.GetReverseTebanside(genjo.Pside_teban)); } } return(hubNode); }