%%%------------------------------------------------------------ %%% Gerenciador de campeonato %%% %%% Modificado em 06/12/2000 para mudar a saída das jogadas e %%% exibir o placar do campeonato %%% (por Vinicius Fortuna) %%% %%% Modificado em 21/11/2000 para o jogo Connect Four %%% %%% Modificado em 14/09/99 para executar um campeonato simplificado %%% envolvendo apenas um jogador contra todos %%% os outros e vice-versa (By Z.) %%% %%% Modificado em 08/09/99 para Prolog - jogo da velha modif. %%% usamos SWI Prolog %%% %%% Predicado principal: chama-se campeonato %%% %%% campeonato(Jogadores). %%% %%% Recebe uma lista de nomes de pacotes e promove um campeonato %%% entre os ditos cujos. Cada pacote devera' possuir as funcoes %%% necessarias para promover partidas entre os pacotes. %%% Todos jogam contra todos. %%% %%% Cada par de jogadores joga duas partidas para que cada %%% jogador tenha a chance de jogar tanto como Branco quanto como %%% Preto . O Branco sempre comeca. %%% Recebe lista de jogadores, executa campeonato campeonato(Jogadores) :- carrega_modulos(Jogadores), inicializa_placar(Jogadores), member(Jog1, Jogadores), member(Jog2, Jogadores), Jog1 \= Jog2, nl, write(Jog1), write(' versus '), write(Jog2), nl, % partida e' um predicado que nunca pode falhar da primeira vez, % mas deve sempre falhar ao ser re-satisfeita partida([0,[],[]],Jog1,Jog2,_,Result), processa_resultado(Jog1, Jog2, Result), nl, write(Result), nl, fail. % repete ate' acabar campeonato(_) :- nl, imprime_placar, nl. %%% Recebe um Jogador e uma lista de jogadores, executa campeonato campeonato(Jogador,Jogadores) :- carrega_modulos(Jogadores), inicializa_placar([Jogador|Jogadores]), member(Jog, Jogadores), Jog \= Jogador, nl, write(Jogador), write(' versus '), write(Jog), nl, % partida e' um predicado que nunca pode falhar da primeira vez, % mas deve sempre falhar ao ser re-satisfeita partida([0,[],[]],Jogador,Jog,_,Result), processa_resultado(Jogador, Jog, Result), nl, write(Result), nl, fail. campeonato(Jogador,Jogadores) :- member(Jog, Jogadores), Jog \= Jogador, nl, write(Jog), write(' versus '), write(Jogador), nl, partida([0,[],[]],Jog,Jogador,_,Result), processa_resultado(Jog, Jogador, Result), nl, write(Result), nl, fail. % repete ate' acabar campeonato(Jogador,_) :- nl, imprime_placar(Jogador), nl. %%% Processa o resultado da partida processa_resultado(Branco, Preto, [desclassificado, branco]) :- atualiza_placar(Branco, [0, 0, 0, 1]), atualiza_placar(Preto, [1, 0, 0, 0]). processa_resultado(Branco, Preto, [desclassificado, preto]) :- atualiza_placar(Branco, [1, 0, 0, 0]), atualiza_placar(Preto, [0, 0, 0, 1]). processa_resultado(Branco, Preto, [vitoria, branco]) :- atualiza_placar(Branco, [1, 0, 0, 0]), atualiza_placar(Preto, [0, 0, 1, 0]). processa_resultado(Branco, Preto, [vitoria, preto]) :- atualiza_placar(Branco, [0, 0, 1, 0]), atualiza_placar(Preto, [1, 0, 0, 0]). processa_resultado(Branco, Preto, [empate]) :- atualiza_placar(Branco, [0, 1, 0, 0]), atualiza_placar(Preto, [0, 1, 0, 0]). atualiza_placar(Jog, [V, E, P, D]) :- placar([Jog, VV, VE, VP, VD]), retract(placar([Jog, VV, VE, VP, VD])), NV is VV+V, NE is VE+E, NP is VP+P, ND is VD+D, assert(placar([Jog, NV, NE, NP, ND])), !. atualiza_placar(_, _). inicializa_placar(Jogadores) :- retractall(placar(_)), zera_placar(Jogadores). zera_placar([]). zera_placar([Jog|RJogs]) :- retractall(placar([Jog| _])), assert(placar([Jog, 0, 0, 0, 0])), zera_placar(RJogs). compara(Delta, [_, V1, E1, _, _], [_, V2, E2, _, _]) :- % +0.1 para evitar Pts1==Pts2, pois predsort elimina valores iguais Pts1 is 2*V1+E1, Pts2 is 2*V2+E2+0.1, compare(Delta, Pts2, Pts1). compara([_, V1, E1, _, _], [_, V2, E2, _, _]) :- Pts1 is 2*V1+E1, Pts2 is 2*V2+E2, Pts1 > Pts2. imprime_placar :- findall(X, placar(X), L), predsort(compara, L, SL), write(SL). imprime_placar(Jogador) :- placar([Jogador|R]), write([Jogador|R]). %%% -------------------------------------------------- %%% Modulo gerenciador de jogo %%% Rotinas para executar uma partida % globais %%% A funcao partida recebe uma posicao, dois modulos, %%% a ultima jogada, e deve produzir um resultado. %%% So' que este resultado `as vezes depende de chamada %%% recursiva de partida. %%% O valor retornado e' um dos seguintes: %%% [desclassificado, branco ] ---> se o primeiro jogador fez invalida %%% [desclassificado, preto ] ---> se o segundo jogador fez invalida %%% [vitoria, branco ] ---> se o primeiro jogador ganhou %%% [vitoria, preto ] ---> se o segundo jogador ganhou %%% [empate] ---> se empatar partida(Posicao, _, _, Ultima_Jogada, Result) :- decidiu(Posicao, Ultima_Jogada, Result), !. partida([N,B,P], Modulo_Branco, Modulo_Preto, Ultima_Jogada, Result) :- pega_vez(N, Vez), % jogo e' um predicado que nunca pode falhar % o argumento Vez deve sempre estar instanciado com branco ou preto jogo(Vez, N, Modulo_Branco, Modulo_Preto, Ultima_Jogada, Nova_Jogada), N1 is N + 1, (Vez==branco -> nl, NVez is N/2 + 1, write(NVez), write('. '), write(Nova_Jogada); write(' , '), write(Nova_Jogada)), !, % determina_result nunca pode falhar na primeira, e % sempre deve falhar ao ser re-satisfeito determina_result([N1,B,P], Modulo_Branco, Modulo_Preto, Nova_Jogada, Vez, Result). % Determina_result e' o responsavel por verificar se houve % jogada invalida ou se a partida pode prosseguir. determina_result(Posicao, Modulo_Branco, Modulo_Preto, Jogada, Vez, Result) :- valida(Posicao,Jogada,Vez), !, % atualiza nunca pode falhar na primeira chamada, % e sempre deve falhar ao ser re-satisfeito atualiza(Posicao, Jogada, Vez, Nova_Posicao), partida(Nova_Posicao, Modulo_Branco, Modulo_Preto, Jogada, Result). determina_result(_, _, _, _, Vez, [desclassificado, Vez]). % Predicado decidiu verifica apenas se houve vitoria ou % empate. Desclassificacao fica a cargo de outros predicados. decidiu(Posicao, Ultima_Jogada, [vitoria, Vez]) :- ganhou(Posicao, Ultima_Jogada, Vez). decidiu(Posicao, _, [empate]) :- empatou(Posicao). ganhou([_N,B,_P], Ultima_Jogada, branco) :- fechou(B, Ultima_Jogada). ganhou([_N,_B,P], Ultima_Jogada, preto) :- fechou(P, Ultima_Jogada). fechou(Jogadas, Jogada) :- linha(Linha), member(Jogada,Linha), subset(Linha,Jogadas). linha(Linha) :- horiz_line(Linha). linha(Linha) :- vert_line(Linha). linha(Linha) :- diag_line(Linha). horiz_line([[A,X],[B,X],[C,X],[D,X]]) :- member(X,[1,2,3,4,5,6]), letter_quad([A,B,C,D]). vert_line([[A,X],[A,Y],[A,Z],[A,W]]) :- member(A,[a,b,c,d,e,f,g]), number_quad_inc([X,Y,Z,W]). diag_line([[A,X],[B,Y],[C,Z],[D,W]]) :- letter_quad([A,B,C,D]), number_quad([X,Y,Z,W]). letter_quad([A,B,C,D]) :- append(_,[A,B,C,D|_],[a,b,c,d,e,f,g]). number_quad(X) :- number_quad_inc(X). number_quad(X) :- number_quad_dec(X). number_quad_inc([X,Y,Z,W]) :- append(_,[X,Y,Z,W|_],[1,2,3,4,5,6]). number_quad_dec([X,Y,Z,W]) :- append(_,[X,Y,Z,W|_],[6,5,4,3,2,1]). empatou([N,_,_]) :- N >= 42. % Recebe posicao, retorna vez de quem e' pega_vez(N, branco) :- 0 is N mod 2. pega_vez(N, preto) :- 1 is N mod 2. % Efetua jogada. Se predicado chamado do outro modulo % falhar, instancia Nova_Jogada com o atomo 'falhou'. jogo(branco, N, Modulo_Branco, _, _, Nova_Jogada) :- primeira_vez(N), Term =.. [branco_inicia,Nova_Jogada], call(Modulo_Branco:Term). jogo(branco, _, Modulo_Branco, _, Ultima_Jogada, Nova_Jogada) :- Term =.. [branco_responde,Ultima_Jogada,Nova_Jogada], call(Modulo_Branco:Term). jogo(preto, N, _, Modulo_Preto, Ultima_Jogada, Nova_Jogada) :- primeira_vez(N), Term =.. [preto_inicia,Ultima_Jogada,Nova_Jogada], call(Modulo_Preto:Term). jogo(preto, _, _, Modulo_Preto, Ultima_Jogada, Nova_Jogada) :- Term =.. [preto_responde,Ultima_Jogada,Nova_Jogada], call(Modulo_Preto:Term). jogo(_,_,_,_,_,'falhou'). %%%------------------------------------------------------------ %%% Predicado carrega: carrega o pacote de um jogador carrega_modulos(Jogadores) :- member(Jog, Jogadores), carrega(Jog), fail. carrega_modulos(_). carrega(Jogador) :- concat_atom([Jogador,'.prolog'],Filename), consult(Filename). %%%------------------------------------------------------------ %%% Demais predicados % Primeira_vez: se neste numero de posicao sera' feita % a primeira jogada do jogador de quem e' a vez primeira_vez(N) :- N =< 1. % Valida: testa se a jogada (arg.2) 'e valida na posicao (arg.1) % obs: Vez (arg,3) nao interessa neste caso, por isso anonima valida(Posicao, Jogada, _Vez) :- dentro(Jogada), valida_aux(Posicao,Jogada). dentro([Coluna, Linha]) :- member(Coluna, [a,b,c,d,e,f,g]), 1 =< Linha, Linha =< 6. valida_aux([_,B,_], Jogada ) :- member(Jogada, B), !, fail. valida_aux([_,_,P], Jogada ) :- member(Jogada, P), !, fail. valida_aux( _, [_,1] ) :- !. valida_aux([_,B,P], [Col, Lin]) :- LinAnt is Lin - 1, ocupada(B,P,[Col,LinAnt]). ocupada(B,_,Jogada) :- member(Jogada,B). ocupada(_,P,Jogada) :- member(Jogada,P). % Atualiza: constroi nova posicao a partir da antiga e da jogada atualiza([N,B,P], Jogada, branco, [N,[Jogada|B],P]). atualiza([N,B,P], Jogada, preto , [N,B,[Jogada|P]]).