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