Condition
A rule without conditions is always accepted when evaluated. A condition determines whether a rule is accepted or not. Conditions are added by chaining methods after to.
Condition types
Section titled “Condition types”There are three types of conditions: Count, Is, Chance.
The count condition checks how many cells of a given element (or kind) are present in the neighborhood. The rule is accepted only if the actual count is one of the specified values.
// Space becomes alien only if exactly 1 alien is in the neighborhoodspace.to(alien).count(alien, 1);You can pass multiple values. The condition passes if the count matches any of them:
// Alien survives if it has 2 or 3 alien neighborsalien.to(alien).count(alien, 2, 3);You can also pass an array of values:
alien.to(space).count(alien, [0, 1, 4, 5, 6, 7, 8]);When called with no count values, all positive counts are matched (1 through 8 for square, 1 through 4 for cross). Zero is excluded, so this form means “at least one”:
// Matches if there is at least one alien neighborspace.to(alien).count(alien);You can also count by neighbor reference instead of a specific element. This counts how many neighbors match whatever element is at the referenced position:
// Count how many neighbors match the element above the current cellspace.to(alien).count(vi.neighbor.TOP, 3);Helpers
Section titled “Helpers”Helpers are convenience functions exposed through vi.helpers that make it easier to construct count arrays.
between()
Section titled “between()”The between helper generates a range of whole numbers from the given start to finish (inclusive):
const { between } = vi.helpers;
space.to(alien).count(alien, between(1, 5));// same asspace.to(alien).count(alien, [1, 2, 3, 4, 5]);The not helper returns every valid count value except the ones specified. It is useful for expressing “anything but this value”:
const { not } = vi.helpers;
space.to(alien).count(alien, not(2));// in a square neighborhood the line above is equivalent to:space.to(alien).count(alien, [0, 1, 3, 4, 5, 6, 7, 8]);You can also pass an array to exclude multiple values:
space.to(alien).count(alien, not([2, 3]));// equivalent to:space.to(alien).count(alien, [0, 1, 4, 5, 6, 7, 8]);You can combine not with between:
space.to(alien).count(alien, not(between(3, 6)));// equivalent to:space.to(alien).count(alien, [0, 1, 2, 7, 8]);even() and odd()
Section titled “even() and odd()”These helpers generate arrays of even numbers (zero included) and odd numbers respectively:
const { even, odd } = vi.helpers;
space.to(alien).count(alien, even());// same asspace.to(alien).count(alien, [0, 2, 4, 6, 8]);
space.to(alien).count(alien, odd());// same asspace.to(alien).count(alien, [1, 3, 5, 7]);In a "cross" neighborhood the ranges adjust accordingly ([0, 2, 4] for even, [1, 3] for odd).
The is condition checks whether a specific neighbor is a certain element, kind, or matches another neighbor position.
Compare a neighbor with a specific element:
const { neighbor } = vi;
// Space becomes alien if the cell above is an alienspace.to(alien).is(neighbor.TOP, alien);Compare a neighbor with a kind (matches any element that extends the kind):
const { neighbor } = vi;
space.to(alien).is(neighbor.TOP, sentient);Compare two neighbor positions (the rule passes if both positions hold the same element):
const { neighbor } = vi;
// Space becomes alien if the cell above and the cell below are the same elementspace.to(alien).is(neighbor.TOP, neighbor.BOTTOM);Chance
Section titled “Chance”The chance condition introduces randomness. It accepts with a probability of part / whole:
// 1 in 1000 chance for the cell to become an alien each stepspace.to(alien).chance(1, 1000);If whole is omitted, it defaults to 100:
// 5% chancespace.to(alien).chance(5);Multiple conditions
Section titled “Multiple conditions”You can add more than one condition per rule. When that is the case, the rule is accepted only if every condition is met. To modify the strategy used for the acceptance of rules, you can use the accept method on the builder chain. This method stops the chain — you cannot add more conditions after determining the accept strategy.
There are 4 strategies available:
"all"(default): every condition has to be met in order for the rule to be accepted."any": at least one condition has to be met in order for the rule to be accepted."one": one and only one condition has to be met in order for the rule to be accepted."none": every condition has to be left unmet in order for the rule to be accepted.
space.to(alien).count(alien, 1).chance(1, 1000).accept("any");"none" is also useful as a way to negate a single condition:
const { neighbor } = vi;
space.to(house).is(neighbor.BOTTOM, liquid).accept("none");We build a house on top of another cell only if the cell below is not of liquid kind.