-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathplanner.pl
58 lines (49 loc) · 2.11 KB
/
planner.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
% breadth-first version, avoids infinite recursion
:- module(planner,[calculate_plan/2, apply_action/3]).
:- use_module(story_data).
calculate_plan(InitialState, Plan) :-
ord_empty(ClosedSet),
state_plan_node(InitialState, [], Node),
process_queue([Node], ClosedSet, NodeOut),
!,
Plan = NodeOut.plan.
state_plan_node(State, Plan, node{ state:State, plan:Plan }).
process_queue(OpenList, ClosedSet, _) :-
% this clause just writes to the debug monitor
length(OpenList, OpenLen),
length(ClosedSet, ClosedLen),
debug(planner(process_queue), 'open ~w closed ~w', [OpenLen, ClosedLen]),
fail.
process_queue([HeadNode|_], _, HeadNode) :-
state_plan_node(HeadState, _, HeadNode),
done(HeadState),
!.
process_queue([HeadNode|TailNodes], ClosedSet, NodeOut) :-
findall(Node, take_action(HeadNode, ClosedSet, Node), OutcomeNodes),
append(TailNodes, OutcomeNodes, Queue),
state_plan_node(HeadState, _, HeadNode),
close_state(ClosedSet, HeadState, ClosedList0),
process_queue(Queue, ClosedList0, NodeOut).
done(State) :-
findall(G, member(goal(G), State), Goals),
intersection(Goals, State, Goals).
% take an action; check its outcome against the closed list; and add its action term to the plan
take_action(NodeIn, ClosedSet, NodeOut) :-
% action/1 is defined in the story data
action(ActionStep, ActionDict),
state_plan_node(StateIn, PlanIn, NodeIn),
apply_action(StateIn, ActionDict, StateOut),
state_not_closed(StateOut, ClosedSet),
append(PlanIn, [ActionStep], PlanOut),
state_plan_node(StateOut, PlanOut, NodeOut).
apply_action(StateIn, ActionDict, StateOut) :-
subtract(StateIn, ActionDict.negprereqs, StateIn),
intersection(ActionDict.prereqs, StateIn, ActionDict.prereqs),
subtract(StateIn, ActionDict.removes, S0),
append(S0, ActionDict.adds, StateOut).
state_not_closed(State, ClosedSet) :-
list_to_ord_set(State, StateOrdSet),
\+ ord_memberchk(StateOrdSet, ClosedSet).
close_state(ClosedSetIn, State, ClosedSetOut) :-
list_to_ord_set(State, StateOrdSet),
ord_add_element(ClosedSetIn, StateOrdSet, ClosedSetOut).