Beispiel #1
0
        public static KifuNode MovebetuSky_ToHubNode(Dictionary <ShootingStarlightable, KyokumenWrapper> movebetuSkys, Playerside nextTebanside)
        {
            KifuNode hubNode = new KifuNodeImpl(null, null, Playerside.Empty);

            foreach (KeyValuePair <ShootingStarlightable, KyokumenWrapper> nextNode in movebetuSkys)
            {
                hubNode.Add_NextNode(
                    Util_Sky.ToSfenMoveText(nextNode.Key),
                    new KifuNodeImpl(nextNode.Key, nextNode.Value, nextTebanside)
                    );
            }

            return(hubNode);
        }
Beispiel #2
0
        /// <summary>
        /// 取った駒を差替えます。
        ///
        /// 棋譜読取時用です。マウス操作時は、流れが異なるので使えません。
        /// </summary>
        public void AppendChildB_Swap(
            PieceType tottaSyurui,
            SkyConst src_Sky,
            string hint
            )
        {
            if (this.CountTesumi(this.CurNode) < 1)
            {
                // ルートしか無いなら
                goto gt_EndMethod;
            }

            if (null == src_Sky)
            {
                throw new Exception("ノードを追加しようとしましたが、指定されたnewSkyがヌルです。");
            }


            Playerside genTebanside = ((KifuNode)this.CurNode).Tebanside;
            // 現在のノードを削除します。そのとき、もともとのキー を覚えておきます。
            ShootingStarlightable motoKey = (ShootingStarlightable)this.PopCurrentNode().Key;

            // もともとのキーの、取った駒の種類だけを差替えます。
            RO_ShootingStarlight sasikaeKey = Util_Sky.New(motoKey.LongTimeAgo, motoKey.Now, tottaSyurui);//motoKey.Finger,

            // キーを差替えたノード
            Node <ShootingStarlightable, KyokumenWrapper> sasikaeNode = new KifuNodeImpl(sasikaeKey, new KyokumenWrapper(src_Sky), genTebanside);

            System.Diagnostics.Debug.Assert(!this.CurNode.ContainsKey_NextNodes(Util_Sky.ToSfenMoveText(sasikaeNode.Key)));


            // さきほど カレントノードを削除したので、
            // 今、カレントノードは、1つ前のノードになっています。
            // ここに、差替えたノードを追加します。
            this.CurNode.Add_NextNode(Util_Sky.ToSfenMoveText(sasikaeNode.Key), sasikaeNode);
            sasikaeNode.PreviousNode = this.CurNode;


            this.CurNode = sasikaeNode;

            Logger.Trace("リンクトリストの、最終ノードは差し替えられた hint=[" + hint + "] item=[" + Util_Sky.ToSfenMoveText(sasikaeKey) + "]");
            // memberName=[" + memberName + "] sourceFilePath=[" + sourceFilePath + "] sourceLineNumber=[" + sourceLineNumber + "]

gt_EndMethod:
            ;
        }
Beispiel #3
0
        /// <summary>
        /// 次の局面の一覧をもった、入れ物ノードを返します。
        /// </summary>
        /// <param name="kifu"></param>
        /// <param name="pside_genTeban"></param>
        /// <returns></returns>
        public static KifuNode ToNextNodes_AsHubNode(
            Maps_OneAndMulti <Finger, ShootingStarlightable> komabetuAllMove,
            Node <ShootingStarlightable, KyokumenWrapper> siteiNode,
            Playerside pside_genTeban)
        {
            KifuNode hubNode = new KifuNodeImpl(null, null, Playerside.Empty);//蝶番

#if DEBUG
            string dump = komabetuAllMove.Dump();
#endif

            foreach (KeyValuePair <Finger, List <ShootingStarlightable> > entry1 in komabetuAllMove.Items)
            {
                Finger figKoma = entry1.Key;// 駒

                // 駒の動ける升全て
                foreach (ShootingStarlightable move in entry1.Value)
                {
                    RO_Star_Koma koma = Util_Koma.AsKoma(move.Now);

                    SyElement masu = koma.Masu;

                    SkyConst nextSky = Util_Sasu.Sasu(siteiNode.Value.ToKyokumenConst, figKoma, masu, pside_genTeban);

                    Node <ShootingStarlightable, KyokumenWrapper> nextNode = new KifuNodeImpl(move, new KyokumenWrapper(nextSky), KifuNodeImpl.GetReverseTebanside(pside_genTeban));//次のノード

                    string sfenText = Util_Sky.ToSfenMoveText(move);
                    if (hubNode.ContainsKey_NextNodes(sfenText))
                    {
                        // 既存の指し手なら無視
                        System.Console.WriteLine("既存の指し手なので無視します。sfenText=[" + sfenText + "]");
                    }
                    else
                    {
                        hubNode.Add_NextNode(Util_Sky.ToSfenMoveText(move), nextNode);
                    }
                }
            }

            return(hubNode);
        }
Beispiel #4
0
        /// <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)));
        }
