Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
187
Task/Maze-generation/AWK/maze-generation.awk
Normal file
187
Task/Maze-generation/AWK/maze-generation.awk
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
#!/usr/bin/awk -f
|
||||
|
||||
# Remember: AWK is 1-based, for better or worse.
|
||||
|
||||
BEGIN {
|
||||
# The maze dimensions.
|
||||
width = 20; # Global
|
||||
height = 20; # Global
|
||||
resetMaze();
|
||||
|
||||
# Some constants.
|
||||
top = 1;
|
||||
bottom = 2;
|
||||
left = 3;
|
||||
right = 4;
|
||||
|
||||
# Randomize the PRNG.
|
||||
randomize();
|
||||
|
||||
# Visit all the cells starting at a random point.
|
||||
visitCell(getRandX(), getRandY());
|
||||
|
||||
# Show the result.
|
||||
printMaze();
|
||||
}
|
||||
|
||||
# Wander through the maze removing walls as we go.
|
||||
function visitCell(x, y, dirList, dir, nx, ny, ndir, pi) {
|
||||
setVisited(x, y); # This cell has been visited.
|
||||
|
||||
# Visit neighbors in a random order.
|
||||
dirList = getRandDirList();
|
||||
for (dir = 1; dir <= 4; dir++) {
|
||||
# Get coordinates of a random neighbor (next in random direction list).
|
||||
ndir = substr(dirList, dir, 1);
|
||||
nx = getNextX(x, ndir);
|
||||
ny = getNextY(y, ndir);
|
||||
|
||||
# Visit an unvisited neighbor, removing the separating walls.
|
||||
if (wasVisited(nx, ny) == 0) {
|
||||
rmWall(x, y, ndir);
|
||||
rmWall(nx, ny, getOppositeDir(ndir));
|
||||
visitCell(nx, ny)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Display the text-mode maze.
|
||||
function printMaze( x, y, r, w) {
|
||||
for (y = 1; y <= height; y++) {
|
||||
for (pass = 1; pass <= 2; pass++) { # Go over each row twice: top, middle
|
||||
for (x = 1; x <= width; x++) {
|
||||
if (pass == 1) { # top
|
||||
printf("+");
|
||||
printf(hasWall(x, y, top) == 1 ? "---" : " ");
|
||||
if (x == width) printf("+");
|
||||
}
|
||||
else if (pass == 2) { # left, right
|
||||
printf(hasWall(x, y, left) == 1 ? "|" : " ");
|
||||
printf(" ");
|
||||
if (x == width) printf(hasWall(x, y, right) == 1 ? "|" : " ");
|
||||
}
|
||||
}
|
||||
print;
|
||||
}
|
||||
}
|
||||
for (x = 1; x <= width; x++) printf("+---"); # bottom row
|
||||
print("+"); # bottom right corner
|
||||
}
|
||||
|
||||
# Given a direction, get its opposite.
|
||||
function getOppositeDir(d) {
|
||||
if (d == top) return bottom;
|
||||
if (d == bottom) return top;
|
||||
if (d == left) return right;
|
||||
if (d == right) return left;
|
||||
}
|
||||
|
||||
# Build a list (string) of the four directions in random order.
|
||||
function getRandDirList( dirList, randDir, nx, ny, idx) {
|
||||
dirList = "";
|
||||
while (length(dirList) < 4) {
|
||||
randDir = getRandDir();
|
||||
if (!index(dirList, randDir)) {
|
||||
dirList = dirList randDir;
|
||||
}
|
||||
}
|
||||
return dirList;
|
||||
}
|
||||
|
||||
# Get x coordinate of the neighbor in a given a direction.
|
||||
function getNextX(x, dir) {
|
||||
if (dir == left) x = x - 1;
|
||||
if (dir == right) x = x + 1;
|
||||
if (!isGoodXY(x, 1)) return -1; # Off the edge.
|
||||
return x;
|
||||
}
|
||||
|
||||
# Get y coordinate of the neighbor in a given a direction.
|
||||
function getNextY(y, dir) {
|
||||
if (dir == top) y = y - 1;
|
||||
if (dir == bottom) y = y + 1;
|
||||
if (!isGoodXY(1, y)) return -1; # Off the edge.
|
||||
return y;
|
||||
}
|
||||
|
||||
# Mark a cell as visited.
|
||||
function setVisited(x, y, cell) {
|
||||
cell = getCell(x, y);
|
||||
if (cell == -1) return;
|
||||
cell = substr(cell, 1, 4) "1"; # walls plus visited
|
||||
setCell(x, y, cell);
|
||||
}
|
||||
|
||||
# Get the visited state of a cell.
|
||||
function wasVisited(x, y, cell) {
|
||||
cell = getCell(x, y);
|
||||
if (cell == -1) return 1; # Off edges already visited.
|
||||
return substr(getCell(x,y), 5, 1);
|
||||
}
|
||||
|
||||
# Remove a cell's wall in a given direction.
|
||||
function rmWall(x, y, d, i, oldCell, newCell) {
|
||||
oldCell = getCell(x, y);
|
||||
if (oldCell == -1) return;
|
||||
newCell = "";
|
||||
for (i = 1; i <= 4; i++) { # Ugly as concat of two substrings and a constant?.
|
||||
newCell = newCell (i == d ? "0" : substr(oldCell, i, 1));
|
||||
}
|
||||
newCell = newCell wasVisited(x, y);
|
||||
setCell(x, y, newCell);
|
||||
}
|
||||
|
||||
# Determine if a cell has a wall in a given direction.
|
||||
function hasWall(x, y, d, cell) {
|
||||
cell = getCell(x, y);
|
||||
if (cell == -1) return 1; # Cells off edge always have all walls.
|
||||
return substr(getCell(x, y), d, 1);
|
||||
}
|
||||
|
||||
# Plunk a cell into the maze.
|
||||
function setCell(x, y, cell, idx) {
|
||||
if (!isGoodXY(x, y)) return;
|
||||
maze[x, y] = cell
|
||||
}
|
||||
|
||||
# Get a cell from the maze.
|
||||
function getCell(x, y, idx) {
|
||||
if (!isGoodXY(x, y)) return -1; # Bad cell marker.
|
||||
return maze[x, y];
|
||||
}
|
||||
|
||||
# Are the given coordinates in the maze?
|
||||
function isGoodXY(x, y) {
|
||||
if (x < 1 || x > width) return 0;
|
||||
if (y < 1 || y > height) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Build the empty maze.
|
||||
function resetMaze( x, y) {
|
||||
delete maze;
|
||||
for (y = 1; y <= height; y++) {
|
||||
for (x = 1; x <= width; x++) {
|
||||
maze[x, y] = "11110"; # walls (up, down, left, right) and visited state.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Random things properly scaled.
|
||||
|
||||
function getRandX() {
|
||||
return 1 + int(rand() * width);
|
||||
}
|
||||
|
||||
function getRandY() {
|
||||
return 1 +int(rand() * height);
|
||||
}
|
||||
|
||||
function getRandDir() {
|
||||
return 1 + int(rand() * 4);
|
||||
}
|
||||
|
||||
function randomize() {
|
||||
"echo $RANDOM" | getline t;
|
||||
srand(t);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue