ygdra/tools/maze.gd

155 lines
4.8 KiB
GDScript

class_name Maze
extends Reference
# Represents an area of cell
var width: int = 0
var height: int = 0
var cells = []
var events = []
var entrance = Vector2()
var exit = Vector2()
var nb_chests: int = 0
# For submazes, as they modify their parent maze
var parent: Maze = null # Submaze parent maze
var offset_x = 0
var offset_y = 0
# Initialize a maze
func _init(w: int, h: int):
assert(w > 0)
assert(h > 0)
width = w
height = h
cells.clear()
cells.resize(w * h)
for i in range(w * h):
cells[i] = Cell.new()
# Initialize a submaze from a parent maze.
func init_from(w: int, h: int, that: Maze, x: int, y: int):
assert(w > 0)
assert(h > 0)
width = w
height = h
parent = that
offset_x = x
offset_y = y
# Get the index for the cell at position (x,y)
func index(x: int, y: int):
return x + y * width
# Get the cell at the position (x,y)
func at(x: int, y: int):
if parent == null:
return cells[index(x, y)]
else:
parent.at(x + offset_x, y + offset_y)
# Check if a position is inside the area
func is_inside(x: int, y: int):
return (x >= 0) and (x < width) and (y >= 0) and (y < height)
# Get a submaze of this maze.
# The submaze if a view of this maze, so a modification of the submaze cells modify this maze.
func submaze(x: int, y: int, w: int, h: int):
assert(x > 0)
assert(y > 0)
assert((x + w) <= width)
assert((y + h) <= height)
var ret = load("res://tools/maze.gd").new()
ret.init_from(w, h, self, x, y)
return ret
# Transformations
# Identity : do nothing
func identity(_x: int = 0, _y: int = 0, _w: int = width, _h: int = height):
pass
# Horizontal flip
func horizontal_flip(x: int = 0, y: int = 0, w: int = width, h: int = height):
if parent == null:
for j in range(0, h):
for i in range(0, w/2):
var idx_cell = index(x + i, y + j)
var idx_other = index(x + w - 1 - i, y + j)
var cell = cells[idx_cell]
cells[idx_cell] = cells[idx_other]
cells[idx_other] = cell
for j in range(0, h):
for i in range(0, w):
var idx_cell = index(x + i, y + j)
cells[idx_cell].horizontal_flip()
else:
parent.horizontal_flip(offset_x + x, offset_y + y, w, h)
# Vertical flip
func vertical_flip(x: int = 0, y: int = 0, w: int = width, h: int = height):
if parent == null:
for j in range(0, h/2):
for i in range(0, w):
var idx_cell = index(x + i, y + j)
var idx_other = index(x + i, y + h - 1 - j)
var cell = cells[idx_cell]
cells[idx_cell] = cells[idx_other]
cells[idx_other] = cell
for j in range(0, h):
for i in range(0, w):
var idx_cell = index(x + i, y + j)
cells[idx_cell].vertical_flip()
else:
parent.vertical_flip(offset_x + x, offset_y + y, w, h)
# Rotation 180° = horizontal flip + vertical flip
func rotate_180(x: int = 0, y: int = 0, w: int = width, h: int = height):
self.horizontal_flip(x, y, w, h)
self.vertical_flip(x, y, w, h)
# Rotation 90° in trigonometric direction (counter-clockwise)
func rotate_90():
# TODO
pass
# Rotation 270° in trigonometric direction (counter-clockwise), or 90° clockwise
func rotate_270():
# TODO
pass
# Transposition (mirror -45°)
func transpose(x: int = 0, y: int = 0, w: int = width, h: int = height):
if parent == null:
for j in range(0, h):
for i in range(j + 1, w):
var idx_cell = index(x + i, y + j)
var idx_other = index(y + j, x + i)
var cell = cells[idx_cell]
cells[idx_cell] = cells[idx_other]
cells[idx_other] = cell
for j in range(0, h):
for i in range(0, w):
var idx_cell = index(x + i, y + j)
cells[idx_cell].transpose()
else:
parent.transpose(offset_x + x, offset_y + y, w, h)
# Anti-transposition (mirror 45°)
func antitranspose(x: int = 0, y: int = 0, w: int = width, h: int = height):
if parent == null:
for j in range(0, h):
for i in range(0, w - 1 - j):
var idx_cell = index(x + i, y + j)
var idx_other = index(y + h - 1 - j, x + w - 1 - i)
var cell = cells[idx_cell]
cells[idx_cell] = cells[idx_other]
cells[idx_other] = cell
for j in range(0, h):
for i in range(0, w):
var idx_cell = index(x + i, y + j)
cells[idx_cell].antitranspose()
else:
parent.antitranspose(offset_x + x, offset_y + y, w, h)
# Player-interaction functions
func visit(pos: Vector2):
at(pos.x, pos.y).visited = true