这是一个很酷的问题。我相信可以通过在房间放置位置上的行动计划来解决。
定义国家世界如下:
//State:
// A list of room states.
// Room state:
// - Does room exist?
// - Where is room's location?
// - What is the room's size?
将约束定义为:
// Constraint(<1>, <2>):
// - If room <1> and <2> exist, Room <1> is adjacent to Room <2>
如您所描述的,“相邻”(共享至少3个邻居)
甲约束被认为是无效每当两个房间不相邻,并且两个室存在。
定义一个国家要有效时:
// foreach Constraint:
// The Constraint is "not invalidated".
// foreach Room:
// The room does not intersect another room.
给定当前状态,将动作定义为房间的放置。该行动是有效的,只要从动作产生的状态中是有效的。因此,我们可以为每个状态生成一个动作列表:
// Returns a list of valid actions from the current state
function List<Action> GetValidActions(State current, List<Constraint> constraints):
List<Action> actions = new List<Action>();
// For each non-existent room..
foreach Room room in current.Rooms:
if(!room.Exists)
// Try to put it at every possible location
foreach Position position in Dungeon:
State next = current.PlaceRoom(room, position)
// If the next state is valid, we add that action to the list.
if(next.IsValid(constraints))
actions.Add(new Action(room, position));
现在,你留下的是一个曲线图,其中美国是节点,和操作是链接。我们的目标是要找到一个国家是既有效,并且所有的房间都被放置。我们可以通过以任意方式搜索图形(也许使用深度优先搜索)来找到有效的放置位置。搜索将如下所示:
// Given a start state (with all rooms set to *not exist*), and a set of
// constraints, finds a valid end state where all the constraints are met,
// using a depth-first search.
// Notice that this gives you the power to pre-define the starting conditions
// of the search, to for instance define some key areas of your dungeon by hand.
function State GetFinalState(State start, List<Constraint> constraints)
Stack<State> stateStack = new Stack<State>();
State current = start;
stateStack.push(start);
while not stateStack.IsEmpty():
current = stateStack.pop();
// Consider a new state to expand from.
if not current.checked:
current.checked = true;
// If the state meets all the constraints, we found a solution!
if(current.IsValid(constraints) and current.AllRoomsExist()):
return current;
// Otherwise, get all the valid actions
List<Action> actions = GetValidActions(current, constraints);
// Add the resulting state to the stack.
foreach Action action in actions:
State next = current.PlaceRoom(action.room, action.position);
stateStack.push(next);
// If the stack is completely empty, there is no solution!
return NO_SOLUTION;
现在生成的地牢的质量将取决于考虑房间和动作的顺序。您可以通过随机排列每个阶段所执行的动作,从而随机浏览状态动作图,来获得有趣且不同的结果。搜索效率将在很大程度上取决于您可以拒绝无效状态的速度。每当您要查找有效动作时,它可能有助于从约束条件生成有效状态。