Skip to content

Commit 06abaee

Browse files
committed
fix: Issues with stair exploration
This commit is a significant rewrite of stair-related aspects of travel. Although qw doesn't get stuck often these days with the recent improvements to exploration and travel, this case in Orc revealed that it still has some blind spots. Specific qw got shafted from Orc:1, partially explored Orc:2 to reveal two upstairs, and got stuck in a loop between Orc:1 and Orc:2 when the upstairs it took lead to a disconnected cell with no further stairs. In this case the necessary backtracking was broken as a result of tight control travel has now over unexplored stair searches. The code to determine the next travel depth and associated direction was relatively difficult to understand in terms of it repeating various bits of logic several times in the relevant function. This commit refactors and simplifies the logic into fewer functions with more general code. It removes special state tracking for stairs searches that's made redundant by aforementioned recent changes to stairs direction searches. We also no longer use an explicit backtracking state variable, instead relying on stair state resets and the backtracking plan to put us in a state that has us search new stairs on the level to which we backtrack.
1 parent 448b382 commit 06abaee

File tree

7 files changed

+123
-176
lines changed

7 files changed

+123
-176
lines changed

source/gameplans.lua

Lines changed: 2 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -754,127 +754,7 @@ function gameplan_options()
754754
return GAMEPLANS[plan]
755755
end
756756

757-
function dir_key(dir)
758-
return dir == DIR.DOWN and ">" or "<"
759-
end
760-
761-
-- Adjust depth for any backtracking, reversing to our previous level and
762-
-- searching in the opposite direction. Otherwise we only set the dir if the
763-
-- level is autoexplored.
764-
function final_depth_dir(branch, depth, dir, backtrack)
765-
if backtrack then
766-
return depth + dir, -dir
767-
elseif autoexplored_level(branch, depth) then
768-
return depth, dir
769-
else
770-
return depth
771-
end
772-
end
773-
774-
function finalize_exploration_depth(branch, depth)
775-
if not autoexplored_level(branch, depth) then
776-
return depth
777-
end
778-
779-
-- We just backtracked from an adjacent level to this depth. We'll not
780-
-- return to the final search depth we calculate, but rather try to reach
781-
-- that search depth via unexplored stairs from the current depth.
782-
local backtrack = backtracked_to == make_level(branch, depth)
783-
784-
function all_reachable(branch, depth, dir)
785-
return count_stairs(branch, depth, dir, FEAT_LOS.REACHABLE)
786-
== num_required_stairs(branch, depth, dir)
787-
end
788-
789-
function all_explored(branch, depth, dir)
790-
return count_stairs(branch, depth, dir, FEAT_LOS.REACHABLE)
791-
== count_stairs(branch, depth, dir, FEAT_LOS.EXPLORED)
792-
end
793-
794-
local up_depth = depth - 1
795-
local up_unreach = true
796-
local depth_up_all_reachable, up_finished, up_lev
797-
if up_depth >= 1 then
798-
depth_up_all_reachable = all_reachable(branch, depth, DIR.UP)
799-
up_lev = make_level(branch, up_depth)
800-
up_unreach
801-
= count_stairs(branch, depth, DIR.UP, FEAT_LOS.REACHABLE) == 0
802-
up_finished = depth_up_all_reachable
803-
or autoexplored_level(branch, up_depth)
804-
and all_explored(branch, up_depth, DIR.DOWN)
805-
end
806-
807-
depth_up_finished = depth_up_all_reachable
808-
or all_explored(branch, depth, DIR.UP)
809-
810-
local down_depth = depth + 1
811-
local down_unreach = true
812-
local depth_down_all_reachable, down_finished, down_lev
813-
if down_depth <= branch_depth(branch) then
814-
depth_down_all_reachable = all_reachable(branch, depth, DIR.DOWN)
815-
down_depth_lev = make_level(branch, down_depth)
816-
down_unreach =
817-
count_stairs(branch, depth, DIR.DOWN, FEAT_LOS.REACHABLE) == 0
818-
down_finished = depth_down_all_reachable
819-
or autoexplored_level(branch, down_depth)
820-
and all_explored(branch, down_depth, DIR.UP)
821-
end
822-
823-
depth_down_finished = depth_down_all_reachable
824-
or all_explored(branch, depth, DIR.DOWN)
825-
826-
if up_unreach then
827-
if depth_down_finished then
828-
if down_unreach then
829-
return depth
830-
end
831-
832-
if down_finished then
833-
level_stair_reset(branch, depth, DIR.DOWN)
834-
level_stair_reset(branch, down_depth, DIR.UP)
835-
return depth
836-
end
837-
838-
return final_depth_dir(branch, down_depth, DIR.UP, backtrack)
839-
end
840-
841-
return depth, DIR.DOWN
842-
end
843-
844-
if up_finished then
845-
if depth_up_finished then
846-
if depth_down_finished then
847-
if down_unreach then
848-
-- We don't try stair resets if we're still looking for the
849-
-- rune. This way we'll instead try branch-end-specific
850-
-- plans for e.g. Swamp.
851-
if have_branch_runes(branch)
852-
or depth < branch_rune_depth(branch) then
853-
level_stair_reset(branch, up_depth, DIR.DOWN)
854-
level_stair_reset(branch, depth, DIR.UP)
855-
end
856-
return depth
857-
end
858-
859-
if down_finished then
860-
level_stair_reset(branch, up_depth, DIR.DOWN)
861-
level_stair_reset(branch, depth, DIR.UP)
862-
level_stair_reset(branch, depth, DIR.DOWN)
863-
level_stair_reset(branch, down_depth, DIR.UP)
864-
return depth
865-
end
866-
end
867-
868-
return final_depth_dir(branch, down_depth, DIR.UP, backtrack)
869-
end
870-
871-
return depth, DIR.UP
872-
end
873-
874-
return final_depth_dir(branch, up_depth, DIR.DOWN, backtrack)
875-
end
876-
877-
function explore_next_range_depth(branch, min_depth, max_depth)
757+
function next_exploration_depth(branch, min_depth, max_depth)
878758
-- The earliest depth that either lacks autoexplore or doesn't have all
879759
-- stairs reachable.
880760
local branch_max = branch_depth(branch)
@@ -909,7 +789,7 @@ function set_gameplan(status, gameplan)
909789
gameplan_depth = where_depth
910790
elseif gameplan_branch then
911791
gameplan_depth
912-
= explore_next_range_depth(gameplan_branch, min_depth, max_depth)
792+
= next_exploration_depth(gameplan_branch, min_depth, max_depth)
913793

914794
if gameplan == zot_end and not gameplan_depth then
915795
gameplan_depth = branch_depth("Zot")

source/plans-explore.lua

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
function plan_autoexplore()
2-
if disable_autoexplore
3-
-- Autoexplore will try to take us near any runed doors. We don't
4-
-- even attempt it if doing a stairs search, since it would move us
5-
-- off our map travel destination.
6-
or stairs_search
7-
or free_inventory_slots() == 0 then
2+
if disable_autoexplore or free_inventory_slots() == 0 then
83
return false
94
end
105

@@ -231,8 +226,8 @@ function set_plan_explore2()
231226
{plan_go_to_pan_downstairs, "try_go_to_pan_downstairs"},
232227
{plan_enter_abyss, "enter_abyss"},
233228
{plan_go_to_abyss_portal, "try_go_to_abyss_portal"},
229+
{plan_take_unexplored_stairs, "take_unexplored_stairs"},
234230
{plan_go_to_unexplored_stairs, "try_go_to_unexplored_stairs"},
235-
{plan_take_unexplored_stairs, "try_take_unexplored_stairs"},
236231
{plan_shopping_spree, "try_shopping_spree"},
237232
{plan_go_to_orb, "try_go_to_orb"},
238233
{plan_go_command, "try_go_command"},

source/plans-stairs.lua

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
function plan_go_to_unexplored_stairs()
22
if not can_waypoint
3-
or stairs_search
43
or not stairs_search_dir
54
or where_branch ~= travel_branch
65
or where_depth ~= travel_depth then
76
return false
87
end
98

