Kind
A kind is a way to group elements that share common behavior. Unlike elements, kinds have no color and cannot appear directly on the grid. They exist to reduce duplication and make rule definitions more expressive.
Creating a kind
Section titled “Creating a kind”const creature = vi.kind("creature");The name must be unique across all elements and kinds.
Extending a kind
Section titled “Extending a kind”Elements extend a kind by passing it in an array when they are created:
const creature = vi.kind("creature");
const fish = vi.element("fish", "blue", [creature]);const bird = vi.element("bird", "orange", [creature]);An element can extend more than one kind:
const creature = vi.kind("creature");const flying = vi.kind("flying");
const bird = vi.element("bird", "orange", [creature, flying]);Defining rules on kinds
Section titled “Defining rules on kinds”Rules can be defined on a kind just like on an element. When a rule is defined on a kind, it applies to every element that extends that kind, with lower priority than rules defined directly on the element.
const creature = vi.kind("creature");
const empty = vi.element("empty", "black");const fish = vi.element("fish", "blue", [creature]);const bird = vi.element("bird", "orange", [creature]);
// Any creature dies when completely isolated (no creatures nearby)creature.to(empty).count(creature, 0);In this example, fish and bird both inherit the rule: if a creature has zero creatures in its neighborhood, it becomes empty. Without kinds, we would have to write this rule separately for each element. This is the key benefit: shared behavior, defined once.
Since kind rules have lower priority than element rules, you can still override them for specific elements:
// Birds have their own specific rule: they survive near other birdsbird.to(bird).count(bird, 2, 3);
// The kind rule still acts as a fallback for both fish and birdcreature.to(empty).count(creature, 0);Here, bird checks its own rule first. If that doesn’t match, it falls back to the kind rule. fish has no element-level rules, so the kind rule is the only one it uses.
Using kinds in conditions
Section titled “Using kinds in conditions”Kinds can be used in count and is conditions. When a condition checks for a kind, it matches any element that extends that kind.
// An empty cell becomes a fish if exactly 3 creatures are nearby// (regardless of whether those creatures are fish or birds)empty.to(fish).count(creature, 3);
// Check if the cell above is any creatureempty.to(fish).is(vi.neighbor.TOP, creature);This is useful when you want a condition to match a group of elements without listing each one individually.