fix(monsters): finish deleting experienceReward, column included

Design ruling R7 abolishes XP as a concept and says the column goes with
it, but no task in the plan actually dropped it -- the plan only dropped
characters.experience and combat_rewards.experience_granted. Task 9
removed experienceReward from the seed literals, leaving
monster_definitions.experience_reward as a NOT NULL column with no
default that nothing supplies. The first monster insert against a real
database would have failed on a constraint violation.

No suite here could have caught it: none of them connect to Postgres.

Drops the column in the slice migration (which has never been run, so
amending it in place is correct rather than stacking a second one),
removes the entity field, and clears the three test fixtures that still
set it. silver_min/silver_max deliberately stay -- spec 15 keeps a
direct currency drop available as a lore-valid exception, and XP has no
such carve-out.

Also retargets the seed idempotency test off renown: 1, which is the
seed's own default and so could not distinguish "preserved" from
"reset to default".

NOTE ON SCOPE: this commit also absorbs a Prettier reformatting pass
that was already sitting uncommitted in the working tree, which is why
it touches ~59 files. That churn is purely cosmetic line-rewrapping --
verified by inspection, and the suite is green at 267/267 with the build
at exactly the 3 expected errors owned by Tasks 10 and 11. The repo is
not Prettier-clean at baseline (119 files still flagged), so this was a
partial run by an earlier step, not a deliberate repo-wide format.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Bastian Wagner
2026-08-21 14:07:47 +02:00
parent dce26e00ad
commit 8835671657
59 changed files with 1368 additions and 399 deletions

View File

@@ -160,7 +160,9 @@ export class CreateLootAndRewards1788600000000 implements MigrationInterface {
'ALTER TABLE "monster_definitions" DROP COLUMN "loot_table_id"',
);
await queryRunner.query('DROP INDEX "IDX_loot_table_entries_table_item"');
await queryRunner.query('DROP INDEX "IDX_loot_table_entries_table_position"');
await queryRunner.query(
'DROP INDEX "IDX_loot_table_entries_table_position"',
);
await queryRunner.query('DROP TABLE "loot_table_entries"');
await queryRunner.query('DROP INDEX "IDX_loot_tables_key"');
await queryRunner.query('DROP TABLE "loot_tables"');

View File

@@ -7,9 +7,7 @@ import { MigrationInterface, QueryRunner } from 'typeorm';
* alone — the map and hunt screens still render them. Backfill defaults keep
* existing rows valid; the seed replaces them with authored content.
*/
export class CreateLocalLocationView1788700000000
implements MigrationInterface
{
export class CreateLocalLocationView1788700000000 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'ALTER TABLE "location_definitions" ADD COLUMN "region_name" character varying(150) NOT NULL DEFAULT \'\'',

View File

@@ -2,10 +2,18 @@ import { MigrationInterface, QueryRunner } from 'typeorm';
export class ExtendCombatEventTypes1790000000000 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TYPE "combat_event_type_enum" ADD VALUE 'HEAL'`);
await queryRunner.query(`ALTER TYPE "combat_event_type_enum" ADD VALUE 'DEFEND'`);
await queryRunner.query(`ALTER TYPE "combat_event_type_enum" ADD VALUE 'TELEGRAPH'`);
await queryRunner.query(`ALTER TYPE "combat_event_type_enum" ADD VALUE 'INTERRUPT'`);
await queryRunner.query(
`ALTER TYPE "combat_event_type_enum" ADD VALUE 'HEAL'`,
);
await queryRunner.query(
`ALTER TYPE "combat_event_type_enum" ADD VALUE 'DEFEND'`,
);
await queryRunner.query(
`ALTER TYPE "combat_event_type_enum" ADD VALUE 'TELEGRAPH'`,
);
await queryRunner.query(
`ALTER TYPE "combat_event_type_enum" ADD VALUE 'INTERRUPT'`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {

View File

@@ -13,7 +13,9 @@ export class CreateRenownAndReputation1791000000000 implements MigrationInterfac
'ALTER TABLE "characters" ADD CONSTRAINT "CHK_characters_renown" CHECK ("renown" >= 1 AND "renown" <= 15)',
);
await queryRunner.query('ALTER TABLE "characters" DROP COLUMN "level"');
await queryRunner.query('ALTER TABLE "characters" DROP COLUMN "experience"');
await queryRunner.query(
'ALTER TABLE "characters" DROP COLUMN "experience"',
);
// --- ItemDefinition: drop requiredLevel (spec §14, design R4) ---
await queryRunner.query(
@@ -48,6 +50,14 @@ export class CreateRenownAndReputation1791000000000 implements MigrationInterfac
'ALTER TABLE "combat_rewards" DROP COLUMN "experience_granted"',
);
// --- MonsterDefinition: XP is abolished as a concept (spec §1, design R7).
// `silver_min`/`silver_max` deliberately stay -- spec §15 keeps a direct
// currency drop available as a lore-valid exception -- but XP has no such
// carve-out, so the column goes with the concept. ---
await queryRunner.query(
'ALTER TABLE "monster_definitions" DROP COLUMN "experience_reward"',
);
// --- ReputationFaction (spec §9) ---
await queryRunner.query(`CREATE TABLE "reputation_factions" (
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
@@ -141,14 +151,22 @@ export class CreateRenownAndReputation1791000000000 implements MigrationInterfac
'DROP INDEX "IDX_character_renown_milestones_character_milestone"',
);
await queryRunner.query('DROP TABLE "character_renown_milestones"');
await queryRunner.query('DROP INDEX "IDX_renown_milestone_definitions_key"');
await queryRunner.query(
'DROP INDEX "IDX_renown_milestone_definitions_key"',
);
await queryRunner.query('DROP TABLE "renown_milestone_definitions"');
await queryRunner.query('DROP INDEX "IDX_character_reputation_character_faction"');
await queryRunner.query(
'DROP INDEX "IDX_character_reputation_character_faction"',
);
await queryRunner.query('DROP TABLE "character_reputation"');
await queryRunner.query('DROP INDEX "IDX_reputation_factions_key"');
await queryRunner.query('DROP TABLE "reputation_factions"');
await queryRunner.query(
'ALTER TABLE "monster_definitions" ADD COLUMN "experience_reward" integer NOT NULL DEFAULT 0',
);
await queryRunner.query(
'ALTER TABLE "combat_rewards" ADD COLUMN "experience_granted" integer NOT NULL DEFAULT 0',
);
@@ -175,12 +193,16 @@ export class CreateRenownAndReputation1791000000000 implements MigrationInterfac
'ALTER TABLE "item_definitions" ADD COLUMN "required_level" integer NOT NULL DEFAULT 1',
);
await queryRunner.query('ALTER TABLE "characters" ADD COLUMN "level" integer NOT NULL DEFAULT 1');
await queryRunner.query(
'ALTER TABLE "characters" ADD COLUMN "level" integer NOT NULL DEFAULT 1',
);
await queryRunner.query(
'ALTER TABLE "characters" ADD COLUMN "experience" integer NOT NULL DEFAULT 0',
);
await queryRunner.query('UPDATE "characters" SET "level" = "renown"');
await queryRunner.query('ALTER TABLE "characters" DROP CONSTRAINT "CHK_characters_renown"');
await queryRunner.query(
'ALTER TABLE "characters" DROP CONSTRAINT "CHK_characters_renown"',
);
await queryRunner.query('ALTER TABLE "characters" DROP COLUMN "renown"');
}
}

View File

@@ -8,7 +8,8 @@ describe('combat system schema', () => {
const metadata = getMetadataArgsStorage();
const relations = metadata.relations.filter(
(relation) => relation.target === Combat || relation.target === CombatEvent,
(relation) =>
relation.target === Combat || relation.target === CombatEvent,
);
expect(
@@ -19,10 +20,26 @@ describe('combat system schema', () => {
})),
).toEqual(
expect.arrayContaining([
expect.objectContaining({ onDelete: 'RESTRICT', propertyName: 'character', target: Combat }),
expect.objectContaining({ onDelete: 'RESTRICT', propertyName: 'huntEncounter', target: Combat }),
expect.objectContaining({ onDelete: 'RESTRICT', propertyName: 'monster', target: Combat }),
expect.objectContaining({ onDelete: 'CASCADE', propertyName: 'combat', target: CombatEvent }),
expect.objectContaining({
onDelete: 'RESTRICT',
propertyName: 'character',
target: Combat,
}),
expect.objectContaining({
onDelete: 'RESTRICT',
propertyName: 'huntEncounter',
target: Combat,
}),
expect.objectContaining({
onDelete: 'RESTRICT',
propertyName: 'monster',
target: Combat,
}),
expect.objectContaining({
onDelete: 'CASCADE',
propertyName: 'combat',
target: CombatEvent,
}),
]),
);
});
@@ -37,7 +54,10 @@ describe('combat system schema', () => {
);
expect(index).toBeDefined();
const indexMetadata = index as typeof index & { options?: { unique?: boolean }; unique?: boolean };
const indexMetadata = index as typeof index & {
options?: { unique?: boolean };
unique?: boolean;
};
expect(indexMetadata?.options?.unique ?? indexMetadata?.unique).toBe(true);
});
});

