murdokugen
v1.0.2
Published
TypeScript library to generate Murdoku boards and semantic hints with zones, solutions, and obstacles
Downloads
18
Maintainers
Readme
MurdokuGen
TypeScript library to generate Murdoku boards and semantic hints.
It produces three aligned maps:
zoneMap: zone id per cell (0..n)solutionMap: people placement (0empty,1person)obstacleMap: blocked cells (0free,1obstacle)
Installation
npm install murdokugenQuick Start
import generateMurdoku from "murdokugen";
const width = 6;
const height = 6;
const zonesCount = 4;
const obstaclesCount = 8;
const { zoneMap, solutionMap, obstacleMap } = generateMurdoku(
width,
height,
zonesCount,
obstaclesCount,
);
console.log(zoneMap, solutionMap, obstacleMap);API
generateMurdoku(width, height, zonesCount, obstaclesCount)
Returns:
{
zoneMap: number[][];
solutionMap: number[][];
obstacleMap: number[][];
}Behavior summary:
solutionMapplacesmin(width, height)people (1s), with at most one person per row and per column.obstacleMapalways keeps people cells blocked (1) and adds extra obstacles respecting zone limits.- Zone generation enforces contiguous zones and validates impossible inputs.
Hint System
The library can generate language-agnostic hints and then format them with your own labels/templates.
import generateMurdoku, {
Direction,
HintType,
formatHint,
generateHints,
type HintGeneratorPlugin,
} from "murdokugen";
const { zoneMap, solutionMap, obstacleMap } = generateMurdoku(6, 6, 4, 6);
const customHintPlugin: HintGeneratorPlugin = {
id: "custom-zone-focus",
generate: (context) => {
const zoneZeroCount = context.personsByZone.get(0)?.length ?? 0;
return [
{
id: "",
type: HintType.ZoneCount,
difficulty: "easy",
payload: {
zoneId: 0,
personCount: zoneZeroCount,
},
},
];
},
};
const hints = generateHints(zoneMap, solutionMap, obstacleMap, {
hintCount: 8,
plugins: [customHintPlugin],
allowedTypes: [
HintType.SameZone,
HintType.ZoneCount,
HintType.AdjacentObstacle,
HintType.CardinalRelation,
],
difficulty: "mixed",
includeBuiltIns: true,
deduplicate: true,
strictMode: false,
});
for (const hint of hints) {
const text = formatHint(hint, {
personLabel: (personId) => `Person ${personId}`,
zoneLabel: (zoneId) => `Zone ${zoneId}`,
directionLabel: (direction) => {
if (direction === Direction.North) return "north";
if (direction === Direction.South) return "south";
if (direction === Direction.East) return "east";
return "west";
},
});
console.log(hint.id, text);
}Built-in hint types
HintType.SameZoneHintType.ZoneCountHintType.AdjacentObstacleHintType.CardinalRelation
generateHints(..., options)
Options:
hintCount?: numberallowedTypes?: HintType[]difficulty?: "easy" | "medium" | "hard" | "mixed"includeBuiltIns?: boolean(defaulttrue)plugins?: HintGeneratorPlugin[]strictMode?: boolean(defaultfalse)deduplicate?: boolean(defaulttrue)random?: () => number
formatHint(hint, context)
Formatting context:
personLabel?: (personId: number) => stringzoneLabel?: (zoneId: number) => stringdirectionLabel?: (direction: Direction) => stringtemplates?: Partial<Record<HintType, (hint: Hint) => string>>
Development
npm run build
npm test
npm run test:coverageLicense
ISC
