3
votes

So, I am developing a game with Unity3D, and I'm using Prolog for IA planning. My problem is very similar to the monkey and banana problem, but I'm having problems on asserting a new initial state.

By changing the initial state, my character would be able to plan again his actions whenever something important on the environment changed.

But let's get back to my problem:

I'm passing a string to prolog, via socket, and I want to build a list of facts. Then, I'd like to use these facts as the initial state for my planning procedure.

I'm able to write the socket's input stream on the SWI terminal by transforming the byte array into a list of chars. I am also able to get a string back from the prolog server, by writing something on the output stream. But I don't know how I am supposed to turn those characters/string into a list of facts.

Also, I'd like to use that list of facts as an initial state, by passing it to the planning procedure like I would pass an argument to a function in an imperative programming language (if that were the case).

What I'd like to do is something like this (pseudocode):

% on the prolog server, we have a main function
% we get a bytestream (In), 
% turn it into a list of facts
% use it as the initial state
% and write Plan to the output stream (Out).

loopback(In, Out) :-    
    \+at_end_of_stream(In),     
    read_pending_input(In, Codes, []),              
    atom_codes(AtomList, Codes),       %bytes into a list of atoms
    toFacts(Init, AtomList),           %??? Init = AtomList to list of facts
    test(Init, Plan),                  %pass Init as the initial state
    format(Out, '~s', Plan),            %Get the plan back and write to the output
    flush_output(Out),
    loopback(In, Out).

% Init should look like this - a mere list of facts:
Init = [on(monkey, floor),
        on(box, floor),
        at(monkey, a),
        at(box, b),
        at(bananas, c),
        status(bananas, hanging)].

% The planning predicate - Init as an argument, Plan is the result
test(Init, Plan):- 
    write('Initial state:'),nl, 
    write_sol(Init),
    Goal = [status(bananas, grabbed)],
    nl,write('Goal state:'),nl,
    write(Goal),nl,
        solve(Init,Goal,Plan).

I am really stuck right now, I hope someone can help me. Thank you!

References:

Full monkey banana problem code.

SWI socket server code example.

2

2 Answers

2
votes

You have many choices: the simplest seems to be read_from_codes

test :-  
  S = "[on(monkey, floor),
        on(box, floor),
        at(monkey, a),
        at(box, b),
        at(bananas, c),
        status(bananas, hanging)].",
  read_from_codes(S, T),
  writeln(T).

results in

?- test.
[on(monkey,floor),on(box,floor),at(monkey,a),at(box,b),at(bananas,c),status(bananas,hanging)]
true.

But the exchange of structured data could be easier using a devoted protocol like JSON. I used it just via AJAX/jQuery. Maybe overkill for your use case...

1
votes

In http://tinycog.sourceforge.net/ we are using the SWI-Prolog HTTP server and Unity3D HTTP calls to build an interface using JSON libraries on both end for encoding of complex terms etc. Actually a small C# script on the Unity3D side just sends the position of all GameObjects to an SWI-Server and receives a list of commands that to be executed on the Unity3D level including "goto", "grab" and "fire". The SWI-Prolog code is in the GIT repository, the Unity3D code in C# is part of the client ZIP in the project files.