Beispiel #5
0
        /// <summary>
        /// 棋譜データを元に、符号リスト1(*1)を出力します。
        ///
        ///     *1…「▲2六歩△8四歩▲7六歩」といった書き方。
        ///
        /// </summary>
        /// <param name="fugoList"></param>
        public static string ToJapaneseKifuText(
            KifuTree kifu
            )
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("position ");

            sb.Append(kifu.GetProperty(KifuTreeImpl.PropName_Startpos));
            sb.Append(" moves ");

            // 採譜用に、新しい対局を用意します。
            KifuTree saifuKifu;

            {
                saifuKifu = new KifuTreeImpl(
                    new KifuNodeImpl(
                        Util_Sky.NullObjectMove,
                        new KyokumenWrapper(new SkyConst(Util_Sky.New_Hirate())),    //日本の符号読取時
                        Playerside.P2
                        )
                    );
                saifuKifu.Clear();// 棋譜を空っぽにします。

                saifuKifu.SetProperty(KifuTreeImpl.PropName_FirstPside, Playerside.P1);
                saifuKifu.SetProperty(KifuTreeImpl.PropName_Startpos, "startpos");//平手の初期局面 // FIXME:平手とは限らないのでは?
            }


            kifu.ForeachHonpu(kifu.CurNode, (int tesumi, KyokumenWrapper kWrap, Node <ShootingStarlightable, KyokumenWrapper> node6, ref bool toBreak) =>
            {
                if (0 == tesumi)
                {
                    goto gt_EndLoop;
                }


                FugoJ fugo;

                //------------------------------
                // 符号の追加(記録係)
                //------------------------------
                KyokumenWrapper saifu_kWrap = saifuKifu.CurNode.Value;

                KifuNode newNode = new KifuNodeImpl(
                    node6.Key,
                    new KyokumenWrapper(saifu_kWrap.ToKyokumenConst),
                    KifuNodeImpl.GetReverseTebanside(((KifuNode)saifuKifu.CurNode).Tebanside)
                    );

                // TODO: ↓?
                ((KifuNode)saifuKifu.CurNode).AppendChildA_New(newNode);
                saifuKifu.CurNode = newNode;

                RO_Star_Koma koma = Util_Koma.AsKoma(((ShootingStarlightable)node6.Key).LongTimeAgo);

                fugo = JFugoCreator15Array.ItemMethods[(int)Haiyaku184Array.Syurui(koma.Haiyaku)](node6.Key, saifu_kWrap);//「▲2二角成」なら、馬(dst)ではなくて角(src)。

                sb.Append(fugo.ToText_UseDou(node6));

                gt_EndLoop:
                ;
            });

            return(sb.ToString());
        }
Beispiel #6
0
        /// <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);
        }
Beispiel #7
0
        /// <summary>
        /// これが通称【水際のいんちきプログラム】なんだぜ☆
        /// 必要により、【成り】の指し手を追加します。
        /// </summary>
        public static void AddNariMove(
            KifuNode node_yomiCur,
            KifuNode hubNode
            )
        {
            Dictionary <string, ShootingStarlightable> newMoveList = new Dictionary <string, ShootingStarlightable>();

            hubNode.Foreach_NextNodes((string key, Node <ShootingStarlightable, KyokumenWrapper> nextNode, ref bool toBreak) =>
            {
                RO_Star_Koma srcKoma = Util_Koma.AsKoma(nextNode.Key.LongTimeAgo);
                RO_Star_Koma dstKoma = Util_Koma.AsKoma(nextNode.Key.Now);

                bool isPromotionable;
                if (!Converter04.IsPromotionable(out isPromotionable, srcKoma, dstKoma))
                {
                    // エラー
                    goto gt_Next1;
                }

                if (isPromotionable)
                {
                    ShootingStarlightable move = new RO_ShootingStarlight(
                        //figKoma,//駒
                        srcKoma,// 移動元
                        new RO_Star_Koma(
                            dstKoma.Pside,
                            dstKoma.Masu,
                            KomaSyurui14Array.ToNariCase(dstKoma.Syurui) //強制的に【成り】に駒の種類を変更
                            ),                                           // 移動先
                        PieceType.None                                   //取った駒不明
                        );

                    // TODO: 一段目の香車のように、既に駒は成っている場合があります。無い指し手だけ追加するようにします。
                    string moveStr = Util_Sky.ToSfenMoveText(move);//重複防止用のキー
                    if (!newMoveList.ContainsKey(moveStr))
                    {
                        newMoveList.Add(moveStr, move);
                    }
                }

                gt_Next1:
                ;
            });


            // 新しく作った【成り】の指し手を追加します。
            foreach (ShootingStarlightable newMove in newMoveList.Values)
            {
                // 指す前の駒
                RO_Star_Koma sasumaenoKoma = Util_Koma.AsKoma(newMove.LongTimeAgo);

                // 指した駒
                RO_Star_Koma sasitaKoma = Util_Koma.AsKoma(newMove.Now);

                // 現局面
                SkyConst src_Sky = node_yomiCur.Value.ToKyokumenConst;

                // 指す前の駒を、盤上のマス目で指定
                Finger figSasumaenoKoma = Util_Sky.Fingers_AtMasuNow(src_Sky, sasumaenoKoma.Masu).ToFirst();

                // 新たな局面
                KyokumenWrapper kyokumenWrapper = new KyokumenWrapper(Util_Sasu.Sasu(src_Sky, figSasumaenoKoma, sasitaKoma.Masu, KifuNodeImpl.GetReverseTebanside(node_yomiCur.Tebanside)));



                try
                {
                    string moveStr = Util_Sky.ToSfenMoveText(newMove);

                    if (!hubNode.ContainsKey_NextNodes(moveStr))
                    {
                        // 指し手が既存でない局面だけを追加します。

                        hubNode.Add_NextNode(
                            moveStr,
                            new KifuNodeImpl(
                                newMove,
                                kyokumenWrapper,//node_yomiCur.Value,//FIXME: 成りの手を指した局面を作りたい。
                                KifuNodeImpl.GetReverseTebanside(node_yomiCur.Tebanside)
                                )
                            );
                    }
                }
                catch (Exception ex)
                {
                    // 既存の指し手
                    StringBuilder sb = new StringBuilder();
                    {
                        hubNode.Foreach_NextNodes((string key, Node <ShootingStarlightable, KyokumenWrapper> nextNode, ref bool toBreak) =>
                        {
                            sb.Append("「");
                            sb.Append(Util_Sky.ToSfenMoveText(nextNode.Key));
                            sb.Append("」");
                        });
                    }

                    //>>>>> エラーが起こりました。
                    // どうにもできないので  ログだけ取って、上に投げます。
                    Logger.Error(ex.GetType().Name + " " + ex.Message + ":新しく作った「成りの指し手」を既存ノードに追加していた時です。:追加したい指し手=「" + Util_Sky.ToSfenMoveText(newMove) + "」既存の手=" + sb.ToString());
                    throw;
                }
            }

            // gt_EndMethod:
            // ;
        }
