Add support for nesting in random creature generation. (#34)
This builds upon #30 and #33 by adding support for randomly nested symbols in complexity levels 0-4 of the creature page. Currently, we don't _recursively_ nest symbols, so e.g. we won't make an eye containing an eye containing a cube. And for now we'll only add a nested symbol if the parent symbol has the `always_nest` metadata property defined.pull/35/head
rodzic
b2aab6fa21
commit
c803c41bd0
|
@ -24,6 +24,19 @@ const SYMBOL_MAP = new Map(
|
||||||
SvgVocabulary.map((symbol) => [symbol.name, symbol])
|
SvgVocabulary.map((symbol) => [symbol.name, symbol])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/** Symbols that can be the "root" (i.e., main body) of a creature. */
|
||||||
|
const ROOT_SYMBOLS = SvgVocabulary.filter(
|
||||||
|
(data) => data.meta?.always_be_nested !== true
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Symbols that can be attached to the main body of a creature. */
|
||||||
|
const ATTACHMENT_SYMBOLS = ROOT_SYMBOLS;
|
||||||
|
|
||||||
|
/** Symbols that can be nested within any part of a creature. */
|
||||||
|
const NESTED_SYMBOLS = SvgVocabulary.filter(
|
||||||
|
(data) => data.meta?.always_nest !== true
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the data for the given symbol, throwing an error
|
* Returns the data for the given symbol, throwing an error
|
||||||
* if it doesn't exist.
|
* if it doesn't exist.
|
||||||
|
@ -36,6 +49,25 @@ function getSymbol(name: string): SvgSymbolData {
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a parent symbol, return an array of random children to be nested within
|
||||||
|
* it.
|
||||||
|
*
|
||||||
|
* Can return an empty array e.g. if the parent symbol doesn't have
|
||||||
|
* any nesting areas.
|
||||||
|
*/
|
||||||
|
function getNestingChildren(parent: SvgSymbolData, rng: Random): JSX.Element[] {
|
||||||
|
const { meta, specs } = parent;
|
||||||
|
if (meta?.always_nest && specs?.nesting) {
|
||||||
|
const indices = range(specs.nesting.length);
|
||||||
|
const child = rng.choice(NESTED_SYMBOLS);
|
||||||
|
return [
|
||||||
|
<CreatureSymbol data={child} key="nested" nestInside indices={indices} />,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Randomly creates a symbol with the given number of
|
* Randomly creates a symbol with the given number of
|
||||||
* types of attachments. The symbol itself, and where the
|
* types of attachments. The symbol itself, and where the
|
||||||
|
@ -46,7 +78,7 @@ function getSymbolWithAttachments(
|
||||||
rng: Random
|
rng: Random
|
||||||
): JSX.Element {
|
): JSX.Element {
|
||||||
const children: JSX.Element[] = [];
|
const children: JSX.Element[] = [];
|
||||||
const root = rng.choice(SvgVocabulary);
|
const root = rng.choice(ROOT_SYMBOLS);
|
||||||
if (root.specs) {
|
if (root.specs) {
|
||||||
const attachmentKinds = rng.uniqueChoices(
|
const attachmentKinds = rng.uniqueChoices(
|
||||||
Array.from(iterAttachmentPoints(root.specs))
|
Array.from(iterAttachmentPoints(root.specs))
|
||||||
|
@ -55,7 +87,7 @@ function getSymbolWithAttachments(
|
||||||
numAttachmentKinds
|
numAttachmentKinds
|
||||||
);
|
);
|
||||||
for (let kind of attachmentKinds) {
|
for (let kind of attachmentKinds) {
|
||||||
const attachment = rng.choice(SvgVocabulary);
|
const attachment = rng.choice(ATTACHMENT_SYMBOLS);
|
||||||
const indices = range(root.specs[kind]?.length ?? 0);
|
const indices = range(root.specs[kind]?.length ?? 0);
|
||||||
children.push(
|
children.push(
|
||||||
<CreatureSymbol
|
<CreatureSymbol
|
||||||
|
@ -63,10 +95,12 @@ function getSymbolWithAttachments(
|
||||||
key={children.length}
|
key={children.length}
|
||||||
attachTo={kind}
|
attachTo={kind}
|
||||||
indices={indices}
|
indices={indices}
|
||||||
|
children={getNestingChildren(attachment, rng)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
children.push(...getNestingChildren(root, rng));
|
||||||
return <CreatureSymbol data={root} children={children} />;
|
return <CreatureSymbol data={root} children={children} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue