47 lines
1.5 KiB
Text
47 lines
1.5 KiB
Text
import <Utilities/Random.sl>;
|
|
import <Utilities/Sequence.sl>;
|
|
|
|
POINT ::= (X: int, Y: int);
|
|
RET_VAL ::= (World: int(2), Rand: RandomGenerator<int, int>, Point: POINT);
|
|
|
|
randomWalk(x, y, world(2), rand) :=
|
|
let
|
|
randX := getRandom(rand);
|
|
randY := getRandom(randX.Generator);
|
|
nextX := x + (randX.Value mod 3) - 1;
|
|
nextY := y + (randY.Value mod 3) - 1;
|
|
newStartX := (randX.Value mod (size(world) - 2)) + 2;
|
|
newStartY := (randY.Value mod (size(world) - 2)) + 2;
|
|
|
|
numNeighbors := world[y-1,x-1] + world[y-1,x] + world[y-1,x+1] +
|
|
world[y,x-1] + world[y,x+1] +
|
|
world[y+1,x-1] + world[y+1,x] + world[y+1,x+1];
|
|
|
|
outOfBounds := nextX <= 1 or nextY <= 1 or nextX >= size(world) or nextY >= size(world);
|
|
in
|
|
randomWalk(newStartX, newStartY, world, randY.Generator) when world[y,x] = 1 or outOfBounds
|
|
else
|
|
(X: x, Y: y) when numNeighbors > 0
|
|
else
|
|
randomWalk(nextX, nextY, world, randY.Generator);
|
|
|
|
step(rand, world(2)) :=
|
|
let
|
|
walkSeed := getRandom(rand);
|
|
newParticle := randomWalk(size(world)/2,size(world)/2, world, seedRandom(walkSeed.Value));
|
|
|
|
newWorld[j] :=
|
|
world[j] when j /= newParticle.Y
|
|
else
|
|
setElementAt(world[j], newParticle.X, 1);
|
|
in
|
|
(World: newWorld, Rand: walkSeed.Generator, Point: newParticle);
|
|
|
|
|
|
initialWorld(worldSize, seed) :=
|
|
let
|
|
world[i,j] := 1 when i = worldSize / 2 and j = worldSize / 2 else 0
|
|
foreach i within 1 ... worldSize,
|
|
j within 1 ... worldSize;
|
|
in
|
|
(World: world, Rand: seedRandom(seed), Point: (X: worldSize / 2, Y: worldSize / 2));
|