View File

@@ -7,7 +7,8 @@ describe('character_equipment schema', () => {
const metadata = getMetadataArgsStorage();
const column = metadata.columns.find(
(candidate) =>
candidate.target === CharacterEquipment && candidate.propertyName === 'slot',
candidate.target === CharacterEquipment &&
candidate.propertyName === 'slot',
);
expect(column).toBeDefined();

View File

@@ -7,7 +7,8 @@ describe('combat_events.type enum', () => {
it('includes the Playable Slice 0.6 event types', () => {
const metadata = getMetadataArgsStorage();
const column = metadata.columns.find(
(candidate) => candidate.target === CombatEvent && candidate.propertyName === 'type',
(candidate) =>
candidate.target === CombatEvent && candidate.propertyName === 'type',
);
expect(column).toBeDefined();

View File

@@ -29,21 +29,31 @@ describe('loot and rewards schema', () => {
});
it('keeps one stack per character per item definition', () => {
expect(uniqueIndexFor(CharacterItem, ['characterId', 'itemDefinitionId'])).toBe(true);
expect(
uniqueIndexFor(CharacterItem, ['characterId', 'itemDefinitionId']),
).toBe(true);
});
it('keeps loot-table content keys and entry positions unique', () => {
expect(uniqueIndexFor(ItemDefinition, ['key'])).toBe(true);
expect(uniqueIndexFor(LootTable, ['key'])).toBe(true);
expect(uniqueIndexFor(LootTableEntry, ['lootTableId', 'position'])).toBe(true);
expect(uniqueIndexFor(LootTableEntry, ['lootTableId', 'itemDefinitionId'])).toBe(true);
expect(uniqueIndexFor(LootTableEntry, ['lootTableId', 'position'])).toBe(
true,
);
expect(
uniqueIndexFor(LootTableEntry, ['lootTableId', 'itemDefinitionId']),
).toBe(true);
});
it('maps reward and loot relations with the documented onDelete behavior', () => {
const relations = getMetadataArgsStorage().relations.filter((relation) =>
[CombatReward, CombatRewardItem, CharacterItem, LootTableEntry, MonsterDefinition].includes(
relation.target as never,
),
[
CombatReward,
CombatRewardItem,
CharacterItem,
LootTableEntry,
MonsterDefinition,
].includes(relation.target as never),
);
expect(
@@ -54,16 +64,56 @@ describe('loot and rewards schema', () => {
})),
).toEqual(
expect.arrayContaining([
expect.objectContaining({ onDelete: 'CASCADE', propertyName: 'combat', target: CombatReward }),
expect.objectContaining({ onDelete: 'RESTRICT', propertyName: 'character', target: CombatReward }),
expect.objectContaining({ onDelete: 'CASCADE', propertyName: 'combatReward', target: CombatRewardItem }),
expect.objectContaining({ onDelete: 'RESTRICT', propertyName: 'characterItem', target: CombatRewardItem }),
expect.objectContaining({ onDelete: 'RESTRICT', propertyName: 'itemDefinition', target: CombatRewardItem }),
expect.objectContaining({ onDelete: 'CASCADE', propertyName: 'character', target: CharacterItem }),
expect.objectContaining({ onDelete: 'RESTRICT', propertyName: 'itemDefinition', target: CharacterItem }),
expect.objectContaining({ onDelete: 'CASCADE', propertyName: 'lootTable', target: LootTableEntry }),
expect.objectContaining({ onDelete: 'RESTRICT', propertyName: 'itemDefinition', target: LootTableEntry }),
expect.objectContaining({ onDelete: 'RESTRICT', propertyName: 'lootTable', target: MonsterDefinition }),
expect.objectContaining({
onDelete: 'CASCADE',
propertyName: 'combat',
target: CombatReward,
}),
expect.objectContaining({
onDelete: 'RESTRICT',
propertyName: 'character',
target: CombatReward,
}),
expect.objectContaining({
onDelete: 'CASCADE',
propertyName: 'combatReward',
target: CombatRewardItem,
}),
expect.objectContaining({
onDelete: 'RESTRICT',
propertyName: 'characterItem',
target: CombatRewardItem,
}),
expect.objectContaining({
onDelete: 'RESTRICT',
propertyName: 'itemDefinition',
target: CombatRewardItem,
}),
expect.objectContaining({
onDelete: 'CASCADE',
propertyName: 'character',
target: CharacterItem,
}),
expect.objectContaining({
onDelete: 'RESTRICT',
propertyName: 'itemDefinition',
target: CharacterItem,
}),
expect.objectContaining({
onDelete: 'CASCADE',
propertyName: 'lootTable',
target: LootTableEntry,
}),
expect.objectContaining({
onDelete: 'RESTRICT',
propertyName: 'itemDefinition',
target: LootTableEntry,
}),
expect.objectContaining({
onDelete: 'RESTRICT',
propertyName: 'lootTable',
target: MonsterDefinition,
}),
]),
);
});
@@ -72,14 +122,16 @@ describe('loot and rewards schema', () => {
const columns = getMetadataArgsStorage().columns;
const silver = columns.find(
(candidate) => candidate.target === Character && candidate.propertyName === 'silver',
(candidate) =>
candidate.target === Character && candidate.propertyName === 'silver',
);
expect(silver).toBeDefined();
expect(silver?.options.type).toBe('integer');
const lootTableId = columns.find(
(candidate) =>
candidate.target === MonsterDefinition && candidate.propertyName === 'lootTableId',
candidate.target === MonsterDefinition &&
candidate.propertyName === 'lootTableId',
);
expect(lootTableId).toBeDefined();
expect(lootTableId?.options.nullable).toBe(true);
@@ -88,7 +140,8 @@ describe('loot and rewards schema', () => {
it('stores drop chance as a numeric column so probabilities stay data-driven', () => {
const dropChance = getMetadataArgsStorage().columns.find(
(candidate) =>
candidate.target === LootTableEntry && candidate.propertyName === 'dropChance',
candidate.target === LootTableEntry &&
candidate.propertyName === 'dropChance',
);
expect(dropChance?.options.type).toBe('numeric');
@@ -111,11 +164,19 @@ describe('loot and rewards schema', () => {
expect(upQueries).toEqual(
expect.arrayContaining([
// The database half of the "one reward per combat" invariant (spec §7, §37).
expect.stringContaining('CREATE UNIQUE INDEX "IDX_combat_rewards_combat"'),
expect.stringContaining('CREATE UNIQUE INDEX "IDX_character_items_character_item"'),
expect.stringContaining('CREATE UNIQUE INDEX "IDX_combat_reward_items_reward_item"'),
expect.stringContaining(
'CREATE UNIQUE INDEX "IDX_combat_rewards_combat"',
),
expect.stringContaining(
'CREATE UNIQUE INDEX "IDX_character_items_character_item"',
),
expect.stringContaining(
'CREATE UNIQUE INDEX "IDX_combat_reward_items_reward_item"',
),
expect.stringContaining('ALTER TABLE "characters" ADD COLUMN "silver"'),
expect.stringContaining('ALTER TABLE "monster_definitions" ADD COLUMN "loot_table_id"'),
expect.stringContaining(
'ALTER TABLE "monster_definitions" ADD COLUMN "loot_table_id"',
),
]),
);

View File

@@ -19,9 +19,13 @@ function columnNames(target: unknown): string[] {
function uniqueIndexFor(target: unknown, columns: string[]): boolean {
const index = getMetadataArgsStorage().indices.find(
(candidate) =>
candidate.target === target && columns.every((column) => candidate.columns?.includes(column)),
candidate.target === target &&
columns.every((column) => candidate.columns?.includes(column)),
);
const meta = index as typeof index & { options?: { unique?: boolean }; unique?: boolean };
const meta = index as typeof index & {
options?: { unique?: boolean };
unique?: boolean;
};
return (meta?.options?.unique ?? meta?.unique) === true;
}
@@ -52,7 +56,9 @@ describe('Slice 0.6.5 entity metadata', () => {
});
it('CharacterReputation enforces one row per character per faction', () => {
expect(uniqueIndexFor(CharacterReputation, ['characterId', 'factionId'])).toBe(true);
expect(
uniqueIndexFor(CharacterReputation, ['characterId', 'factionId']),
).toBe(true);
});
it('RenownMilestoneDefinition has a unique key', () => {

View File

@@ -35,8 +35,12 @@ describe('CreateRenownAndReputation1791000000000', () => {
it('backfills renown from level BEFORE dropping the level column', async () => {
const up = await runUp();
const backfillIndex = up.findIndex((sql) => sql.includes('LEAST(GREATEST("level", 1), 15)'));
const dropLevelIndex = up.findIndex((sql) => sql.includes('DROP COLUMN "level"'));
const backfillIndex = up.findIndex((sql) =>
sql.includes('LEAST(GREATEST("level", 1), 15)'),
);
const dropLevelIndex = up.findIndex((sql) =>
sql.includes('DROP COLUMN "level"'),
);
expect(backfillIndex).toBeGreaterThanOrEqual(0);
expect(dropLevelIndex).toBeGreaterThanOrEqual(0);
@@ -47,8 +51,12 @@ describe('CreateRenownAndReputation1791000000000', () => {
it('adds the renown range constraint only AFTER the backfill has populated valid values', async () => {
const up = await runUp();
const backfillIndex = up.findIndex((sql) => sql.includes('LEAST(GREATEST("level", 1), 15)'));
const constraintIndex = up.findIndex((sql) => sql.includes('CHK_characters_renown'));
const backfillIndex = up.findIndex((sql) =>
sql.includes('LEAST(GREATEST("level", 1), 15)'),
);
const constraintIndex = up.findIndex((sql) =>
sql.includes('CHK_characters_renown'),
);
expect(backfillIndex).toBeGreaterThanOrEqual(0);
expect(constraintIndex).toBeGreaterThanOrEqual(0);
@@ -62,7 +70,9 @@ describe('CreateRenownAndReputation1791000000000', () => {
expect(up).toEqual(
expect.arrayContaining([
expect.stringContaining('ALTER TABLE "item_definitions" DROP COLUMN "required_level"'),
expect.stringContaining(
'ALTER TABLE "item_definitions" DROP COLUMN "required_level"',
),
]),
);
});
@@ -72,8 +82,12 @@ describe('CreateRenownAndReputation1791000000000', () => {
expect(up).toEqual(
expect.arrayContaining([
expect.stringContaining(`SET "type" = 'EQUIPMENT' WHERE "type" IN ('WEAPON', 'ARMOR')`),
expect.stringContaining(`SET "type" = 'TRADE_GOOD' WHERE "type" = 'MATERIAL'`),
expect.stringContaining(
`SET "type" = 'EQUIPMENT' WHERE "type" IN ('WEAPON', 'ARMOR')`,
),
expect.stringContaining(
`SET "type" = 'TRADE_GOOD' WHERE "type" = 'MATERIAL'`,
),
expect.stringContaining('DROP TYPE "item_type_enum"'),
expect.stringContaining(
`CREATE TYPE "item_type_enum" AS ENUM ('EQUIPMENT', 'TRADE_GOOD', 'TROPHY', 'QUEST_ITEM', 'CONSUMABLE')`,
@@ -87,30 +101,63 @@ describe('CreateRenownAndReputation1791000000000', () => {
expect(up).toEqual(
expect.arrayContaining([
expect.stringContaining('ALTER TABLE "combat_rewards" DROP COLUMN "experience_granted"'),
expect.stringContaining(
'ALTER TABLE "combat_rewards" DROP COLUMN "experience_granted"',
),
]),
);
});
/**
* XP is abolished outright (design R7), so the column goes with the concept.
* It is NOT NULL with no default, so leaving it behind while the seed stops
* supplying a value would fail every monster insert against a real database
* -- a break no suite here can catch, since none of them connect to Postgres.
*/
it('drops experience_reward from monster_definitions', async () => {
const up = await runUp();
expect(up).toEqual(
expect.arrayContaining([
expect.stringContaining(
'ALTER TABLE "monster_definitions" DROP COLUMN "experience_reward"',
),
]),
);
});
it('keeps silver_min and silver_max on monster_definitions', async () => {
const up = await runUp();
expect(up.join(' ')).not.toContain('"silver_min"');
expect(up.join(' ')).not.toContain('"silver_max"');
});
it('creates all five new tables with their unique constraints', async () => {
const up = await runUp();
expect(up).toEqual(
expect.arrayContaining([
expect.stringContaining('CREATE TABLE "reputation_factions"'),
expect.stringContaining('CREATE UNIQUE INDEX "IDX_reputation_factions_key"'),
expect.stringContaining(
'CREATE UNIQUE INDEX "IDX_reputation_factions_key"',
),
expect.stringContaining('CREATE TABLE "character_reputation"'),
expect.stringContaining(
'CREATE UNIQUE INDEX "IDX_character_reputation_character_faction" ON "character_reputation" ("character_id", "faction_id")',
),
expect.stringContaining('CREATE TABLE "renown_milestone_definitions"'),
expect.stringContaining('CREATE UNIQUE INDEX "IDX_renown_milestone_definitions_key"'),
expect.stringContaining(
'CREATE UNIQUE INDEX "IDX_renown_milestone_definitions_key"',
),
expect.stringContaining('CREATE TABLE "character_renown_milestones"'),
expect.stringContaining(
'CREATE UNIQUE INDEX "IDX_character_renown_milestones_character_milestone" ON "character_renown_milestones" ("character_id", "milestone_id")',
),
expect.stringContaining('CREATE TABLE "turn_in_definitions"'),
expect.stringContaining('CREATE UNIQUE INDEX "IDX_turn_in_definitions_key"'),
expect.stringContaining(
'CREATE UNIQUE INDEX "IDX_turn_in_definitions_key"',
),
]),
);
});
@@ -125,14 +172,27 @@ describe('CreateRenownAndReputation1791000000000', () => {
expect.stringContaining('DROP TABLE "renown_milestone_definitions"'),
expect.stringContaining('DROP TABLE "character_reputation"'),
expect.stringContaining('DROP TABLE "reputation_factions"'),
expect.stringContaining('ALTER TABLE "combat_rewards" ADD COLUMN "experience_granted"'),
expect.stringContaining('ALTER TABLE "item_definitions" ADD COLUMN "required_level"'),
expect.stringContaining(
'ALTER TABLE "monster_definitions" ADD COLUMN "experience_reward"',
),
expect.stringContaining(
'ALTER TABLE "combat_rewards" ADD COLUMN "experience_granted"',
),
expect.stringContaining(
'ALTER TABLE "item_definitions" ADD COLUMN "required_level"',
),
expect.stringContaining('ALTER TABLE "characters" ADD COLUMN "level"'),
expect.stringContaining('ALTER TABLE "characters" ADD COLUMN "experience"'),
expect.stringContaining('ALTER TABLE "characters" DROP COLUMN "renown"'),
expect.stringContaining(
'ALTER TABLE "characters" ADD COLUMN "experience"',
),
expect.stringContaining(
'ALTER TABLE "characters" DROP COLUMN "renown"',
),
]),
);
const turnInDropIndex = down.findIndex((sql) => sql.includes('DROP TABLE "turn_in_definitions"'));
const turnInDropIndex = down.findIndex((sql) =>
sql.includes('DROP TABLE "turn_in_definitions"'),
);
const reputationFactionsDropIndex = down.findIndex((sql) =>
sql.includes('DROP TABLE "reputation_factions"'),
);

View File

@@ -129,7 +129,10 @@ describe('seedVisibleVerticalSlice', () => {
Object.assign(characterRepository.rows[0], {
currentLocationId: BURNED_ROAD_ID,
currentHp: 57,
renown: 1,
// Deliberately NOT the seed default of 1: if a re-seed clobbered player
// state back to defaults, an assertion on the default value could not
// tell the difference.
renown: 5,
});
await seedVisibleVerticalSlice(dataSource);
@@ -168,7 +171,7 @@ describe('seedVisibleVerticalSlice', () => {
expect.objectContaining({
currentLocationId: BURNED_ROAD_ID,
currentHp: 57,
renown: 1,
renown: 5,
}),
);