Search code examples
prologplanning

Two room planner Blocks world Prolog


I need some very basic help on how to approach this problem. I have a one room planner that, given a start state and end state, it solves this using recursion. However, I want to solve this for two states (aka rooms). I decided that setting flags would be my best bet since each state of the rooms is either in room1 or room2. However I do not know how to implement this. Any can push me in the right direction?

Just to clarify, the new states would be (ontable(X), room1) instead of ontable(X)

:- module( planner,
       [
           plan/4,change_state/3,conditions_met/2,member_state/2,
           move/3,go/2,test/0,test2/0
       ]).

:- [utils].

plan(State, Goal, _, Moves) :-  equal_set(State, Goal),
                write('moves are'), nl,
                reverse_print_stack(Moves).
plan(State, Goal, Been_list, Moves) :-
                move(Name, Preconditions, Actions),
                conditions_met(Preconditions, State),
                change_state(State, Actions, Child_state),
                not(member_state(Child_state, Been_list)),
                stack(Child_state, Been_list, New_been_list),
                stack(Name, Moves, New_moves),
            plan(Child_state, Goal, New_been_list, New_moves),!.

change_state(S, [], S).
change_state(S, [add(P)|T], S_new) :-   change_state(S, T, S2),
                    add_to_set(P, S2, S_new), !.
change_state(S, [del(P)|T], S_new) :-   change_state(S, T, S2),
                    remove_from_set(P, S2, S_new), !.
conditions_met(P, S) :- subset(P, S).

member_state(S, [H|_]) :-   equal_set(S, H).
member_state(S, [_|T]) :-   member_state(S, T).

/* move types */

move(pickup(X), [handempty, clear(X), on(X, Y)],
        [del(handempty), del(clear(X)), del(on(X, Y)),
                 add(clear(Y)), add(holding(X))]).

move(pickup(X), [handempty, clear(X), ontable(X)],
        [del(handempty), del(clear(X)), del(ontable(X)),
                 add(holding(X))]).

move(putdown(X), [holding(X)],
        [del(holding(X)), add(ontable(X)), add(clear(X)),
                  add(handempty)]).

move(stack(X, Y), [holding(X), clear(Y)],
        [del(holding(X)), del(clear(Y)), add(handempty), add(on(X, Y)),
                  add(clear(X))]).

move(goroom1, [handempty], []).
move(goroom1, [holding(X)], []).

move(goroom2, [handempty], []).
move(goroom2, [holding(X)], []).

/* run commands */

go(S, G) :- plan(S, G, [S], []).

test :- go([handempty, ontable(b), ontable(c), on(a, b), clear(c), clear(a)],
              [handempty, ontable(c), on(a,b), on(b, c), clear(a)]).

test2 :- go([handempty, ontable(b), ontable(c), on(a, b), clear(c), clear(a)],
              [handempty, ontable(a), ontable(b), on(c, b), clear(a), clear(c)]).

Solution

  • So I solved it by using flags basically. So for each move predicate I basically add a room1 and room2 flag. If they are true then it does the action. So for example ontable(X) in room1 then del ontable and add holding(X) in room1. I also add two predicates to move between rooms. The biggest hurdle was moving from procedural logic to state logic. So if handempty is in room1 then it can only move to room2! @CapelliC thank you for the advice