/** * Conways Game of Life * * The universe of the Game of Life is an infinite two-dimensional orthogonal grid of square cells, * each of which is in one of two possible states, alive or dead. Every cell interacts with its * eight neighbours, which are the cells that are horizontally, vertically, or diagonally adjacent. * At each step in time, the following transitions occur: * * Any live cell with fewer than two live neighbours dies, as if caused by under-population. * Any live cell with two or three live neighbours lives on to the next generation. * Any live cell with more than three live neighbours dies, as if by overcrowding. * Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction. * * The initial pattern constitutes the seed of the system. The first generation is created by * applying the above rules simultaneously to every cell in the seed-births and deaths occur * simultaneously, and the discrete moment at which this happens is sometimes called a tick * (in other words, each generation is a pure function of the preceding one). The rules continue * to be applied repeatedly to create further generations. * * Modelled in VDM-SL by Nick Battle and Peter Gorm Larsen and animation made by * Claus Ballegaard Nielsen
*/
module Conway exportsall
definitions
values
GENERATE = 3; -- Number of neighbours to cause generation
SURVIVE = {2, 3}; -- Numbers of neighbours to ensure survival, else death
types
Point :: -- Plain is indexed by integers
x : int
y : int;
Population = setof Point;
functions -- Generate the Points around a given Point
around: Point -> setof Point
around(p) ==
{ mk_Point(p.x + x, p.y + y) | x, y inset { -1, 0, +1 }
& x <> 0 or y <> 0 } postcardRESULT < 9;
-- Count the number of live cells around a given point
neighbourCount: Population * Point -> nat
neighbourCount(pop, p) == card { q | q inset around(p) & q inset pop } postRESULT < 9;
-- Generate the set of empty cells that will become live
newCells: Population -> setof Point
newCells(pop) == dunion
{
{ q | q inset around(p)
& q notinset pop and neighbourCount(pop, q) = GENERATE }
| p inset pop
} postRESULTinter pop = {}; -- None currently live
-- Generate the set of cells to die
deadCells: Population -> setof Point
deadCells(pop) ==
{ p | p inset pop
& neighbourCount(pop, p) notinset SURVIVE } postRESULTinter pop = RESULT; -- All currently live
-- Perform one generation
generation: Population -> Population
generation(pop) ==
(pop \ deadCells(pop)) union newCells(pop);
-- Generate a sequence of N generations
generations: nat1 * Population -> seqof Population
generations(n,pop) == let new_p = generation(pop) in if n = 1 then [new_p] else [new_p] ^ generations(n-1,new_p) measure measureGenerations;
measureGenerations: nat1 * Population -> nat
measureGenerations(n,-) == n;
-- Generate an offset of a Population (for testing gliders)
offset: Population * int * int -> Population
offset(pop, dx, dy) ==
{ mk_Point(x + dx, y + dy) | mk_Point(x, y) inset pop };
-- Test whether two Populations are within an offset of each other
isOffset: Population * Population * nat1 -> bool
isOffset(pop1, pop2, max) == exists dx, dy inset {-max, ..., max}
& (dx <> 0 or dy <> 0) and offset(pop1, dx, dy) = pop2;
-- Test whether a game is N-periodic
periodN: Population * nat1 -> bool
periodN(pop, n) == (generation ** n)(pop) = pop;
-- Test whether a game disappears after N generations
disappearN: Population * nat1 -> bool
disappearN(pop, n) ==
(generation ** n)(pop) = {};
-- Test whether a game is N-gliding within max cells
gliderN: Population * nat1 * nat1 -> bool
gliderN(pop, n, max) ==
isOffset(pop, (generation ** n)(pop), max);
-- Versions of the three tests that check that N is the least value
periodNP: Population * nat1 -> bool
periodNP(pop, n) ==
{ a | a inset {1, ..., n} & periodN(pop, a) } = {n};
disappearNP: Population * nat1 -> bool
disappearNP(pop, n) ==
{ a | a inset {1, ..., n} & disappearN(pop, a) } = {n};
gliderNP: Population * nat1 * nat1 -> bool
gliderNP(pop, n, max) ==
{ a | a inset {1, ..., n} & gliderN(pop, a, max) } = {n};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.