make ships claim targets
This commit is contained in:
@@ -297,6 +297,10 @@ WorldConfig ConfigLoader::loadWorld(const std::string& path)
|
||||
throw makeError(file, "waves", "gap_min_seconds > gap_max_seconds");
|
||||
}
|
||||
|
||||
cfg.targeting.targetScoreFormula = requireFormula(tbl["targeting"]["target_score_formula"], file, "targeting.target_score_formula");
|
||||
cfg.targeting.overclaimPenaltyFormula = requireFormula(tbl["targeting"]["overclaim_penalty_formula"], file, "targeting.overclaim_penalty_formula");
|
||||
cfg.targeting.hysteresis = requireDouble(tbl["targeting"]["target_hysteresis"], file, "targeting.target_hysteresis");
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,14 @@
|
||||
|
||||
#include "tinyexpr.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
// tinyexpr has no built-in min/max; expose them so config formulas can
|
||||
// clamp (e.g. a floored overclaim penalty "max(0.5, 1 - 0.1*x)").
|
||||
double formulaMin(double a, double b) { return a < b ? a : b; }
|
||||
double formulaMax(double a, double b) { return a > b ? a : b; }
|
||||
}
|
||||
|
||||
Formula::Formula(Formula&& other) noexcept
|
||||
: m_source(std::move(other.m_source))
|
||||
, m_x(std::move(other.m_x))
|
||||
@@ -37,11 +45,14 @@ Formula Formula::compile(const std::string& source)
|
||||
result.m_x = std::make_unique<double>(0.0);
|
||||
|
||||
const te_variable variables[] = {
|
||||
{ "x", result.m_x.get(), 0, nullptr },
|
||||
{ "x", result.m_x.get(), TE_VARIABLE, nullptr },
|
||||
{ "min", reinterpret_cast<const void*>(&formulaMin), TE_FUNCTION2 | TE_FLAG_PURE, nullptr },
|
||||
{ "max", reinterpret_cast<const void*>(&formulaMax), TE_FUNCTION2 | TE_FLAG_PURE, nullptr },
|
||||
};
|
||||
|
||||
int errorPos = 0;
|
||||
result.m_expr = te_compile(result.m_source.c_str(), variables, 1, &errorPos);
|
||||
const int variableCount = static_cast<int>(sizeof(variables) / sizeof(variables[0]));
|
||||
result.m_expr = te_compile(result.m_source.c_str(), variables, variableCount, &errorPos);
|
||||
|
||||
if (result.m_expr == nullptr)
|
||||
{
|
||||
@@ -66,3 +77,4 @@ double Formula::evaluate(double x) const
|
||||
*m_x = x;
|
||||
return te_eval(m_expr);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,14 @@ struct WorldWaves
|
||||
double bossQuietAfterSeconds; // suppress normal waves this long after boss (REQ-WAV-QUIET)
|
||||
};
|
||||
|
||||
// Ship target selection (claim-aware scoring).
|
||||
struct WorldTargeting
|
||||
{
|
||||
Formula targetScoreFormula; // x = distance / max weapon range; higher = better
|
||||
Formula overclaimPenaltyFormula; // x = competing claim count; factor in [0,1]
|
||||
double hysteresis; // fractional margin a challenger must beat the current target by
|
||||
};
|
||||
|
||||
struct WorldConfig
|
||||
{
|
||||
int heightTiles; // REQ-GW-HEIGHT
|
||||
@@ -56,4 +64,5 @@ struct WorldConfig
|
||||
WorldExpansion expansion;
|
||||
WorldPush push;
|
||||
WorldWaves waves;
|
||||
WorldTargeting targeting;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user