next up previous contents
Next: Affichage du dialogue Up: Implémentation du simulateur de Previous: Compilation des jeux et

Simulation du dialogue


/*****************************************************************************/
/*                                                                           */
/* 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).



Christophe Delord
1998-09-02