/// <summary> /// 後手からも、先手のような座標で指示できるように変換します。 /// </summary> /// <param name="masu"></param> /// <param name="pside"></param> /// <returns></returns> public static SyElement BothSenteView(SyElement masu, Playerside pside) { SyElement result = masu; // 将棋盤上で後手なら、180°回転します。 if (Okiba.ShogiBan == Util_Masu.Masu_ToOkiba(masu) && pside == Playerside.P2) { result = Masu_Honshogi.Items_All[80 - Util_Masu.AsMasuNumber(masu)]; } // 将棋盤で先手、または 駒台か 駒袋なら、指定されたマスにそのまま入れます。 return(result); }
/// <summary> /// 0.0d ~100.0d の範囲で、評価値を返します。数字が大きい方がグッドです。 /// </summary> /// <param name="input_node"></param> /// <param name="playerInfo"></param> /// <returns></returns> public override void Keisan(out KyHyokaItem kyokumenScore, KyHandanArgs args) { double score; SkyConst src_Sky = args.Node.Value.ToKyokumenConst; // // 「紐が付いていない駒の少なさ」による加点。 // int mikataHimoduki = 0; // 味方の駒に、味方の駒の利きが1つ被っていれば+1。 int mikataNeraware = 0; // 味方の駒に、相手の駒の利きが1つ被っていれば+1。 int aiteHimoduki = 0; // 相手の駒に、相手の駒の利きが1つ被っていれば+1。 int aiteNeraware = 0; // 相手の駒に、味方の駒の利きが1つ被っていれば+1。 List <string> mikataYaburareMasu = new List <string>(); int aiteWin = 0; // 利きの枚数で相手が勝っていた件数。 List <string> aiteYaburareMasu = new List <string>(); int mikataWin = 0; // 利きの枚数で味方が勝っていた件数。 // // 駒の利きの計算。 // KomanoKiki komanoKiki = KomanoKikiImpl.MasuBETUKikisu(src_Sky, args.Node.Tebanside); // // 味方の駒があるマスの得点は、マイナスなら集計。(減点法) // 敵の駒があるマスの得点は、プラスなら集計。(減点法) // // 駒は40枚あり、貫通して加点するのもある。 // foreach (Finger figKoma in Finger_Honshogi.Items_KomaOnly)// 全駒 { RO_Star_Koma koma = Util_Koma.AsKoma(src_Sky.StarlightIndexOf(figKoma).Now); if (Okiba.ShogiBan != Util_Masu.Masu_ToOkiba(koma.Masu)) { goto gt_Next2; } if (args.PlayerInfo.Playerside == koma.Pside) { // 味方の駒 // その升に利いている味方の利きの数。 int mikataKiki = komanoKiki.Kikisu_AtMasu_Mikata[Util_Masu.AsMasuNumber(koma.Masu)]; // その升に利いている相手の利きの数。 int aiteKiki = komanoKiki.Kikisu_AtMasu_Teki[Util_Masu.AsMasuNumber(koma.Masu)]; mikataHimoduki += mikataKiki; mikataNeraware += aiteKiki; // 破られる場合 if (mikataKiki < aiteKiki) { aiteWin++; mikataYaburareMasu.Add(Converter04.Masu_ToKanji(koma.Masu)); } } else { // 相手の駒 // その升に利いている相手の利きの数。 int aiteKiki = komanoKiki.Kikisu_AtMasu_Mikata[Util_Masu.AsMasuNumber(koma.Masu)]; // その升に利いている味方の利きの数。 int mikataKiki = komanoKiki.Kikisu_AtMasu_Teki[Util_Masu.AsMasuNumber(koma.Masu)]; aiteHimoduki = aiteKiki; aiteNeraware = mikataKiki; // 破られる場合 if (aiteKiki < mikataKiki) { mikataWin++; aiteYaburareMasu.Add(Converter04.Masu_ToKanji(koma.Masu)); } } gt_Next2: ; } // 集計。 score = (double)(mikataWin - aiteWin) * 1.0 + 50.0d; string meisai = ""; #if DEBUG // 明細 { StringBuilder sb = new StringBuilder(); sb.Append(" " + score); sb.Append("点 "); sb.Append(" 衝突箇所勝ち数=" + (mikataWin - aiteWin)); sb.Append(" 味方が破られる" + aiteWin + "箇所"); foreach (string s in mikataYaburareMasu) { sb.Append("["); sb.Append(s); sb.Append("]"); } sb.Append(" 相手が破られる" + mikataWin + "箇所"); foreach (string s in aiteYaburareMasu) { sb.Append("["); sb.Append(s); sb.Append("]"); } meisai = sb.ToString(); } #endif kyokumenScore = new KyHyoka100limitItemImpl(args.TenonagareGenjo.ScoreKeisu, score, meisai); }
/// <summary> /// 別方法試し中。 /// /// </summary> /// <param name="src_Sky"></param> public static KomanoKikiImpl BETUKAI(SkyConst src_Sky, Playerside tebanside) { // ①現手番の駒の移動可能場所_被王手含む List_OneAndMulti <Finger, SySet <SyElement> > komaBETUSusumeruMasus; Util_MovableMove.LA_Get_KomaBETUSusumeruMasus( out komaBETUSusumeruMasus, //進めるマス new MmGenjo_MovableMasuImpl( true, //本将棋か src_Sky, //現在の局面 tebanside, //手番 false //相手番か ), null ); KomanoKikiImpl self = new KomanoKikiImpl(); // // 「升ごとの敵味方」を調べます。 // foreach (Finger figKoma in Finger_Honshogi.Items_KomaOnly)// 全駒 { RO_Star_Koma koma = Util_Koma.AsKoma(src_Sky.StarlightIndexOf(figKoma).Now); self.HMasu_PlayersideList[Util_Masu.AsMasuNumber(koma.Masu)] = koma.Pside; } // // 駒のない升は無視します。 // // // 駒のあるマスに、その駒の味方のコマが効いていれば 味方+1 // foreach (Finger figKoma in Finger_Honshogi.Items_KomaOnly)// 全駒 { // // 駒 // RO_Star_Koma koma = Util_Koma.AsKoma(src_Sky.StarlightIndexOf(figKoma).Now); // 将棋盤上の戦駒のみ判定 if (Okiba.ShogiBan != Util_Masu.Masu_ToOkiba(koma.Masu)) { goto gt_Next1; } // // 駒の利き FIXME:貫通してないか? // komaBETUSusumeruMasus.Foreach_Entry((Finger figKoma2, SySet <SyElement> kikiZukei, ref bool toBreak) => { IEnumerable <SyElement> kikiMasuList = kikiZukei.Elements; foreach (SyElement masu in kikiMasuList) { // その枡に利いている駒のハンドルを追加 if (self.HMasu_PlayersideList[Util_Masu.AsMasuNumber(masu)] == Playerside.Empty) { // 駒のないマスは無視。 } else if (self.HMasu_PlayersideList[Util_Masu.AsMasuNumber(masu)] == koma.Pside) { // 利きのあるマスにある駒と、この駒のプレイヤーサイドが同じ。 self.Kikisu_AtMasu_Mikata[Util_Masu.AsMasuNumber(masu)] += 1; } else { // 反対の場合。 self.Kikisu_AtMasu_Teki[Util_Masu.AsMasuNumber(masu)] += 1; } } }); gt_Next1: ; } return(self); }
/// <summary> /// 「成り」ができるなら真。 /// </summary> /// <returns></returns> private static bool IsPromotionable( out bool isPromotionable, RO_Star_Koma srcKoma, RO_Star_Koma dstKoma ) { bool successful = true; isPromotionable = false; if (Okiba.ShogiBan != Util_Masu.Masu_ToOkiba(srcKoma.Masu)) { successful = false; goto gt_EndMethod; } if (KomaSyurui14Array.IsNari(srcKoma.Syurui)) { // 既に成っている駒は、「成り」の指し手を追加すると重複エラーになります。 // 成りになれない、で正常終了します。 goto gt_EndMethod; } int srcDan; if (!Util_MasuNum.MasuToDan(srcKoma.Masu, out srcDan)) { throw new Exception("段に変換失敗"); } int dstDan; if (!Util_MasuNum.MasuToDan(dstKoma.Masu, out dstDan)) { throw new Exception("段に変換失敗"); } // 先手か、後手かで大きく処理を分けます。 switch (dstKoma.Pside) { case Playerside.P1: { if (srcDan <= 3) { // 3段目から上にあった駒が移動したのなら、成りの資格ありです。 isPromotionable = true; goto gt_EndMethod; } if (dstDan <= 3) { // 3段目から上に駒が移動したのなら、成りの資格ありです。 isPromotionable = true; goto gt_EndMethod; } } break; case Playerside.P2: { if (7 <= srcDan) { // 7段目から下にあった駒が移動したのなら、成りの資格ありです。 isPromotionable = true; goto gt_EndMethod; } if (7 <= dstDan) { // 7段目から下に駒が移動したのなら、成りの資格ありです。 isPromotionable = true; goto gt_EndMethod; } } break; default: throw new Exception("未定義のプレイヤーサイドです。"); } gt_EndMethod: ; return(successful); }
/// <summary> /// 0.0d ~100.0d の範囲で、評価値を返します。数字が大きい方がグッドです。 /// </summary> /// <param name="input_node"></param> /// <param name="playerInfo"></param> /// <returns></returns> public override void Keisan(out KyHyokaItem kyokumenScore, KyHandanArgs args) { double score = 50.0d; SkyConst src_Sky = args.Node.Value.ToKyokumenConst; // // 「紐が付いていない駒の少なさ」による加点。 // // 自分の駒について、味方の駒の利きが被っていれば+1(貫通) // 敵の駒の利きが被っていれば-1(貫通) // // 敵の駒について、味方の駒の利きが被っていれば+1(貫通) // 敵の駒の利きが被っていれば-1(貫通) // // // 駒のない升は無視し、 // 駒のあるマスに、その駒の味方のコマが効いていれば +1 // 駒のあるマスに、その駒の相手のコマが効いていれば -1 // foreach (Finger figKoma in Finger_Honshogi.Items_KomaOnly)// 全駒 { RO_Star_Koma koma = Util_Koma.AsKoma(src_Sky.StarlightIndexOf(figKoma).Now); if (Okiba.ShogiBan != Util_Masu.Masu_ToOkiba(koma.Masu)) { goto gt_Next1; } // 将棋盤上のみ。 // 駒の利き SySet <SyElement> kikiZukei = Util_Sky.KomaKidou_Potential(figKoma, src_Sky); IEnumerable <SyElement> kikiMasuList = kikiZukei.Elements; // 通し double toosi = kikiMasuList.Count(); // 係数 switch (koma.Syurui) { case PieceType.P: toosi *= this.Keisu_Fu; break; case PieceType.L: toosi *= this.Keisu_Kyo; break; case PieceType.N: toosi *= this.Keisu_Kei; break; case PieceType.S: toosi *= this.Keisu_Gin; break; case PieceType.G: toosi *= this.Keisu_Kin; break; case PieceType.K: toosi *= this.Keisu_Oh; break; case PieceType.R: toosi *= this.Keisu_Hisya; break; case PieceType.B: toosi *= this.Keisu_Kaku; break; case PieceType.PR: toosi *= this.Keisu_Ryu; break; case PieceType.PB: toosi *= this.Keisu_Uma; break; case PieceType.PP: toosi *= this.Keisu_Tokin; break; case PieceType.PL: toosi *= this.Keisu_NariKyo; break; case PieceType.PN: toosi *= this.Keisu_NariKei; break; case PieceType.PS: toosi *= this.Keisu_NariGin; break; default: break; } if (args.PlayerInfo.Playerside == koma.Pside) { // 味方の駒 score += toosi; } else { // 敵の駒 score -= toosi; } gt_Next1: ; } string meisai = ""; #if DEBUG // 明細 { StringBuilder sb = new StringBuilder(); sb.Append("略"); meisai = sb.ToString(); } #endif kyokumenScore = new KyHyoka100limitItemImpl(args.TenonagareGenjo.ScoreKeisu, score, meisai); }
/// <summary> /// デバッグ用文字列を作ります。 /// </summary> /// <param name="masus"></param> /// <param name="memo"></param> /// <returns></returns> public static string Log_Masus(SySet <SyElement> masus, string memo) { StringBuilder sb = new StringBuilder(); int errorCount = 0; // フォルスクリア bool[] ban81 = new bool[81]; // フラグ立て foreach (Basho hMasu in masus.Elements) { if (Okiba.ShogiBan == Util_Masu.Masu_ToOkiba(Masu_Honshogi.Items_All[hMasu.MasuNumber])) { ban81[hMasu.MasuNumber] = true; } } sb.AppendLine("...(^▽^)さて、局面は☆?"); if (null != memo && "" != memo.Trim()) { sb.AppendLine(memo); } sb.AppendLine(" 9 8 7 6 5 4 3 2 1"); sb.AppendLine("┏━┯━┯━┯━┯━┯━┯━┯━┯━┓"); for (int dan = 1; dan <= 9; dan++) { sb.Append("┃"); for (int suji = 9; suji >= 1; suji--)// 筋は左右逆☆ { SyElement masu = Util_Masu.OkibaSujiDanToMasu(Okiba.ShogiBan, suji, dan); if (Okiba.ShogiBan == Util_Masu.Masu_ToOkiba(masu)) { if (ban81[Util_Masu.AsMasuNumber(masu)]) { sb.Append("●"); } else { sb.Append(" "); } } else { errorCount++; sb.Append(" "); } if (suji == 1)//1筋が最後だぜ☆ { sb.Append("┃"); sb.AppendLine(ConverterKnSh.Int_ToKanSuji(dan)); } else { sb.Append("│"); } } if (dan == 9) { sb.AppendLine("┗━┷━┷━┷━┷━┷━┷━┷━┷━┛"); } else { sb.AppendLine("┠─┼─┼─┼─┼─┼─┼─┼─┼─┨"); } } // 後手駒台 sb.Append("エラー数:"); sb.AppendLine(errorCount.ToString()); sb.AppendLine("...(^▽^)ドウダッタカナ~☆"); return(sb.ToString()); }