8func create_room(seed:int, options:Dictionary = {}) -> Dictionary:
9 var size:Array = options.get(
"size", [5, 5])
if options.get(
"size", [])
is Array
else [5, 5]
10 var width:int = max(3,
int(size[0])
if size.size() >= 1
else 5)
11 var height:int = max(3,
int(size[1])
if size.size() >= 2
else 5)
12 var start:Array = options.get(
"start", [
int(floor(width / 2.0)), height - 1])
if options.get(
"start", [])
is Array
else [
int(floor(width / 2.0)), height - 1]
13 var target:Array = options.get(
"target", [
int(floor(width / 2.0)), 0])
if options.get(
"target", [])
is Array
else [
int(floor(width / 2.0)), 0]
14 var required_rooms:int = clampi(
int(options.get(
"required_rooms", 4)), 1, width * height)
15 var state:Dictionary = {
18 "size": [width, height],
19 "current": _clamped_cell(start, width, height),
20 "target": _clamped_cell(target, width, height),
21 "required_rooms": required_rooms,
26 state = reveal_around(state, state.get(
"current", []),
int(options.get(
"reveal_radius", 1)))
30func enter_next_room(state:Dictionary) -> Dictionary:
31 var next:Dictionary = state.duplicate(true)
32 if bool(next.get(
"complete", false)):
34 var size:Array = next.get(
"size", [5, 5])
if next.get(
"size", [])
is Array
else [5, 5]
35 var width:int = max(1,
int(size[0])
if size.size() >= 1
else 5)
36 var height:int = max(1,
int(size[1])
if size.size() >= 2
else 5)
37 var current:Array = next.get(
"current", [0, 0])
if next.get(
"current", [])
is Array
else [0, 0]
38 var target:Array = next.get(
"target", [width - 1, 0])
if next.get(
"target", [])
is Array
else [width - 1, 0]
39 var step:Array = _step_toward(current, target)
40 next[
"current"] = _clamped_cell(step, width, height)
41 next[
"entered_count"] =
int(next.get(
"entered_count", 0)) + 1
42 next = reveal_around(next, next.get(
"current", []), 1)
43 if _same_cell(next.get(
"current", []), target)
or int(next.get(
"entered_count", 0)) >=
int(next.get(
"required_rooms", 1)):
44 next[
"complete"] = true
48func reveal_around(state:Dictionary, cell:Array, radius:int = 1) -> Dictionary:
49 var next:Dictionary = state.duplicate(true)
50 var size:Array = next.get(
"size", [5, 5])
if next.get(
"size", [])
is Array
else [5, 5]
51 var width:int = max(1,
int(size[0])
if size.size() >= 1
else 5)
52 var height:int = max(1,
int(size[1])
if size.size() >= 2
else 5)
53 var center:Array = _clamped_cell(cell, width, height)
54 var revealed:Array = next.get(
"revealed", [])
if next.get(
"revealed", [])
is Array
else []
55 for y
in range(
int(center[1]) - radius,
int(center[1]) + radius + 1):
56 for x
in range(
int(center[0]) - radius,
int(center[0]) + radius + 1):
57 if x < 0
or y < 0
or x >= width
or y >= height:
59 var key:String =
"%d,%d" % [x, y]
60 if not revealed.has(key):
62 next[
"revealed"] = revealed
66func is_complete(state:Dictionary) -> bool:
67 return bool(state.get(
"complete", false))
70func progress_text(state:Dictionary) -> String:
71 return "%d/%d rooms" % [
int(state.get(
"entered_count", 0)),
int(state.get(
"required_rooms", 1))]
74func _step_toward(current:Array, target:Array) -> Array:
75 var cx:int =
int(current[0])
if current.size() >= 1
else 0
76 var cy:int =
int(current[1])
if current.size() >= 2
else 0
77 var tx:int =
int(target[0])
if target.size() >= 1
else cx
78 var ty:int =
int(target[1])
if target.size() >= 2
else cy
80 cy +=
int(sign(float(ty - cy)))
82 cx +=
int(sign(float(tx - cx)))
86func _clamped_cell(raw:Array, width:int, height:int) -> Array:
87 var x:int =
int(raw[0])
if raw.size() >= 1
else 0
88 var y:int =
int(raw[1])
if raw.size() >= 2
else 0
89 return [clampi(x, 0, width - 1), clampi(y, 0, height - 1)]
92func _same_cell(a:Array, b:Array) -> bool:
93 return a.size() >= 2
and b.size() >= 2
and int(a[0]) ==
int(b[0])
and int(a[1]) ==
int(b[1])