Shrinking is broken

This commit is contained in:
2024-12-17 00:57:21 +03:00
parent 4c2049f05c
commit 6f2ab0105d
11 changed files with 606 additions and 94 deletions

View File

@@ -140,7 +140,7 @@ entries=[ {
"type": "zone",
"zone_type": 0
}, {
"children": [ 54, 55, 56, 57, 58 ],
"children": [ 54, 55, 56, 57 ],
"commands": [ ],
"index": 18,
"name": "zone_3",
@@ -148,7 +148,7 @@ entries=[ {
"type": "zone",
"zone_type": 1
}, {
"children": [ 59, 60 ],
"children": [ 58, 59 ],
"commands": [ ],
"index": 19,
"name": "zone_0",
@@ -156,7 +156,7 @@ entries=[ {
"type": "zone",
"zone_type": 0
}, {
"children": [ 61, 62 ],
"children": [ 60, 61 ],
"commands": [ ],
"index": 20,
"name": "zone_1",
@@ -304,7 +304,7 @@ entries=[ {
"type": "room",
"window": true
}, {
"children": [ 63, 64, 65 ],
"children": [ 62, 63, 64 ],
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
"index": 35,
"name": "zone_0",
@@ -312,7 +312,7 @@ entries=[ {
"type": "zone",
"zone_type": 0
}, {
"children": [ 66, 67 ],
"children": [ 65, 66 ],
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
"index": 36,
"name": "zone_1",
@@ -330,7 +330,7 @@ entries=[ {
"type": "room",
"window": true
}, {
"children": [ 68 ],
"children": [ 67 ],
"commands": [ [ 5, [ ] ] ],
"index": 38,
"name": "stair_0",
@@ -340,7 +340,7 @@ entries=[ {
"type": "room",
"window": true
}, {
"children": [ 69, 70, 71 ],
"children": [ 68, 69, 70 ],
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
"index": 39,
"name": "zone_0",
@@ -348,7 +348,7 @@ entries=[ {
"type": "zone",
"zone_type": 0
}, {
"children": [ 72, 73 ],
"children": [ 71, 72 ],
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
"index": 40,
"name": "zone_1",
@@ -356,7 +356,7 @@ entries=[ {
"type": "zone",
"zone_type": 1
}, {
"children": [ 74 ],
"children": [ 73 ],
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
"index": 41,
"name": "zone_0",
@@ -364,7 +364,7 @@ entries=[ {
"type": "zone",
"zone_type": 0
}, {
"children": [ 75, 76 ],
"children": [ 74, 75 ],
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
"index": 42,
"name": "zone_1",
@@ -372,7 +372,7 @@ entries=[ {
"type": "zone",
"zone_type": 1
}, {
"children": [ 77 ],
"children": [ 76 ],
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
"index": 43,
"name": "zone_0",
@@ -380,7 +380,7 @@ entries=[ {
"type": "zone",
"zone_type": 0
}, {
"children": [ 78 ],
"children": [ 77 ],
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
"index": 44,
"name": "zone_1",
@@ -388,7 +388,7 @@ entries=[ {
"type": "zone",
"zone_type": 1
}, {
"children": [ 79 ],
"children": [ 78 ],
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
"index": 45,
"name": "zone_0",
@@ -396,7 +396,7 @@ entries=[ {
"type": "zone",
"zone_type": 0
}, {
"children": [ 80 ],
"children": [ 79 ],
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
"index": 46,
"name": "zone_1",
@@ -517,16 +517,6 @@ entries=[ {
"children": [ ],
"commands": [ ],
"index": 58,
"name": "enterance_1",
"order": 5,
"room_area": 16.0,
"room_type": 304,
"type": "room",
"window": true
}, {
"children": [ ],
"commands": [ ],
"index": 59,
"name": "wc_0",
"order": 1,
"room_area": 0.0,
@@ -536,7 +526,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ ],
"index": 60,
"index": 59,
"name": "bathroom_0",
"order": 2,
"room_area": 64.0,
@@ -546,7 +536,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ ],
"index": 61,
"index": 60,
"name": "studio_0",
"order": 1,
"room_area": 144.0,
@@ -556,7 +546,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ ],
"index": 62,
"index": 61,
"name": "enterance_0",
"order": 2,
"room_area": 0.0,
@@ -566,7 +556,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 63,
"index": 62,
"name": "bathroom_0",
"order": 0,
"room_area": 16.0,
@@ -576,7 +566,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 64,
"index": 63,
"name": "wc_0",
"order": 1,
"room_area": 16.0,
@@ -586,7 +576,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 65,
"index": 64,
"name": "bedroom_0",
"order": 2,
"room_area": 36.0,
@@ -596,7 +586,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 66,
"index": 65,
"name": "living_room_0",
"order": 0,
"room_area": 36.0,
@@ -606,7 +596,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 67,
"index": 66,
"name": "kitchen_0",
"order": 1,
"room_area": 16.0,
@@ -614,17 +604,17 @@ entries=[ {
"type": "room",
"window": true
}, {
"children": [ 81, 82 ],
"children": [ 80, 81 ],
"commands": [ ],
"floor_index": 1,
"index": 68,
"index": 67,
"name": "floor_0",
"order": 0,
"type": "floor"
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 69,
"index": 68,
"name": "wc_0",
"order": 0,
"room_area": 16.0,
@@ -634,7 +624,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 70,
"index": 69,
"name": "bathroom_0",
"order": 1,
"room_area": 16.0,
@@ -644,7 +634,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 71,
"index": 70,
"name": "bedroom_0",
"order": 2,
"room_area": 64.0,
@@ -654,7 +644,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 72,
"index": 71,
"name": "kitchen_0",
"order": 0,
"room_area": 16.0,
@@ -664,7 +654,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 73,
"index": 72,
"name": "living_room_0",
"order": 1,
"room_area": 144.0,
@@ -674,7 +664,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 74,
"index": 73,
"name": "bathroom_0",
"order": 0,
"room_area": 16.0,
@@ -684,7 +674,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 75,
"index": 74,
"name": "kitchen_0",
"order": 0,
"room_area": 64.0,
@@ -694,7 +684,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 76,
"index": 75,
"name": "living_room_0",
"order": 1,
"room_area": 64.0,
@@ -704,7 +694,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 77,
"index": 76,
"name": "wc_0",
"order": 0,
"room_area": 16.0,
@@ -714,7 +704,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 78,
"index": 77,
"name": "living_room_0",
"order": 0,
"room_area": 64.0,
@@ -724,7 +714,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 79,
"index": 78,
"name": "bathroom_0",
"order": 0,
"room_area": 16.0,
@@ -734,7 +724,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ [ 5, [ ] ] ],
"index": 80,
"index": 79,
"name": "living_room_0",
"order": 0,
"room_area": 64.0,
@@ -742,24 +732,24 @@ entries=[ {
"type": "room",
"window": true
}, {
"children": [ 83 ],
"children": [ 82 ],
"commands": [ ],
"index": 81,
"index": 80,
"name": "zone_0",
"order": 0,
"type": "zone",
"zone_type": 1
}, {
"children": [ 84, 85 ],
"children": [ 83, 84 ],
"commands": [ ],
"index": 82,
"index": 81,
"name": "unit_0",
"order": 0,
"type": "unit"
}, {
"children": [ ],
"commands": [ ],
"index": 83,
"index": 82,
"name": "storage_room_0",
"order": 0,
"room_area": 64.0,
@@ -767,17 +757,17 @@ entries=[ {
"type": "room",
"window": true
}, {
"children": [ 86 ],
"children": [ 85 ],
"commands": [ ],
"index": 84,
"index": 83,
"name": "zone_0",
"order": 0,
"type": "zone",
"zone_type": 0
}, {
"children": [ 87 ],
"children": [ 86 ],
"commands": [ ],
"index": 85,
"index": 84,
"name": "zone_1",
"order": 0,
"type": "zone",
@@ -785,7 +775,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ ],
"index": 86,
"index": 85,
"name": "wc_0",
"order": 0,
"room_area": 16.0,
@@ -795,7 +785,7 @@ entries=[ {
}, {
"children": [ ],
"commands": [ ],
"index": 87,
"index": 86,
"name": "living_room_0",
"order": 0,
"room_area": 16.0,

View File

@@ -1007,6 +1007,12 @@ void BuildingLayoutGraphUI::draw_2d_grid_view(Control *draw)
true);
mcount++;
});
if (fc.has<WorldEditor::components::path>())
draw->draw_circle(
Vector2(dx + 0.5f * dsize,
dy + 0.5f * dsize),
dsize * 0.12f,
Color(0.3f, 0.3f, 1.0f, 1.0f));
print_line(
"draw cell: (" + itos(x) + ", " +
itos(y) + ") (" + String::num(dx) +

View File

@@ -404,8 +404,8 @@ void graph_module::zones_graph_module(flecs::world &ecs,
else
xr = xr.grow(1);
int xarea = xr.size.x * xr.size.y * 16;
sum += MAX(xarea, MIN_ROOM_SIZE) * 10 /
8;
sum += MAX(xarea, MIN_ROOM_SIZE) * 35 /
80;
assert(sum >= 0.0f);
count_rooms++;
}

View File

@@ -475,9 +475,19 @@ void grow_job_queue::iterate()
assert(this);
flecs::query<growth_regions> q =
grid_e.world().query_builder<growth_regions>().build();
#if 0
flecs::query<region_tree> qm =
grid_e.world().query_builder<region_tree>().build();
#endif
q.each([this](flecs::entity e, growth_regions &g) {
flecs::log::warn("pre floor: %s", e.path().c_str());
});
#if 0
qm.each([this](flecs::entity em, region_tree &rt) {
rt.dump(em);
assert(rt.check(em));
});
#endif
q.each([this](flecs::entity e, growth_regions &g) {
flecs::log::warn("floor: %s", e.path().c_str());
flecs::log::warn("job count: %d", g.job_list.size());
@@ -522,21 +532,29 @@ void grow_job_queue::iterate()
assert(false);
break;
}
{
const region_tree *rtree = e.get<region_tree>();
assert(rtree);
assert(rtree->check(grid_floor_e));
}
g.job_list.pop_front();
// if (common_count > 0)
// break;
}
flecs::log::dbg(
"processed jobs (created region initial positions): %d",
g.job_list.size());
g.job_list.clear();
flecs::query<region_tree> qm =
grid_e.world().query_builder<region_tree>().build();
qm.each([this](flecs::entity em, region_tree &rt) {
assert(rt.check(em));
});
qm.each([this](flecs::entity em, region_tree &rt) {
rt.shrink_rooms(em);
});
qm.each([this](flecs::entity em, region_tree &rt) {
rt.place(em);
});
flecs::log::dbg(
"processed jobs (created region initial positions): %d",
g.job_list.size());
});
}

View File

@@ -560,6 +560,7 @@ void growth_module::mark_doors(flecs::world &&ecs_)
[&room_e](flecs::entity re) {
room_e = re;
});
cell_e.add<WorldEditor::components::path>();
flecs::entity next_cell_e =
data[ke->get()].id2entity[path[k + 1]];
next_cell_e.each<
@@ -567,6 +568,7 @@ void growth_module::mark_doors(flecs::world &&ecs_)
[&next_room_e](flecs::entity re) {
next_room_e = re;
});
next_cell_e.add<WorldEditor::components::path>();
if (room_e.is_valid() &&
next_room_e.is_valid()) {
if (exits.has(room_e.id()) &&

View File

@@ -63,6 +63,7 @@ void region_tree::split(flecs::entity grid_floor_e,
count++;
e = e->next();
}
assert(base_rtree->check(grid_floor_e));
}
const region_tree *region_tree::find(flecs::entity_t which) const
@@ -136,6 +137,7 @@ void region_tree::grow(flecs::entity grid_floor_e, bool limited)
const struct region_tree *base_rtree = grid_floor_e.get<region_tree>();
assert(base_rtree);
make_random r(11365);
assert(base_rtree->check(grid_floor_e));
#ifdef TESTS
flecs::log::warn("grow");
#endif
@@ -176,6 +178,7 @@ void region_tree::grow(flecs::entity grid_floor_e, bool limited)
return hash_one_uint64((uint64_t)ptr);
}
};
Vector2i pos = get_global_center();
while (1) {
e = special_grow_list.front();
int count = 0;
@@ -187,29 +190,64 @@ void region_tree::grow(flecs::entity grid_floor_e, bool limited)
e = e->next();
continue;
}
Vector2i dir = pos - item->region.rect.position;
struct region backup = item->region;
RegionRect2i parent_rect = item->parent->region.rect;
switch (variant) {
case 0:
if (dir.x > 0)
item->region.rect.position.x =
parent_rect.position.x +
parent_rect.size.x - 1;
else if (dir.x < 0)
item->region.rect.position.x =
parent_rect.position.x;
if (dir.y > 0)
item->region.rect.position.y =
parent_rect.position.y +
parent_rect.size.y - 1;
else if (dir.y < 0)
item->region.rect.position.y =
parent_rect.position.y;
break;
case 1:
if (dir.x > 0)
item->region.rect.position.x =
parent_rect.position.x +
parent_rect.size.x - 1;
else if (dir.x < 0)
item->region.rect.position.x =
parent_rect.position.x;
break;
case 2:
if (dir.y > 0)
item->region.rect.position.y =
parent_rect.position.y +
parent_rect.size.y - 1;
else if (dir.y < 0)
item->region.rect.position.y =
parent_rect.position.y;
break;
case 3:
item->region.rect.position.x =
parent_rect.position.x +
parent_rect.size.x - 1;
break;
case 1:
case 4:
item->region.rect.position.x =
parent_rect.position.x;
break;
case 2:
case 5:
item->region.rect.position.y =
parent_rect.position.y +
parent_rect.size.y - 1;
break;
case 3:
case 6:
item->region.rect.position.y =
parent_rect.position.y;
break;
}
if (variant > 3) {
if (variant > 6) {
do {
item->region.rect.position.x =
parent_rect.position.x +
@@ -363,6 +401,7 @@ void region_tree::grow(flecs::entity grid_floor_e, bool limited)
queue.clear();
assert(base_rtree->check(grid_floor_e));
}
assert(base_rtree->check(grid_floor_e));
}
bool region_tree::check(flecs::entity grid_floor_e) const
@@ -407,6 +446,7 @@ bool region_tree::check(flecs::entity grid_floor_e) const
float aspect = (float)check_regions[i].size.x /
(float)check_regions[i].size.y;
if (aspect < 0.25f || aspect > 4.0f) {
flecs::log::err("bad aspect ratio");
ok = false;
break;
}
@@ -456,6 +496,219 @@ bool region_tree::check(flecs::entity grid_floor_e) const
return ok;
}
// TODO: calculate if rooms touch each other and shrink smaller one
void region_tree::shrink_rooms(flecs::entity grid_floor_e)
{
int i, accepted = 0;
assert(!parent);
dump(grid_floor_e);
List<struct region_tree *> queue, shrinkable;
List<struct region_tree *> left_rooms, right_rooms, forward_rooms,
backward_rooms, inside_rooms;
List<struct region_tree *>::Element *rp, *rp1, *rp2;
struct touching_result {
struct region_tree *first;
struct region_tree *second;
int how;
};
const struct region_tree *base_rtree = grid_floor_e.get<region_tree>();
assert(base_rtree);
assert(base_rtree->check(grid_floor_e));
List<struct touching_result> touching;
int grid_size = grid_floor_e
.get<WorldEditor::components::
buildings_layout_grid_floor>()
->grid_size;
queue.push_back(this);
while (!queue.empty()) {
const struct region_tree *item = queue.front()->get();
queue.pop_front();
if (item->region.can_grow)
return;
if (item->is_leaf() && item->region.can_move)
return;
for (i = 0; i < (int)item->children.size(); i++)
queue.push_back(item->children[i]);
}
queue.clear();
queue.push_back(this);
while (!queue.empty()) {
struct region_tree *item = queue.front()->get();
queue.pop_front();
int acceptable = 0;
if (item->is_shrinkable())
acceptable = 0xf;
flecs::log::dbg("acceptable: %d", acceptable);
if ((acceptable & 0xf) == 0xf) {
shrinkable.push_back(item);
accepted++;
int rx, px, ry, py;
rx = item->region.rect.position.x;
px = item->parent->region.rect.position.x;
if (rx == px) {
left_rooms.push_back(item);
acceptable |= (1 << 4);
}
rx = item->region.rect.position.x +
item->region.rect.size.x - 1;
px = item->parent->region.rect.position.x +
item->parent->region.rect.size.x - 1;
if (rx == px) {
right_rooms.push_back(item);
acceptable |= (1 << 5);
}
ry = item->region.rect.position.y;
py = item->parent->region.rect.position.y;
if (ry == py) {
forward_rooms.push_back(item);
acceptable |= (1 << 6);
}
ry = item->region.rect.position.y +
item->region.rect.size.y - 1;
py = item->parent->region.rect.position.y +
item->parent->region.rect.size.y - 1;
if (ry == py) {
backward_rooms.push_back(item);
acceptable |= (1 << 7);
}
if ((acceptable & 0xf0) == 0)
inside_rooms.push_back(item);
flecs::log::dbg("acceptable: %d", acceptable);
}
for (i = 0; i < (int)item->children.size(); i++)
queue.push_back(item->children[i]);
}
#if 0
rp1 = rooms.front();
while (rp1) {
rp2 = rooms.front();
while (rp2) {
if (rp1 == rp2) {
rp2 = rp2->next();
continue;
}
int style = rp1->get()->what_touching(rp2->get());
struct region_tree *item1 = rp1->get(),
*item2 = rp2->get();
if (style & TOUCH_RIGHT) {
if (shrinkable.find(item2)) {
if (!right_rooms.find(item2))
right_rooms.push_back(item2);
} else if (shrinkable.find(item1)) {
if (!left_rooms.find(item1))
left_rooms.push_back(item1);
}
}
if (style & TOUCH_LEFT) {
if (shrinkable.find(item2)) {
if (!left_rooms.find(item2))
left_rooms.push_back(item2);
} else if (shrinkable.find(item1)) {
if (!right_rooms.find(item1))
right_rooms.push_back(item1);
}
}
if (style & TOUCH_FORWARD) {
if (shrinkable.find(item2)) {
if (!forward_rooms.find(item2))
forward_rooms.push_back(item2);
} else if (shrinkable.find(item1)) {
if (!backward_rooms.find(item1))
backward_rooms.push_back(item1);
}
}
if (style & TOUCH_BACKWARD) {
if (shrinkable.find(item2)) {
if (!backward_rooms.find(item2))
backward_rooms.push_back(item2);
} else if (shrinkable.find(item1)) {
if (!forward_rooms.find(item1))
forward_rooms.push_back(item1);
}
}
rp2 = rp2->next();
}
rp1 = rp1->next();
}
#endif
int shrunk = 0;
int shrink_mode = SHRINK_LEFT_ROOM;
while (1) {
switch (shrink_mode) {
case SHRINK_LEFT_ROOM:
rp = left_rooms.front();
break;
case SHRINK_RIGHT_ROOM:
rp = right_rooms.front();
break;
case SHRINK_FORWARD_ROOM:
rp = forward_rooms.front();
break;
case SHRINK_BACKWARD_ROOM:
rp = backward_rooms.front();
break;
case SHRINK_INSIDE_ROOM:
rp = inside_rooms.front();
break;
}
while (rp) {
struct region backup = rp->get()->region;
List<struct region_tree *> neighbors;
switch (shrink_mode) {
case SHRINK_LEFT_ROOM:
get_neighbors(grid_floor_e, RIGHT, &neighbors);
if (neighbors.size() > 0) {
rp->get()->region.rect.size.x -= 1;
shrunk++;
}
break;
case SHRINK_RIGHT_ROOM:
get_neighbors(grid_floor_e, LEFT, &neighbors);
if (neighbors.size() > 0) {
rp->get()->region.rect.position.x += 1;
rp->get()->region.rect.size.x -= 1;
shrunk++;
}
break;
case SHRINK_FORWARD_ROOM:
get_neighbors(grid_floor_e, BACKWARD,
&neighbors);
if (neighbors.size() > 0) {
rp->get()->region.rect.size.y -= 1;
shrunk++;
}
break;
case SHRINK_BACKWARD_ROOM:
get_neighbors(grid_floor_e, FORWARD,
&neighbors);
if (neighbors.size() > 0) {
rp->get()->region.rect.position.y += 1;
rp->get()->region.rect.size.y -= 1;
shrunk++;
}
break;
case SHRINK_INSIDE_ROOM:
// TODO: check neighbors
rp->get()->region.rect =
rp->get()->region.rect.grow(-1);
shrunk++;
break;
default:
assert(false);
}
if (!base_rtree->check(grid_floor_e))
rp->get()->region = backup;
assert(base_rtree->check(grid_floor_e));
rp = rp->next();
}
if (shrink_mode >= SHRINK_INSIDE_ROOM)
break;
shrink_mode++;
}
assert(base_rtree->check(grid_floor_e));
// assert(accepted == 0 || shrunk > 0);
grid_floor_e.modified<region_tree>();
}
void region_tree::place(flecs::entity grid_floor_e) const
{
int i, j, k;
@@ -568,10 +821,13 @@ void region_tree::place(flecs::entity grid_floor_e) const
void region_tree::move(flecs::entity grid_floor_e)
{
if (!parent)
return;
struct region_tree *base_rtree = grid_floor_e.get_mut<region_tree>();
assert(base_rtree);
List<struct region_tree *> queue;
List<struct region_tree *> movables;
List<struct region_tree *> movables_sorted;
int count = 0;
Vector2i center;
queue.push_back(base_rtree);
@@ -595,37 +851,97 @@ void region_tree::move(flecs::entity grid_floor_e)
flecs::log::dbg("center: %d %d", center.x, center.y);
while (!movables.empty()) {
struct region_tree *item = movables.front()->get();
Vector2i dir = item->region.rect.get_center() - center;
int d = dir.x * dir.x + dir.y * dir.y;
movables.pop_front();
List<struct region_tree *>::Element *e = movables.front();
bool ok = true;
while (e) {
struct region_tree *check = e->get();
Vector2i dir2 =
check->region.rect.get_center() - center;
int d2 = dir2.x * dir2.x + dir2.y * dir2.y;
if (d2 > d) {
ok = false;
break;
}
e = e->next();
}
if (ok)
movables_sorted.push_back(item);
else
movables.push_back(item);
}
flecs::log::dbg("sorting done");
int fail_count = 0;
while (!movables_sorted.empty()) {
struct region_tree *item = movables_sorted.front()->get();
if (!item->region.can_move)
continue;
Vector2i dir = item->region.rect.get_center() - center, dir1,
dir2;
if (dir.x * dir.x > dir.y * dir.y) {
dir1.x = CLAMP(dir.x, -1, 1);
dir1.y = 0;
} else if (dir.x * dir.x < dir.y * dir.y) {
dir1.x = 0;
dir1.y = CLAMP(dir.y, -1, 1);
}
dir2.x = CLAMP(dir.x, -1, 1);
dir2.y = CLAMP(dir.y, -1, 1);
flecs::log::dbg("direction: %d %d", dir.x, dir.y);
RegionRect2i backup = item->region.rect;
item->region.rect.position += dir1;
if (base_rtree->check(grid_floor_e)) {
queue.push_back(item);
continue;
} else {
item->region.rect = backup;
item->region.rect.position += dir2;
if (base_rtree->check(grid_floor_e)) {
queue.push_back(item);
continue;
Vector2i gcenter = item->get_global_center();
Vector2i dir = item->parent->region.rect.get_center() -
(center * 2 + gcenter * 4);
int flag1 = (item->region.rect.position.x +
item->region.rect.position.y) &
(1 << 1);
int flag2 = (item->region.rect.position.x +
item->region.rect.position.y) &
(1 << 2);
if (dir.x == 0 && dir.y == 0) {
if (flag1) {
dir.x = 0;
if (flag2)
dir.y = 1;
else
dir.y = -1;
} else {
item->region.rect = backup;
item->region.can_move = false;
if (flag2)
dir.x = 1;
else
dir.x = -1;
dir.y = 0;
}
}
Vector2i mdir1, mdir2;
mdir1.x = CLAMP(dir.x, -1, 1);
mdir1.y = 0;
mdir2.x = 0;
mdir2.y = CLAMP(dir.y, -1, 1);
flecs::log::dbg("direction: %d %d", dir.x, dir.y);
flecs::log::dbg("direction1: %d %d", mdir1.x, mdir1.y);
flecs::log::dbg("direction2: %d %d", mdir2.x, mdir2.y);
flecs::log::dbg("position: %d %d", item->region.rect.position.x,
item->region.rect.position.y);
RegionRect2i backup = item->region.rect;
item->region.rect.position += mdir1;
flecs::log::dbg("updated position: %d %d",
item->region.rect.position.x,
item->region.rect.position.y);
bool ok1 = false, ok2 = false;
if (base_rtree->check(grid_floor_e)) {
fail_count = 0;
flecs::log::dbg("can still move");
ok1 = true;
} else {
ok1 = false;
item->region.rect = backup;
item->region.rect.position += mdir2;
if (base_rtree->check(grid_floor_e))
ok2 = true;
else
ok2 = false;
}
if (!ok1 && !ok2) {
fail_count++;
item->region.rect = backup;
if (fail_count > 10) {
item->region.can_move = false;
movables_sorted.pop_front();
flecs::log::dbg("can't move, going to next");
fail_count = 0;
}
} else
continue;
}
grid_floor_e.modified<region_tree>();
}
@@ -702,7 +1018,156 @@ bool region_tree::is_special() const
{
return flag_special;
}
bool region_tree::is_touching(const struct region_tree *other) const
{
int flags = what_touching(other);
return (flags > 0);
}
void region_tree::get_room_nodes(
List<const struct region_tree *> *node_list) const
{
List<const struct region_tree *> queue;
queue.push_back(this);
while (!queue.empty()) {
int i;
const struct region_tree *item = queue.front()->get();
queue.pop_front();
if (item->is_leaf() && item->is_a_room()) {
node_list->push_back(item);
}
for (i = 0; i < (int)item->children.size(); i++)
queue.push_back(item->children[i]);
}
}
void region_tree::get_room_nodes(List<struct region_tree *> *node_list)
{
List<struct region_tree *> queue;
queue.push_back(this);
while (!queue.empty()) {
int i;
struct region_tree *item = queue.front()->get();
queue.pop_front();
if (item->is_leaf() && item->is_a_room()) {
node_list->push_back(item);
}
for (i = 0; i < (int)item->children.size(); i++)
queue.push_back(item->children[i]);
}
}
void region_tree::get_neighbors(flecs::entity grid_floor_e, int direction,
List<struct region_tree *> *neighbors) const
{
List<struct region_tree *> rooms;
List<struct region_tree *>::Element *el;
struct region_tree *base_rtree = grid_floor_e.get_mut<region_tree>();
assert(base_rtree);
base_rtree->get_room_nodes(&rooms);
RegionRect2i neighbor_rect = region.rect;
neighbors->clear();
switch (direction) {
case LEFT:
neighbor_rect.position.x -= 1;
neighbor_rect.size.x = 1;
break;
case RIGHT:
neighbor_rect.position.x += region.rect.size.x;
neighbor_rect.size.x = 1;
break;
case FORWARD:
neighbor_rect.position.y -= 1;
neighbor_rect.size.y = 1;
break;
case BACKWARD:
neighbor_rect.position.y += region.rect.size.y;
neighbor_rect.size.y = 1;
break;
default:
assert(false);
break;
}
el = rooms.front();
while (el) {
if (el->get() == this) {
el = el->next();
continue;
}
bool neighbor = false;
if (neighbor_rect == el->get()->region.rect)
neighbor = true;
if (neighbor_rect.encloses(el->get()->region.rect))
neighbor = true;
if (neighbor_rect.intersects(el->get()->region.rect))
neighbor = true;
if (el->get()->region.rect.encloses(neighbor_rect))
neighbor = true;
if (el->get()->region.rect.intersects(neighbor_rect))
neighbor = true;
if (neighbor)
neighbors->push_back(el->get());
el = el->next();
}
}
int region_tree::what_touching(const region_tree *other) const
{
int i;
RegionRect2i right = region.rect, left = region.rect,
forward = region.rect, backward = region.rect;
right.position.x = region.rect.position.x + region.rect.size.x;
left.position.x = region.rect.position.x - region.rect.size.x;
forward.position.y = region.rect.position.y - region.rect.size.y;
backward.position.y = region.rect.position.y + region.rect.size.y;
int flags = 0;
RegionRect2i rects[] = { right, left, forward, backward };
for (i = 0; i < (int)sizeof(rects) / (int)sizeof(rects[0]); i++) {
if (other->region.rect == rects[i])
flags |= (1 << i);
if (other->region.rect.encloses(rects[i]))
flags |= (1 << i);
if (other->region.rect.intersects(rects[i]))
flags |= (1 << i);
if (rects[i].encloses(other->region.rect))
flags |= (1 << i);
}
return flags;
}
bool region_tree::is_shrinkable() const
{
int acceptable = 0;
if (region.rect.size.x > 2)
acceptable |= (1 << 0);
if (region.rect.size.y > 2)
acceptable |= (1 << 1);
if (is_leaf())
acceptable |= (1 << 2);
if (parent)
acceptable |= (1 << 3);
return (acceptable & 0xf) == 0xf;
}
Vector2i region_tree::get_global_center() const
{
Vector2i center;
int i;
const struct region_tree *r = this;
while (r->parent)
r = r->parent;
for (i = 0; i < r->children.size(); i++)
center += r->children[i]->region.rect.get_center();
return center;
}
Vector2i region_tree::get_center() const
{
return region.rect.get_center();
}
int region_tree::area() const
{
return region.rect.get_area();
}
bool region_tree::check_candidate(int i, const RegionRect2i &candidate) const
{
int j;

View File

@@ -22,6 +22,7 @@ struct region_tree {
void grow(flecs::entity grid_floor_e, bool limited = true);
bool check(flecs::entity grid_floor_e) const;
void place(flecs::entity grid_floor_e) const;
void shrink_rooms(flecs::entity grid_floor_e);
void move(flecs::entity grid_floor_e);
void get_rects(List<RegionRect2i> *rect_list) const;
void get_leaf_nodes(List<const struct region_tree *> *node_list) const;
@@ -29,6 +30,35 @@ struct region_tree {
bool is_a_room(flecs::entity grid_floor_e) const;
bool is_a_room() const;
bool is_special() const;
bool is_touching(const struct region_tree *other) const;
enum {
TOUCH_RIGHT = 1,
TOUCH_LEFT = 2,
TOUCH_FORWARD = 4,
TOUCH_BACKWARD = 8,
};
enum {
SHRINK_LEFT_ROOM = 1, // shrink right side
SHRINK_RIGHT_ROOM, // shrink left side
SHRINK_FORWARD_ROOM, // shrink "upper" side
SHRINK_BACKWARD_ROOM, // shrink "lower" side
SHRINK_INSIDE_ROOM, // shrink "inside" room (all sides?)
};
enum {
LEFT = 1,
RIGHT,
FORWARD,
BACKWARD,
};
void get_room_nodes(List<const struct region_tree *> *node_list) const;
void get_room_nodes(List<struct region_tree *> *node_list);
void get_neighbors(flecs::entity grid_floor_e, int direction,
List<struct region_tree *> *neighbors) const;
int what_touching(const struct region_tree *other) const;
bool is_shrinkable() const;
Vector2i get_global_center() const;
Vector2i get_center() const;
int area() const;
private:
bool check_candidate(int i, const RegionRect2i &candidate) const;

View File

@@ -119,6 +119,7 @@ public:
List<Pair<int, flecs::entity_t> > floors;
int growth_size;
};
struct path {};
struct belongs {};
struct border {};
struct belongs_room {};