2022.1 Prova 4 - Questão 1: Agente inteligente para o jogo de xadrez#
Vamos desenvolver a base para um agente inteligente capaz de jogar xadrez. O objetivo não é construir o agente em si, mas preparar as funções necessárias.
Nesta atividade utilizaremos apenas um subconjunto das peças existentes: rei (♔), cavalo (♘), torre (♖) e bispo (♗). Cada peça tem uma maneira de se mover pelo tabuleiro. Esses movimentos estão indicados na página de movimentos.
Note que estamos usando um tabuleiro invertido no eixo \(y\) em relação a tabuleiros comuns. Isso foi feito para os índices da matriz e do tabuleiro ficarem parecidos.
Esta notação é mostrada na figura a seguir.
Também note que sempre vamos fazer as análises do ponto de vista de uma peça de cada vez apenas, e ainda que valem regras diferentes das do xadrez, para simplicidade:
- Pode-se capturar o rei
- O jogo continua sem o rei
- Os valores considerados para as peças não são acurados
Importante
Faça o download do exercício pelo link no final desta página!
Nível Básico (C)#
Para o nível básico, você deve implementar uma função chamada calcula_movimentos_possiveis(tabuleiro, peca, linha, coluna)
para o rei, bispo e torre (o cavalo está no proficiente). O tabuleiro é representado por uma lista com 8 listas, com 8 strings cada. Cada elemento dessa lista de listas será uma das strings abaixo:
String | Significado | Em português | |
---|---|---|---|
'' |
String vazia | Espaço vazio | |
'PM' |
Possible Movement | Movimento possível | |
♔ | 'WK' |
White King | Rei Branco |
♘ | 'WN' |
White kNight | Cavalo Branco |
♖ | 'WR' |
White Rook | Torre Branca |
♗ | 'WB' |
White Bishop | Bispo Branco |
♚ | 'BK' |
Black King | Rei Preto |
♞ | 'BN' |
Black kNight | Cavalo Preto |
♜ | 'BR' |
Black Rook | Torre Preta |
♝ | 'BB' |
Black Bishop | Bispo Preto |
Note que além das peças e do espaço vazio, temos também 'PM'
, que indica que aquela posição pode ser alcançada a partir da posição atual de uma determinada peça.
Alguns exemplos:
Exemplo 1#
No exemplo abaixo temos um bispo preto na linha 3 e coluna 5:
[
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', 'BB', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
]
Exemplo 2#
No exemplo abaixo temos um cavalo branco na linha 2 e coluna 4 e um rei preto na linha 4 e coluna 5.
[
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', 'WN', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', 'BK', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
]
A função calcula_movimentos_possiveis(tabuleiro, peca, linha, coluna)
deve receber um tabuleiro representado como a lista de listas descrita acima, uma peça (string da tabela acima) e a sua posição (linha e coluna). A função deve:
- Adicionar a peça na posição indicada (linha e coluna);
- Preencher todas as posições para as quais a peça pode se mover com a string
'PM'
.
Os movimentos de cada peça podem ser encontrados na página de movimentos.
Para o nível básico a função não precisa se preocupar com a presença de outras peças no tabuleiro. Ou seja, no nível básico você pode supor que o tabuleiro sempre virá vazio. Exemplos:
Para o tabuleiro de entrada abaixo:
[
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
]
Com a peça 'BB'
, a linha 3
e a coluna 2
, sua função deve devolver a matriz (lista de listas):
[
['', '', '', '', '', 'PM', '', ''],
['PM', '', '', '', 'PM', '', '', ''],
['', 'PM', '', 'PM', '', '', '', ''],
['', '', 'BB', '', '', '', '', ''],
['', 'PM', '', 'PM', '', '', '', ''],
['PM', '', '', '', 'PM', '', '', ''],
['', '', '', '', '', 'PM', '', ''],
['', '', '', '', '', '', 'PM', ''],
]
Para o mesmo tabuleiro vazio, a peça 'WN'
, a linha 1
e coluna 4
, sua função deve devolver a matriz:
[
['', '', 'PM', '', '', '', 'PM', ''],
['', '', '', '', 'WN', '', '', ''],
['', '', 'PM', '', '', '', 'PM', ''],
['', '', '', 'PM', '', 'PM', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
]
Nível Proficiente (B)#
Para o nível proficiente, você deve modificar a sua função calcula_movimentos_possiveis
para que ela também considere a existência de outras peças no tabuleiro. Assim, os movimentos devem ser limitados em caso de oclusão ou bloqueio por outras peças.
Quando existe uma peça em seu caminho, o movimento da torre, bispo e rei são limitados (o cavalo pode se mover mesmo se houver oclusão). Neste caso, o caminho fica interrompido pela peça. Existem duas possibilidades:
- Quando é uma peça inimiga no caminho, ela pode ser capturada;
- Quando é uma peça da mesma cor, o caminho é interrompido uma casa antes.
Veja os exemplos abaixo:
O bispo branco está na posição 4,4
Quando são encontrados os movimentos possíveis, as peças brancas interrompem seu caminho. As peças pretas podem ser capturadas por este bispo, portanto a posição do adversário é uma posição possível de alcançar.
Note que na imagem abaixo quando temos um bispo preto, a situação se inverte. Este bispo pode avançar nas casas em que havia peças brancas, capturando-as.
Você agora também deve implementar os movimentos possíveis para o cavalo.
Nível Avançado (A)#
Você deve agora criar a função analisa_ameaças
que recebe uma matriz com o tabuleiro, uma linha, uma coluna, e uma string que identifica uma peça.
Esta função devolve uma nova matriz (do tipo lista de listas) em que só há "PM" nas casas em que a peça que vai se movimentar não corre o risco de ser capturada por um inimigo na jogada seguinte.
O objetivo é calcular os movimentos possíveis daquela peça, depois remover o sinal "PM" das posições que são atacadas por peças inimigas.
Vejamos o exemplo a seguir:
Inicialmente chamamos a função calcula_movimentos_possiveis
assim como nos exercícios anteriores.
Agora encontramos as posições em que a peça não será capturada por nenhum inimigo.
OBS.: A posição que contém uma peça inimiga não é atacada por ela.
Essa sua função precisa fazer um uso inteligente da função
calcula_movimentos_possiveis
Dica: A função calcula_movimentos_possíveis sobrescreve os conteúdos da matriz de entrada.
Se você quiser criar uma cópia antes de sobrescrever, use a função copy.deepcopy()
.