Beispiel #8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="figMovedKoma"></param>
        /// <param name="move">棋譜に記録するために「指す前/指した後」を含めた手。</param>
        /// <param name="kifu"></param>
        /// <param name="isMakimodosi"></param>
        private static void Kifusasi25(
            out Finger figMovedKoma,
            ShootingStarlightable move,
            KifuTree kifu,
            bool isMakimodosi
            ,
            [CallerMemberName] string memberName    = "",
            [CallerFilePath] string sourceFilePath  = "",
            [CallerLineNumber] int sourceLineNumber = 0
            )
        {
            figMovedKoma = Fingers.Error_1;

            SkyConst src_Sky = kifu.CurNode.Value.ToKyokumenConst;

            //------------------------------------------------------------
            // 選択  :  動かす駒
            //------------------------------------------------------------
            if (isMakimodosi)
            {
                // [巻戻し]のとき
                //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                // 打った駒も、指した駒も、結局は将棋盤の上にあるはず。

                RO_Star_Koma koma = Util_Koma.AsKoma(move.Now);

                // 動かす駒
                figMovedKoma = Util_Sky.Finger_AtMasuNow_Shogiban(
                    src_Sky,
                    koma.Pside,
                    koma.Masu//[巻戻し]のときは、先位置が 駒の居場所。
                    );
            }
            else
            {
                // 進むとき
                //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                //------------------------------
                // 符号の追加(一手進む)
                //------------------------------
                KifuNode genKyokumenCopyNode = new KifuNodeImpl(move, new KyokumenWrapper(src_Sky), KifuNodeImpl.GetReverseTebanside(((KifuNode)kifu.CurNode).Tebanside));

                // TODO: ↓?
                ((KifuNode)kifu.CurNode).AppendChildA_New(genKyokumenCopyNode);
                kifu.CurNode = genKyokumenCopyNode;

                if (Util_Sky.IsDaAction(move))
                {
                    //----------
                    // 駒台から “打”
                    //----------

                    RO_Star_Koma srcKoma = Util_Koma.AsKoma(move.LongTimeAgo);
                    RO_Star_Koma dstKoma = Util_Koma.AsKoma(move.Now);


                    figMovedKoma = Util_Sky.FingerNow_BySyuruiIgnoreCase(
                        src_Sky,
                        Util_Masu.GetOkiba(srcKoma.Masu),
                        Haiyaku184Array.Syurui(dstKoma.Haiyaku)
                        );
                }
                else
                {
                    //----------
                    // 将棋盤から
                    //----------

                    RO_Star_Koma srcKoma = Util_Koma.AsKoma(move.LongTimeAgo);
                    RO_Star_Koma dstKoma = Util_Koma.AsKoma(move.Now);


                    figMovedKoma = Util_Sky.Finger_AtMasuNow_Shogiban(
                        src_Sky,
                        dstKoma.Pside,
                        Util_Masu.OkibaSujiDanToMasu(
                            Util_Masu.GetOkiba(Masu_Honshogi.Items_All[Util_Masu.AsMasuNumber(dstKoma.Masu)]),
                            Util_Masu.AsMasuNumber(srcKoma.Masu)
                            )
                        );
                }
            }
        }