import { findTableByCode } from "@/data/contentHelpers"; import type { ContentPack } from "@/types/content"; import type { EncounterState, RoomState } from "@/types/state"; import { lookupTable, type TableLookupResult } from "./tables"; import type { DiceRoller } from "./dice"; export type EncounterResolutionResult = { room: RoomState; encounter?: EncounterState; lookup?: TableLookupResult; }; const ROOM_HINT_TO_TABLE: Array<{ pattern: RegExp; tableCode: string }> = [ { pattern: /\bdogs?\b/i, tableCode: "L1D" }, { pattern: /\bguards?\b/i, tableCode: "L1G" }, { pattern: /\bmartial\b/i, tableCode: "L1M" }, { pattern: /\bworkers?\b/i, tableCode: "L1W" }, { pattern: /\blabourers?\b/i, tableCode: "L1P" }, { pattern: /\bpreacher\b/i, tableCode: "L1P" }, { pattern: /\banimals?\b/i, tableCode: "L1A" }, { pattern: /\bsnakes?\b/i, tableCode: "L1A" }, { pattern: /\bfungal\b/i, tableCode: "L1F" }, { pattern: /\bslimy\b/i, tableCode: "L1F" }, { pattern: /\bcrate\b/i, tableCode: "L1CE" }, ]; function splitEncounterLabel(label: string) { return label .split(/\sand\s/i) .map((part) => part.trim()) .filter(Boolean); } function inferEncounterTableCode(room: RoomState) { const noteText = room.notes.join(" "); const flagText = room.flags.join(" "); const combinedText = `${noteText} ${flagText}`; for (const mapping of ROOM_HINT_TO_TABLE) { if (mapping.pattern.test(combinedText)) { return mapping.tableCode; } } return undefined; } function isNonEncounterRoom(room: RoomState) { const noteText = room.notes.join(" ").toLowerCase(); return noteText.includes("nothing here") || noteText.includes("no encounter"); } export function resolveRoomEncounter( content: ContentPack, room: RoomState, roller?: DiceRoller, ): EncounterResolutionResult { if (room.encounter?.resolved) { return { room, encounter: room.encounter, }; } if (isNonEncounterRoom(room)) { const emptyEncounter: EncounterState = { id: `${room.id}.encounter`, creatureIds: [], creatureNames: [], resultLabel: "No encounter", resolved: true, }; return { room: { ...room, encounter: emptyEncounter, }, encounter: emptyEncounter, }; } const tableCode = inferEncounterTableCode(room); if (!tableCode) { return { room }; } const table = findTableByCode(content, tableCode); const lookup = lookupTable(table, { roller }); const creatureNames = splitEncounterLabel(lookup.entry.label); const encounter: EncounterState = { id: `${room.id}.encounter`, sourceTableCode: tableCode, creatureIds: creatureNames.map((_, index) => `${room.id}.creature.${index + 1}`), creatureNames, resultLabel: lookup.entry.label, resolved: true, }; return { room: { ...room, encounter, }, encounter, lookup, }; }