Skip to content

Commit 8561e33

Browse files
committed
Make fungeon precondition configurable. Add growth point forking in dungeon generator.
1 parent e27600e commit 8561e33

File tree

5 files changed

+104
-17
lines changed

5 files changed

+104
-17
lines changed

addons/wfc/examples/demo_wfc_2d_tilemap.tscn

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,19 @@ backtracking_limit = -1
3232

3333
[sub_resource type="Resource" id="Resource_26rrk"]
3434
script = ExtResource("2_71acl")
35+
wall_border_size = Vector2i(1, 2)
36+
free_gap = Vector2i(2, 2)
37+
room_half_size_base = Vector2i(2, 2)
38+
room_half_size_variation = Vector2i(2, 2)
39+
room_probability = 0.5
40+
road_len_base = 15
41+
road_len_variation = 5
42+
fork_probability = 0.5
43+
full_fork_probability = 0.5
44+
passable_area_ratio = 0.1
45+
iterations_limit = 1000
46+
road_class = "wfc_dungeon_road"
47+
wall_class = "wfc_dungeon_wall"
3548

3649
[sub_resource type="Resource" id="Resource_uafrt"]
3750
script = ExtResource("3_iuw6v")

addons/wfc/problems/2d/preconditions/precondition_2d_base.gd

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@ extends RefCounted
44
func prepare():
55
"""
66
May calculate data necessary for this precondition.
7-
8-
Must be called exactly once on one object.
7+
8+
Must be called at most once on one object.
99
"""
1010
pass
1111

1212
func read_domain(coords: Vector2i) -> WFCBitSet:
1313
"""
1414
Returns initial domain of a cell at given coordinates.
15-
15+
1616
Returns null if this precondition doesn't limit domain of cell at given coordinates.
17-
17+
1818
Must not be called before completion of prepare() call.
1919
"""
2020
return null

addons/wfc/problems/2d/preconditions/precondition_2d_dungeon.gd

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const STATE_PASSAGE = 2
2929

3030
func coord_to_id(c: Vector2i) -> int:
3131
assert(rect.has_point(c))
32-
32+
3333
var rel_c: Vector2i = c - rect.position
3434

3535
return rel_c.x + rel_c.y * rect.size.x
@@ -46,7 +46,7 @@ func _meta_to_bool(meta: Array) -> bool:
4646
for x in meta:
4747
if x:
4848
return true
49-
49+
5050
return false
5151

