/// <summary> /// 評価明細項目の追加。 /// </summary> /// <param name="name"></param> /// <param name="item"></param> public void Add(string name, KyHyokaMeisai_Koumoku item) { if (this.items.ContainsKey(name)) { this.items[name] = item; } else { this.items.Add(name, item); } }
/// <summary> /// 評価明細の書き出し。 /// </summary> /// <param name="id"></param> /// <param name="node"></param> /// <param name="treeFolder"></param> /// <param name="env"></param> public static void AAAA_Write_HyokaMeisai( IEngineConf engineConf, string id, KifuNode node, string treeFolder, KyokumenPngEnvironment env ) { StringBuilder sb = new StringBuilder(); // 見出し sb.Append(id); sb.Append(" "); sb.Append(((int)node.Score).ToString()); sb.Append(" "); switch (node.Value.KyokumenConst.KaisiPside) { case Playerside.P1: sb.Append("P2が指し終えた局面。手番P1"); break; case Playerside.P2: sb.Append("P1が指し終えた局面。手番P2"); break; case Playerside.Empty: sb.Append("手番Empty"); break; } sb.AppendLine(); foreach (KeyValuePair <string, KyHyokaMeisai_Koumoku> entry in node.KyHyokaSheet_Mutable.Items) { KyHyokaMeisai_Koumoku koumoku = ((KyHyokaMeisai_Koumoku)entry.Value); sb.Append(" "); sb.Append(entry.Key); //項目名 sb.Append(" "); sb.Append(koumoku.UtiwakeValue); //評価値 sb.Append(" "); sb.Append(koumoku.Utiwake);//内訳 sb.AppendLine(); } sb.AppendLine(); ////------------------------------ //// TODO: 局面ハッシュ ////------------------------------ //sb.Append("hash:"); //sb.AppendLine(Conv_Sky.ToKyokumenHash(node.Value.ToKyokumenConst).ToString()); //sb.AppendLine(); File.AppendAllText($"{env.OutFolder}{treeFolder}{engineConf.GetResourceBasename("HyokaMeisaiLogTxtBasename")}", sb.ToString()); }
public GohosyuListItem(int count, string sfen, string jsaMoveStr #if DEBUG || LEARN , KyHyokaMeisai_Koumoku komawariMeisai, KyHyokaMeisai_Koumoku ppMeisai #endif ) { this.count = count; this.sfen = sfen; this.jsaMoveStr = jsaMoveStr; #if DEBUG || LEARN this.komawariMeisai = komawariMeisai; this.ppMeisai = ppMeisai; #endif }
/// <summary> /// 二駒関係の評価値を算出します。 /// </summary> public void DoScoreing_ForLearning( KifuNode node #if DEBUG || LEARN , out KyHyokaMeisai_Koumoku out_komawariMeisai, out KyHyokaMeisai_Koumoku out_ppMeisai #endif ) { //---------------------------------------- // Komawari //---------------------------------------- { Hyokakansu_Komawari handan = new Hyokakansu_Komawari(); float score; handan.Evaluate( out score, #if DEBUG || LEARN out out_komawariMeisai, #endif node.Value.KyokumenConst, this.Fv //参照してもらうだけ。 ); } //---------------------------------------- // PP //---------------------------------------- { Hyokakansu_NikomaKankeiPp handan_pp = new Hyokakansu_NikomaKankeiPp(); float score; handan_pp.Evaluate( out score, #if DEBUG || LEARN out out_ppMeisai, #endif node.Value.KyokumenConst, this.Fv //参照してもらうだけ。 ); } }
/// <summary> /// 評価値を返します。先手が有利ならプラス、後手が有利ならマイナス、互角は 0.0 です。 /// </summary> /// <param name="input_node"></param> /// <param name="playerInfo"></param> /// <returns></returns> public override void Evaluate( out float out_score, #if DEBUG || LEARN out KyHyokaMeisai_Koumoku out_meisaiKoumoku_orNull, #endif SkyConst src_Sky, FeatureVector featureVector ) { out_score = 0.0f;//互角 switch (src_Sky.KaisiPside) { case Playerside.P1: out_score = float.MinValue; break; case Playerside.P2: out_score = float.MaxValue; break; default: throw new Exception("千日手判定をしようとしましたが、先後の分からない局面データがありました。"); } //gt_EndMethod: // ; //---------------------------------------- // 明細項目 //---------------------------------------- #if DEBUG || LEARN string utiwake = ""; // 明細 { StringBuilder sb = new StringBuilder(); sb.Append($"千日手。 score=[{out_score}]"); utiwake = sb.ToString(); } out_meisaiKoumoku_orNull = new KyHyokaMeisai_KoumokuImpl(utiwake, out_score); #endif }
/// <summary> /// 評価値を返します。先手が有利ならプラス、後手が有利ならマイナス、互角は 0.0 です。 /// </summary> /// <param name="input_node"></param> /// <returns></returns> public override void Evaluate( out float out_score, #if DEBUG || LEARN out KyHyokaMeisai_Koumoku out_meisaiKoumoku_orNull, #endif SkyConst src_Sky, FeatureVector fv ) { out_score = 0.0f; // -999~999(*bairitu) が 40×40個ほど足し合わせた数になるはず。 #if DEBUG float[] komabetuMeisai = new float[Finger_Honshogi.Items_KomaOnly.Length]; #endif // // 盤上にある駒だけ、項目番号を調べます。 // //---------------------------------------- // 項目番号リスト //---------------------------------------- // // 40個の駒と、14種類の持ち駒があるだけなので、 // 54個サイズの長さがあれば足りるんだぜ☆ 固定長にしておこう☆ // int nextIndex = 0; int[] komokuArray_unsorted = new int[54]; //昇順でなくても構わないアルゴリズムにすること。 for (int i = 0; i < Finger_Honshogi.Items_KomaOnly.Length; i++) // 全駒 { RO_Star koma = Util_Starlightable.AsKoma(src_Sky.StarlightIndexOf(Finger_Honshogi.Items_KomaOnly[i]).Now); if (Okiba.ShogiBan == Conv_SyElement.ToOkiba(koma.Masu)) { // 盤上 komokuArray_unsorted[nextIndex] = Util_FvParamIndex.ParamIndex_Banjo(koma); nextIndex++; } else { // 持ち駒は、ここでは無視します。 } } // 持ち駒:先後×7種類 for (int iPside = 0; iPside < Array_Playerside.Items_PlayerOnly.Length; iPside++) { for (int iKomasyurui = 0; iKomasyurui < Array_Komasyurui.MotiKoma7Syurui.Length; iKomasyurui++) { komokuArray_unsorted[nextIndex] = Util_FvParamIndex.ParamIndex_Moti(src_Sky, Array_Playerside.Items_PlayerOnly[iPside], Array_Komasyurui.MotiKoma7Syurui[iKomasyurui]); nextIndex++; } } //Array.Sort(komokuArray_unsorted); // // // 例えば、[1P1三歩、2P2一桂]という組み合わせと、[2P2一桂、1P1三歩]という組み合わせは、同じだが欄が2つある。 // そこで、表の半分を省きたい。 // しかし、表を三角形にするためには、要素は昇順にソートされている必要がある。 // 合法手1つごとにソートしていては、本末転倒。 // そこで、表は正方形に読み、内容は三角形の部分にだけ入っているということにする。 // // // 例えば、[1P1三歩、1P1三歩]という組み合わせもある。これは、自分自身の絶対位置の評価として試しに、残しておいてみる☆ // // for (int iA = 0; iA < nextIndex; iA++) { int p1 = komokuArray_unsorted[iA]; for (int iB = 0; iB < nextIndex; iB++) { int p2 = komokuArray_unsorted[iB]; if (p1 <= p2) // 「p2 < p1」という組み合わせは同じ意味なので省く。「p1==p2」は省かない。 { //---------------------------------------- // よし、組み合わせだぜ☆! //---------------------------------------- out_score += fv.NikomaKankeiPp_ForMemory[p1, p2]; } else { //---------------------------------------- // 使っていない方の三角形だぜ☆! //---------------------------------------- // スルー。 } } } //---------------------------------------- // 明細項目 //---------------------------------------- #if DEBUG || LEARN string utiwake = ""; // 内訳 { StringBuilder sb = new StringBuilder(); sb.Append(" PP "); sb.Append(out_score); sb.Append("点"); utiwake = sb.ToString(); } out_meisaiKoumoku_orNull = new KyHyokaMeisai_KoumokuImpl(utiwake, out_score); #endif }
/// <summary> /// 評価値を返します。先手が有利ならプラス、後手が有利ならマイナス、互角は 0.0 です。 /// </summary> /// <param name="args"></param> /// <returns></returns> public override void Evaluate( out float out_score, #if DEBUG || LEARN out KyHyokaMeisai_Koumoku out_meisaiKoumoku_orNull, #endif SkyConst srcSky, FeatureVector fv ) { float score_p1 = 0.0f; float score_p2 = 0.0f;//2Pは、負の数なほどグッドということに注意。 srcSky.Foreach_Starlights((Finger finger, IMoveHalf light, ref bool toBreak) => { RO_Starlight ms = (RO_Starlight)light; RO_Star koma = Util_Starlightable.AsKoma(ms.Now); // 駒の種類による点数 float komaScore_temp = fv.Komawari[(int)koma.Komasyurui]; // 持ち駒は、価値を高めます。(ボーナス)序盤に駒をぽんぽん打つのを防ぐため。 if ( (Okiba.Sente_Komadai | Okiba.Gote_Komadai).HasFlag(Conv_SyElement.ToOkiba(koma.Masu)) ) { //komaScore_temp *= 1.05f;// 1.05倍だと、相手の桂馬の利きに、桂馬をタダ捨てした。足りてないか。 komaScore_temp *= 1.13f; //komaScore_temp *= 1.25f;// 1.25倍だと、金、金、角を打たずに王手されて終わってしまった。ボーナスを付けすぎたか☆ } if (koma.Pside == Playerside.P1) { score_p1 += komaScore_temp; } else { // 駒割は、他の評価値と違って、 // 1プレイヤーも、2プレイヤーも正の数になっている。 // 2プレイヤーは 符号を反転させること。 score_p2 += -komaScore_temp; } }); // // 2プレイヤーは 負の数になっている(負の数が多いほど有利)ので、 // 足すだけでいい。 // out_score = score_p1 + score_p2; //---------------------------------------- // 明細項目 //---------------------------------------- #if DEBUG || LEARN string utiwake = ""; // 明細 { StringBuilder sb = new StringBuilder(); sb.Append("駒割"); utiwake = sb.ToString(); } // 明細項目 out_meisaiKoumoku_orNull = new KyHyokaMeisai_KoumokuImpl(utiwake, out_score); #endif }