next up previous contents
Next: Simulation du dialogue Up: Implémentation du simulateur de Previous: Déclarations diverses

Compilation des jeux et des agents


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



Christophe Delord
1998-09-02