Skip to content

Commit 96eda19

Browse files
committed
Fix: Meadow themeroom fill could disrupt room joining
This was uncovered by the debug fuzzer and was quickly reproducible once I discovered the room-and-fill combination that could most easily cause it (the "Circular, small" room). It was a known issue, with a comment indicating it was simply too difficult to avoid and was a rare case anyway. That's not good enough if it causes fuzzer crashes. The fix is a lot of lines of code, but is a more general solution that allows an arbitrary number of trees to be placed, rather than assuming there will only be 1 tree. There is still no guarantee that 2 trees won't be generated in some way that blocks easy travel through the interior of the room.
1 parent c0e9064 commit 96eda19

1 file changed

Lines changed: 51 additions & 6 deletions

File tree

dat/themerms.lua

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -374,12 +374,57 @@ themeroom_fills = {
374374
contents = function()
375375
local interior = selection.room()
376376
des.terrain(interior, 'g')
377-
if interior:numpoints() > 8 then
378-
-- in the original implementation this tried to pick points not against
379-
-- a wall so as not to block doors. now that this is a fill, that's too
380-
-- hard to do.
381-
for i = 1, d(4)-2 do
382-
des.terrain(interior:rndcoord(), 'T')
377+
-- Maybe place a couple trees, but we must take care to avoid placing
378+
-- trees such that there are no longer any points on any edge that are
379+
-- valid to place a door on.
380+
-- Note that this will be obsolete if at some point the room joining
381+
-- code is updated so that it can connect to any point on a room edge
382+
-- and not be required to connect to a specific wall.
383+
--
384+
-- 1. Find the selection's bounding box. (should this be a core
385+
-- selection function? maybe if it gets reused elsewhere)
386+
local lx = 1000
387+
local hx = 0
388+
local ly = 1000
389+
local hy = 0
390+
interior:iterate(function(x, y)
391+
lx = math.min(lx, x)
392+
hx = math.max(hx, x)
393+
ly = math.min(ly, y)
394+
hy = math.max(hy, y)
395+
end)
396+
397+
-- 2. Store the number of points on each edge.
398+
local pointsN, pointsE, pointsS, pointsW
399+
pointsN, pointsE, pointsS, pointsW = 0, 0, 0, 0
400+
interior:iterate(function(x, y)
401+
if x == lx then pointsW = pointsW + 1 end
402+
if x == hx then pointsE = pointsE + 1 end
403+
if y == ly then pointsN = pointsN + 1 end
404+
if y == hy then pointsS = pointsS + 1 end
405+
end)
406+
407+
-- 3. Tree creation loop
408+
for i = 1, d(4)-2 do
409+
-- a. Pop a random coord from the selection
410+
local pt = interior:rndcoord(1)
411+
local onW = (pt.x == lx)
412+
local onN = (pt.y == ly)
413+
local onE = (pt.x == hx)
414+
local onS = (pt.y == hy)
415+
416+
if (onW and pointsW == 1) or (onN and pointsN == 1)
417+
or (onE and pointsE == 1) or (onS and pointsS == 1) then
418+
-- do nothing
419+
else
420+
-- make the tree, but decrement any appropriate edge counters
421+
-- since we might make more trees; if we're not on any edge no
422+
-- counters will be affected
423+
des.terrain(pt, 'T')
424+
if onW then pointsW = pointsW - 1 end
425+
if onN then pointsN = pointsN - 1 end
426+
if onE then pointsE = pointsE - 1 end
427+
if onS then pointsS = pointsS - 1 end
383428
end
384429
end
385430
end,

0 commit comments

Comments
 (0)