All pastes #806024 Raw Edit

Anonymous

public text v1 · immutable
·published 2007-12-04 22:13 UTC
rendered paste body
:- include(soquetes).
:- include(possibilidades).
:- include(vitoria).

/*********************************************************** Inicio do jogo */
jogar(local, Adversario, Porta) :-
    geraTab(Tab),
    conecta_adversario(Adversario, Porta, Soquete),
    joga(local, Tab, Soquete).

jogar(remoto, _, Porta) :-
    geraTab(Tab),
    espera_adversario(Porta, Soquete),
    joga(remoto, Tab, Soquete).


/****************************************************** Sucessao de jogadas */
joga(_, Tab, _) :-
    empate(Tab),
    format("Empate!~n", []).

/* jogada local */
joga(local, Tab, Soquete) :-
    format("Definindo jogada ... ~n", []),
    max(Tab, _, _, (X, Y, Z)), !,
    envia_jogada(Soquete, X, Y, Z),
    atualizaTab(local, (X, Y, Z), Tab, NovoTab),
    imprime(NovoTab),
    (              
        vitoria(NovoTab, Quem),
        Quem == x     /* acho que Quem == x eh desnecessario */
        ->
           format("Jogo terminado. Vitoria!~n", [])
        ;  
           joga(remoto, NovoTab, Soquete)
    ).


/* jogada remota */
joga(remoto, Tab, Soquete) :-
    format("Esperando Jogada remota ... ", []),
    recebe_jogada(Soquete, X, Y, Z),
    atualizaTab(remoto, (X, Y, Z), Tab, NovoTab),
    imprime(NovoTab),
    (
        vitoria(NovoTab, Quem),
        Quem == o              /* idem ao do x */
        ->
            format("Jogo termindao. Derrota!~n", [])
        ;
            joga(local, NovoTab, Soquete)
    ).


/************************************************ Gera um tabuleiro inicial */
/* a representacao foi feita com uma lista de 4 listas de 16 posicoes,
 * sendo que cada valor pode ser:
 *    0: indica casa vazia
 *    x: um jogador
 *    o: o outro jogador
 * e cada lista de 16 representa uma dimensao.
 */
geraTab(Tabuleiro) :-
    Tabuleiro = [ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
                  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
                  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
                  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] ].


/************************************************* Atualizacao do tabuleiro */
atualizaTab(Quem, (X, Y, Z), Tab, NovoTab) :-
    Offset is Z + 4 * Y,
    atualiza(Quem, X, 0, Tab, Offset, [], NovoTab).

/* acha a dimensao que deve ser alterada e chama altera() */
atualiza(_, _, _, [], _, Tab, Tab).

atualiza(Quem, NDim, NDimAtual, [Dim|Resto], Offset, TabAtual, TabFinal) :-
    NDim \= NDimAtual,
    append(TabAtual, [Dim], NovoTab),
    NDimNovo is NDimAtual + 1,
    atualiza(Quem, NDim, NDimNovo, Resto, Offset, NovoTab, TabFinal).

atualiza(Quem, NDim, NDim, [Dim|Resto], Offset, TabAtual, TabFinal) :-
    altera(Quem, Dim, Offset, 0, [], NovaDim),
    append(TabAtual, [NovaDim|Resto], NovoTab),
    atualiza(_, _, _, [], _, NovoTab, TabFinal).

/* Efetua a alteracao e retorna a nova Dimensao */
altera(_, [], _, _, Dimensao, Dimensao).

altera(Quem, [H|T], Offset, OffsetCorrente, Dimensao, DimensaoFinal) :-
    Offset \= OffsetCorrente,
    append(Dimensao, [H], NovaDimensao),
    NovoOffset is OffsetCorrente + 1,
    altera(Quem, T, Offset, NovoOffset, NovaDimensao, DimensaoFinal).

altera(local, [_|T], Offset, Offset, Dimensao, DimensaoFinal) :-
    append(Dimensao, [x|T], NovaDimensao),
    altera(_, [], _, _, NovaDimensao, DimensaoFinal).

altera(remoto, [_|T], Offset, Offset, Dimensao, DimensaoFinal) :-
    append(Dimensao, [o|T], NovaDimensao),
    altera(_, [], _, _, NovaDimensao, DimensaoFinal).


/*************************************************** Impressao do tabuleiro */
/* imprime o tabuleiro */
imprime([Dimensao|[]]) :-
    imprimeDim(Dimensao).
imprime([Dimensao|Resto]) :-
    imprimeDim(Dimensao),
    format("~2n", []),
    imprime(Resto), !.

/* imprime as dimensoes do tabuleiro */
imprimeDim([A,B,C,D|R]) :-
    imprimeC(A),
    format(" | ", []),
    imprimeC(B),
    format(" | ", []),
    imprimeC(C),
    format(" | ", []),
    imprimeC(D),
    format("~n-------------~n", []),
    imprimeDim(R).
