public static void Update(Hyokati hyokati, Option <Phase> optionalPhase, int teme) { var phaseIndex = OptionalPhase.IndexOf(optionalPhase); if (Conv_Hyokati.InTumeTesu(hyokati)) { // 詰め手数が表示されているぜ☆ if (Util_Taikyoku.PNNantedume_Teme[phaseIndex] == int.MaxValue) { // 詰め手数が新たに表示されたようだぜ☆ Util_Taikyoku.PNNantedume_Teme[phaseIndex] = teme; } // 前から表示されていたのなら、そのままだぜ☆(^▽^) } else { // 詰め手数は、表示されていないぜ☆ if (Util_Taikyoku.PNNantedume_Teme[phaseIndex] != int.MaxValue) { // 詰め手数が消えたようだぜ☆ Util_Taikyoku.PNNantedume_Teme[phaseIndex] = int.MaxValue; } // もともと表示されていなかったのなら、そのままだぜ☆(^▽^) } }
/// <summary> /// 反転できるものは反転するぜ☆(^▽^) /// </summary> /// <param name="ref_hyokati"></param> /// <returns></returns> public static void Hanten(ref Hyokati ref_hyokati) { if (Conv_Hyokati.InHyokatiOrTumeTesu(ref_hyokati)) { ref_hyokati = (Hyokati)(-(int)ref_hyokati); } }
/// <summary> /// 符号を反転したものを返す /// </summary> public HyokatiUtiwake ToHanten() { Hyokati edaBest2 = EdaBest; Conv_Hyokati.Hanten(ref edaBest2); Hyokati komawari2 = Komawari; Conv_Hyokati.Hanten(ref komawari2); Hyokati nikoma2 = Nikoma; Conv_Hyokati.Hanten(ref nikoma2); Hyokati okimari2 = Okimari; Conv_Hyokati.Hanten(ref okimari2); return(new HyokatiUtiwake(edaBest2, komawari2, nikoma2, okimari2, Riyu, RiyuHosoku)); }
void Assert() { if (Conv_Hyokati.InHyokati(EdaBest)) { Debug.Assert((int)EdaBest == (int)Komawari + (int)Nikoma + (int)Okimari, $@"評価値の整合性エラー☆ hyokatiUtiwake.EdaBest =[{EdaBest}] hyokatiUtiwake.Komawari=[{Komawari}] hyokatiUtiwake.Nikoma =[{Nikoma}] hyokatiUtiwake.Okimari =[{Okimari}] riyu =[{Riyu}] riyuHosoku =[{RiyuHosoku}] " ); } }
public static bool TryParse(Kyokumen ky, string commandline, ref int caret, out SeisekiMove out_result, SeisekiKyokumen owner, StringBuilder syuturyoku) { bool successfule = true; // 指し手☆ if (!Med_Parser.TryFenMove(Option_Application.Optionlist.USI, commandline, ref caret, ky.Sindan, out Move ss)) { successfule = false; } // 応手☆ if (!Med_Parser.TryFenMove(Option_Application.Optionlist.USI, commandline, ref caret, ky.Sindan, out Move ss2)) { successfule = false; } // バージョン(これは無いこともある☆ 評価値のパーサーを使いまわし) if (!Conv_Hyokati.TryParse(commandline, ref caret, out int version, syuturyoku)) { version = 0; //successfule = false; } // 勝った回数(評価値のパーサーを使いまわし) if (!Conv_Hyokati.TryParse(commandline, ref caret, out int kati, syuturyoku)) { successfule = false; } // 引き分けた回数 if (!Conv_Hyokati.TryParse(commandline, ref caret, out int hikiwake, syuturyoku)) { successfule = false; } // 負けた回数 if (!Conv_Hyokati.TryParse(commandline, ref caret, out int make, syuturyoku)) { successfule = false; } out_result = new SeisekiMove(ss, ss2, version, kati, hikiwake, make, owner); return(successfule); }
/// <summary> /// 評価値を更新するぜ☆(^▽^) /// </summary> /// <param name="erandaSasite">実際に選んだ指し手☆</param> /// <param name="erandaHyokati">実際に選んだ手の評価値☆</param> public static void Update(Move erandaSasite, Hyokati erandaHyokati, Kyokumen ky, StringBuilder syuturyoku) { JosekiKyokumen joKy_orNull = Option_Application.Joseki.GetKyokumen(Util_KikaiGakusyu.KaisiKyHash); if (null == joKy_orNull)// この局面の定跡データが入っていなければ、そもそも 学習できないぜ☆(^▽^) { return; } // 成績表を見て、現局面で最も勝率の高い指し手を、教師とするぜ☆(^~^) Move kyosiSs = Option_Application.Seiseki.GetSasite_Winest(ky, out float kyosiSyoritu_notUse); Hyokati kyosiHyokati; // 教師の手の評価値☆ if (Util_KikaiGakusyu.FirstAndHappaFens.ContainsKey(kyosiSs)) // 教師の手はあるはずだろ☆(^~^)? { // まず、一手指すぜ☆ Nanteme nanteme = new Nanteme(); ky.DoMove(Option_Application.Optionlist.USI, kyosiSs, MoveType.N00_Karappo, ref nanteme, ky.CurrentOptionalPhase, syuturyoku); // 評価値を調べようぜ☆(^▽^) Hyokati komawariHyokati = ky.Komawari.Get(ky.CurrentOptionalPhase); Hyokati nikomaHyokati = ky.Nikoma.Get(true); kyosiHyokati = (int)komawariHyokati + nikomaHyokati; // 一手戻そうぜ☆(^▽^) ky.UndoMove(Option_Application.Optionlist.USI, kyosiSs, syuturyoku); } else { return; } // 教師の手の評価値が、一番高いとは限らないぜ☆(^~^) if (!Conv_Hyokati.InHyokati(kyosiHyokati)) { // 教師の評価値が、メートの数字などになっている場合は、学習はできないぜ☆(>_<) return; } Kyokumen happaKy = new Kyokumen(); int caret_temp2; double sumSigmoidY = 0.0d;// 積分☆ // 深さが異なるので、自分の局面、相手の局面 の数も異なり、 // 足す局面と、引く局面の数が合わなくなるぜ☆(^~^) // ↓ // せっかく 1P、2P の評価値を持っているのだから、 // 1P から引いた分は 2P に足す、ということでどうか☆(^~^)? // では、今回の合法手を全て見ていくぜ☆(^~^) foreach (KeyValuePair <Move, List <string> > entry in Util_KikaiGakusyu.FirstAndHappaFens) { if (entry.Key == kyosiSs) { // 教師の手は、今回はスルーするぜ☆(^▽^) continue; } // さて、教師以外の手だが……☆(^~^) HyokatiUtiwake sonotanoTe_hyokatiUtiwake; // まず、一手指すぜ☆ Nanteme nanteme = new Nanteme(); ky.DoMove(Option_Application.Optionlist.USI, entry.Key, MoveType.N00_Karappo, ref nanteme, ky.CurrentOptionalPhase, syuturyoku); // 評価値を調べようぜ☆(^▽^) ky.Hyoka(out sonotanoTe_hyokatiUtiwake, HyokaRiyu.Yososu, true// ランダムな局面で学習したりもするし☆(^~^) ); // 一手戻そうぜ☆(^▽^) ky.UndoMove(Option_Application.Optionlist.USI, entry.Key, syuturyoku); if (!Conv_Hyokati.InHyokati(sonotanoTe_hyokatiUtiwake.EdaBest)) { // その他の手の評価値が、メートの数字などになっている場合は、学習はできないぜ☆(>_<) continue; } // 教師の手と、それ以外の手の 評価値の差を、 // シグモイドの x に当てはめて、y を求めるぜ☆ double sigmoidY = Option_Application.Optionlist.NikomaGakusyuKeisu * Util_Sigmoid.Sigmoid(erandaHyokati - kyosiHyokati); // 教師の手(=一番評価値が高い手)より 評価値が上回っている手は、 // すると、 0.5 < y < 1 となるな☆ // 下回っていれば、 // 0 < y < 0.5 となるな☆ var(exists1, phase1) = Util_Tansaku.StartingPhase.Match; var(exists2, phase2) = happaKy.CurrentOptionalPhase.Match; // この点数を、葉 から かき集めるぜ☆www(^▽^) foreach (string happaFen in entry.Value) { caret_temp2 = 0; happaKy.ParsePositionvalue(Option_Application.Optionlist.USI, happaFen, ref caret_temp2, false, false, out string moves, syuturyoku); // この局面の2駒関係を、シグモイドの y 点分、下げるぜ☆ sumSigmoidY += Util_NikomaKankei.DecrementParamerter_KikaiGakusyu( happaKy, (exists1 && exists2 && phase1 == phase2) ? -sigmoidY : sigmoidY//自分の手番なら 引く☆ ); } } // 下げてかき集めた シグモイドの y の量を、 // 教師の指し手の葉に 山分けするぜ☆(^▽^) double yamawake = sumSigmoidY / (double)Util_KikaiGakusyu.FirstAndHappaFens[kyosiSs].Count; foreach (string happaFen in Util_KikaiGakusyu.FirstAndHappaFens[kyosiSs])// 教師の手はあるはずだろ☆(^~^)? { caret_temp2 = 0; happaKy.ParsePositionvalue(Option_Application.Optionlist.USI, happaFen, ref caret_temp2, false, false, out string moves, syuturyoku); var(exists1, phase1) = Util_Tansaku.StartingPhase.Match; var(exists2, phase2) = happaKy.CurrentOptionalPhase.Match; // 各葉に 山分けだぜ☆(^~^) Util_NikomaKankei.IncrementParamerter_KikaiGakusyu( happaKy, (exists1 && exists2 && phase1 == phase2) ? -yamawake : yamawake//自分の手番なら 足すぜ☆ ); } }
/// <summary> /// 評価値の表示。 /// 基本的に数字なんだが、数字の前に説明がつくことがあるぜ☆(^~^) /// 説明は各括弧で囲んであるぜ☆(^▽^) /// </summary> /// <param name="hyokati"></param> /// <param name="syuturyoku"></param> public static void Setumei(Hyokati hyokati, StringBuilder syuturyoku) { if (Conv_Hyokati.InSyokiti(hyokati)) { if (Option_Application.Optionlist.USI) { // USI syuturyoku.Append(((int)hyokati).ToString()); } else if (Hyokati.Syokiti_Alpha == hyokati) { syuturyoku.Append($"[α未設定] {(int)hyokati}"); } else if (Hyokati.Syokiti_Beta == hyokati) { syuturyoku.Append("[β未設定] {(int)hyokati}"); } else { throw new Exception("予期しない初期値だぜ☆(^~^)"); } return; } else if (Hyokati.TumeTesu_SeiNoSu_HyakuTeDume <= hyokati) { if (Hyokati.Sonota <= hyokati) { // その他☆(^~^) if (Option_Application.Optionlist.USI) { // USI syuturyoku.Append("0"); } else { switch (hyokati) { case Hyokati.Sonota_SyobuNasi: { syuturyoku.Append($"[SyobuNasi] {(int)hyokati}"); } break; default: { StringBuilder mojiretu1 = new StringBuilder(); mojiretu1.Append("[予期しない評価値だぜ☆(^~^) "); Conv_Hyokati.Setumei(hyokati, mojiretu1); mojiretu1.Append($"] {(int)hyokati}"); syuturyoku.AppendLine(mojiretu1.ToString()); throw new Exception(mojiretu1.ToString()); } } } } else { // 詰み手数が見えたときだぜ☆(^▽^) if (Option_Application.Optionlist.USI) { syuturyoku.Append("mate "); syuturyoku.Append(((int)(Hyokati.TumeTesu_SeiNoSu_ReiTeDume - (int)hyokati)).ToString()); } else { syuturyoku.Append("[katu "); syuturyoku.Append(((int)(Hyokati.TumeTesu_SeiNoSu_ReiTeDume - (int)hyokati)).ToString()); syuturyoku.Append("] "); syuturyoku.Append(((int)hyokati).ToString()); } } return; } else if (hyokati <= Hyokati.TumeTesu_FuNoSu_HyakuTeTumerare) { // 詰めを食らうぜ☆(>_<) if (Option_Application.Optionlist.USI) { syuturyoku.Append("mate "); syuturyoku.Append(((int)(Hyokati.TumeTesu_FuNoSu_ReiTeTumerare - (int)hyokati)).ToString()); } else { // 負数で出てくるのを、正の数に変換して表示するぜ☆(^▽^) syuturyoku.Append("[makeru "); syuturyoku.Append((-(int)(Hyokati.TumeTesu_FuNoSu_ReiTeTumerare - (int)hyokati)).ToString()); syuturyoku.Append("] "); syuturyoku.Append(((int)hyokati).ToString()); } return; } // 評価値☆ syuturyoku.Append("cp "); syuturyoku.Append(((int)hyokati).ToString());//enum型の名前が出ないように一旦int型に変換 }
public void CountUpTume() { EdaBest = Conv_Hyokati.CountUpTume(EdaBest); }