Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/engine/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1014,7 +1014,8 @@ export interface EngineStats {
* (and, within the current level, can fluctuate) until the exit is reached,
* at which point it becomes the baseline the next level carries forward. */
score: number;
/** Enemies defeated this level ("bugs squashed" for the commit summary). */
/** Enemies defeated this level. Surfaced to the player as the commit
* summary's and both run-end screens' "Kills" row, via `statRows`. */
kills: number;
/** True once any cheat has fired this run — drives the HUD's persistent
* "run not recorded" badge. See `PlayerState.cheatsUsed`. */
Expand Down
1 change: 0 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3674,7 +3674,6 @@ function launchLevel(path: string, parsed: ParsedFile, source: string | null, ca
hud.showCommitSummary(
{
linesRefactored: parsed.linesOfCode,
bugsSquashed: stats.kills,
stats: statsScreenInfo(stats.levelScoreBreakdown, stats.levelPlayerStats),
},
() => void advanceToNextLevel(stats),
Expand Down
21 changes: 15 additions & 6 deletions src/ui/gameHud.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,24 +166,33 @@ describe("GameHud — overlay content per method", () => {
});

it("showCommitSummary draws its stats and has no body lines", () => {
hud.showCommitSummary({ linesRefactored: 120, bugsSquashed: 3 }, vi.fn());
hud.showCommitSummary({ linesRefactored: 120 }, vi.fn());
const texts = fillTextCalls();
expect(texts).toContain("COMMIT SUMMARY");
expect(texts).toContain("Lines refactored");
expect(texts).toContain("120");
expect(texts).toContain("Bugs squashed");
expect(texts).toContain("3");
expect(texts).toContain("Continue");
});

it("showCommitSummary also draws the curated stat rows when given stats", () => {
hud.showCommitSummary({ linesRefactored: 120, bugsSquashed: 3, stats: fakeStatsScreenInfo() }, vi.fn());
hud.showCommitSummary({ linesRefactored: 120, stats: fakeStatsScreenInfo() }, vi.fn());
const texts = fillTextCalls();
expect(texts).toContain("Weapon accuracy");
expect(texts).toContain("Time survived");
expect(texts).toContain("Damage taken");
});

it("shows the kill count exactly once, as \"Kills\"", () => {
// Regression: "Bugs squashed" used to sit directly above the stats block
// and render the same number as its "Kills" row, one line apart. The two
// rows were built in different files, which is why it survived review and
// was only caught by playing a level.
hud.showCommitSummary({ linesRefactored: 120, stats: fakeStatsScreenInfo() }, vi.fn());
const texts = fillTextCalls();
expect(texts).not.toContain("Bugs squashed");
expect(texts.filter((t) => t === "Kills")).toHaveLength(1);
});

it("showMultiplayerResults draws the given title/color and one row per player", () => {
hud.showMultiplayerResults(
"MULTIPLAYER: CAMPAIGN COMPLETE",
Expand Down Expand Up @@ -652,7 +661,7 @@ describe("GameHud — no overlay squeezes its own text", () => {
// "Path … · Map … · Lore … · Secrets … · Streaks …" needs 446px against
// the 286px each side gets in a 620-wide box — the one case that was
// squeezed even *with* `wide` set, so no fixed width could have fixed it.
hud.showCommitSummary({ linesRefactored: 1234, bugsSquashed: 567, stats: fakeStatsScreenInfo() }, vi.fn());
hud.showCommitSummary({ linesRefactored: 1234, stats: fakeStatsScreenInfo() }, vi.fn());
expectNothingSqueezed();
});

Expand Down Expand Up @@ -692,7 +701,7 @@ describe("GameHud — no overlay squeezes its own text", () => {
const screens: [string, () => void][] = [
["kernel panic", () => hud.showKernelPanic(stats, vi.fn(), { cheated: true })],
["kernel panic + rollback", () => hud.showKernelPanic(undefined, vi.fn(), { rollback: { remaining: 2, onRollback: vi.fn() } })],
["commit summary", () => hud.showCommitSummary({ linesRefactored: 1234, bugsSquashed: 567, stats }, vi.fn())],
["commit summary", () => hud.showCommitSummary({ linesRefactored: 1234, stats }, vi.fn())],
["build successful", () => hud.showBuildSuccessful(stats, vi.fn())],
["level start", () => hud.showLevelStart({ campaign: "stage06_pipeline.py", levelName: "stage06_pipeline.py", roomCount: 12, enemyCount: 34, secretRoomCount: 2 }, vi.fn())],
// The worst string in the repo by a distance: `main.ts`'s balance-mismatch
Expand Down
27 changes: 23 additions & 4 deletions src/ui/gameHud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,29 @@ export interface StatsScreenInfo {
/** Stats shown on the post-level commit summary. */
export interface CommitSummaryInfo {
linesRefactored: number;
bugsSquashed: number;
/** This level's own curated stats/breakdown — omitted shows just the two
* fields above, same as before this existed. */
/** This level's own curated stats/breakdown — omitted shows just the line
* count above, same as before this existed.
*
* The kill count lives in here (`statRows`' "Kills"), not as a field of its
* own. It used to be both: a "Bugs squashed" row sat directly above the
* stats block and rendered the identical number, because the two rows are
* built in different files and nobody saw them together until someone
* played a level.
*
* **The duplication is why it was noticed; the name is why "Kills" won.**
* This game reads somebody's real source code, so "Bugs squashed: 47" is a
* claim that their file contained 47 defects. It did not — it contained
* enemies derived from cyclomatic complexity, and complexity is not defects.
* Never let a label assert something about the player's codebase that the
* generator has no basis for; "Kills" describes what actually happened and
* claims nothing.
*
* Secondary, but it points the same way: the game has a *literal* `Bug`.
* `placeTodoEncounter` (`map/generation/lore.ts`) spawns one beside a
* TODO/FIXME terminal, and it is rare — measured on the demo campaign the
* tech-debt mix is trap 4 / mine 3 / Bug 1 across all 17 levels. So the row
* named the one entity here that really is a bug, while counting everything
* except it. */
stats?: StatsScreenInfo;
}

Expand Down Expand Up @@ -178,7 +198,6 @@ export class GameHud {
lines: [],
stats: [
["Lines refactored", String(info.linesRefactored)],
["Bugs squashed", String(info.bugsSquashed)],
...(info.stats ? statRows(info.stats) : []),
],
buttonLabel: "Continue",
Expand Down