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