/// <summary> /// 指したあとの、次の局面を作るだけ☆ /// </summary> /// <param name="src_Sky"></param> /// <param name="finger"></param> /// <param name="masu"></param> /// <param name="pside_genTeban"></param> /// <param name="logTag"></param> /// <returns></returns> public static SkyConst Sasu( SkyConst src_Sky, //指定局面 Finger finger, //動かす駒 SyElement masu, //移動先マス bool toNaru //成るなら真 ) { SkyBuffer sky_buf = new SkyBuffer(src_Sky); // 現局面を元に、新規局面を書き換えます。 sky_buf.SetKaisiPside(Conv_Playerside.Reverse(src_Sky.KaisiPside)); // 開始先後を逆転させます。 sky_buf.SetTemezumi(sky_buf.Temezumi + 1); // 1手進めます。 SkyConst src_Sky2 = SkyConst.NewInstance(sky_buf, -1 //sky_bufでもう変えてあるので、そのまま。 ); // 移動先に相手の駒がないか、確認します。 Finger tottaKoma = Util_Sky_FingersQuery.InMasuNow(src_Sky2, masu).ToFirst(); if (tottaKoma != Fingers.Error_1) { // なにか駒を取ったら SyElement akiMasu; if (src_Sky.KaisiPside == Playerside.P1) { akiMasu = Util_IttesasuRoutine.GetKomadaiKomabukuroSpace(Okiba.Sente_Komadai, src_Sky2); } else { akiMasu = Util_IttesasuRoutine.GetKomadaiKomabukuroSpace(Okiba.Gote_Komadai, src_Sky2); } RO_Star koma = Util_Starlightable.AsKoma(sky_buf.StarlightIndexOf(tottaKoma).Now); // FIXME:配役あってるか? sky_buf.PutOverwriteOrAdd_Starlight(tottaKoma, new RO_Starlight(new RO_Star(src_Sky.KaisiPside, akiMasu, koma.Komasyurui)));//tottaKoma, } // 駒を1個動かします。 // FIXME: 取った駒はどうなっている? { RO_Star koma = Util_Starlightable.AsKoma(sky_buf.StarlightIndexOf(finger).Now); PieceType komaSyurui = koma.Komasyurui; if (toNaru) { komaSyurui = Util_Komasyurui14.ToNariCase(komaSyurui); } sky_buf.PutOverwriteOrAdd_Starlight(finger, new RO_Starlight(new RO_Star(src_Sky.KaisiPside, masu, komaSyurui))); } return(SkyConst.NewInstance(sky_buf, -1//sky_bufでもう進めてあるので、そのまま。 )); }
/// <summary> /// [巻戻し]時の、駒台にもどる動きを吸収。 /// </summary> /// <param name="syurui2"></param> /// <param name="move">棋譜に記録するために「指す前/指した後」を含めた手。</param> /// <param name="kifu"></param> /// <param name="isMakimodosi"></param> /// <returns></returns> private static IMoveHalf Do37_KomaOnDestinationMasu( PieceType syurui2, IMove move, SkyConst src_Sky ) { IMoveHalf dst; RO_Star srcKoma = Util_Starlightable.AsKoma(move.LongTimeAgo); //移動元 RO_Star dstKoma = Util_Starlightable.AsKoma(move.Now); //移動先 SyElement masu; if ( Okiba.Gote_Komadai == Conv_SyElement.ToOkiba(srcKoma.Masu) || Okiba.Sente_Komadai == Conv_SyElement.ToOkiba(srcKoma.Masu) ) { //>>>>> 1手前が駒台なら // 駒台の空いている場所 masu = Util_IttesasuRoutine.GetKomadaiKomabukuroSpace(Conv_SyElement.ToOkiba(srcKoma.Masu), src_Sky); // 必ず空いている場所があるものとします。 } else { //>>>>> 1手前が将棋盤上なら // その位置 masu = srcKoma.Masu;//戻し先 } dst = new RO_Starlight( //move.Finger, new RO_Star(dstKoma.Pside, masu,//戻し先 syurui2) ); return(dst); }
/// <summary> /// 駒を取る動き。 /// </summary> private static void Do61_KomaToru( IMoveHalf dst, SkyConst susunda_Sky_orNull_before,//駒を取られたとき、局面を変更します。 out Finger out_figFoodKoma, out RO_Star out_food_koma, out Playerside pside, out SyElement akiMasu ) { RO_Star dstKoma = Util_Starlightable.AsKoma(dst.Now); //---------- // 将棋盤上のその場所に駒はあるか //---------- out_figFoodKoma = Util_Sky_FingersQuery.InMasuNow(susunda_Sky_orNull_before, dstKoma.Masu).ToFirst();//盤上 if (Fingers.Error_1 != out_figFoodKoma) { //>>>>> 指した先に駒があったなら // // 取られる駒 // out_food_koma = Util_Starlightable.AsKoma(susunda_Sky_orNull_before.StarlightIndexOf(out_figFoodKoma).Now); #if DEBUG Logger.Trace($"駒取った={out_food_koma.Komasyurui}{Environment.NewLine}"); #endif // // 取られる駒は、駒置き場の空きマスに移動させます。 // Okiba okiba; switch (dstKoma.Pside) { case Playerside.P1: { okiba = Okiba.Sente_Komadai; pside = Playerside.P1; } break; case Playerside.P2: { okiba = Okiba.Gote_Komadai; pside = Playerside.P2; } break; default: { //>>>>> エラー: 先後がおかしいです。 throw new Exception($@"エラー: 先後がおかしいです。 dst.Pside={dstKoma.Pside}"); } } // // 駒台に駒を置く動き // { // 駒台の空きスペース akiMasu = Util_IttesasuRoutine.GetKomadaiKomabukuroSpace(okiba, susunda_Sky_orNull_before); if (Masu_Honshogi.IsErrorBasho(akiMasu)) { //>>>>> エラー: 駒台に空きスペースがありませんでした。 throw new Exception($@"エラー: 駒台に空きスペースがありませんでした。 駒台={Okiba.Gote_Komadai}"); } //>>>>> 駒台に空きスペースがありました。 } } else { out_food_koma = null; pside = Playerside.Empty; akiMasu = Masu_Honshogi.Query_Basho(Masu_Honshogi.nError); } }
/// <summary> /// 一手指します。 /// </summary> /// <param name="ittesasuArg"></param> /// <param name="ittesasu_mutable"></param> /// <param name="ittesasuResult"></param> /// <param name="memberName"></param> /// <param name="sourceFilePath"></param> /// <param name="sourceLineNumber"></param> public static void Before1( IttesasuArg ittesasuArg, out IttesasuResult ittesasuResult, string hint , [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0 ) { //------------------------------ // 用意 //------------------------------ ittesasuResult = new IttesasuResultImpl(Fingers.Error_1, Fingers.Error_1, null, PieceType.None, null); SkyConst kaisi_Sky = ittesasuArg.KaisiKyokumen.KyokumenConst; // 一手指し開始局面(不変) Node <IMove, KyokumenWrapper> editNodeRef; // 編集対象ノード(巻き戻し時と、進む時で異なる) //------------------------------ // 符号(局面)の追加 //------------------------------ { //進むときは、必ずノードの追加と、カレントの移動がある。 //現局面ノードのクローンを作成します。 editNodeRef = new KifuNodeImpl(ittesasuArg.KorekaranoMove, new KyokumenWrapper( SkyConst.NewInstance_ReversePside(kaisi_Sky, ittesasuArg.KorekaranoTemezumi_orMinus1)) ); ittesasuResult.Susunda_Sky_orNull = editNodeRef.Value.KyokumenConst; } //------------------------------ // 動かす駒を移動先へ。 //------------------------------ Debug.Assert(null != ittesasuArg.KorekaranoMove, "これからの指し手がヌルでした。"); Finger figMovedKoma; Util_IttesasuRoutine.Do24_UgokasuKoma_IdoSakiHe( out figMovedKoma, ittesasuArg.KorekaranoMove, ittesasuArg.KaisiTebanside, kaisi_Sky, hint ); ittesasuResult.FigMovedKoma = figMovedKoma; //動かした駒更新 Debug.Assert(Fingers.Error_1 != ittesasuResult.FigMovedKoma, "動かした駒がない☆!?エラーだぜ☆!"); RO_Star korekaranoKoma = Util_Starlightable.AsKoma(ittesasuArg.KorekaranoMove.Now); IMoveHalf afterStar; { afterStar = Util_IttesasuRoutine.Do36_KomaOnDestinationMasu( korekaranoKoma.Komasyurui, ittesasuArg.KorekaranoMove, ittesasuResult.Susunda_Sky_orNull ); } // Sky 局面データは、この関数の途中で何回か変更されます。ローカル変数に退避しておくと、同期が取れなくなります。 //------------------------------------------------------------ // 駒を取る //------------------------------------------------------------ Finger figFoodKoma = Fingers.Error_1; RO_Star food_koma = null; Playerside food_pside = Playerside.Empty; SyElement food_akiMasu = Masu_Honshogi.Query_Basho(Masu_Honshogi.nError); { Util_IttesasuRoutine.Do61_KomaToru( afterStar, ittesasuResult.Susunda_Sky_orNull, out figFoodKoma, out food_koma, out food_pside, out food_akiMasu ); if (Fingers.Error_1 != figFoodKoma) { //>>>>> 指した先に駒があったなら ittesasuResult.FoodKomaSyurui = food_koma.Komasyurui; } else { ittesasuResult.FoodKomaSyurui = PieceType.None; } } Debug.Assert(figMovedKoma != Fingers.Error_1, "駒を動かせなかった?1"); if (Fingers.Error_1 != figFoodKoma) { //------------------------------------------------------------ // 指した駒と、取った駒の移動 //------------------------------------------------------------ //------------------------------ // 局面データの書き換え //------------------------------ ittesasuResult.Susunda_Sky_orNull = SkyConst.NewInstance_OverwriteOrAdd_Light( ittesasuResult.Susunda_Sky_orNull, ittesasuArg.KorekaranoTemezumi_orMinus1, // // 指した駒 // figMovedKoma, //指した駒番号 afterStar, //指した駒 // // 取った駒 // figFoodKoma, new RO_Starlight( new RO_Star( food_pside, food_akiMasu, //駒台の空きマスへ food_koma.ToNarazuCase() // 取られた駒の種類。表面を上に向ける。 ) ) ); } else { //------------------------------------------------------------ // 指した駒の移動 //------------------------------------------------------------ ittesasuResult.Susunda_Sky_orNull = SkyConst.NewInstance_OverwriteOrAdd_Light( ittesasuResult.Susunda_Sky_orNull, //駒を取って変化しているかもしれない? ittesasuArg.KorekaranoTemezumi_orMinus1, // これから作る局面の、手目済み。 // // 指した駒 // figMovedKoma, afterStar, // // 手得計算 // korekaranoKoma.Komasyurui, 0,// TODO: suji or index korekaranoKoma.Masu ); } editNodeRef.Value.SetKyokumen(ittesasuResult.Susunda_Sky_orNull); // ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ // この時点で、必ず現局面データに差替えあり // ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ // // ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ // 局面データに変更があったものとして進めます。 // ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ittesasuResult.FigFoodKoma = figFoodKoma; //取った駒更新 // // ノード ittesasuResult.Set_SyuryoNode_OrNull = editNodeRef;// この変数を返すのがポイント。棋譜とは別に、現局面。 }
/// <summary> /// /// </summary> /// <param name="kifu"></param> /// <param name="restText"></param> /// <param name="startposImporter"></param> /// <param name="logTag"></param> public static ParsedKyokumen ToParsedKyokumen( Model_Manual model_Manual,// Gui局面を使用 StartposImporter startposImporter, KifuParserA_Genjo genjo ) { ParsedKyokumen parsedKyokumen = new ParsedKyokumenImpl(); //------------------------------ // 初期局面の先後 //------------------------------ if (startposImporter.RO_SfenStartpos.PsideIsBlack) { // 黒は先手。 parsedKyokumen.FirstPside = Playerside.P1; } else { // 白は後手。 parsedKyokumen.FirstPside = Playerside.P2; } //------------------------------ // 駒の配置 //------------------------------ parsedKyokumen.KifuNode = new KifuNodeImpl( Util_Sky258A.RootMove, //ルートなので new KyokumenWrapper( SkyConst.NewInstance( startposImporter.ToSky( parsedKyokumen.FirstPside, startposImporter.RO_SfenStartpos.Temezumi // FIXME: 将棋所だと常に 1 かも?? ), -1 // src_Sky_Newで設定済みだからそのまま。 ) ) ); //------------------------------ // 駒袋に表示されている駒を、駒台に表示されるように移します。 //------------------------------ { //------------------------------ // 持ち駒 ▲王 //------------------------------ if (0 < startposImporter.RO_SfenStartpos.Moti1K) { parsedKyokumen.MotiList.Add(new MotiItemImpl(PieceType.K, startposImporter.RO_SfenStartpos.Moti1K, Playerside.P1)); } //------------------------------ // 持ち駒 ▲飛 //------------------------------ if (0 < startposImporter.RO_SfenStartpos.Moti1R) { parsedKyokumen.MotiList.Add(new MotiItemImpl(PieceType.R, startposImporter.RO_SfenStartpos.Moti1R, Playerside.P1)); } //------------------------------ // 持ち駒 ▲角 //------------------------------ if (0 < startposImporter.RO_SfenStartpos.Moti1B) { parsedKyokumen.MotiList.Add(new MotiItemImpl(PieceType.B, startposImporter.RO_SfenStartpos.Moti1B, Playerside.P1)); } //------------------------------ // 持ち駒 ▲金 //------------------------------ if (0 < startposImporter.RO_SfenStartpos.Moti1G) { parsedKyokumen.MotiList.Add(new MotiItemImpl(PieceType.G, startposImporter.RO_SfenStartpos.Moti1G, Playerside.P1)); } //------------------------------ // 持ち駒 ▲銀 //------------------------------ if (0 < startposImporter.RO_SfenStartpos.Moti1S) { parsedKyokumen.MotiList.Add(new MotiItemImpl(PieceType.S, startposImporter.RO_SfenStartpos.Moti1S, Playerside.P1)); } //------------------------------ // 持ち駒 ▲桂 //------------------------------ if (0 < startposImporter.RO_SfenStartpos.Moti1N) { parsedKyokumen.MotiList.Add(new MotiItemImpl(PieceType.N, startposImporter.RO_SfenStartpos.Moti1N, Playerside.P1)); } //------------------------------ // 持ち駒 ▲香 //------------------------------ if (0 < startposImporter.RO_SfenStartpos.Moti1L) { parsedKyokumen.MotiList.Add(new MotiItemImpl(PieceType.L, startposImporter.RO_SfenStartpos.Moti1L, Playerside.P1)); } //------------------------------ // 持ち駒 ▲歩 //------------------------------ if (0 < startposImporter.RO_SfenStartpos.Moti1P) { parsedKyokumen.MotiList.Add(new MotiItemImpl(PieceType.P, startposImporter.RO_SfenStartpos.Moti1P, Playerside.P1)); } //------------------------------ // 持ち駒 △王 //------------------------------ if (0 < startposImporter.RO_SfenStartpos.Moti2k) { parsedKyokumen.MotiList.Add(new MotiItemImpl(PieceType.K, startposImporter.RO_SfenStartpos.Moti2k, Playerside.P2)); } //------------------------------ // 持ち駒 △飛 //------------------------------ if (0 < startposImporter.RO_SfenStartpos.Moti2r) { parsedKyokumen.MotiList.Add(new MotiItemImpl(PieceType.R, startposImporter.RO_SfenStartpos.Moti2r, Playerside.P2)); } //------------------------------ // 持ち駒 △角 //------------------------------ if (0 < startposImporter.RO_SfenStartpos.Moti2b) { parsedKyokumen.MotiList.Add(new MotiItemImpl(PieceType.B, startposImporter.RO_SfenStartpos.Moti2b, Playerside.P2)); } //------------------------------ // 持ち駒 △金 //------------------------------ if (0 < startposImporter.RO_SfenStartpos.Moti2g) { parsedKyokumen.MotiList.Add(new MotiItemImpl(PieceType.G, startposImporter.RO_SfenStartpos.Moti2g, Playerside.P2)); } //------------------------------ // 持ち駒 △銀 //------------------------------ if (0 < startposImporter.RO_SfenStartpos.Moti2s) { parsedKyokumen.MotiList.Add(new MotiItemImpl(PieceType.S, startposImporter.RO_SfenStartpos.Moti2s, Playerside.P2)); } //------------------------------ // 持ち駒 △桂 //------------------------------ if (0 < startposImporter.RO_SfenStartpos.Moti2n) { parsedKyokumen.MotiList.Add(new MotiItemImpl(PieceType.N, startposImporter.RO_SfenStartpos.Moti2n, Playerside.P2)); } //------------------------------ // 持ち駒 △香 //------------------------------ if (0 < startposImporter.RO_SfenStartpos.Moti2l) { parsedKyokumen.MotiList.Add(new MotiItemImpl(PieceType.L, startposImporter.RO_SfenStartpos.Moti2l, Playerside.P2)); } //------------------------------ // 持ち駒 △歩 //------------------------------ if (0 < startposImporter.RO_SfenStartpos.Moti2p) { parsedKyokumen.MotiList.Add(new MotiItemImpl(PieceType.P, startposImporter.RO_SfenStartpos.Moti2p, Playerside.P2)); } } //------------------------------------------------------------------------------------------------------------------------ // 移動 //------------------------------------------------------------------------------------------------------------------------ for (int i = 0; i < parsedKyokumen.MotiList.Count; i++) { Playerside itaruPside; //(至)先後 Okiba itaruOkiba; //(至)置き場 if (Playerside.P2 == parsedKyokumen.MotiList[i].Playerside) { // 宛:後手駒台 itaruPside = Playerside.P2; itaruOkiba = Okiba.Gote_Komadai; } else { // 宛:先手駒台 itaruPside = Playerside.P1; itaruOkiba = Okiba.Sente_Komadai; } //------------------------------ // 駒を、駒袋から駒台に移動させます。 //------------------------------ { parsedKyokumen.buffer_Sky = new SkyBuffer(model_Manual.GuiSkyConst); Fingers komas = Util_Sky_FingersQuery.InOkibaKomasyuruiNow( SkyConst.NewInstance( // FIXME: SkyConstではなく、Skyではだめなのか☆? parsedKyokumen.buffer_Sky, -1 //そのまま。 ), Okiba.KomaBukuro, parsedKyokumen.MotiList[i].Komasyurui ); int moved = 1; foreach (Finger koma in komas.Items) { // 駒台の空いている枡 SyElement akiMasu = Util_IttesasuRoutine.GetKomadaiKomabukuroSpace( itaruOkiba, SkyConst.NewInstance( parsedKyokumen.buffer_Sky, -1//そのまま ) ); parsedKyokumen.buffer_Sky.PutOverwriteOrAdd_Starlight( koma, new RO_Starlight( new RO_Star( itaruPside, akiMasu, parsedKyokumen.MotiList[i].Komasyurui ) ) ); if (parsedKyokumen.MotiList[i].Maisu <= moved) { break; } moved++; } } }//for return(parsedKyokumen); }
public string Execute( ref KifuParserA_Result result, Model_Taikyoku model_Taikyoku, out KifuParserA_State nextState, KifuParserA owner, KifuParserA_Genjo genjo ) { // 現局面。 SkyConst src_Sky = model_Taikyoku.Kifu.CurNode.Value.KyokumenConst; // Debug.Assert(!Util_MasuNum.OnKomabukuro((int)((RO_Star_Koma)src_Sky.StarlightIndexOf((Finger)0).Now).Masu), "カレント、駒が駒袋にあった。"); bool isHonshogi = true;//FIXME:暫定 // 現在の手番の開始局面+1 int korekaranoTemezumi = src_Sky.Temezumi + 1; nextState = this; if (0 < genjo.InputLine.Trim().Length) { IMove nextTe = Util_Sky258A.NullObjectMove; string rest; //「6g6f」形式と想定して、1手だけ読込み string str1; string str2; string str3; string str4; string str5; string str6; string str7; string str8; string str9; if (SfenMovesTextConv.ToTokens( genjo.InputLine, out str1, out str2, out str3, out str4, out str5, out rest) && !(str1 == "" && str2 == "" && str3 == "" && str4 == "" && str5 == "") ) { ConvSfenMoveTokens.ToMove( isHonshogi, str1, //123456789 か、 PLNSGKRB str2, //abcdefghi か、 * str3, //123456789 str4, //abcdefghi str5, //+ out nextTe, model_Taikyoku.Kifu, "棋譜パーサーA_SFENパース1" ); } else { //>>>>> 「6g6f」形式ではなかった☆ //「▲6六歩」形式と想定して、1手だけ読込み if (Conv_JsaFugoText.ToTokens( genjo.InputLine, out str1, out str2, out str3, out str4, out str5, out str6, out str7, out str8, out str9, out rest, model_Taikyoku.Kifu)) { if (!(str1 == "" && str2 == "" && str3 == "" && str4 == "" && str5 == "" && str6 == "" && str7 == "" && str8 == "" && str9 == "")) { Conv_JsaFugoTokens.ToMove( str1, //▲△ str2, //123…9、123…9、一二三…九 str3, //123…9、123…9、一二三…九 str4, // “同” str5, //(歩|香|桂|… str6, // 右|左… str7, // 上|引 str8, //成|不成 str9, //打 out nextTe, model_Taikyoku.Kifu ); } } else { //「6g6f」形式でもなかった☆ Logger.Error($"(^△^)「{genjo.InputLine}」vs【{this.GetType().Name}】 : !? 次の一手が読めない☆ inputLine=[{genjo.InputLine}]"); genjo.ToBreak_Abnormal(); goto gt_EndMethod; } } genjo.InputLine = rest; if (null != nextTe) { IttesasuResult ittesasuResult = new IttesasuResultImpl(Fingers.Error_1, Fingers.Error_1, null, PieceType.None, null); // //FIXME: これが悪さをしていないか☆? //FIXME: スピードが必要なので省略。 //Application.DoEvents(); // 時間のかかる処理の間にはこれを挟みます。 // //------------------------------ // ★棋譜読込専用 駒移動 //------------------------------ //Logger.Trace($"一手指し開始 : 残りの符号つ「{genjo.InputLine}」"); // //↓↓将棋エンジンが一手指し(進める) // Util_IttesasuRoutine.Before1( new IttesasuArgImpl( model_Taikyoku.Kifu.CurNode.Value, src_Sky.KaisiPside, nextTe, //FIXME: if文で分けているので、これがヌルなはずはないと思うが。 korekaranoTemezumi //これから作る局面の、手目済み。 ), out ittesasuResult, "KifuParserA_StateA2_SfenMoves#Execute" ); Util_IttesasuRoutine.Before2( ref ittesasuResult ); //---------------------------------------- // 次ノード追加、次ノードをカレントに。 //---------------------------------------- Util_IttesasuRoutine.After3_ChangeCurrent( model_Taikyoku.Kifu, ConvMoveStrSfen.ToMoveStrSfen(ittesasuResult.Get_SyuryoNode_OrNull.Key), ittesasuResult.Get_SyuryoNode_OrNull ); result.Out_newNode_OrNull = ittesasuResult.Get_SyuryoNode_OrNull; //↑↑一手指し //exceptionArea = 1090; //Logger.Trace(Util_Sky307.Json_1Sky( // src_Sky, // "一手指し終了", // "SFENパース2", // src_Sky.Temezumi//読み進めている現在の手目 // )); } else { genjo.ToBreak_Abnormal(); throw new Exception($"\(^o^)/Moveオブジェクトがない☆! inputLine=[{genjo.InputLine}]"); } } else { //Logger.Trace($"(^△^)現局面まで進んだのかだぜ☆?\n{Util_Sky307.Json_1Sky( // src_Sky, // "棋譜パース", // "SFENパース3", // src_Sky.Temezumi//読み進めている現在の手目 // )}"); genjo.ToBreak_Normal();//棋譜パーサーAの、唯一の正常終了のしかた。 } gt_EndMethod: return(genjo.InputLine); }