/// <summary> /// 評価値の値をわかりやすく文字列化する。 /// </summary> /// <param name="value"></param> /// <returns></returns> public static string Pretty(this EvalValue value) { if (value.IsSpecialValue()) { switch (value) { case EvalValue.Unknown: return("不明"); case EvalValue.MatePlus: return("MATE(手数不明)"); case EvalValue.MatedMinus: return("MATED(手数不明)"); case EvalValue.NoValue: return(""); // これ表示するとおかしくなるので表示なしにしとく。 } // int にキャストしないと 0手 が Zero手 と出力される if (value > 0) { return($"MATE({(int)(EvalValue.Mate - value)}手)"); } if (value < 0) { return($"MATED({(int)(value - EvalValue.Mated)}手)"); } } // 0以外は符号付きで出力 return(((int)value).ToString("+0;-0;0")); }
/// <summary> /// 形勢判断の文字列に変換する /// </summary> /// <param name="value"></param> /// <returns></returns> public static string ToEvalJudgement(this EvalValue value) { if (value.IsSpecialValue()) { if (value > 0) { return("先手勝ち"); } else { return("後手勝ち"); } } else { var v = (int)value; if (v > 0) { return ((v >= 2000) ? "先手勝勢" : (v >= 800) ? "先手優勢" : (v >= 300) ? "先手有利" : "形勢互角"); } else { return ((v <= -2000) ? "後手勝勢" : (v <= -800) ? "後手優勢" : (v <= -300) ? "後手有利" : "形勢互角"); } } }
static GameEvaluationData randomEval(Random rand, int player, int length) { var list = new List <EvalValue>(); EvalValue score = (EvalValue)70; for (var i = 0; i < length; ++i) { if (1 - (i & 1) == player) { list.Add(EvalValue.NoValue); } else if ((Int32)score < -100000000) { if (score >= EvalValue.Mated) { list.Add(score = score - 1); } else { list.Add(score = EvalValue.Mated); } } else if ((Int32)score > +1000000000) { if (score <= EvalValue.Mate) { list.Add(score = score + 1); } else { list.Add(score = EvalValue.Mate); } } else { if (rand.Next(0, 500000) < Math.Abs((Int32)score)) { if (score < 0) { list.Add(score = EvalValue.Mated + rand.Next(0, 32)); } else { list.Add(score = EvalValue.Mate - rand.Next(0, 32)); } } else { float nextScore = (float)score * 1.02f + (player < 2 ? 0.00004f : 0.00002f) * rand.Next(-100, +100) * rand.Next(-100, +100) * rand.Next(-1000, +1000); score = (EvalValue)Math.Max(Math.Min(nextScore, +10000000), -10000000); list.Add(score); } } } return(new GameEvaluationData() { values = list }); }
/// <summary> /// 評価値を反転する。 /// </summary> public EvalValueEx negate() { EvalValue eval = (Eval != EvalValue.Unknown && Eval != EvalValue.NoValue) ? (EvalValue)(-(Int32)Eval) : Eval; ScoreBound bound; switch (Bound) { case ScoreBound.Upper: bound = ScoreBound.Lower; break; case ScoreBound.Lower: bound = ScoreBound.Upper; break; default: bound = Bound; break; } return(new EvalValueEx(eval, bound)); }
/// <summary> /// 形勢判断の文字列に変換する /// </summary> /// <param name="value"></param> /// <param name="handicapped">駒落ちであるか</param> /// <returns></returns> public static string ToEvalJudgement(this EvalValue value, bool handicapped) { var black = handicapped ? "下手" : "先手"; var white = handicapped ? "上手" : "後手"; if (value.IsSpecialValue()) { if (value > 0) { return($"{black}勝ち"); } else { return($"{white}勝ち"); } } else { var v = (int)value; if (v > 0) { return ((v >= 2000) ? $"{black}勝勢" : (v >= 800) ? $"{black}優勢" : (v >= 300) ? $"{black}有利" : "形勢互角"); } else { return ((v <= -2000) ? $"{white}勝勢" : (v <= -800) ? $"{white}優勢" : (v <= -300) ? $"{white}有利" : "形勢互角"); } } }
public EvalValueEx(EvalValue eval, ScoreBound bound) { Eval = eval; Bound = bound; }
/// <summary> /// EvalValueが通常の評価値の値ではなく、特殊な意味を持つ値であるかを判定する。 /// ※ 通常の評価値の値は -1000000 ~ +1000000までであるものとする。 /// </summary> /// <param name="value"></param> /// <returns></returns> public static bool IsSpecialValue(this EvalValue value) { return(!(-1000000 <= (int)value && (int)value <= +1000000)); }
internal override Value Eval(Value arg, IScope scope) { Map map = arg.AsMap; ValueMap mapOrScope = map["map"] as ValueMap; Value prevValue = map["previous"]; Value nextValue = map["next"]; Value value = null; if (map["line"] is ValueRaw) { value = new EvalValue(); nextValue = map["line"]; } else if (map["functionKey"] is ValueString) { string name = map["functionKey"].AsString; value = scope.GetValue(new Token(name)); } ValueFunction function = value as ValueFunction; IScope where = mapOrScope.Scope; if (where != null) where.AddOnExit(function, prevValue, nextValue); return ValueNil.Nil; }