Congo
Autores:
Carlos Alberto Loureiro Nunes
Pedro Nuno Verde Cerqueira
Grupo 54, Turma 5
Outubro de 2008
Relatório Intercalar do 1º Trabalho Prático da
Disciplina de Programação em Lógica
Outubro de 2008
III
Resumo
Índice
Resumo iii
Índice iv
Lista de Figuras vi
Glossário viii
1. Introdução ix
1.1 Enquadramento...................................................................................................................ix
1.2 Motivação............................................................................................................................ix
1.3 Objectivos...........................................................................................................................ix
1.4 Estrutura do Relatório...........................................................................................................x
2. Descrição do jogo xi
2.1 Introdução...........................................................................................................................xi
2.2 História................................................................................................................................xi
2.3 Regras do Jogo...................................................................................................................xii
2.3.1 Tabuleiro, Regras Básicas e Notação..........................................................................xii
2.3.2 Objectivo....................................................................................................................xiii
2.3.3 Peças e Movimentos...................................................................................................xiii
2.3.3.1 Leão.....................................................................................................................xiii
2.3.3.2 Elefante...............................................................................................................xiii
2.3.3.3 Macaco................................................................................................................xiv
2.3.3.4 Crocodilo.............................................................................................................xiv
2.3.3.5 Girafa....................................................................................................................xv
2.3.3.6 Zebra.....................................................................................................................xv
2.3.3.7 Peão.....................................................................................................................xvi
2.3.3.8 Super Peão...........................................................................................................xvi
2.3.4 Fim do jogo................................................................................................................xvi
V
4. Representação de um Movimento xx
Bibliografia 27
VI
Lista de Figuras
Lista de Tabelas
Glossário
Elephant Roll – No Congo diz-se que existem um elephant roll quando dois
elefantes do mesmo jogador estão colocados ao longo de uma linha ou coluna de modo a
poderem capturar qualquer posição da mesma linha ou coluna em que se encontram.
Stalemate – Diz-se que acontece stalemate quando no xadrez, um jogador não pode
fazer nenhuma jogada sem por o seu rei em cheque. Desta forma dá-se um empate. No
Congo não existe cheque. Se o leão é ameaçado por uma peça adversária e não é de
alguma forma protegido, no turno seguinte pode ser capturado terminando o jogo.
9
Capítulo 1
1. Introdução
1.1 Enquadramento
Este trabalho enquadra-se na realização de objectivos pedagógicos da disciplina de
Programação em Lógica, do 1º semestre, do 3º ano, da Licenciatura em Engenharia
Informática e de Computação da Faculdade de Engenharia da Universidade do Porto.
Estes objectivos apresentam-se explicitados na secção 3 deste capítulo.
1.2 Motivação
O jogo Congo é um jogo semelhante ao Xadrez o que só por si já o torna
interessante. Alem disso o Congo apresenta características únicas num jogo de tabuleiro,
como a existência de um rio, elevando ainda mais o grau de interesse. Existem multiplas
regras, e usam-se várias estratégias complexas para obter uma condição de vitória. Em
resumo , é um jogo naturalmente desafiante para os seus jogadores, que testa as suas
capacidades de pensamento estratégico e lógico.
Outra possível razão para a escolha deste jogo em particular é a sua grande
popularidade, sendo uma das variantes de xadrez mais jogadas. Acrescentando ao desafio
o desejo de criar uma implementação de grande qualidade, para os padrões da maioria dos
seus jogadores.
1.3 Objectivos
Os objectivos deste trabalho intersectam os da disciplina:
● Adquirir familiaridade com os paradigmas da programação em lógica e com a
linguagem Prolog.
● Desenvolver as competências de raciocínio abstracto e de representação de
problemas de forma declarativa ao invés do que tinha-mos feito até agora na
programação funcional;
10
Capítulo 2
2. Descrição do jogo
2.1 Introdução
O Congo é um jogo muito semelhante ao Xadrez, na medida em que é um jogo de
tabuleiro por turnos em que existem várias peças diferentes por jogador e o objectivo é
capturar apenas uma das peças (o rei no caso do xadrez). As diferenças mais notórias entre
os dois jogos é a existência de um rio na linha do meio, onde as peças podem eventual-
mente “afogar-se”, e obviamente o facto de as peças se moverem de maneira diferente (ver
figura 1). Existem também outras diferenças que serão descritas mais detalhadamente nas
próximas secções deste capítulo.
2.2 História
O Congo foi inventado por Demian Freeling quando este tinha apenas sete anos,
em 1982. Tornou-se rapidamente na segunda variante de Xadrez mais popular no clube de
jogos "Fanatic" na Twente University, Noruega. Existem poucos jogos criados por
crianças tão jovens que sejam tão interessantes para os adultos. Christian Freeling, o pai
de Demian, é um criador de jogos muito conhecido e autor do sítio www.mindsports.com
juntamente com Ed Van Zon. É de facto notável que o jogo Congo apareça na capa do
livro David Pritchard's, 'The Encyclopedia of Chess Variants' (G&P Publications, P.O.
Box 20, Godalming, Surrey GU8 4YP, UK. - ISBN 0-9524142-0-1).
12
Na linha central existe um rio, a azul, e os quadrados de 3x3 células cinzentos, designam-
se por castelos dos leões.
Para qualquer peça com a excepção do crocodilo, que não se afoga, e do Leão que não
pode entrar no rio:
● Se uma peça termina o seu movimento no rio, tem que o abandonar no próximo
turno ou afoga-se;
● A peça afogada é removida no fim do turno quer se tenha movido dentro do rio,
quer não. Qualquer captura que faça e termine no rio é válida.
13
2.3.2 Objectivo
O objectivo do Congo é capturar o Leão do oponente. Ao contrário do xadrez não
há nenhuma regra que proíba o Leão de se mover para uma posição em que fique em
cheque, seria simplesmente capturado e finalizaria o jogo. Como é obrigatório os
jogadores moverem sempre uma peça no seu turno, não existe stalemate (ver glossário).
2.3.3.1 Leão
O leão movimenta-se e captura como o rei do xadrez, ou seja para 1 célula á sua
volta em qualquer direcção. Contudo não pode sair do seu "castelo" de 3x3 células.
Adicionalmente, se um leão está na mesma coluna que o leão adversário, ou na
mesma diagonal, e não existem outras peças entre eles, ambos estão em cheque e o
jogador ao qual o turno actual pertence pode capturar o leão adversário e ganhar o jogo.
2.3.3.2 Elefante
O elefante pode mover-se e capturar uma ou duas células ao longo da linha ou
coluna em que se encontra. O movimento de duas células é um salto para a célula final e
não é afectado pela existência de peças de qualquer das equipas, na célula sobre a qual
salta.
14
2.3.3.3 Macaco
Os macacos movem-se (mas não capturam) como o rei do xadrez. Estes, capturam
saltando (sobre a peça capturada) ao longo das linhas, colunas ou diagonais, para a célula
imediatamente a seguir, que tem que estar vazia. O macaco pode efectuar múltiplas
capturas no mesmo turno (embora não seja obrigado), desde que não salte sobre a mesma
peça mais que um vez.
2.3.3.4 Crocodilo
O crocodilo move-se e captura como o rei no xadrez. Contudo dependendo se
encontra em terra ou no rio:
● Quando em terra também se pode mover e capturar qualquer célula na coluna
até ao rio (incluindo a célula do rio).
● Quando no rio, o crocodilo pode mover-se e capturar qualquer outra célula do
rio. Como já foi referido anteriormente o crocodilo não se afoga.
15
2.3.3.5 Girafa
As girafas podem mover-se e capturam para a segunda célula ao longo da linha,
coluna ou diagonal em que se encontra, sem se ver afectada por qualquer peça sobre a qual
salte, seja ela branca ou preta. Também pode mover-se (mas não capturar) como o rei do
xadrez.
2.3.3.6 Zebra
A zebra move-se e captura como o cavalo do xadrez, ou seja: avança duas células
ao longo da linha ou coluna em que se encontra; vira noventa graus para um dos lados;
avança uma célula ao longo da linha ou coluna para onde se encontra virada. O
movimento da zebra é um salto e não se vê afectado pelas peças de qualquer das cores,
sobre as as quais salta.
16
2.3.3.7 Peão
Os peões, podem mover-se e capturar para a frente: uma célula na mesma coluna
para a frente, ou uma célula na diagonal para a frente. Quando estão na linha
imediatamente a seguir ao rio podem retroceder, movendo-se (mas não capturando) uma
ou duas células para trás. Quando um peão atinge a última linha é promovido para "super
peão", descrito a seguir. Observe a figura seguinte que ilustra os movimentos do peão e
“super peão”.
Capítulo 3
Leão 1 9 1
Elefante 2 10 2
Macaco 3 11 1
Crocodilo 4 12 1
Girafa 5 13 1
Zebra 6 14 1
Peão 7 15 7
Super Peão 8 16 0
19
Capítulo 4
4. Representação de um Movimento
O Congo, tal como o Xadrez, é caracterizado pela existência de várias peças com
tipos de movimentos diferentes.
Segue-se uma visão mais formal dos tipos de movimento que estão disponíveis
para cada peça.
Para melhor descrever a complexidade dos movimentos possíveis expomos as
seguintes duas tabelas, que abordam a questão dos movimentos de uma forma mais formal
do que a que foi usada no capítulo 2.
Distância
Designaçã (número
Direcção Descrição
o Formal de
células)
N, S, E, W, NE,
QD_1 1 1 célula em Qualquer Direcção
NW, SE, SW
N, S, E, W, NE,
QD_2 2 2 células em Qualquer Direcção
NW, SE, SW
1 ou 2 células na horizontal ou vertical
XY_12 N ,S, E, W 1–2
(direcção X ou Y)
NEE, NNE, SEE,
SSE, NWW,
CX 2+1 Como o Cavalo do Xadrez
NNW, SWW,
SSW
Qualquer número de células na direcção
X_Q E, W 1–6
X
A coluna (direcção Y) até ao Rio (célula
Y_QR N 1–3
do rio incluída)
1 célula para a Frente (na vertical ou
F_1 N, NE, NW 1
diagonal)
X_1 E, W 1 1 célula para um dos lados (direcção X)
Retroceder 1 ou 2 células na mesma
RY_12 S 1–2
coluna (direcção Y)
RD_12 SE. SW 1–2 Retroceder 1 ou 2 células na Diagonal
movimento, embora internamente não seja relevante, torna-se útil para nós humanos
aceder a esta informação.
Existe ainda a necessidade de representar os movimentos, eventualmente
múltiplos, dos macacos. Neste caso, estes são representados por:
monkey-(Xi, Yi)-[(Xcapture1, Ycapture1)*(Xf1, Yf1),
(Xcapture2, Ycapture2)*(Xf2, Yf2), ..., (Xcapturen,
Ycapturen)*(Xfn, Yfn)]
Neste movimento, mais uma vez (Xi, Yi) é a posição inicial da peça, (Xcapturen,
Ycapturen) são as posições capturadas pelo sub-movimentos e (Xfh, Yfh) são as
posições finais dos sub-movimentos, com h de 1 a n. Como já foi dito antes, o macaco é a
única peça que captura a célula sobre a qual salta, e não a célula em que termina o
movimento. Convém notar que a célula no ponto médio de (Xi, Yi) (Xf1, Yf1) e nos pontos
médios de (Xfh, Yfh) (Xfh+1, Yfh+1) com h de 1 a n – 1 são as células capturadas. O n, usado
como índice final dos sub-movimentos do macaco, não será nunca maior que 14, pois 14 é
o número de peças do adversário.
Actualmente tudo o que diz respeito aos movimentos já está implementado. É
inclusivamente possível mostrar no ecrã todos os movimentos possíveis para o jogador 1
(jogador de cima), usando o predicado print_moves(1, Board), onde Board foi instanciado
com um tabuleiro. Por exemplo para a configuração inicial do tabuleiro e considerando
que o eixo dos Y aponta para baixo (notação interna), para o jogador de cima os
movimentos possíveis são.
| ?- initial_board(Board), print_moves(1, Board).
[elephant-(3,1)-(3,3),elephant-(5,1)-(5,3),giraffe-(1,1)-
(1,3),giraffe-(1,1)-(3,3),zebra-(7,1)-(6,3),pawn-(1,2)-
(1,3),pawn-(1,2)-(2,3),pawn-(2,2)-(2,3),pawn-(2,2)-
(3,3),pawn-(2,2)-(1,3),pawn-(3,2)-(3,3),pawn-(3,2)-
(4,3),pawn-(3,2)-(2,3),pawn-(4,2)-(4,3),pawn-(4,2)-
(5,3),pawn-(4,2)-(3,3),pawn-(5,2)-(5,3),pawn-(5,2)-
(6,3),pawn-(5,2)-(4,3),pawn-(6,2)-(6,3),pawn-(6,2)-
(7,3),pawn-(6,2)-(5,3),pawn-(7,2)-(7,3),pawn-(7,2)-(6,3)]
[lion-(5,2)-(5,1),lion-(5,2)-(5,3),lion-(5,2)-(4,2),lion-
(5,2)-(4,1),lion-(5,2)-(4,3),lion-(5,2)-(5,7),elephant-
(3,1)-(3,2),elephant-(3,1)-(4,1),elephant-(3,1)-
23
(3,3),elephant-(3,1)-(5,1),giraffe-(1,1)-(2,2),giraffe-
(1,1)-(1,3),giraffe-(1,1)-(3,3),crocodile-(6,1)-
(6,2),crocodile-(6,1)-(5,1),crocodile-(6,1)-(7,2),crocodile-
(6,1)-(6,3),crocodile-(6,1)-(6,4),zebra-(7,1)-(6,3),pawn-
(1,2)-(1,3),pawn-(1,2)-(2,3),pawn-(6,5)-(6,6),pawn-(6,5)-
(7,6),pawn-(6,5)-(5,6),pawn-(4,6)-(4,7),pawn-(4,6)-
(5,7),pawn-(4,6)-(3,7),pawn-(6,5)-(6,4),pawn-(6,5)-
(6,3),monkey-(2,1)-(3,2),monkey-multiple-(2,1)-
[(2,2)*(2,3)],monkey-multiple-(2,1)-[(2,2)*(2,3),
(2,4)*(2,5)],monkey-multiple-(2,1)-[(2,2)*(2,3),(2,4)*(2,5),
(3,5)*(4,5)]]
24
Capítulo 5
5.Visualização do Tabuleiro
Existem dois predicados com a funcionalidade de visualizar o tabuleiro:
print_board e print_board_advanced. O predicado print_board mostra o
tabuleiro de uma forma muito simples e compacta. Por outro lado,
print_board_advanced mostra o tabuleiro de forma mais inteligível, representando
cada peça numa área de 5 linhas por 9 colunas usando caracteres ASCII e os modos de cor
da consola Linux. Alem da representação das peças, os predicados de visualização
também apresentam o rio, os castelos e a legenda das linhas e colunas.
A representação em “gráficos de texto” de 5 linhas por 9 colunas não permite
grande qualidade na representação gráfica, contudo achamos, que mesmo assim é mais
“amigável” que a simples. Na figura seguinte pode observar-se a saída produzida por
print_board (em cima) e por print_board_advanced (em baixo) numa shell
linux.
25
Capítulo 6
6.Conclusões e Perspectivas de
Desenvolvimento
Em perspectiva, olhando para o trabalho já realizado, conclui-se que os objectivos
foram cumpridos e adivinha-se que o resto da implementação será também muito
interessante.
Estando a aplicação num ponto em que é capaz de gerar todos os movimentos
possíveis para um dado jogador faltam ainda construir as seguintes partes:
● Interface para perguntar modo de jogo (Humano vs Humano, Computador vs
Computador, Humano vs Computador), interface para perguntar nível de
dificuldade, e ainda uma interface para um jogador efectuar um jogada
● Escolha da melhor jogada de acordo com o nível de dificuldade (Jogada aleatória,
Melhor jogada local, Minimax, etc.)
● Interface de comunicação/controlo usando sockets TCP/IP para modulo em C+
+/OpenGL desenvolvido em LASO
Fazendo o balanço entre o já alcançado e o ainda por alcançar, estima-se que se
tenha completado 35% a 45% do trabalho a realizar.
O jogo Congo alem de ser muito interessante do ponto de vista da inteligência
artificial, também o é do ponto de vista da interface 3D a desenvolver em LASO. Isto
porque além de se desenvolver um modelo de uma peça que pode mover-se em 4
direcções e um tabuleiro (como no caso das damas), no Congo existem 8 peças diferentes
por jogador, com variados movimentos, e ainda um “rio”.
Note-se que, adaptar este motor de jogo para resolver outro qualquer jogo do
género (em tabuleiro, por turnos alternados, estado conhecido), é razoavelmente fácil.
Basta para isso alterar a representação do estado, a geração de jogadas, e o método de
avaliação do estado.
Bibliografia
[1] Eugénio Oliveira e Luís Paulo Reis, Materiais da Disciplina de Programação em Lógica,
disponível online a partir de http://paginas.fe.up.pt/~eol/LP/0809/ (consultado em Outubro de
2008).
[2] Christian Freeling and Ed van Zon, Congo, http://www.mindsports.nl/index.php/side-
dishes/more-games-by-cf?start=31 (consultado em Outubro de 2008)
[3] Leon Sterling e Ehud Shapiro, The Art of Prolog – Advanced Programing Thechniques,
Second Edition; capítulo 16 secção 1 “All-Solutions Predicates”
[4] Daniel Diaz, GNU Prolog Manual, Edition 1,7 (GNU Prolog version 1.2.18)
27
Anexos
Anexo 1: Funcionamento do motor de jogo do Congo
28
Anexo 2: Capturas de ecrâ
29
Figura 11: Captura de ecrâ com um possível meio-jogo 2
30
Anexo 3: Código Fonte
% Congo
%
% Autores:
% Carlos Nunes
% Pedro Cerqueira
%
% FEUP PLOG 2008
%
% tested with gnu prolog "gprolog"
% should be ANSI prolog
% 2 - Lion
% 3 - Elephant
% 4 - Monkey
% 5 - Crocodile
% 6 - Giraffe
% 7 - Zebra
% 8 - SuperPawn
% 9 - Pawn
% i 121 6ª 10 -> 12
% order g, m, e , l, e, c, z
river_y(4).
min_x(1).
min_y(1).
max_x(7).
max_y(7).
%inside_castle(Player, X, Y)
31
inside_castle_aux(X):- X >= 3, X =< 5.
inside_castle(1, X, Y):- inside_castle_aux(X), Y =< 3, !.
inside_castle(2, X, Y):- inside_castle_aux(X), Y >= 5.
initial_board(
[
[ 5, 3, 2, 1, 2, 4, 6],
[ 8, 8, 8, 8, 8, 8, 8],
[ 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0],
[16,16,16,16,16,16,16],
[13,11,10, 9,10,12,14]
]).
initial_river_depth([0,0,0,0,0,0,0]).
test_moves_board(
[
[ 5, 3, 2, 0, 0, 4, 6],
[ 8,16, 0, 0, 1, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0],
[ 0,15, 0, 0, 0, 0,12],
[ 0, 0,10, 0, 0, 8, 0],
[ 0, 0, 0, 8, 0, 0, 0],
[ 0, 0, 0, 0, 9, 0, 0]
]).
test_board_2(
[
[ 0, 3, 0, 1, 0, 4, 6],
[ 0,16, 0, 0, 3, 0, 0],
[ 0, 0, 0, 0, 0, 5, 0],
[ 0,12, 0, 0, 0, 0, 0],
[ 0, 0,10, 0, 0, 8, 0],
[ 0,16, 0, 8, 0, 0, 0],
[ 0, 0, 0, 0, 9, 0, 0]
32
]).
other_player(Player, Other):-
Other is 2 - (Player - 1).
piece_player(Piece, 1):-
Piece >= 1,
Piece =< 8.
piece_player(Piece, 2):-
Piece >= 9,
Piece =< 16.
33
piece(2, giraffe, 13).
piece(2, zebra, 14).
piece(2, superpawn, 15).
piece(2, pawn, 16).
lion(Piece):-piece_type(Piece, 1).
elephant(Piece):-piece_type(Piece, 2).
monkey(Piece):-piece_type(Piece, 3).
crocodile(Piece):-piece_type(Piece, 4).
giraffe(Piece):-piece_type(Piece, 5).
zebra(Piece):-piece_type(Piece, 6).
superpawn(Piece):-piece_type(Piece, 7).
pawn(Piece):-piece_type(Piece, 8).
% == PRINT BOARD ==
horizontal_sep:-
reset_color,
write(' +---------+---------+---------+---------+---------
+---------+---------+'),
nl.
print_board_advanced(Board):-
nl,
write(' A B C D E F
G'),
nl,
print_board_advanced_aux(Board, 1), !.
print_board_advanced_aux([], _):-
horizontal_sep,
!.
34
print_line_adv(1, Line, Y),
Y1 is Y + 1,
print_board_advanced_aux(LinesRem, Y1), !.
numer_or_not(SubLineNum, Y):-
0 =:= (SubLineNum + 2) mod 5,
write(Y), !.
numer_or_not(_, _):-
write(' ').
print_line_adv( 6, _ , _):-!.
set_color(1, 0):-
write('[01;31m').
set_color(2, 0):-
write('[01;37m').
35
% river colors
set_color(1, -1):-
write('[01;31;44m').
set_color(2, -1):-
write('[01;37;44m').
% verde 32 amarelo 33 white 37
% castle colors
set_color(1, -2):-
write('[01;31;47m').
set_color(2, -2):-
write('[01;37;47m').
reset_color:-
write('[00m').
36
print_subcell( Cell, SubLineNum , _, _):-
piece_type(Cell, Type),
piece_player(Cell, Player),
set_color(Player, 0),
txt( Type, SubLineNum ),
reset_color,
write('|'),
!.
print_subcell(_ , _ , X, Y):-
inside_castle(_, X, Y),
set_color(_, -2),
txt(0, _),
reset_color,
%write('[01;47m'),
write('|'),
!.
print_subcell( _, _, _, Y ):-
river_y(Y),
set_color(1, -1),
txt(0, _),
reset_color,
%write('[01;44m'),
write('|'),
!.
print_subcell(_, _, _, _ ):-
reset_color,
txt(0, _),
write('|').
37
print_board_header:-
write(' A B C D E F G'), nl.
print_board(Board):-
nl,
print_board_header,
print_lines(1,Board),
print_board_header,!.
print_lines(_,[]).
print_lines(N,[Line|RemBoard]):-
write(N), write(' '), print_line(N, Line), write(N), nl,
N2 is N+1,
print_lines(N2, RemBoard).
print_line(_, []).
print_line(N, [Cell|RemBoard]):-
river_y(Ry),
N \= Ry,
print_cell(Cell), write(' '),
print_line(N,RemBoard), !.
print_line(N, [0|RemBoard]):-
% Cell =:= 0, % vazio
print_cell(-1), write(' '),
print_line(N, RemBoard), !.
print_line(N, [Cell|RemBoard]):-
print_cell(Cell), write(' '),
print_line(N, RemBoard).
print_cell(0):-write(' ').
print_cell(-1):-write('~~'). % just for printing, theere are no -1 in map
print_cell(-2):-write('..'). % just for printing, theere are no -1 in map
print_cell(1):-write('L1').
38
print_cell(2):-write('E1').
print_cell(3):-write('M1').
print_cell(4):-write('C1').
print_cell(5):-write('G1').
print_cell(6):-write('Z1').
print_cell(7):-write('S1').
print_cell(8):-write('P1').
print_cell(9):-write('L2').
print_cell(10):-write('E2').
print_cell(11):-write('M2').
print_cell(12):-write('C2').
print_cell(13):-write('G2').
print_cell(14):-write('Z2').
print_cell(15):-write('S2').
print_cell(16):-write('P2').
% ============================
% movement coords predicates
% ============================
move_coords( (x0, yn, D), X, Y, X1, Y1):- X1 is X, Y1 is Y - D, inside(X1,
Y1).
move_coords( (x0, ys, D), X, Y, X1, Y1):- X1 is X, Y1 is Y + D, inside(X1,
Y1).
move_coords( (xe, y0, D), X, Y, X1, Y1):- X1 is X + D, Y1 is Y, inside(X1,
Y1).
move_coords( (xw, y0, D), X, Y, X1, Y1):- X1 is X - D, Y1 is Y, inside(X1,
Y1).
move_coords( (xe, yn, D), X, Y, X1, Y1):-
X1 is X + D, Y1 is Y - D, inside(X1, Y1).
move_coords( (xw, yn, D), X, Y, X1, Y1):-
X1 is X - D, Y1 is Y - D, inside(X1, Y1).
39
move_coords( (xe, ys, D), X, Y, X1, Y1):-
X1 is X + D, Y1 is Y + D, inside(X1, Y1).
move_coords( (xw, ys, D), X, Y, X1, Y1):-
X1 is X - D, Y1 is Y + D, inside(X1, Y1).
% ============================
% BOARD RELATED UTILS
% ===========================
empty(X, Y, Board):-
what_is_at(X, Y, Board, 0).
40
empty_path_line(X, Y, X1, Board):-
minimum(X, X1, Xmin),
maximum(X, X1, Xmax),
Xmin1 is Xmin + 1,
Xmin1 =< Xmax,
empty_path_line_aux(Xmin1, Y, Xmax, Board), !.
empty_path_line_aux(X, _, X, _).
% ================
empty_path_column_aux(_, Y, Y, _).
41
Xinc_a =< 1,
abs(Yinc, Yinc_a),
Yinc_a =< 1,
Xmid is X + Xinc,
Ymid is Y + Yinc.
from_other_player(Player, X, Y, Board):-
other_player(Player, Other),
what_is_at(X, Y, Board, W),
piece_player(W, Other).
42
% ============================
% change board cells
% ============================
test1:-
initial_board(B),
change_board(3, 4, 9, B, Newboard),
print_board(Newboard).
43
By1 is Y + 1,
change_board_aux(X, Y, Value, By1, BoardRes, NewRes).
apply_move(Player, monkey-submove-(Xi,Yi)-[(Xcapture,Ycapture)*(Xf,Yf)],
Board, NewBoard):-
change_board(Xi, Yi, 0, Board, NewBoard1),
change_board(Xcapture, Ycapture, 0, NewBoard1, NewBoard2),
piece(Player, monkey, PieceValue),
change_board(Xf, Yf, PieceValue, NewBoard2, NewBoard).
apply_move(Player, monkey-multiple-(Xi,Yi)-[(Xcapture,Ycapture)*(Xf,Yf)|
Resto], Board, NewBoard):-
apply_move(Player, monkey-submove-(Xi,Yi)-[(Xcapture,Ycaptu-
re)*(Xf,Yf)], Board, Board1),
apply_move(Player, monkey-multiple-(Xf,Yf)-Resto, Board1, NewBo-
ard),
!.
44
inc_river_pieces_depth( [ PieceDepth | RiverDepthRest ], [ PieceDepth | Ne-
wRiverDepthRest ] ):-
PieceDepth =:= 0, % no piece in this river position
inc_river_pieces_depth(RiverDepthRest, NewRiverDepthRest), !.
membro_pos_lista(Membro, N, Lista):-
membro_pos_procura(Membro, 1, N, Lista).
membro_pos_procura(Membro, N, N, [Membro|_]).
membro_pos_procura(Membro, P, N, [_|T]):-
P2 is P+1,
membro_pos_procura(Membro, P2, N, T).
% end of from Damas by Luis Paulo Reis
print_moves(Player, Board):-
%initial_board(Board),
list_moves(Player, Board, Lista),
nl, write(Lista),
print_board(Board),
print_board_advanced(Board).
45
% lion special capture of oposite lion (same column)
valid_move(Player, lion-(X,Y)-(Xf,Yf) , Board):-
piece(Player, lion, BoardValue),
membrotab(BoardValue, X, Y, Board),
% where is the other lion?
other_player(Player, OtherPlayer),
piece(OtherPlayer, lion, OBoardValue),
membrotab(OBoardValue, OX, OY, Board),
X =:= OX,
% no one between them
empty_path_column(X, Y, OY, Board),
Xf is OX,
Yf is OY.
46
move_coords( (xw, y0, 1), X, Y, Xf, Yf) ;
% elephant "jumps"
move_coords( (x0, ys, 2), X, Y, Xf, Yf) ;
move_coords( (x0, yn, 2), X, Y, Xf, Yf) ;
move_coords( (xe, y0, 2), X, Y, Xf, Yf) ;
move_coords( (xw, y0, 2), X, Y, Xf, Yf)
),
( empty(Xf,Yf, Board) ; from_other_player(Player, Xf, Yf, Board) ).
47
empty_path_column(X, Y, Yf, Board),
( empty(Xf,Yf, Board) ; from_other_player(Player, Xf, Yf, Board) ).
48
move_coords( (xw, ys, 1), X, Y, Xf, Yf) ;
move_coords( (xe, y0, 1), X, Y, Xf, Yf) ;
move_coords( (xw, y0, 1), X, Y, Xf, Yf)
),
( empty(Xf,Yf, Board) ; from_other_player(Player, Xf, Yf, Board) ).
% pawn move/capture
valid_move(Player, pawn-(X,Y)-(Xf,Yf) , Board):-
piece(Player, pawn, BoardValue),
membrotab(BoardValue, X, Y, Board),
( move_coords( (x0, ys, 1), X, Y, Xf, Yf) ;
move_coords( (xe, ys, 1), X, Y, Xf, Yf) ;
move_coords( (xw, ys, 1), X, Y, Xf, Yf) ),
49
( empty(Xf,Yf, Board) ; from_other_player(Player, Xf, Yf, Board) ).
% pawn retreat move (not capture) when after river (1 cell distance)
valid_move(Player, pawn-(X,Y)-(Xf,Yf) , Board):-
piece(Player, pawn, BoardValue),
membrotab(BoardValue, X, Y, Board),
river_y(Yriver),
Yafter_river is Yriver + 1,
Yafter_river == Y,
move_coords( (x0, yn, 1), X, Y, Xf, Yf),
empty(Xf,Yf, Board).
% pawn retreat move (not capture) when after river (2 cell distance)
valid_move(Player, pawn-(X,Y)-(Xf,Yf) , Board):-
piece(Player, pawn, BoardValue),
membrotab(BoardValue, X, Y, Board),
river_y(Yriver),
Yafter_river is Yriver + 1,
Yafter_river == Y,
move_coords( (x0, yn, 2), X, Y, Xf, Yf),
middle_cell(X, Y, Xf, Yf, Xmid, Ymid),
empty(Xmid,Ymid, Board),
empty(Xf,Yf, Board).
50
optional_submove(Player,Pf,Board2).
optional_submove(_,_,_).
valid_monkey_submove(Player, monkey-submove-(X,Y)-[(XCome,YCome)*(Xf,Yf)],
Board):-
piece(Player, monkey, BoardValue),
membrotab(BoardValue, X, Y, Board),
move_coords( (_, _, 2), X, Y, Xf, Yf),
empty(Xf,Yf, Board),
middle_cell(X, Y, Xf, Yf, XCome, YCome),
from_other_player(Player, XCome, YCome, Board).
txt(0,_):-write(' ').
txt(2,1):-write(' / | ').
txt(2,2):-write(' | o | ').
txt(2,3):-write(' | /\\_ ').
txt(2,4):-write(' <==/ ').
txt(2,5):-write(' \\\\ ').
51
txt(3,1):-write(' ___ ').
txt(3,2):-write(' ^|o o|^ ').
txt(3,3):-write(' | " | ').
txt(3,4):-write(' \\_/ ').
txt(3,5):-write(' ').
txt(4,1):-write(' ').
txt(4,2):-write(' \\ _ ').
txt(4,3):-write(' \\/.\\_ ').
txt(4,4):-write(' ------- ').
txt(4,5):-write(' ').
txt(5,1):-write(' oo ').
txt(5,2):-write(' ||/\\ ').
txt(5,3):-write(' | . \\ ').
txt(5,4):-write(' | _ \\ ').
txt(5,5):-write(' | | \\/ ').
txt(8,1):-write(' _ ').
txt(8,2):-write(' /_\\ ').
txt(8,3):-write(' \\ / ').
txt(8,4):-write(' |_| ').
txt(8,5):-write(' /___\\ ').
52