/*****************************************************************************/ /* */ /* Analyse et generation du code des jeux et des agents */ /* */ /*****************************************************************************/ :-module(compil, [ analyser/1, compiler_kb/6 ] ). :-use_module([tools,subst,decls,dialogue,rapport]). /*****************************************************************************/ /* */ /* Initialisation du module */ /* */ /*****************************************************************************/ default_game( default_game = [ entrance = true, invariant = true, exit = false, perception = [], update = [], generation = [], interdiction = [] ] ). default_agent( default_agent = [ % memory = 1000, depth = 3, % redondances = yes, acclist = nobody, % La chaine doit etre limitee kb = [], games = [], start = default_game ] ). init:- empty([game_db,agent_db]), default_game(GAME), recordz(game_db,GAME), default_agent(AGENT), recordz(agent_db,AGENT), forall(user:agents(X,_),empty_module(X)), retractall(user:agents(_,_)). %:-init. /*****************************************************************************/ /* */ /* Analyse du fichier de description des jeux et des agents */ /* */ /*****************************************************************************/ /* Le fichier de description contient des termes (en fait, c'est Prolog qui * fait la plus grosse partie de l'analyse). Il faut ensuite fabriquer la * description complete des jeux et des agents (importations). A la fin de * l'analyse, on a une base de donnees complete des jeux et des agents (c'est * la forme developpee de la description initiale) prete a etre compilee en * clauses Prolog */ /* REMARQUE IMPORTANTE SUR L'IMPORTATION DE REGLES * Lors de l'importation d'un jeu, on utilise la cle complete !!!!! */ analyser(FICHIER):- writef("Analyse du fichier %t\n",[FICHIER]), ( open(FICHIER,read,F) -> scan(F) ; writef("ERREUR : Fichier introuvable (%t)\n",[FICHIER]) ). scan(F):- repeat, read(F,TERM), ( TERM=end_of_file -> true ; traite(TERM), fail ), close(F), writef("\nAnalyse terminee\n"). dot:-writef(".%f"). traite(TERM0):- bracket_to_list(TERM0,TERM), ( TERM=(import FILE) -> analyser(FILE) ; TERM=(game KEY=DESCR) -> build_game(KEY,DESCR) ; TERM=(agent NAME=DESCR) -> build_agent(NAME,DESCR) ; TERM=(BILL and JOHN are speaking) -> make_all(BILL,JOHN) ; error("Impossible de traiter %t\n",[TERM]) ), !. make_all(BILL,JOHN):- compiler_agent(BILL), compiler_agent(JOHN), retractall(user:agents(_,_)), user:assertz(agents(BILL,JOHN)), user:assertz(agents(JOHN,BILL)). /*****************************************************************************/ /* */ /* Description d'un jeu */ /* */ /*****************************************************************************/ build_game(KEY,DESCR):- ( ( recorded(game_db,KEY=_) -> warning("Le jeu %t est deja defini.\n",[KEY]) ; % Construction de la partie importee findall(IMPORTED_RULES, ( ( GAME_NAME=default_game ; member(import GAME_NAME,DESCR) ), chk(recorded(game_db,GAME_NAME=IMPORTED_RULES), "Le jeu %t n'est pas defini.\n",[GAME_NAME]) ), ALL_IMPORTED_RULES ), merge_descr(DESCR,ALL_IMPORTED_RULES,COMPLETE_GAME), recordz(game_db,KEY=COMPLETE_GAME) ) ; error("Impossible de construire le jeu %t.\n",[KEY]) ), dot, !. /*****************************************************************************/ /* */ /* Fusion d'une description et d'une liste de description */ /* */ /*****************************************************************************/ %Il faut traiter le cas ou VAL n'est pas une liste !!!!! merge_descr(DESCR,ATT=VAL,NEW_DESCR):- !, ( member(ATT=OLD_VAL,DESCR,REST) -> ( is_list(VAL) -> append(OLD_VAL,VAL,NEW_VAL), NEW_DESCR=[ATT=NEW_VAL|REST] ; NEW_DESCR=DESCR ) ; NEW_DESCR=[ATT=VAL|DESCR] ). merge_descr(DESCR,[],NEW_DESCR):- !, sublist(not_import,DESCR,NEW_DESCR). merge_descr(DESCR,[DESCR1|REST],NEW_DESCR):- !, merge_descr(DESCR,DESCR1,NEW_DESCR1), merge_descr(NEW_DESCR1,REST,NEW_DESCR). not_import(import _):-!,fail. not_import(_). /* Version fonctionnelle (qui marche pas encore) merge_descr(DESCR,ATT=VAL) <- member(ATT=OLD_VAL,DESCR,REST) -> (is_list(VAL) -> [ATT=(OLD_VAL++VAL)|REST] | DESCR) | [ATT=VAL|DESCR]. merge_descr(DESCR,[]) <- subtract(DESCR,[import _]). merge_descr(DESCR,[DESCR1|REST]) <- merge_descr(merge_descr(DESCR,DESCR1),REST). */ /*****************************************************************************/ /* */ /* Description d'un agent */ /* */ /*****************************************************************************/ build_agent(NAME,DESCR):- ( ( recorded(agent_db,NAME=_) -> warning("L'agent %t est deja defini.\n",[NAME]) ; % Construction de la partie importee findall(IMPORTED_DESCR, ( ( IMPORTED_NAME=default_agent ; member(import IMPORTED_NAME,DESCR) ), chk(recorded(agent_db,IMPORTED_NAME=IMPORTED_DESCR), "L'agent %t n'est pas defini.\n",[IMPORTED_NAME]) ), ALL_IMPORTED_DESCR ), merge_agent_descr(ALL_IMPORTED_DESCR,COMPLETE_IMPORTED_DESCR), sublist(not_import,DESCR,NO_IMPORT), merge_agent_descr( [ COMPLETE_IMPORTED_DESCR, NO_IMPORT ], COMPLETE_DESCR ), make_accointances(COMPLETE_DESCR,DESCR_WITH_ACCOINTANCES), sublist(not_accointance,COMPLETE_DESCR,NO_ACCOINTANCE), merge_agent_descr( [ NO_ACCOINTANCE, DESCR_WITH_ACCOINTANCES ], COMPLETE_DESCR_WITH_ACCOINTANCES ), make_acc_list(append,NAME,COMPLETE_DESCR_WITH_ACCOINTANCES, FINAL_DESCR), recordz(agent_db,NAME=FINAL_DESCR) ) ; error("Impossible de construire l'agent %t\n",[NAME]) ), dot, !. not_accointance(accointance=_):-!,fail. not_accointance(_). make_accointances(DESCR,DESCR_WITH_ACCOINTANCES):- ( ( member(accointance=NAME,DESCR), chk(recorded(agent_db,NAME=NAME_DESCR), "L'agent %t n'est pas defini.\n",[NAME]) ; NAME=nobody, NAME_DESCR=[] ), swap(x,y,NAME_DESCR,DESCRyx), subst( [ 'B'(X,L) >>> BL if (is_list(L), maplist(add_arg('B'(X)),L,BL)), 'B'(X,K=V) >>> K=BV if (is_list(V), maplist(add_arg('B'(X)),V,BV)), 'B'(X,start=G) >>> start = X b G, 'B'(X,K=V) >>> K=V, 'B'(X,(CA|A then B|CB)) >>> ((CA|'B'(X,A)) then ('B'(X,B)|CB)), 'B'(X,(CA|A then B)) >>> ((CA|'B'(X,A)) then ('B'(X,B))), 'B'(X,(A then B|CB)) >>> (('B'(X,A)) then ('B'(X,B)|CB)), 'B'(X,(A then B)) >>> (('B'(X,A)) then ('B'(X,B))), 'B'(X,(CA|A when B|CB)) >>> ((CA|'B'(X,A)) when ('B'(X,B)|CB)), 'B'(X,(CA|A when B)) >>> ((CA|'B'(X,A)) when ('B'(X,B))), 'B'(X,(A when B|CB)) >>> (('B'(X,A)) when ('B'(X,B)|CB)), 'B'(X,(A when B)) >>> (('B'(X,A)) when ('B'(X,B))), 'B'(X,(A->B)) >>> ('B'(X,A)->'B'(X,B)), 'B'(X,(A and B)) >>> ('B'(X,A) and 'B'(X,B)), 'B'(X,(A or B)) >>> ('B'(X,A) or 'B'(X,B)), 'B'(X,-A) >>> -'B'(X,A), 'B'(X,A) >>> (X b A) ], 'B'(x,DESCRyx), BxDESCRyx ), forall( ( member(start=X b GAME,BxDESCRyx) ; member(games=GAME_LIST,BxDESCRyx), member(X b GAME,GAME_LIST) ), make_game_image(X b GAME) ), make_acc_list(replace,NAME,BxDESCRyx,BxDESCRyx_WITH_ACCOINTANCES), subtract(BxDESCRyx_WITH_ACCOINTANCES,[games=_,start=_], DESCR_WITH_ACCOINTANCES) ), !. add_arg(T,A,TA):- T=..[F|ARGS], append(ARGS,[A],ARGSA), TA=..[F|ARGSA]. make_acc_list(REPLACE,NAME,DESCR,NEW_DESCR):- member(acclist=ACCLIST,DESCR,REST), member(start=START,REST), member(depth=DEPTH,REST), member(games=GAMES,REST), ( REPLACE=replace, ACCLIST=(_,OLDLIST) ; OLDLIST=ACCLIST ), !, NEW_DESCR = [acclist=((NAME,START,DEPTH,GAMES),OLDLIST)|REST]. make_acc_list(_,_,_,[acclist=nobody]). make_game_image(X b GAME):- ( recorded(game_db,X b GAME=_) % deja fait, ok ; chk(recorded(game_db,GAME=DESCR), "Le jeu %t n'est pas defini.\n",[GAME]), swap(x,y,DESCR,DESCRyx), subst( [ [generation=_|L] >>> L, [interdiction=_|L] >>> L, 'B'(X,perception=PERCEPTION) >>> perception='BP'(X,PERCEPTION), 'B'(X,L) >>> BL if (is_list(L), maplist(add_arg('B'(X)),L,BL)), 'BP'(X,L) >>> BL if (is_list(L), maplist(add_arg('BP'(X)),L,BL)), 'B'(X,K=V) >>> K=BV if (is_list(V), maplist(add_arg('B'(X)),V,BV)), 'B'(X,K=V) >>> K='B'(X,V), ('B'(X,(P=>Q|C#F))) >>> ('B'(X,P)=>'B'(X,Q)|C#F) if dot, ('B'(X,(P=>Q|C))) >>> ('B'(X,P)=>'B'(X,Q)|C) if dot, ('B'(X,(P=>Q#F))) >>> ('B'(X,P)=>'B'(X,Q)#F) if dot, ('B'(X,(P=>Q))) >>> ('B'(X,P)=>'B'(X,Q)) if dot, ('BP'(X,(P=>Q|C#F))) >>> (P=>'B'(X,Q)|C#F) if dot, ('BP'(X,(P=>Q|C))) >>> (P=>'B'(X,Q)|C) if dot, ('BP'(X,(P=>Q#F))) >>> (P=>'B'(X,Q)#F) if dot, ('BP'(X,(P=>Q))) >>> (P=>'B'(X,Q)) if dot, 'B'(X,(A->B)) >>> ('B'(X,A)->'B'(X,B)), 'B'(X,(A and B)) >>> ('B'(X,A) and 'B'(X,B)), 'B'(X,(A or B)) >>> ('B'(X,A) or 'B'(X,B)), 'B'(X,-A) >>> -'B'(X,A), 'B'(X,A) >>> (X b A) ], 'B'(X,DESCRyx), BxDESCRyx ), recordz(game_db,X b GAME=BxDESCRyx) ), !. /*****************************************************************************/ /* */ /* Fusion de la description de plusieurs agents */ /* */ /*****************************************************************************/ merge_agent_descr(DESCR_LIST,COMPLETE_DESCR):- merge_agents(DESCR_LIST,[],COMPLETE_DESCR). merge_agents([],DESCR,DESCR):-!. merge_agents([DESCR|REST],BEFORE,AFTER):- !, merge2(DESCR,BEFORE,CURRENT), merge_agents(REST,CURRENT,AFTER). merge2([],DESCR,DESCR):-!. merge2([ATT=VAL|DESCR],BEFORE,AFTER):- !, ( is_list(VAL) -> ( member(ATT=OLD_VAL,BEFORE,REST) -> append(OLD_VAL,VAL,CURRENT_VAL), CURRENT=[ATT=CURRENT_VAL|REST] ; CURRENT=[ATT=VAL|BEFORE] ) ; ( member(ATT=_,BEFORE,REST) -> CURRENT=[ATT=VAL|REST] ; CURRENT=[ATT=VAL|BEFORE] ) ), merge2(DESCR,CURRENT,AFTER). /*****************************************************************************/ /* */ /* Affichage de BD initiale */ /* */ /*****************************************************************************/ afficher_bd_initiale:- writef("Base de donnees initiale :\n\n"), ( writef("Jeux :\n\n"), CLE=game_db ; writef("Agents :\n\n"), CLE=agent_db ), recorded(CLE,ITEM), numbervars(ITEM,0,_), aff_ensemble(ITEM), nl, fail. afficher_bd_initiale:-nl. aff_ensemble(NOM=ENS):- writef("%t =\n{\n",[NOM]), member(ATT=VAL,ENS), writef("\t%t = ",[ATT]), aff_val(VAL), nl, fail. aff_ensemble(_):- writef("}.\n"). aff_val(VAL):- ( is_list(VAL) -> ( writef("\n\t{\n"), member(E,VAL), writef("\t\t%t\n",[E]), fail ; writef("\t}\n") ) ; writef("%t\n",[VAL]) ). /*****************************************************************************/ /* */ /* Simplification d'une clause avant assertion */ /* */ /*****************************************************************************/ :-module_transparent clean_assertz/2. clean_assertz(M,(HEAD:-BODY)):- simpl(BODY,CLEAN_BODY), ( CLEAN_BODY=true, M:assertz(HEAD) ; CLEAN_BODY=fail ; M:assertz(HEAD:-CLEAN_BODY) ), !. simpl(A,B):- subst( [ (true,X) >>> X, (X,true) >>> X, state(_,_,_,_,_,F,true) >>> F=9999, state(_,_,_,_,_,_,false) >>> fail, true and X >>> X, X and true >>> X, true or X >>> true, X or true >>> true, false and X >>> false, X and false >>> false, false or X >>> X, X or false >>> X, -true >>> false, -false >>> true, -(-X) >>> X, -(X and Y) >>> -X or -Y, -(X or Y) >>> -X and -Y, state(X,Y,T,K,D,F,E1 and E2) >>> ( state(X,Y,T,K,D,F1,E1), state(X,Y,T,K,D,F2,E2), F is min(F1,F2) ), F is FE*1 >>> F=FE ], A,B ). expand_sequences(A,B):- subst( [ x b [C|SC] >>> x b ([C|SC]:t), x b ([C]:T) >>> x b (C:T), x b ([C|SC]:T) >>> x b (SC:T) and x b (C:T-L) if length(SC,L) ], A,B ). /*****************************************************************************/ /* */ /* Compilation d'un agent */ /* */ /*****************************************************************************/ /* La description d'un agent se fait dans un module dynamique identifie * par le nom de l'agent. Tous les jeux connus de l'agent sont aussi * compiles dans ce module. */ /* Les predicats produits prennent en parametre : * X, Y : Nom des agents * T : Instant courant * K : Cle du jeu en cours * D : Profondeur restante disponible */ compiler_agent(X):- writef("\nCompilation de l'agent %t\n",[X]), dot, chk(recorded(agent_db,X=DESCR),"L'agent %t n'est pas defini.\n",[X]), empty_module(X), expand_sequences(DESCR,DESCR1), subst([x>>>X,y>>>Y,t>>>T],DESCR1,DESCR2), forall(member(ITEM,DESCR2),compiler_agent(X,Y,T,ITEM)), completer(X), writef("\nCompilation terminee\n"). %compiler_agent(_,_,_,_):-trace,fail. compiler_agent(X,Y,T,kb=KB):- !, forall(member(ITEM,KB),compiler_kb(X,Y,T,ITEM)). /* compiler_agent(X,Y,T,games=GAMES):- !, forall(member(ITEM,GAMES),compiler_game(X,Y,T,ITEM)). compiler_agent(X,Y,T,start=START_GAME):- !, X:asserta(start_game(START_GAME)), compiler_game(X,Y,T,START_GAME). compiler_agent(X,_,_,depth=MAX_DEPTH):- !, dot, X:asserta(max_depth(MAX_DEPTH)). */ compiler_agent(_X,_Y,_T,acclist=nobody):- !. compiler_agent(X,Y,T,acclist=((NAME,START,DEPTH,GAMES),ACCLIST)):- !, dot, compiler_agent(X,Y,T,acclist=ACCLIST), X:assertz(start_game(NAME,START)), X:assertz(max_depth(NAME,DEPTH)), X:assertz(accointance(NAME)), forall(member(ITEM,GAMES), ( compiler_game(X,Y,T,ITEM), X:asserta(one_game(NAME,ITEM)) ) ), compiler_game(X,Y,T,START). compiler_agent(_,_,_,games=_):-!. compiler_agent(_,_,_,start=_):-!. compiler_agent(_,_,_,depth=_):-!. compiler_agent(X,_,_,ITEM):- error("Impossible de compiler %t de l'agent %t\n",[ITEM,X]). /*****************************************************************************/ /* */ /* Compilation d'une base de connaissance */ /* */ /*****************************************************************************/ /* Compilation d'une regle d'inference : assertZ <- a la fin de la base !!! * * C0 | P then Q | C1 * Si C0 ok alors instancier Q puis P puis verifier C1 (chainage arriere) * Cette regle est traduite par : * inference(X,Y,T,K,D,F,Q):- * C0, * D1 is D-1, * state(X,Y,T,K,D1,F,P), * C1, * memoriser_etat(X,Q,F,_). * * De plus, pour utiliser une regle d'inference en chainage avant, * il faut la convertir en une regle de mise a jour des etats mentaux * visible dans tous les jeux (K non instancie) * C0 | P then Q | C1 devient P => Q | C1 * (La condition C0 n'est utile qu'en chainage arriere) * * C1 | Q when P | C0 * Regle d'inference qui ne fonctionneme qu'en chainage arriere * La traduction est la meme que 'then' sans la compilation de la * regle de mise a jour correspondante */ compiler_kb(X,Y,T,(A then B)):- !, dot, ( A=(C0|P) ; P=A, C0=true ), ( B=(Q|C1) ; Q=B, C1=true ), clean_assertz(X,(inference(X,Y,T,K,D,F,Q):- C0, D1 is D-1, state(X,Y,T,K,D1,F,P), C1, dialogue:memoriser_etat(X,Q,F,_) )), compiler_update(X,Y,T,_,(P=>Q|C1)). compiler_kb(X,Y,T,(B when A)):- !, dot, ( A=(P|C0) ; P=A, C0=true ), ( B=(C1|Q) ; Q=B, C1=true ), clean_assertz(X,(inference(X,Y,T,K,D,F,Q):- C0, D1 is D-1, state(X,Y,T,K,D1,F,P), C1, dialogue:memoriser_etat_sans_propager(X,Q,F,_) )). /* compiler_kb(X,Y,T,(A then B)):- !, dot, ( A=(C0|P) ; P=A, C0=true ), ( B=(Q|C1) ; Q=B, C1=true ), clean_assertz(X,(inference(X,Y,T,K,D,F,Q):- C0, D1 is D-1, state(X,Y,T,K,D1,F,P), C1, dialogue:memoriser_etat(X,Q,F,_) )), compiler_update(X,Y,T,_,(P=>Q|C1)). */ /* Compilation d'un etat mental : assertA <- au debut de la base !!! * * E etat mental est traduit par : * state(X,Y,T,K,D,F,ST):-flag(<ref>,F,F+1). * sachant qu'il y a dans la base : state(...,ST):-inference(...,ST). * (chainage arriere) */ compiler_kb(X,Y,T,ST):- compiler_kb(X,Y,T,ST,1,_). % ICI IL FAUDRA PENSER A AJOUTER LE POIDS DE ST A LA PLACE MEMOIRE % OCCUPPEE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! compiler_kb(X,Y,T,ST0,F0,ST):- % construit le terme simplifie ST subst([-(-(P)) >>> P],ST0,ST), ( ifdef(afficher_rapport) -> enregistrer_modification(X,ST) ; true ), gen_ref(REF), X:flag(REF,_,F0), X:asserta(state(X,Y,T,_K,_D,F,ST):-flag(REF,F,F+1)). /*****************************************************************************/ /* */ /* Compilation d'un jeu */ /* */ /*****************************************************************************/ /* compiler_game(X,Y,T,GAME):- recorded(game_db,THE_GAME=DESCR), functor(THE_GAME,GAME,_), expand_sequences(DESCR,DESCR1), % subst(DESCR1,[X/x,Y/y,T/t],DESCR2), subst([x>>>X,y>>>Y,t>>>T],DESCR1,DESCR2), forall(member(ITEM,DESCR2),compiler_game(X,Y,T,THE_GAME,ITEM)). */ compiler_game(X,Y,T,GAME):- recorded(game_db,ONE_GAME=ONE_DESCR), subst([x>>>X,y>>>Y],ONE_GAME,GAME), expand_sequences(ONE_DESCR,DESCR), subst([x>>>X,y>>>Y,t>>>T],DESCR,DESCR1), forall(member(ITEM,DESCR1),compiler_game(X,Y,T,GAME,ITEM)). /*****************************************************************************/ /* */ /* Compilation des differents types de regles */ /* */ /*****************************************************************************/ compiler_game(X,Y,T,K,perception=PERCEPTIONS):- forall(member(ITEM,PERCEPTIONS),compiler_perception(X,Y,T,K,ITEM)). compiler_game(X,Y,T,K,update=UPDATES):- forall(member(ITEM,UPDATES),compiler_update(X,Y,T,K,ITEM)). compiler_game(X,Y,T,K,generation=GENERATIONS):- forall(member(ITEM,GENERATIONS),compiler_generation(X,Y,T,K,ITEM)). compiler_game(X,Y,T,K,interdiction=INTERDICTIONS):- forall(member(ITEM,INTERDICTIONS),compiler_interdiction(X,Y,T,K,ITEM)). /* Conditions d'entree, invariant, de sortie * * entrance = COND --> entrance(X,Y,T,K,D,F,GAME):-state(X,Y,T,K,D,F,COND) */ compiler_game(X,Y,T,K,entrance=COND):- dot, clean_assertz(X,(entrance(X,Y,T,OLD_K,D,F,K):-state(X,Y,T,OLD_K,D,F,COND))). compiler_game(X,Y,T,K,invariant=COND):- dot, clean_assertz(X,(invariant(X,Y,T,K,D,F):-state(X,Y,T,K,D,F,COND))). compiler_game(X,Y,T,K,exit=COND):- dot, clean_assertz(X,(exit(X,Y,T,K,D,F):-state(X,Y,T,K,D,F,COND))). /* Regles de perception * * LC => E : * perception(X,Y,T,K,D,M,E):-coups(COUPS),match(LC,COUPS),COND,max_force(M). */ compiler_perception(X,Y,T,K,(LC=>E)):- dot, ( E=(ETAT|COND) ; ETAT=E, COND=true ), clean_assertz(X,(perception(X,Y,T,K,_D,M,ETAT):-coups(COUPS), match(LC,COUPS),COND,max_force(M))). /* Regles de mise a jour * * A => B | C * update(X,Y,T,K,D,A0,F,B):-state(X,Y,T,K,D,F,A1),C. % A0=etat qui apparait * pour tout A0 in A, A1 etant A sachant A0 */ /* WARNING !!!! * subst doit utiliser l'unification AVEC controle d'occurence * (voir tools.pl) */ compiler_update(X,Y,T,K,(LHS=>RHS)):- dot, A=LHS, ( RHS=(B|C) ; B=RHS, C=true ), forall(A0 in A, ( %subst(A,[true/A0],A1), % si l'on fait la substitution, % on perd la force de A0 ! %subst([A0>>>true],A,A1), A1=A, clean_assertz(X,(update(X,Y,T,K,D,A0,F,B):- state(X,Y,T,K,D,F,A1),C)) ) ). /* Regles de generation * * A => B | C # FR FR = Force de la regle * generation(X,Y,T,K,D,F,B):-state(X,Y,T,K,D,FE,A),C,F is FE*FR. */ compiler_generation(X,Y,T,K,(LHS=>RHS)):- dot, A=LHS, ( RHS=(B|C#FR) ; RHS=(B|C), FR=1 ; RHS=(B#FR), C=true ; B=RHS, C=true, FR=1 ), clean_assertz(X,(generation(X,Y,T,K,D,F,B):-state(X,Y,T,K,D,FE,A), C,F is FE*FR)). /* Regles d'interdiction * * A => -B | C # FR * interdiction(X,Y,T,K,D,F,B):-state(X,Y,T,K,D,FE,A),C,F is FE*FR. */ compiler_interdiction(X,Y,T,K,(LHS=>RHS)):- dot, A=LHS, ( RHS=(-B|C#FR) ; RHS=(-B|C), FR=1 ; RHS=(-B#FR), C=true ; -B=RHS, C=true, FR=1 ), clean_assertz(X,(interdiction(X,Y,T,K,D,F,B):-state(X,Y,T,K,D,FE,A), C,F is FE*FR)).