content: regenerate Season 1 with a gentle onboarding difficulty curve

Generator: raise the early bot-win-rate floor to ~0.97 (near-guaranteed first
stages), widen the early move-buffer margin, and delay score-chase/line-sprint
objectives until stage 9/13 so the opening stretch is pure clear-a-gem. Result:
stage 1 now 16 moves (was 11), stages 1-9 all simple gems at 90-99% bot win.
Preserves theme.bgm=season_001; manifest SHA regenerated. Settings tag -> build 4.
This commit is contained in:
2026-06-14 11:02:29 +09:00
parent 1682578501
commit 7c7c7afad0
7 changed files with 880 additions and 861 deletions
+11 -6
View File
@@ -106,8 +106,10 @@ ${reportRows.join('\n')}
/// weaker than the bot, so the floor stays high — and early stages are
/// allowed to be a guaranteed win (onboarding).
(double, double) _band(double t) => (
0.78 - 0.30 * t,
t < 0.4 ? 1.0 : 1.0 - 0.10 * (t - 0.4) / 0.6,
// Near-guaranteed onboarding (the bot easily clears the first stages, so
// a human does too), ramping to a genuine challenge by the season's end.
0.97 - 0.50 * t,
t < 0.5 ? 1.0 : 1.0 - 0.12 * (t - 0.5) / 0.5,
);
(StageConfig, double, List<int>)? _buildCandidate(
@@ -145,7 +147,9 @@ ${reportRows.join('\n')}
movesToWin.sort();
final median = movesToWin[movesToWin.length ~/ 2];
final margin = 0.45 - 0.25 * t;
// Generous early move buffer over what the bot needs (humans place less
// optimally and the piece RNG won't always cooperate), tightening later.
final margin = 1.0 - 0.65 * t;
var moveLimit = (median * (1 + margin)).ceil().clamp(6, 60);
// Validate at the real budget; nudge the budget up/down until the win
@@ -248,11 +252,12 @@ Objective _sampleObjective(
int index, double t, List<PresetCell> preset, SeededRng rng) {
final gemCount =
preset.where((c) => c.type == CellType.gem).length;
// Variety beats: every 5th stage is a score chase, every 7th a line sprint.
if (index % 7 == 6) {
// Keep the opening stretch pure "clear a gem" onboarding; introduce the
// score-chase and line-sprint variety only once the player has settled in.
if (index >= 12 && index % 7 == 6) {
return Objective.clearLines(3 + (t * 7).round() + rng.nextInt(2));
}
if (index % 5 == 4) {
if (index >= 8 && index % 5 == 4) {
return Objective.reachScore(600 + (t * 2400).round() + rng.nextInt(200));
}
return Objective.clearGems(gemCount);