10-
-- No point in trying if we don't have unexplored stairs.
11-
if have_all_stairs(where_branch, where_depth, stairs_search_dir,
12-
FEAT_LOS.EXPLORED) then
13-
return false
14-
end
15-
169
if map_search_attempts == 1 then
1710
map_search_attempts = 0
1811
disable_autoexplore = false
@@ -92,26 +85,35 @@ function plan_transporter_orient_exit()
9285
end
9386

9487
function plan_take_unexplored_stairs()
95-
if not stairs_search then
88+
if not stairs_search_dir then
9689
return false
9790
end
9891

99-
local dir = stone_stair_type(stairs_search)
92+
local dir, num
93+
dir, num = stone_stair_type(view.feature_at(0, 0))
94+
if not dir or dir ~= stairs_search_dir
95+
or stairs_state(where_branch, where_depth, dir, num)
96+
>= FEAT_LOS.EXPLORED then
97+
return false
98+
end
10099

101100
-- Ensure that we autoexplore any new area we arrive in, otherwise, if we
102101
-- have completed autoexplore at least once, we may immediately leave once
103102
-- we see we've found the last missing staircase.
104-
local level = make_level(where_branch, where_depth + dir)
105-
c_persist.autoexplore[level] = AUTOEXP.NEEDED
103+
c_persist.autoexplore[make_level(where_branch, where_depth + dir)]
104+
= AUTOEXP.NEEDED
106105

107106
magic("G" .. dir_key(dir))
108107
return true
109108
end
110109

111110
-- Backtrack to the previous level if we're trying to explore stairs on a
112-
-- travel or gameplan destination level yet have no further accessible
113-
-- unexplored stairs. We require a travel or gameplan stairs search direction
114-
-- to know whether to attempt this and what direction we should backtrack.
111+
-- destination level yet have no further accessible unexplored stairs. We
112+
-- require a travel stairs search direction to know whether to attempt this and
113+
-- what direction we should backtrack. Stairs are reset in the relevant
114+
-- directions on both levels so after we explore the pair of stairs used to
115+
-- return to the previous level, we'll take a different set of stairs from that
116+
-- level via a new travel stairs search direction.
115117
function plan_unexplored_stairs_backtrack()
116118
if not stairs_search_dir
117119
or where_branch ~= travel_branch
@@ -123,7 +125,7 @@ function plan_unexplored_stairs_backtrack()
123125
local next_depth = where_depth + stairs_search_dir
124126
level_stair_reset(where_branch, where_depth, stairs_search_dir)
125127
level_stair_reset(where_branch, next_depth, -stairs_search_dir)
126-
backtracked_to = make_level(where_branch, next_depth)
128+
want_gameplan_update = true
127129
send_travel(where_branch, next_depth)
128130
return true
129131
end

source/stairs.lua

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ function set_stairs(branch, depth, dir, feat_los, min_feat_los)
4747
end
4848
end
4949

50+
function dir_key(dir)
51+
return dir == DIR.DOWN and ">" or "<"
52+
end
53+
5054
function level_stair_reset(branch, depth, dir)
5155
set_stairs(branch, depth, dir, FEAT_LOS.REACHABLE)
5256

@@ -63,18 +67,6 @@ function level_stair_reset(branch, depth, dir)
6367
end
6468
end
6569

66-
function check_stairs_search(feat)
67-
local dir, num
68-
dir, num = stone_stair_type(feat)
69-
if not dir then
70-
return
71-
end
72-
73-
if stairs_state(where_branch, where_depth, dir, num) < FEAT_LOS.EXPLORED then
74-
stairs_search = feat
75-
end
76-
end
77-
7870
function stairs_state(branch, depth, dir, num)
7971
local level = make_level(branch, depth)
8072
if dir == DIR.UP then
@@ -296,7 +288,6 @@ function update_level_map(num)
296288
if feat_uses_map_key(map_search_key, feat) then
297289
record_map_search(num, map_search_key, map_search_pos,
298290
map_search_count, 100 * dx + dy)
299-
check_stairs_search(feat)
300291
end
301292
map_search_key = nil
302293
map_search_pos = nil

0 commit comments

Comments
 (0)