imprimeDim([A,B,C,D]) :-
    imprimeC(A),
    format(" | ", []),
    imprimeC(B),
    format(" | ", []),
    imprimeC(C),
    format(" | ", []),
    imprimeC(D),
    format("~n", []).

/* imprime uma casa do jogo */
imprimeC(0) :-
    format(" ", []), !.
imprimeC(X) :-
    format("~k", [X]).


/*************************************************** Minimax */
/**** MIN ****/
aplica_max([], _, _, _, Acc, Acc).
aplica_max([(T,M)|XS], Nivel, CustoMax, Menor, YS, Acc) :-
    max(T, Nivel, Menor, CN, _, _),

    CustoMax =< CN, !,

    (Menor =< CN 
    -> aplica_max(XS, Nivel, CustoMax, Menor, [(CN, (T, M))|YS], Acc)
    ;  aplica_max(XS, Nivel, CustoMax, CN, [(CN, (T, M))|YS], Acc)
    ).

aplica_max([(T,_)|_], Nivel, CustoMax, Menor, Acc, Acc) :-
    max(T, Nivel, Menor, CN, _, _),
    CustoMax > CN, !.

aplica_max(XS, N, C, YS) :- aplica_max(XS, N, C, 65535, [], YS).

min(Tab, Nivel, _, CustoNovo, TabNovo, Movimento) :-
    Nivel == 0,

    /* M e' o movimento para chegar na tabela T e C o custo */
    findall((C, (T, M)), possiveis(o, Tab, T, M, C), L),

    keysort(L, [(CustoNovo, (TabNovo, Movimento))|_]).

min(Tab, Nivel, CustoMax, CustoNovo, TabNovo, Movimento) :-
    Nivel \== 0,

    /* M e' o movimento para chegar na tabela T e C o custo */
    findall((T,M), possiveis(o, Tab, T, M, _), L),

    NovoNivel is Nivel - 1,

    aplica_max(L, NovoNivel, CustoMax, L2),

    L2 \= [], !,

    keysort(L2, [(CustoNovo, (TabNovo, Movimento))|_]).

min(Tab, Nivel, CustoMax, CustoNovo, TabNovo, Movimento) :-
    Nivel \== 0,

    /* M e' o movimento para chegar na tabela T e C o custo */
    findall((T,M), possiveis(o, Tab, T, M, _), L),

    NovoNivel is Nivel - 1,

    aplica_max(L, NovoNivel, CustoMax, L2),

    L2 = [], !,

    possiveis(x, Tab, TabNovo, Movimento, CustoNovo), !.

/* chamada do min */
min(Tab, CustoNovo, TabNovo, Movimento) :-
    min(Tab, 2, -65535, CustoNovo, TabNovo, Movimento).



/**** MAX ****/
aplica_min([], _, _, _, Acc, Acc).
aplica_min([(T, M)|XS], Nivel, CustoMin, Maior, YS, Acc) :-
    min(T, Nivel, Maior, CN, _, _),

    CustoMin >= CN, !,

    (Maior =< CN
    -> aplica_min(XS, Nivel, CustoMin, CN, [(CN, (T, M))|YS], Acc)
    ;  aplica_min(XS, Nivel, CustoMin, Maior, [(CN, (T, M))|YS], Acc)
    ).

aplica_min([(T,_)|_], Nivel, CustoMin, Maior, Acc, Acc) :-
    min(T, Nivel, Maior, CN, _, _),
    CustoMin < CN, !.

aplica_min(XS, N, C, YS) :- aplica_min(XS, N, C, -65535, [], YS).



max(Tab, Nivel, _, CustoNovo, TabNovo, Movimento) :-
    Nivel == 0,

    /* M e' o movimento para chegar na tabela T e C o custo */
    findall((C, (T, M)), possiveis(x, Tab, T, M, C), L),

    keysort(L, L2),

    last(L2, (CustoNovo, (TabNovo, Movimento))).

max(Tab, Nivel, CustoMin, CustoNovo, TabNovo, Movimento) :-
    Nivel \== 0,
    /* M e' o movimento para chegar na tabela T e C o custo */
    findall((T, M), possiveis(x, Tab, T, M, _), L),

    NovoNivel is Nivel - 1,

    aplica_min(L, NovoNivel, CustoMin, L2),

    L2 \= [], !,

    keysort(L2, L3),

    last(L3, (CustoNovo, (TabNovo, Movimento))).

max(Tab, Nivel, CustoMin, CustoNovo, TabNovo, Movimento) :-
    Nivel \== 0,
    /* M e' o movimento para chegar na tabela T e C o custo */
    findall((T, M), possiveis(x, Tab, T, M, _), L),

    NovoNivel is Nivel - 1,

    aplica_min(L, NovoNivel, CustoMin, L2),

    L2 = [], !,

    possiveis(x, Tab, TabNovo, Movimento, CustoNovo), !.

/* chamada do max */
max(Tab, CustoNovo, TabNovo, Movimento) :-
    max(Tab, 2, 65535, CustoNovo, TabNovo, Movimento).