5252
func learn_classes(
@@ -56,7 +56,7 @@ func learn_classes(
5656
):
5757
passable_domain = WFCBitSet.new(mapper.size())
5858
walls_domain = WFCBitSet.new(mapper.size())
59-
59+
6060
for i in range(mapper.size()):
6161
if _meta_to_bool(mapper.read_tile_meta(i, road_class)):
6262
passable_domain.set_bit(i)
@@ -106,7 +106,7 @@ func _get_start_point() -> Vector2i:
106106
class _GrowthPoint:
107107
var position: Vector2i
108108
var direction: Vector2i
109-
109+
110110
func _init(p: Vector2i, d: Vector2i):
111111
self.position = p
112112
self.direction = d
@@ -120,6 +120,11 @@ class _GrowthPoint:
120120
if reverse:
121121
self.direction *= -1
122122

123+
func rotated(reverse: bool) -> _GrowthPoint:
124+
var gp := _GrowthPoint.new(position, direction)
125+
gp.rotate(reverse)
126+
return gp
127+
123128
func _free_space_around(r: Rect2i):
124129
_replace_rect(
125130
r.grow_individual(
@@ -156,8 +161,6 @@ func _generate(start_point: Vector2i, start_directions: Array[Vector2i]):
156161

157162
var passable_rect: Rect2i = _get_safe_passable_rect()
158163

159-
print('Total rect: ', rect, ' passable rect: ', passable_rect)
160-
161164
assert(passable_area_ratio > 0.0 and passable_area_ratio < 1.0)
162165
var remaining_area: int = passable_area_ratio * passable_rect.get_area()
163166
assert(remaining_area > 0)
@@ -192,19 +195,21 @@ func _generate(start_point: Vector2i, start_directions: Array[Vector2i]):
192195

193196
_free_space_around(road_rect)
194197

195-
gp.rotate(randf() > 0.5)
196-
197-
growth_points.push_back(gp)
198+
if randf() < fork_probability:
199+
growth_points.push_back(gp.rotated(true))
200+
growth_points.push_back(gp.rotated(false))
201+
if randf() < full_fork_probability:
202+
growth_points.push_back(gp)
203+
else:
204+
gp.rotate(randf() > 0.5)
205+
growth_points.push_back(gp)
198206

199207
func prepare():
200208
assert(rect.has_area())
201209

202210
state.resize(rect.get_area())
203211

204212
_generate(_get_start_point(), [Vector2i.DOWN, Vector2i.UP])
205-
#var test_road_rect: Rect2i = Rect2i(10, 10, 100, 1)
206-
#_replace_rect(test_road_rect, STATE_WALL, STATE_PASSAGE)
207-
#_replace_rect(test_road_rect.grow(2), STATE_WALL, STATE_FREE)
208213

209214

210215
func read_domain(coords: Vector2i) -> WFCBitSet:
Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,80 @@
11
extends WFC2DPrecondition2DNullSettings
22
class_name WFC2DPreconditionDungeonSettings
33

4+
@export
5+
var wall_border_size: Vector2i = Vector2i(1, 2)
6+
7+
@export
8+
var free_gap: Vector2i = Vector2i(2, 2)
9+
10+
@export
11+
var room_half_size_base: Vector2i = Vector2i(2, 2)
12+
13+
@export
14+
var room_half_size_variation: Vector2i = Vector2i(2, 2)
15+
16+
@export_range(0.0001, 1.0)
17+
var room_probability: float = 0.5
18+
19+
@export
20+
var road_len_base: int = 15
21+
22+
@export
23+
var road_len_variation: int = 5
24+
25+
@export_range(0.0001, 1.0)
26+
var fork_probability: float = 0.5
27+
28+
@export_range(0.0001, 1.0)
29+
var full_fork_probability: float = 0.5
30+
31+
@export_range(0.0001, 1.0)
32+
var passable_area_ratio: float = 0.1
33+
34+
@export
35+
var iterations_limit: int = 1000
36+
37+
@export
38+
var road_class: String = "wfc_dungeon_road"
39+
40+
@export
41+
var wall_class: String = "wfc_dungeon_wall"
42+
443
func create_precondition(parameters: WFC2DPrecondition2DNullSettings.CreationParameters) -> WFC2DPrecondition:
544
var res: WFC2DPreconditionDungeon = WFC2DPreconditionDungeon.new()
645

746
res.rect = parameters.problem_settings.rect
847

9-
res.learn_classes(parameters.problem_settings.rules.mapper)
48+
res.learn_classes(parameters.problem_settings.rules.mapper, road_class, wall_class)
49+
50+
assert(wall_border_size >= Vector2i.ZERO)
51+
res.wall_border_size = wall_border_size
52+
53+
assert(free_gap >= Vector2i.ZERO)
54+
res.free_gap = free_gap
55+
56+
assert(room_half_size_base > Vector2i.ZERO)
57+
res.room_half_size_base = room_half_size_base
58+
59+
assert(room_half_size_variation > Vector2i.ZERO)
60+
assert(room_half_size_variation <= room_half_size_variation)
61+
res.room_half_size_variation = room_half_size_variation
62+
63+
res.room_probability = room_probability
64+
65+
assert(road_len_base > 0)
66+
res.road_len_base = road_len_base
67+
68+
assert(road_len_variation > 0)
69+
assert(road_len_variation < road_len_base)
70+
res.road_len_variation = road_len_variation
71+
72+
res.fork_probability = fork_probability
73+
res.full_fork_probability = full_fork_probability
74+
res.passable_area_ratio = passable_area_ratio
75+
76+
assert(iterations_limit > 0)
77+
res.iterations_limit = iterations_limit
1078

1179
return res
1280

project.godot

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ config/icon="res://icon.png"
1919

2020
window/size/viewport_width=1920
2121
window/size/viewport_height=1080
22+
window/size/mode=3
2223

2324
[editor]
2425

0 commit comments

Comments
 (0)