This Problem does not exist in every game, only in the more complex ones, but i will try to shorten the problem as good as possible. The gamedescription is written in gdl and is parsed within prolog into prolog clauses. (gdl file attached) My call looks now like this: getunboundmove(Player,Move,Term,State),bagof(Effect,(d_next(Effect,[does(Player,Move)]-State)),Effects). Player=the Player that can do this move, or Var if all player can do this move Move=the move Term=conditions not depending on the current state (game situation) State=conditions depending on the current state -> if the state contains the given clauses, the move is legal (doable) Effects=the changes to the state that will happen when the player does this move for my example, this is: Player = bomberman Move = move(north) Term = [d_role(bomberman, _751), 'd_++'(_797, _872, _751), d_cell(_796, _872, _751)] State = [location(bomberman, 1, 1), \+ blockednorth(_796, _797)] Effects = [location(bomberman, 1, 2)] And now the relevant d_next rule(s) in gdl: ( (<= A) B) means A implies B, all gdl predicates are rewritten in prolog with d_ .. so true = d_true (<= (next (location ?char ?x2 ?y2)) - the effect (role ?char) - char is a rolename (true (location ?char ?x1 ?y1)) - char is at location x1/y1 in the current state (does ?char (move ?dir)) - char does the (move ?dir) move (nextcell ?dir ?x1 ?y1 ?x2 ?y2)) - predicate call (<= (nextcell north ?x ?y ?x ?ynew) (index ?x) (++ ?y ?ynew)) Given Facts (besides others) : (index 1) (++ 1 2) if i only call getunboundmove(Player,Move,Term,State), the solution is: Player = Player Move = move(north) Term = [d_role(Player, _219), 'd_++'(_265, _340, _219), d_cell(_264, _340, _219)] - Read as: role Player exists | _340 is _264 + 1 | cell x=_263,y=_340 exists (the last var is State=_219, but these facts are state independent) State = [location(_73, _264, _265), \+ blockednorth(_264, _265)] - Player _73 is in position _264/_265 (Here _73 should be Player, but thats not importent) | the north of position _264/_265 is not blocked and for effect, i want to get: Effects=[location(Player,_264,_340)] It is essential, that the variable numbers are staying correct, because i need to map the effects to the relevant State/Term conditions I also attached the code if someone is interested. gorgon_player is the main module and with setgame("The gdl file content") u can set the game. The solution i mentioned here is the 5th solution to the given call I know it's alot of stuff written here, but i have essential problems here, would be happy to see some help best regards Wit Jakuczun schrieb: > 2010/2/8 Christian Wirth <tyrion_at_geek-squad.de>: > >> i have a complex problem, i dont even have a clue how to start solving it >> >> .. hopefully i can explain it somehow understandable. I have terms >> describing states of games. those are not grounded. >> The terms are like this: >> State = [location(_73, _264, _265), blockednorth(_264, _265)] >> now i want to determine all possible effects in this state with a given >> move. This can be done by this call: >> d_next(Effect,[does(Player,Move)]-State), but d_next is dynamic compiled >> out of the game description. >> .. to get all possible effects, i use >> findall(Effect,(d_next(Effect,[does(Player,Move)]-State)),Effects) (or >> bagof) >> >> .. but now i have the variables bound, and the state looks like this: >> State = [location(bomberman, 1, 1), blockednorth(_491, _492)] >> That should not happen ! >> >> > Why? > > You could first copy State term (using copy_term predicate) and use > a copy in findall. > > >> The only additional thing i know, that helps is this: >> If a condition is true in a given state is checked by >> >> :- mode d_true(?, +). >> d_true(F,_-Z) :- >> member(F,Z). >> >> > What is a connection between d_true/2 and d_next/2 predicates? What is > F in d_next > predicate? > > >> my current ideas are >> >> a) get a list of all grounded facts and remove them for befor calling >> the predicate. Was not able to do this, because i dont know how to get >> the lis >> >> > Where are facts stored? What do you mean by removing them? > > I do not see what is the algorithm. How are predicates called and what they do? > Maybe providing us with a simple example would be a good idea? > > >> .. i know this mailing list is not exactly the right place, but here i >> got the best answers to prolog problems till now .... >> >> > You can try comp.lang.prolog too. > > Best regards > ; bomberman2p (role bomberman) (role bomberwoman) (init (location bomberman 1 1)) (init (location bomberwoman 8 8)) (init (blockednorth 2 1)) (init (blockednorth 4 1)) (init (blockednorth 5 1)) (init (blockednorth 7 1)) (init (blockednorth 2 2)) (init (blockednorth 4 2)) (init (blockednorth 5 2)) (init (blockednorth 7 2)) (init (blockednorth 2 3)) (init (blockednorth 4 3)) (init (blockednorth 5 3)) (init (blockednorth 7 3)) (init (blockednorth 2 5)) (init (blockednorth 4 5)) (init (blockednorth 5 5)) (init (blockednorth 7 5)) (init (blockednorth 2 6)) (init (blockednorth 4 6)) (init (blockednorth 5 6)) (init (blockednorth 7 6)) (init (blockednorth 2 7)) (init (blockednorth 4 7)) (init (blockednorth 5 7)) (init (blockednorth 7 7)) (init (blockednorth 1 8)) (init (blockednorth 2 8)) (init (blockednorth 3 8)) (init (blockednorth 4 8)) (init (blockednorth 5 8)) (init (blockednorth 6 8)) (init (blockednorth 7 8)) (init (blockednorth 8 8)) (init (blockedeast 1 2)) (init (blockedeast 1 4)) (init (blockedeast 1 5)) (init (blockedeast 1 7)) (init (blockedeast 2 2)) (init (blockedeast 2 4)) (init (blockedeast 2 5)) (init (blockedeast 2 7)) (init (blockedeast 3 2)) (init (blockedeast 3 4)) (init (blockedeast 3 5)) (init (blockedeast 3 7)) (init (blockedeast 5 2)) (init (blockedeast 5 4)) (init (blockedeast 5 5)) (init (blockedeast 5 7)) (init (blockedeast 6 2)) (init (blockedeast 6 4)) (init (blockedeast 6 5)) (init (blockedeast 6 7)) (init (blockedeast 7 2)) (init (blockedeast 7 4)) (init (blockedeast 7 5)) (init (blockedeast 7 7)) (init (blockedeast 8 1)) (init (blockedeast 8 2)) (init (blockedeast 8 3)) (init (blockedeast 8 4)) (init (blockedeast 8 5)) (init (blockedeast 8 6)) (init (blockedeast 8 7)) (init (blockedeast 8 8)) (init (step 1)) (<= (legal ?char (move ?dir)) (role ?char) (true (location ?char ?x ?y)) (legalstep ?dir ?x ?y)) (<= (legal ?char dropbomb) (role ?char)) (<= (next (blockednorth ?x ?y)) (true (blockednorth ?x ?y))) (<= (next (blockedeast ?x ?y)) (true (blockedeast ?x ?y))) (<= (next (location ?char ?x2 ?y2)) (role ?char) (true (location ?char ?x1 ?y1)) (does ?char (move ?dir)) (nextcell ?dir ?x1 ?y1 ?x2 ?y2)) (<= (next (location ?char ?x ?y)) (role ?char) (true (location ?char ?x ?y)) (does ?char dropbomb)) (<= (next (location bomb3 ?x ?y)) (role ?char) (true (location ?char ?x ?y)) (does ?char dropbomb)) (<= (next (location bomb2 ?x ?y)) (true (location bomb3 ?x ?y))) (<= (next (location bomb1 ?x ?y)) (true (location bomb2 ?x ?y))) (<= (next (location bomb0 ?x ?y)) (true (location bomb1 ?x ?y))) (<= (next (location fire ?xf ?y)) (true (location bomb0 ?xb ?y)) (not (true (blockedeast ?xb ?y))) (index ?xf)) (<= (next (location fire ?x ?yf)) (true (location bomb0 ?x ?yb)) (not (true (blockednorth ?x ?yb))) (index ?yf)) (<= (next (step ?n++)) (true (step ?n)) (succ ?n ?n++)) (<= terminal bombermanburned) (<= terminal bomberwomanburned) (<= terminal timeout) (<= (goal bomberman 0) (not timeout) (not bombermanburned) (not bomberwomanburned)) (<= (goal bomberman 0) bombermanburned (not bomberwomanburned)) (<= (goal bomberman 50) bombermanburned bomberwomanburned) (<= (goal bomberman 50) timeout (not bombermanburned) (not bomberwomanburned)) (<= (goal bomberman 100) (not bombermanburned) bomberwomanburned) (<= (goal bomberwoman 0) (not timeout) (not bombermanburned) (not bomberwomanburned)) (<= (goal bomberwoman 0) (not bombermanburned) bomberwomanburned) (<= (goal bomberwoman 50) bombermanburned bomberwomanburned) (<= (goal bomberwoman 50) timeout (not bombermanburned) (not bomberwomanburned)) (<= (goal bomberwoman 100) bombermanburned (not bomberwomanburned)) (<= (legalstep north ?x ?y) (++ ?y ?ynew) (cell ?x ?ynew) (not (blocked ?x ?y ?x ?ynew))) (<= (legalstep south ?x ?y) (-- ?y ?ynew) (cell ?x ?ynew) (not (blocked ?x ?y ?x ?ynew))) (<= (legalstep east ?x ?y) (++ ?x ?xnew) (cell ?xnew ?y) (not (blocked ?x ?y ?xnew ?y))) (<= (legalstep west ?x ?y) (-- ?x ?xnew) (cell ?xnew ?y) (not (blocked ?x ?y ?xnew ?y))) (<= (legalstep nowhere ?x ?y) (cell ?x ?y)) (<= (nextcell north ?x ?y ?x ?ynew) (index ?x) (++ ?y ?ynew)) (<= (nextcell south ?x ?y ?x ?ynew) (index ?x) (-- ?y ?ynew)) (<= (nextcell east ?x ?y ?xnew ?y) (index ?y) (++ ?x ?xnew)) (<= (nextcell west ?x ?y ?xnew ?y) (index ?y) (-- ?x ?xnew)) (<= (nextcell nowhere ?x ?y ?x ?y) (cell ?x ?y)) (<= (blocked ?x ?y1 ?x ?y2) (true (blockednorth ?x ?y1)) (++ ?y1 ?y2)) (<= (blocked ?x ?y2 ?x ?y1) (true (blockednorth ?x ?y1)) (++ ?y1 ?y2)) (<= (blocked ?x1 ?y ?x2 ?y) (true (blockedeast ?x1 ?y)) (++ ?x1 ?x2)) (<= (blocked ?x2 ?y ?x1 ?y) (true (blockedeast ?x1 ?y)) (++ ?x1 ?x2)) (<= (distinctcell ?x1 ?y1 ?x2 ?y2) (cell ?x1 ?y1) (cell ?x2 ?y2) (distinct ?x1 ?x2)) (<= (distinctcell ?x1 ?y1 ?x2 ?y2) (cell ?x1 ?y1) (cell ?x2 ?y2) (distinct ?y1 ?y2)) (<= bombermanburned (true (location bomberman ?x ?y)) (true (location fire ?x ?y))) (<= bomberwomanburned (true (location bomberwoman ?x ?y)) (true (location fire ?x ?y))) (<= timeout (true (step 50))) (index 1) (index 2) (index 3) (index 4) (index 5) (index 6) (index 7) (index 8) (cell 1 8) (cell 2 8) (cell 3 8) (cell 4 8) (cell 5 8) (cell 6 8) (cell 7 8) (cell 8 8) (cell 1 7) (cell 2 7) (cell 3 7) (cell 4 7) (cell 5 7) (cell 6 7) (cell 7 7) (cell 8 7) (cell 1 6) (cell 2 6) (cell 3 6) (cell 4 6) (cell 5 6) (cell 6 6) (cell 7 6) (cell 8 6) (cell 1 5) (cell 2 5) (cell 3 5) (cell 4 5) (cell 5 5) (cell 6 5) (cell 7 5) (cell 8 5) (cell 1 4) (cell 2 4) (cell 3 4) (cell 4 4) (cell 5 4) (cell 6 4) (cell 7 4) (cell 8 4) (cell 1 3) (cell 2 3) (cell 3 3) (cell 4 3) (cell 5 3) (cell 6 3) (cell 7 3) (cell 8 3) (cell 1 2) (cell 2 2) (cell 3 2) (cell 4 2) (cell 5 2) (cell 6 2) (cell 7 2) (cell 8 2) (cell 1 1) (cell 2 1) (cell 3 1) (cell 4 1) (cell 5 1) (cell 6 1) (cell 7 1) (cell 8 1) (++ 1 2) (++ 2 3) (++ 3 4) (++ 4 5) (++ 5 6) (++ 6 7) (++ 7 8) (-- 8 7) (-- 7 6) (-- 6 5) (-- 5 4) (-- 4 3) (-- 3 2) (-- 2 1) (succ 1 2) (succ 2 3) (succ 3 4) (succ 4 5) (succ 5 6) (succ 6 7) (succ 7 8) (succ 8 9) (succ 9 10) (succ 10 11) (succ 11 12) (succ 12 13) (succ 13 14) (succ 14 15) (succ 15 16) (succ 16 17) (succ 17 18) (succ 18 19) (succ 19 20) (succ 20 21) (succ 21 22) (succ 22 23) (succ 23 24) (succ 24 25) (succ 25 26) (succ 26 27) (succ 27 28) (succ 28 29) (succ 29 30) (succ 30 31) (succ 31 32) (succ 32 33) (succ 33 34) (succ 34 35) (succ 35 36) (succ 36 37) (succ 37 38) (succ 38 39) (succ 39 40) (succ 40 41) (succ 41 42) (succ 42 43) (succ 43 44) (succ 44 45) (succ 45 46) (succ 46 47) (succ 47 48) (succ 48 49) (succ 49 50) :- module(cnfresolver). :- export cnf/2, expand/2. :- use_module(game_description_interface). cnf(X,Z) :- expand(X,Y),negations_inside(Y,Y2),conjunctive_normal_form(Y2,Z). % expands the given predicate, the last argument (1) defines how deep recursions are resolved. expand(X,Y) :- expand(X,Y,1). %expand(d_true(X,Y),X,D) :- !. expand(d_true(X,Y),d_true(X,Y),D) :- !. expand((X1;Y1),(X2;Y2),D) :- expand(X1,X2,D), expand(Y1,Y2,D).% expand((X1,Y1),(X2,Y2),D) :- expand(X1,X2,D), expand(Y1,Y2,D).% expand(\+(X1),\+(X2),D) :- expand(X1,X2,D).% expand(X,X,D) :- not(booleanfunc(X)),not(resolvPred(X,C)),C=true,!. expand(X,Y,D) :- resolvPred(X,C),(D>=0,((is_recursive(X),D2 is D-1,expand(C,Y,D2));(not(is_recursive(X)),expand(C,Y,D)))). resolvPred(X,C) :- functor(X,F,A),is_gamedynamic(F/A),gameclause(X,C),C\=true. %source: Simply Logic, Author: Peter Flach negations_inside(A,A) :- not(booleanfunc(A)). negations_inside(\+((A,B)), (C;D)):- negations_inside(\+(A),C),negations_inside(\+(B),D). negations_inside(\+((A;B)), (C,D)):- negations_inside(\+(A),C), negations_inside(\+(B),D). negations_inside(\+(\+(A)),B) :- negations_inside(A,B). negations_inside((A,B), (C,D)):- negations_inside(A,C), negations_inside(B,D). negations_inside((A;B), (C;D)):- negations_inside(A,C), negations_inside(B,D). conjunctive_normal_form(A,A):- disjunction_of_literals(A),!. conjunctive_normal_form(((A,B);C),(D,E)):- !,conjunctive_normal_form((A;C),D),conjunctive_normal_form((B;C),E). conjunctive_normal_form((A;(B,C)), (D,E)):- !,conjunctive_normal_form((A;B),D),conjunctive_normal_form((A;C),E). conjunctive_normal_form(((A,B),C),D) :- !,conjunctive_normal_form((A,B,C),D). conjunctive_normal_form((A,B),(C,D)):- conjunctive_normal_form(A,C),conjunctive_normal_form(B,D). conjunctive_normal_form((A;B),E):-conjunctive_normal_form(A,C),conjunctive_normal_form(B,D),conjunctive_normal_form((C;D),E). disjunction_of_literals(A):- not(booleanfunc(A)). disjunction_of_literals((C;D)):- disjunction_of_literals(C), disjunction_of_literals(D). booleanfunc(\+(X)) :- booleanfunc(X),!. booleanfunc((A,B)) :- !. booleanfunc((A;B)) :- !. %true when the clausebody of the Pred contains the predicate itself. Does not resolve new predicates is_recursive(Pred) :- functor(Pred,F,_),gameclause(Pred,Clause),subfunc(F,Clause). subfunc(SubTerm, Term) :- nonvar(Term),functor(Term,SubTerm,_). subfunc(SubTerm, Term) :- nonvar(Term), functor(Term, _, N), subfunc(N, SubTerm, Term). subfunc(N, SubTerm, Term) :- not(ground(Term)), arg(N, Term, Arg), subfunc(SubTerm, Arg). subfunc(N, SubTerm, Term) :- N > 1, M is N-1, subfunc(M, SubTerm, Term). % Copyright (C) 2008 Stephan Schiffel <stephan.schiffel_at_gmx.de> :- module(game_description_interface, [ % interface to gdl games % game stuff d_goal/3, d_legal/3, d_terminal/1, d_role/2, d_next/2, d_init/2, d_does/3, d_true/2, gameclause/2, is_gamedynamic/1, % loading the rules of the game, and/or overriding the rules with better ones compile_new_rules_from_file/1, compile_new_rules/1 ], eclipse_language). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% :- mode compile_new_rules_from_file(++). compile_new_rules_from_file(Filename) :- compile(Filename). :- mode compile_new_rules(+). compile_new_rules(Clauses) :- make_dynamic(Clauses), expand_goal(Clauses, Clauses1), % make sure we don't get interrupted during compiling (we could end up in some inconsistent state if we have only half of the clauses) (events_defer -> (compile_term(Clauses1) -> events_nodefer ; events_nodefer, fail) ; compile_term(Clauses1) ). make_dynamic(List1) :- (foreach(Clause,List1), foreach(key(Name,Arity)-Clause,KeyList1) do (Clause= (:- _) -> Name=0, Arity=0 % 0 is a number and comes before every atom according to @</2 ; (Clause=(Head:-_) -> true ; Clause=Head), functor(Head,Name,Arity), export(Name/Arity), dynamic(Name/Arity) ) ). :- dynamic(d_goal/3), % gameknowledge is dynamic for clause handling dynamic(d_role/2), dynamic(d_init/2), dynamic(d_next/2), dynamic(d_legal/3), dynamic(d_terminal/1). :- mode d_does(?, ?, ++). d_does(R,A,Moves-_Z) :- member(does(R,A),Moves). % mymember(Moves,does(R,A)). :- mode d_true(?, +). d_true(F,_-Z) :- member(F,Z),nonmember(\+(F),Z). % mymember(Z,F). mymember([A|B],C) :- A\=C,mymember(B,C). mymember([C|B],C) :- !. mymember([],C) :- false. gameclause(Pred,Clause) :- clause(Pred,Clause). is_gamedynamic(Pred) :- is_dynamic(Pred). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % the following will be overwritten by created stuff :- mode d_role(?, ++). d_role(_, _) :- fail. :- mode d_init(?, ++). d_init(_, _) :- fail. :- mode d_next(?, ++). d_next(_, _) :- fail. :- mode d_legal(?, ?, ++). d_legal(_, _, _) :- fail. :- mode d_goal(?, ?, ++). d_goal(_,_, _) :- fail. :- mode d_terminal(++). d_terminal(_) :- fail. % Copyright (C) 2008 Stephan Schiffel <stephan.schiffel_at_gmx.de> % Modified by 2010 Christian Wirth :- module(gdl_parser). :- export(parse_gdl_description_string/2). :- export(parse_gdl_message_string/2). :- export(parse_gdl_term_string/2). :- export(translate_to_sexpr_string/2). :- mode parse_gdl_description_string(+,-). parse_gdl_description_string(String,Axioms) :- parse_string(String, gdl_knowledge_base(Axioms)). :- mode parse_gdl_message_string(+,-). parse_gdl_message_string(String,Message) :- parse_string(String, gdl_message(Message)). :- mode parse_gdl_term_string(+,-). parse_gdl_term_string(String,Term) :- parse_string(String, gdl_term(Term)). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % :- lib(var_name). :- lib(hash). :- local reference(variables). :- mode parse_string(+,?). parse_string(String, GDL_Part) :- string_list(String, List), hash_create(Variables), setval(variables,Variables), phrase(GDL_Part, List, Remainder), (Remainder=[] -> true ; string_list(RemainderString, Remainder), printf("gdl parse error before: \"%w\"\n", [RemainderString]), fail ). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% rename_predicate(Pred,State,Pred2) :- Pred=..[PName|Args], append(Args, [State], Args2), concat_atoms(d_,PName,PName2), Pred2=..[PName2|Args2]. %length(Args2,N), %dynamic(PName2/N). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %gdl_upper(C) --> [C], {uppercasechar(C), !}. uppercasechar(C) :- C>=65, C=<90. % C>="A" , C=<"Z" %gdl_lower(C) --> [C], {lowercasechar(C), !}. lowercasechar(C) :- C>=97, C=<122. % C>="a" , C=<"z" gdl_digit(C) --> [C], {digit(C), !}. digit(C) :- C>=48, C=<57. % C>="0" , C=<"9" %gdl_alpha(C) --> [C], {alpha(C), !}. alpha(33). % "!" alpha(36). % "$" alpha(37). % "%" alpha(38). % "&" alpha(42). % "*" alpha(43). % "+" alpha(45). % "-" alpha(46). % "." alpha(47). % "/" alpha(60). % "<" alpha(61). % "=" alpha(62). % ">" alpha(63). % "?" alpha(64). % "@" alpha(95). % "_" alpha(126). % "~" % gdl_special --> ["\""]; ["#"]; ["'"]; ["("]; [")"]; [","]; ["\\"]; ["^"]; ["`"]. gdl_left_parens --> [40]. % "(" gdl_right_parens --> [41]. % ")" % gdl_backslash(92) --> [92]. % "\" gdl_hashmark --> [35]. % "#" gdl_newline --> [10]. % "\n" % gdl_quotationmark(34) --> [34]. % """ gdl_questionmark --> [63]. % "?" gdl_pipe --> [124]. % "|" gdl_white --> [59] /* ";" */, !, all_to_end_of_line. % single line comment gdl_white --> gdl_hashmark, gdl_pipe, !, all_to_end_of_comment. % multi line comment gdl_white --> [C], {whitespace(C), !}. % normal whitespace whitespace(32). % " " whitespace(9). % "\t" whitespace(13). % "\r" whitespace(10). % "\n" whitespace(12). % "\f" end_of_file([],[]). all_to_end_of_line --> gdl_newline, !. % "\n" all_to_end_of_line --> end_of_file, !. % EOF all_to_end_of_line --> [_], all_to_end_of_line. all_to_end_of_comment --> gdl_pipe, gdl_hashmark, !. all_to_end_of_comment --> [_], all_to_end_of_comment. gdl_white_plus --> gdl_white, !, gdl_white_star. gdl_white_star --> gdl_white, !, gdl_white_star. gdl_white_star --> []. %gdl_normal(C) --> gdl_upper(C),! ; gdl_lower(C),! ; gdl_digit(C),! ; gdl_alpha(C),!. gdl_normal(C) --> [C], {(uppercasechar(C); lowercasechar(C); digit(C); alpha(C)),!}. % % quotedchar ::= \character % gdl_quotedchar([C1,C2]) --> gdl_backslash(C1), [C2]. % word ::= normal | word normal | word\character gdl_word(String) --> gdl_normal(C1), gdl_word2(CList), {string_list(String, [C1|CList])}. gdl_word2(List) --> gdl_word2_nonempty(List), !. gdl_word2([]) --> []. gdl_word2_nonempty([C|List]) --> gdl_normal(C), !, gdl_word2(List). % gdl_word2_nonempty(List2) --> gdl_quotedchar(Cs), !, gdl_word2(List), {append(Cs,List,List2)}. % % charref ::= #\character % gdl_charref(String) --> gdl_hashmark(C), gdl_quotedchar(Cs), {string_list(String,[C|Cs])}. % % string ::= "quotable" % gdl_string(String) --> gdl_quotationmark(C), gdl_quotable(CList), gdl_quotationmark(C), {append([C|CList],[C],List), string_list(String,List)}. % % % quotable ::= empty | quotable strchar | quotable\character % gdl_quotable(List2) --> gdl_quotedchar(Cs), !, gdl_quotable(List), {append(Cs,List,List2)}. % gdl_quotable([C|List]) --> gdl_strchar(C), !, gdl_quotable(List). % gdl_quotable([]) --> []. % % % strchar ::= character - {",\} % gdl_strchar(C) --> [C], {C\=34, C\=92}. % variable ::= indvar | seqvar % gdl_variable(Var) --> gdl_indvar(Var). % indvar ::= ?word gdl_indvar(Var) --> gdl_questionmark, gdl_word(VarName), { getval(variables,Variables), (hash_get(Variables, VarName, Var) -> true ; hash_set(Variables, VarName, Var) % ,first_char_to_upper(VarName,UppercaseVarName), set_var_name(Var,UppercaseVarName) ) }. % seqvar ::= @word % there are no sequence variables in gdl first_char_to_upper(StringLower,StringUpper) :- string_list(StringLower,[CLower|List]), char_to_upper(CLower,CUpper), string_list(StringUpper,[CUpper|List]). char_to_upper(CLower,CUpper) :- lowercasechar(CLower) -> CUpper is CLower-32 ; CUpper=CLower. % operator ::= termop | sentop | defop gdl_operator(String) --> gdl_sentop(String). % others are not valid gdl % termop ::= value | listof | quote | if % defop ::= defobject | defunction | defrelation | deflogical | := | :-> | :<= | :=> % sentop ::= holds | = | /= | not | and | or | => | <= | <=> | forall | exists gdl_sentop(String) --> (gdl_not(String); gdl_and(String); gdl_or(String); gdl_inv_impl(String)), !. % others are not valid gdl gdl_not("not") --> [110,111,116], gdl_word2(W), {W=[]}. % ="not" gdl_and("and") --> [97,110,100], gdl_word2(W), {W=[]}. % ="and" gdl_or("or") --> [111,114], gdl_word2(W), {W=[]}. % ="or" gdl_inv_impl("<=") --> [60,61], gdl_word2(W), {W=[]}. % ="<=" % constant ::= word - variable - operator gdl_constant(Atom) --> gdl_constant2(CList), {string_list(String,CList), atom_string(Atom,String)}. % the next clause can be safely ignored if we don't want to check the description for correctness % gdl_constant2([String|List]) --> gdl_operator(String), !, gdl_word2_nonempty(List). gdl_constant2([C|List]) --> gdl_normal(C), {C\=63}, gdl_word2(List). % C\="?" % term ::= indvar | constant | charref | string | block | funterm | listterm | quoterm | logterm gdl_term(Term) --> gdl_indvar(Term) ; gdl_funterm(Term) ; gdl_constant_term(Term). % others are not valid gdl % gdl_term_star_right_parens ::= term* ) gdl_term_star_right_parens(Terms) --> gdl_white_star, gdl_term_star_right_parens2(Terms). gdl_term_star_right_parens2([]) --> gdl_right_parens, !. gdl_term_star_right_parens2([Term|Terms]) --> gdl_term(Term), gdl_term_star_right_parens(Terms). gdl_term_list([]) --> [110,105,108]. % ="nil" gdl_term_list(Terms) --> gdl_left_parens, gdl_term_star_right_parens(Terms). % funterm ::= (constant term* [seqvar]) % funterm ::= (value term term* [seqvar]) % only the first form and without seqvar is valid gdl gdl_funterm(Function) --> gdl_left_parens, gdl_white_star, gdl_constant(Atom), gdl_term_star_right_parens(Terms), {Function=..[Atom|Terms]}. % listterm ::= (listof term* [seqvar]) % quoterm ::= (quote listexpr) | 'listexpr % listexpr ::= atom | (listexpr*) % atom ::= word | charref | string | block % logterm ::= (if logpair+ [term]) % logpair ::= sentence term % logterm ::= (cond logitem*) % logitem ::= (sentence term) gdl_constant_term(Term) --> gdl_integer(Term), ! ; gdl_constant(Term). % sentence ::= constant | equation | inequality | relsent | logsent | quantsent %gdl_sentence(Sentence) --> gdl_logsent(Sentence) ; gdl_relsent(Sentence) ; gdl_constant(Sentence). % others are not valid gdl gdl_sentence(Sentence, State) --> gdl_left_parens, !, gdl_white_star, gdl_complex_sentence_right_parens(Sentence, State). gdl_sentence(Atom, State) --> gdl_relation_constant(Atom, State). gdl_complex_sentence_right_parens(Sentence, State) --> gdl_logsent2_right_parens(Sentence, State), !. gdl_complex_sentence_right_parens(Sentence, State) --> gdl_relsent2_right_parens(Sentence, State), !. gdl_sentence_star_right_parens(Sentences, State) --> gdl_white_star, gdl_sentence_star_right_parens2(Sentences, State). gdl_sentence_star_right_parens2([], _State) --> gdl_right_parens, !. gdl_sentence_star_right_parens2([Sentence|Sentences], State) --> gdl_sentence(Sentence, State), !, gdl_sentence_star_right_parens(Sentences, State). % equation ::= (= term term) % inequality ::= (/= term term) % relsent ::= (constant term* [seqvar]) % relsent ::= (holds term term* [seqvar]) % only the first without seqvar is gdl gdl_relsent(Relation, State) --> gdl_left_parens, gdl_white_star, gdl_relsent2_right_parens(Relation, State). gdl_relsent2_right_parens(Relation, State) --> gdl_constant(Atom), gdl_term_star_right_parens(Terms), { (Atom=distinct -> Relation=..['\\='|Terms] ; Relation1=..[Atom|Terms], rename_predicate(Relation1, State, Relation) ) }. % logsent ::= (not sentence) | (and sentence*) | (or sentence*) | (=> sentence* sentence) | (<= sentence sentence*) | (<=> sentence sentence) % only "not", "and" and "or" can occur in the body of a valid gdl rule gdl_logsent(Sentence, State) --> gdl_left_parens, gdl_white_star, gdl_logsent2_right_parens(Sentence, State). gdl_logsent2_right_parens(\+(Sentence), State) --> gdl_not(_), !, gdl_white_star, gdl_sentence(Sentence, State), gdl_white_star, gdl_right_parens. gdl_logsent2_right_parens(And, State) --> gdl_and(_), !, gdl_sentence_star_right_parens(Sentences, State), {list_to_and(Sentences, And)}. gdl_logsent2_right_parens(Or, State) --> gdl_or(_), !, gdl_sentence_star_right_parens(Sentences, State), {list_to_or(Sentences, Or)}. gdl_rule(Rule) --> gdl_left_parens, !, gdl_white_star, gdl_rule_right_parens(Rule, _State). gdl_rule(Rule) --> gdl_relation_constant(Atom, _State), { Rule=(Atom:-true) }. gdl_rule_right_parens(Rule, State) --> gdl_inv_impl(_), !, gdl_white_star, gdl_rule_head(Head, State), gdl_sentence_star_right_parens(Sentences, State), {(Sentences=[] -> Rule=(Head:-true) ; list_to_and(Sentences, And), Rule=(Head:-And))}. gdl_rule_right_parens(Rule, State) --> gdl_relsent2_right_parens(Relation, State), {Rule=(Relation:-true)}. gdl_rule_head(Head, State) --> gdl_relsent(Head, State), !. gdl_rule_head(Head, State) --> gdl_relation_constant(Head, State). gdl_relation_constant(Relation, State) --> gdl_constant(Atom), { rename_predicate(Atom, State, Relation) }. % transform lists to prolog conjunctions or disjunctions list_to_and([],true). list_to_and([X],X) :- !. list_to_and([X|List],(X,And)) :- list_to_and(List,And). list_to_or([],fail). list_to_or([X],X) :- !. list_to_or([X|List],(X;Or)) :- list_to_or(List,Or). gdl_integer_string_list_nonempty([C|List]) --> gdl_digit(C), !, gdl_integer_string_list(List). gdl_integer_string_list([C|List]) --> gdl_digit(C), !, gdl_integer_string_list(List). gdl_integer_string_list([]) --> []. gdl_integer_string(S) --> gdl_integer_string_list_nonempty(CList), {string_list(S,CList)}. gdl_integer(I) --> gdl_integer_string(S), {number_string(I,S)}. % quantsent ::= (forall (varspec+) sentence) | (exists (varspec+) sentence) % varspec ::= variable | (variable constant) % form ::= sentence | definition % there are no definitions in gdl and only some types sentences are allowed gdl_form(Axiom) --> gdl_rule(Axiom) %, {writeln(parsed_axiom(Axiom))} . gdl_form_star(Axioms) --> gdl_white_star, gdl_form_star2(Axioms). gdl_form_star2([Axiom|Axioms]) --> gdl_form(Axiom), !, gdl_form_star(Axioms). gdl_form_star2([]) --> []. gdl_knowledge_base([Axiom|Axioms]) --> gdl_white_star, gdl_form(Axiom), gdl_form_star(Axioms). gdl_message(Message) --> gdl_white_star, gdl_left_parens, gdl_white_star, gdl_message2(Message), gdl_white_star, gdl_right_parens, gdl_white_star. gdl_message2(start(MatchID, Role, Axioms, StartClock, PlayClock)) --> [115,116,97,114,116], !, gdl_white_plus, % ="start" gdl_constant(MatchID), gdl_white_star, gdl_constant(Role), gdl_white_star, gdl_left_parens, gdl_knowledge_base(Axioms), gdl_right_parens, gdl_white_star, gdl_integer(StartClock), gdl_white_star, gdl_integer(PlayClock). gdl_message2(play(MatchID, Actions)) --> [112,108,97,121], !, gdl_white_plus, % ="play" gdl_constant(MatchID), gdl_white_star, gdl_term_list(Actions). gdl_message2(replay(MatchID, Actions)) --> [114,101,112,108,97,121], !, gdl_white_plus, % ="replay" gdl_constant(MatchID), gdl_white_star, gdl_term_list(Actions). gdl_message2(stop(MatchID, Actions)) --> [115,116,111,112], !, gdl_white_plus, % ="stop" gdl_constant(MatchID), gdl_white_star, gdl_term_list(Actions). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % translate some prolog term to gdl/kif %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% :- mode translate_to_sexpr_string(+,-). % this first clause will probably not be used and is just here in case there is something wrong translate_to_sexpr_string(V,S) :- var(V), !, term_string(V,S1), concat_string(["?",S1],S). translate_to_sexpr_string([],"nil") :- !. translate_to_sexpr_string([E|L],String) :- !, translate_to_sexpr_string_list([E|L],SAs), join_string(SAs," ",SA), concat_string(["(",SA,")"],String). translate_to_sexpr_string(T,String) :- T=..[F,A1|As],!, % not an atom translate_to_sexpr_string_list([F,A1|As],SAs), join_string(SAs," ",SA), concat_string(["(",SA,")"],String). translate_to_sexpr_string(T,S) :- atom(T), !, atom_string(T,S). translate_to_sexpr_string(T,S) :- number(T), !, number_string(T,S). translate_to_sexpr_string(T,S) :- string(T), !, S=T. translate_to_sexpr_string(T,S) :- !, term_string(T,S). % this is unsafe and shouldn't be used (but it shouldn't be called anyway) translate_to_sexpr_string_list([],[]) :- !. translate_to_sexpr_string_list([A|As],[SA|SAs]) :- !, translate_to_sexpr_string(A,SA), translate_to_sexpr_string_list(As,SAs). % Copyright (C) 2009 Christian Wirth :- module(gorgon_player). :- export getAllMoveInfo/3. :- use_module(prolog_reasoner). :- use_module(cnfresolver). :- use_module(game_description_interface). :- lib("../lib_public/listut"). :- lib("../lib_public/lists"). %A Move in cnf getmovelegal(Player,Move,Term) :- gameclause(d_legal(Player,Move,_),Clause),cnf(Clause,Term). %Splits state depentant (d_true) from other facts. Temporary conversion to string to prevent prolog from solving conjunctionlist((A,B),Independent,Dependent) :- conjunctionlist(A,IndependentA,DependentA),conjunctionlist(B,IndependentB,DependentB),union(IndependentA,IndependentB,Independent),union(DependentA,DependentB,Dependent),!. conjunctionlist((A;B),Independent,Dependent) :- conjunctionlist(A,Independent,Dependent). conjunctionlist((A;B),Independent,Dependent) :- conjunctionlist(B,Independent,Dependent),!. conjunctionlist(\+(d_true(Arg,_)),[],[SArg]) :- term_string(\+(Arg),SArg),!. conjunctionlist(d_true(Arg,_),[],[SArg]) :- term_string(Arg,SArg),!. conjunctionlist(Term,[Term],[]). getunboundmove(Player,Move,List,State) :- getmovelegal(Player,Move,Term),conjunctionlist(Term,List,StringState),maplist(term_string,State,StringState). % retrieves all bound variables getBound(Term,[Term],0) :- ground(Term),atomic(Term),!. getBound(Term,[],0) :- !. getBound(Term,List,N) :- arg(N,Term,Arg),(var(Arg) -> N3=0;arity(Arg,N3)),getBound(Arg,List2,N3),N2 is N-1,getBound(Term,List1,N2),union(List1,List2,List). % retrieves all bound variables in all elements of the list of one unbound move getAllBound(List,Bound) :- findall(X,(member(Element,List),arity(Element,Arity),getBound(Element,X,Arity)),Result),flatten(Result,Bound). %determines all effects of a Move. The term is the cnf term of the move "legal" condition. The returned array is [Player,Move,Effects,Term,State]. getmoveinfo(Array,BoundVarState,BoundVarTerm) :- getunboundmove(Player,Move,Term,State),getAllBound(State,BoundVarState),getAllBound(Term,BoundVarTerm),bagof(Effect,(d_next(Effect,[does(Player,Move)]-State)),Effects),Array=[Player,Move,Effects,Term,State]. % retrieves all bound variables in alle elements of all moves, Move=[Move,Effects,Term,State],BVSL=Bound Variables from State,BVTL = Bound Variables from Term. getAllMoveInfo(Moves,BVSL,BVTL) :- findall(Triple,(getmoveinfo(Array,BVS,BVT),Triple=[Array,BVS,BVT]),Result),findall(Move,(member(Ele,Result),nth0(0,Ele,Move)),Moves),findall(Const,(member(Ele,Result),nth0(1,Ele,NEle),not(free(NEle)),member(Const,NEle)),BVSL1),(length(BVSL1,0);remove_duplicates(BVSL1,BVSL) ),findall(Const,(member(Ele,Result),nth0(2,Ele,NEle),not(free(NEle)),member(Const,NEle)),BVTL1),(length(BVTL1,0);remove_duplicates(BVTL1,BVTL)). remove_duplicates(ListA,ListB) :- setof(E,member(E,ListA),ListB). remove_var_and_roles(ListA,ListB) :- findall(E,getNonvarAndRoles(E,ListA),ListB). getNonvarAndRoles(E,List) :- member(E,List),nonvar(E),not(d_role(E,_)). % Copyright (C) 2008 Stephan Schiffel <stephan.schiffel_at_gmx.de> :- module(prolog_reasoner). :- export parse/2, translate_to_sexpr/2, goal/3, legal_moves/3, state_update/3, terminal/1, setgame/1, init/1, roles/1. :- use_module(gdl_parser). :- use_module(game_description_interface). :- lib(lists). parse(String, Term) :- parse_gdl_term_string(String, Term). translate_to_sexpr(Term, String) :- translate_to_sexpr_string(Term, String). goal(Role, Value, State) :- d_goal(Role, Value, nil-State). legal_moves(Role, Moves, State) :- fast_setof(does(Role, M), d_legal(Role, M, nil-State), Moves). state_update(State, Moves, NextState) :- fast_setof(F, d_next(F, Moves-State), NextState). terminal(State) :- d_terminal(nil-State). setgame(GDLDescriptionString) :- parse_gdl_description_string(GDLDescriptionString, Rules), sort_clauses(Rules, Rules1), compile_new_rules(Rules1). % sort the clauses in a List alphabetically according to the name of the head :- mode sort_clauses(+,-). sort_clauses(List1, List2) :- (foreach(Clause,List1), foreach(key(Name,Arity)-Clause,KeyList1) do (Clause= (:- _) -> Name=0, Arity=0 % 0 is a number and comes before every atom according to @</2 ; (Clause=(Head:-_) -> true ; Clause=Head), functor(Head,Name,Arity) ) ), keysort(KeyList1,KeyList2), (foreach(key(_,_)-Clause,KeyList2), foreach(Clause,List2) do true),!. init(State) :- fast_setof(F, d_init(F, nil-nil), State). roles(Roles) :- findall(R, d_role(R, nil-nil), Roles). fast_setof(X,Expr,Xs) :- findall(X,Expr,Xs1), sort(0,<,Xs1,Xs).Received on Tue Feb 09 2010 - 14:05:00 CET
This archive was generated by hypermail 2.2.0 : Thu Feb 02 2012 - 02:31:58 CET