/*****************************************************************************/ /* */ /* Execution des clauses compilees par le module compil */ /* */ /*****************************************************************************/ :-module(dialogue, [ completer/1, dialoguer/0 ] ). :-use_module([rapport,pasapas,windows,subst]). init:- index(state(1,0,0,0,0,0,1)), index(inference(1,0,0,0,1,0,1)), index(entrance(1,0,0,1,0,0,0)), index(invariant(1,0,0,1,0,0)), index(exit(1,0,0,1,0,0)), index(perception(1,0,0,1,0,0,0)), index(update(1,0,0,1,0,1,0,0)), index(generation(1,0,0,1,0,0,0)), index(interdiction(1,0,0,1,0,0,1)), index(one_game(1,1)). /*****************************************************************************/ /* */ /* Liste des clauses a rajouter a chaque agent */ /* */ /*****************************************************************************/ /* Syntaxe : * a : clause asserta(clause) * z : clause assertz(clause) */ % DANS LES CLAUSES states RAJOUTEES, IL FAUDRA APPELER memoriser_etat SI % ON STOCKE LES REDONDANCES % C'EST EN FAIT DANS memoriser_etat QUE L'ON TRAITERA OU NON LE STOCKAGE % DES REDONDANCES moteur(X, [ z:(state(X,_,_,_,_,9999,true):-!), % Quelle est la force de true z:(state(X,_,_,_,_,_,false):-!,fail), z:(state(X,_,_,_,_,_,X):-var(X),!,fail), z:(state(X,Y,T,K,D,F,A):- subst:subst([-(-P)>>>P],A,B), A\=B, !, state(X,Y,T,K,D,F,B) ), z:(state(X,Y,T,K,D,F,A and B):-state(X,Y,T,K,D,F1,A), state(X,Y,T,K,D,F2,B),F is min(F1,F2)), z:(state(X,Y,T,K,D,F,A or B):-state(X,Y,T,K,D,F,A); state(X,Y,T,K,D,F,B)), z:(state(X,Y,T,K,D,F,-(-A)):-state(X,Y,T,K,D,F,A)), z:(state(X,Y,T,K,D,1,-A):- \+ state(X,Y,T,K,D,_,A)), % Quelle est la force d'un fait nie z:(state(X,Y,T,K,D,F,X b (C:U)):- nonvar(U), \+ integer(U), V is U, state(X,Y,T,K,D,F,X b (C:V))), z:(state(X,Y,T,K,D,F,ST):-inference(X,Y,T,K,D,F,ST)), % z:interdiction(_,_,_,_,_,0,_), a:(inference(_,_,_,_,0,_,_):-!,fail), z:(match(C,[C|_]):-!), % a revoir pour les sequences de coups z:(max_force(F):-dialogue:max_force(X,F)), (:-dynamic agents/2, max_depth/2, inference/7, state/7), (:-dynamic entrance/7, invariant/6, exit/6, one_game/2), (:-dynamic perception/7, update/8, generation/7, interdiction/7), (:-dynamic jeu_courant/2, cur_acc/1), (:-dynamic max_force/1) ] ). /*****************************************************************************/ /* */ /* Completer la definition d'un agent */ /* */ /*****************************************************************************/ /* completer(X):- moteur(X,CLAUSES), forall(member(OU:CLAUSE,CLAUSES), ( OU=z -> X:assertz(CLAUSE) ; X:asserta(CLAUSE) ) ), forall(member((:-INIT),CLAUSES),X:INIT). */ completer(X):- moteur(X,CLAUSES), ( member(a:CLAUSE,CLAUSES), X:asserta(CLAUSE), fail ; member(z:CLAUSE,CLAUSES), X:assertz(CLAUSE), fail ; member((:-INIT),CLAUSES), X:INIT, fail ; true ). /*****************************************************************************/ /* */ /* Dialogue */ /* */ /*****************************************************************************/ dialoguer:- agents(BILL,JOHN), ( feature(unix,true) -> win_init(160,50), ( ifdef(debug_window) -> BOTTOM=45 ; BOTTOM=50 ), win_open(BILL,1,1,65,BOTTOM,BILL), win_open(JOHN,95,1,160,BOTTOM,JOHN), win_open(coups,65,1,95,BOTTOM,"Coups"), ifdef(debug_window,win_open(debug,1,55,160,60,"Debug")) ; win_init(145,40), ( ifdef(debug_window) -> BOTTOM=35 ; BOTTOM=40 ), win_open(BILL,1,1,55,BOTTOM,BILL), win_open(JOHN,90,1,145,BOTTOM,JOHN), win_open(coups,55,1,90,BOTTOM,"Coups"), ifdef(debug_window,win_open(debug,1,35,145,40,"Debug")) ), win_link([BILL,JOHN,coups]), % Il faut propager les etats presents initialement % Il n'apparaissent pas donc ne declenchent pas les regles de maj findall( X:state(X,Y,T,K,D,F,E), ( clause(X:state(X,Y,T,K,D,F,E),flag(FLAG,_,_),REF), flag(FLAG,F,F), erase(REF) ), INIT_KB ), forall( member(X:state(X,Y,T,K,D,F,E),INIT_KB), memoriser_etat(X,E,F,_) ), forall( ( agents(X,_), clause(X:state(X,_,_,_,_,_,E),flag(_,_,_)) ), ( numbervars(E,0,_), win_write(X,"%t\n",[E]) ) ), synchroniser, retractall(user:coups(_)), asserta(user:coups([])), init_rapport, repeat, agents(X,Y), /**************************************** date(T), X:max_depth(D), redefine(synchro), changement_de_jeu(X,Y,T,D), ignore(generer_un_coup(X,Y,T,D,CX)), undefine(synchro), ( ifdef(afficher_rapport) -> afficher_etat_courant(T) ; true ), dire(X,CX), once(regles_de_perception(X,Y,T)), once(regles_de_perception(Y,X,T)), synchroniser, draw_windows, pas_a_pas, ligne_de_separation, *****************************************/ date(T), redefine(synchro), ( X:accointance(NAME), X:rasserta(cur_acc(NAME)), X:max_depth(NAME,D), changement_de_jeu(X,Y,T,D), fail ; true ), ( Y:accointance(NAME), Y:rasserta(cur_acc(NAME)), Y:max_depth(NAME,D), changement_de_jeu(Y,X,T,D), fail ; true ), ignore(generer_un_coup(X,Y,T,D,CX)), undefine(synchro), ifdef(afficher_rapport,afficher_etat_courant(T)), dire(X,CX), ( X:accointance(NAME), X:rasserta(cur_acc(NAME)), once(regles_de_perception(X,Y,T)), fail ; true ), ( Y:accointance(NAME), Y:rasserta(cur_acc(NAME)), once(regles_de_perception(Y,X,T)), fail ; true ), synchroniser, draw_windows, pas_a_pas, ligne_de_separation, fin_du_dialogue, !. fin_du_dialogue:- coups([$ X, $ Y|_]), agents(X,Y). synchroniser:- agents(BILL,JOHN), repeat, win_pos(BILL,_,Y_BILL), win_pos(JOHN,_,Y_JOHN), ( Y_BILL<Y_JOHN -> win_nl(BILL), fail ; true ), ( Y_JOHN<Y_BILL -> win_nl(JOHN), fail ; true ), win_pos(BILL,_,Y_BILL), repeat, win_pos(coups,_,Y_COUPS), ( Y_COUPS<Y_BILL -> win_nl(coups), fail ; true ), !. ligne_de_separation:- agents(BILL,JOHN), windows:maxXY(MAXX,_), for(_,1,MAXX>>2, ( win_write(BILL,"- "), win_write(JOHN,"- "), win_write(coups,"- ") ) ), win_nl(BILL), win_nl(JOHN), win_nl(coups), !. /*****************************************************************************/ /* */ /* Force maximale des etats mentaux */ /* */ /*****************************************************************************/ max_force(X,MF):- flag(max_force,_,0), ( X:clause(state(X,_,_,_,_,_,_),flag(REF,_,_)), flag(REF,F,F), flag(max_force,MF,max(F,MF)), fail ; flag(max_force,MF,MF) ). /* fflag(REF,F1,F2):- flag(REF,F1,F2), F is F2, max_force(MF), ( F>MF -> retract(max_force(_)), asserta(max_force(F)) ; true ). */ /*****************************************************************************/ /* */ /* Changement de jeu */ /* */ /*****************************************************************************/ changement_de_jeu(X,Y,T,D):- sortir_du_jeu_courant(X,Y,T,D), entrer_dans_un_jeu(X,Y,T,D). sortir_du_jeu_courant(X,Y,T,D):- X:cur_acc(NAME), ( once(X:jeu_courant(NAME,JEU_COURANT)), ( X:exit(X,Y,T,JEU_COURANT,D,_) ; \+ X:invariant(X,Y,T,JEU_COURANT,D,_) ) -> retract(X:jeu_courant(NAME,JEU_COURANT)), win_write(X,"%t sort du jeu %t\n",[/*X*/NAME,JEU_COURANT]), win_nl(Y), win_nl(coups), sortir_du_jeu_courant(X,Y,T,D) ; true ), !. entrer_dans_un_jeu(X,Y,T,D):- X:cur_acc(NAME), ( ( X:jeu_courant(NAME,JEU_COURANT) ; X:start_game(NAME,JEU_COURANT) ), !, findall(F:JEU, ( X:one_game(NAME,JEU), X:entrance(X,Y,T,JEU_COURANT,D,F,JEU), \+ X:jeu_courant(NAME,JEU), \+ X:start_game(NAME,JEU) ), JEUX ), merge_sort(JEUX,JEUX_TRIES), ( member(_:JEU,JEUX_TRIES), asserta(X:jeu_courant(NAME,JEU),REF), win_write(X,"%t rentre dans le jeu %t\n",[/*X*/NAME,JEU]), win_nl(Y), win_nl(coups), % Il faut encore pouvoir y rester ( ( X:exit(X,Y,T,JEU,D,_) ; \+ X:invariant(X,Y,T,JEU,D,_) ) -> % on sort immediatement du jeu erase(REF), win_write(X,"... et en resort aussitot.\n"), win_nl(Y), win_nl(coups), fail % on en prend un autre ; true % ok, on y reste ) ; true % cas ou la liste est vide !!! ) ; true ), !. /*****************************************************************************/ /* */ /* Gestion des coups */ /* */ /*****************************************************************************/ date(T):-coups(COUPS),length(COUPS,T). dire(X,CX):- ( var(CX) -> win_write(coups,"Coup vide de %t\n",[X]) ; retract(user:coups(COUPS)), assert(user:coups([CX|COUPS])), win_write(coups,"%t\n",[CX]) ), agents(BILL,JOHN), win_nl(BILL), win_nl(JOHN), !. /*****************************************************************************/ /* */ /* Generation d'un coup */ /* */ /*****************************************************************************/ generer_un_coup(X,Y,T,D,CX):- asserta(X:cur_acc(X),REF), ( X:jeu_courant(X,K) ; X:start_game(X,K) ), !, % Avec !, on ne traite que le dernier jeu findall(F:COUP, ( X:generation(X,Y,T,K,D,FG,COUP), findall(FI,X:interdiction(X,Y,T,K,D,FI,COUP),FIS), max(FIS,FIM), F is FG-FIM, F > 0 ), COUPS ), merge_sort(COUPS,COUPS_TRIES), ifdef(debug_window, win_write(debug,"Coups generables : %t\n",[COUPS_TRIES])), member(_:CX,COUPS_TRIES), erase(REF). /*****************************************************************************/ /* */ /* Regles de perception */ /* */ /*****************************************************************************/ regles_de_perception(X,Y,T):- X:cur_acc(NAME), ( X:jeu_courant(NAME,K) ; X:start_game(NAME,K) ), !, X:max_depth(NAME,D), forall(X:perception(X,Y,T,K,D,F,E),memoriser_etat(X,E,F,_)). /*****************************************************************************/ /* */ /* Memorisation d'un etat mental */ /* */ /*****************************************************************************/ memoriser_etat(X,E,F,E1):-memoriser(X,E,F,E1,true). memoriser_etat_sans_propager(X,E,F,E1):-memoriser(X,E,F,E1,fail). memoriser(X,A and B,F,A1 and B1,PROPAGER):- !, memoriser(X,A,F,A1,PROPAGER), memoriser(X,B,F,B1,PROPAGER). memoriser(X,A or B,F,A1 or B1,PROPAGER):- !, user:agents(X,Y), date(T), ( renforcer(X,A or B,F) -> A1=A, B1=B ; compiler_kb(X,Y,T,A or B,F,A1 or B1), ( PROPAGER -> propager_etat(X,A1 or B1) ; true ) ). % IL FAUT DISTINGUER LES ETATS QUI APPARAISSENT ET DISPARAISSENT memoriser(X,E,F,E1,PROPAGER):- subst([-(-P)>>>P],E,E1), liberer(X,-E1), ( clause(X:state(X,_,_,_,_,_,E1),flag(REF,_,_)) -> X:flag(REF,F0,F0+F) % renforcement de l'etat ; % faire_de_la_place(X,E1), ( ifdef(afficher_nouveaux), E1\=(_ kif _) -> %numbervars(E1,0,_), win_write(X,"%t\n",[E1]), ( ifdef(synchro) -> agents(X,Y), win_nl(Y), win_nl(coups) ; true ) ; true ), compiler_kb(X,_Y,_T,E1,F,_), ( PROPAGER -> propager_etat(X,E1) ; true ) ), !. memoriser(X,E,F,E,PROPAGER):- warning("%t\n",[memoriser(X,E,F,_,PROPAGER)]). % debug propager_etat(X,E):- % Ici, on applique les regles de mise a jour % ( X:jeu_courant(K) % ; X:start_game(K) % ), % !, % X:max_depth(D), % forall(X:update(X,Y,T,K,D,E,FNE,NE),memoriser_etat(X,NE,FNE,_)). ( X:cur_acc(NAME) ; NAME=X ), X:max_depth(NAME,D), forall( ( ( X:jeu_courant(NAME,K) ; X:start_game(NAME,K) ), X:update(X,_Y,_T,K,D,E,FNE,NE) ), memoriser_etat(X,NE,FNE,_) ), !. liberer(X,-(-E)):- !, liberer(X,E). liberer(X,E):- forall(clause(X:state(X,_,_,_,_,_,E),flag(_,_,_),REF),erase(REF)). % Maintenir la force d'une disjonction : Renforcer tous les termes connus % Echec si aucun terme n'a pu etre renforce renforcer(X,A or B,F):- !, ( renforcer(X,A,F) % on peut renforcer A -> ( renforcer(X,B,F) % donc b n'a pas d'importance ; true ) ; renforcer(X,B,F) % sinon il faut pouvoir renforcer B ). renforcer(X,A,F):- clause(X:state(X,_,_,_,_,_,A),flag(REF,_,_)), X:flag(REF,F0,F0+F-F+1).