I’m thinking about how to save/load game state in SWI-Prolog.
Here is the code skeleton of my game:
:- dynamic script_iterator/2. init_iterator(Goal, Iterator) :- reset(Goal,YE,Cont), ( Cont == 0 -> Iterator = done ; YE = yield(Element) -> Iterator = next(Element, Cont) ). next(next(Element,Cont), Element, Iterator) :- init_iterator(Cont, Iterator). yield(Term) :- shift(yield(Term)). wait_frames(0) :- !. wait_frames(N) :- yield(_), N1 is N - 1, wait_frames(N1). %% -- game loop -- game_update(FrameID) :- format("game_update FrameID=~w~n", [FrameID]), forall(script_iterator(Goal, Iterator), ( Iterator \= done -> next(Iterator, _, NewIterator), retract(script_iterator(Goal, Iterator)), assertz(script_iterator(Goal, NewIterator)) ; true ) ). game_init :- load_files('script.pl'), init_iterator(on_game_init, Iterator), assertz(script_iterator(on_game_init, Iterator)). game_fini :- retractall(script_iterator(_,_)), unload_file('script.pl'). main :- game_init, game_update(1), game_update(2), game_update(3), game_update(4), game_update(5), game_update(6), game_update(7), game_update(8), game_fini.
Note that this game is very flexible, it loads another Prolog file
script.pl. Game designers or players can write their own
script.pl to extend game logic.
on_game_init :- writeln("Hello, this game will start in 5 frames"), wait_frames(5), writeln("Game start!") %% ... other logic ... .
Notice that the script supports the “wait N seconds” feature. Here I use frames instead of seconds for simplicity.
A query for first 8 frames:
?- main. Hello, this game will start in 5 frames game_update FrameID=1 game_update FrameID=2 game_update FrameID=3 game_update FrameID=4 game_update FrameID=5 Game start! game_update FrameID=6 game_update FrameID=7 game_update FrameID=8
It works well.
My question is that if the game needs to support SAVE/LOAD, what should I do? For example, at the 3rd frame, the player might click the SAVE button in the menu and exit the game. How do I serialize the continuation state for
I have tried the library(persistency), but it doesn’t work for continuations.
A feasible workaround is to write a Meta-Interpreter, which seems not difficult in Prolog, but what’s the drawbacks of using Meta-Interpreter. Does Meta-Interpreter scale well to other SWI-Prolog features?
Besides Meta-Interpreter, is there any other way to solve this problem? For example, is it possible to run a Prolog program inside a sandbox and the sandbox supports serializing/deserializing?.
Thanks in advance for any advice.