-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodels.py
More file actions
195 lines (161 loc) · 8.62 KB
/
Copy pathmodels.py
File metadata and controls
195 lines (161 loc) · 8.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
from pydantic import BaseModel, field_validator
from typing import List, Optional, Literal, Dict, Tuple
# Definindo um modelo Pydantic para uma peça de damas
class Peca(BaseModel):
tipo: Literal["vazia", "normal", "dama"]
cor: Optional[Literal["branca", "preta"]] = None
@field_validator('cor')
def validar_cor(cls, v, info):
if info.data.get('tipo') != 'vazia' and v is None:
raise ValueError("Peças não vazias devem ter uma cor")
if info.data.get('tipo') == 'vazia' and v is not None:
raise ValueError("Peças vazias não devem ter cor")
return v
# Definindo um modelo para o tabuleiro de damas
class TabuleiroDeXadrez(BaseModel):
tabuleiro: List[List[Peca]]
tamanho: int = 8
@field_validator('tabuleiro')
def validar_tabuleiro(cls, v, info):
tamanho = info.data.get('tamanho', 8)
if len(v) != tamanho:
raise ValueError(f"O tabuleiro deve ter {tamanho} linhas")
for i, linha in enumerate(v):
if len(linha) != tamanho:
raise ValueError(f"A linha {i} deve ter {tamanho} colunas")
return v
def criar_representacao_visual(self) -> str:
"""Cria uma representação visual do tabuleiro"""
representacao = " 0 1 2 3 4 5 6 7\n"
for i, linha in enumerate(self.tabuleiro):
linha_visual = [f"{i}"]
for celula in linha:
if celula.tipo == "vazia":
simbolo = "·"
elif celula.tipo == "normal":
simbolo = "○" if celula.cor == "branca" else "●"
else: # dama
simbolo = "□" if celula.cor == "branca" else "■"
linha_visual.append(simbolo)
representacao += " ".join(linha_visual) + "\n"
return representacao
def criar_representacao_markdown(self) -> str:
"""Cria uma representação visual do tabuleiro em formato Markdown"""
representacao = "| |0|1|2|3|4|5|6|7|\n"
representacao += "|---|---|---|---|---|---|---|---|---|\n"
for i, linha in enumerate(self.tabuleiro):
linha_visual = [f"**{i}**"]
for celula in linha:
if celula.tipo == "vazia":
simbolo = "·"
elif celula.tipo == "normal":
simbolo = "⚪" if celula.cor == "branca" else "⚫"
else: # dama
simbolo = "⭕" if celula.cor == "branca" else "⏺"
linha_visual.append(simbolo)
representacao += "|" + "|".join(linha_visual) + "|\n"
return representacao
def obter_movimentos_validos(self, cor: Literal["branca", "preta"]) -> List[Dict]:
"""Retorna todos os movimentos válidos para a cor especificada"""
movimentos = []
# Direções de movimento básicas (dependendo da cor)
direcoes_basicas = [(-1, -1), (-1, 1)] if cor == "branca" else [(1, -1), (1, 1)]
direcoes_dama = [(-1, -1), (-1, 1), (1, -1), (1, 1)] # Damas podem se mover em todas as direções
# Verifica cada posição no tabuleiro
for linha in range(self.tamanho):
for coluna in range(self.tamanho):
peca = self.tabuleiro[linha][coluna]
# Verifica se a peça é da cor atual
if peca.tipo != "vazia" and peca.cor == cor:
direcoes = direcoes_dama if peca.tipo == "dama" else direcoes_basicas
# Verifica movimentos simples
for dr, dc in direcoes:
nova_linha, nova_coluna = linha + dr, coluna + dc
if (0 <= nova_linha < self.tamanho and
0 <= nova_coluna < self.tamanho and
self.tabuleiro[nova_linha][nova_coluna].tipo == "vazia"):
# Verifica se uma peça normal se tornará uma dama
novo_tipo = peca.tipo
if peca.tipo == "normal":
if (cor == "branca" and nova_linha == 0) or (cor == "preta" and nova_linha == 7):
novo_tipo = "dama"
movimentos.append({
"de": (linha, coluna),
"para": (nova_linha, nova_coluna),
"captura": False,
"novo_tipo": novo_tipo
})
# Verifica capturas
capturas = self._encontrar_capturas(linha, coluna, peca)
movimentos.extend(capturas)
# Prioriza capturas (regra de damas: se existir uma captura, ela deve ser realizada)
capturas = [m for m in movimentos if m["captura"]]
return capturas if capturas else movimentos
def _encontrar_capturas(self, linha: int, coluna: int, peca: Peca) -> List[Dict]:
"""Encontra todas as capturas possíveis para uma peça"""
capturas = []
direcoes = [(-1, -1), (-1, 1), (1, -1), (1, 1)] # Todas as direções diagonais
for dr, dc in direcoes:
# Verifica se é uma peça normal com restrição de direção
if peca.tipo == "normal" and peca.cor == "branca" and dr > 0:
continue
if peca.tipo == "normal" and peca.cor == "preta" and dr < 0:
continue
# Posição do oponente potencial
linha_op, coluna_op = linha + dr, coluna + dc
# Posição após a captura
linha_destino, coluna_destino = linha + 2*dr, coluna + 2*dc
if (0 <= linha_op < self.tamanho and
0 <= coluna_op < self.tamanho and
0 <= linha_destino < self.tamanho and
0 <= coluna_destino < self.tamanho):
# Verifica se há uma peça oponente para capturar
peca_op = self.tabuleiro[linha_op][coluna_op]
if (peca_op.tipo != "vazia" and
peca_op.cor != peca.cor and
self.tabuleiro[linha_destino][coluna_destino].tipo == "vazia"):
# Verifica se uma peça normal se tornará uma dama
novo_tipo = peca.tipo
if peca.tipo == "normal":
if (peca.cor == "branca" and linha_destino == 0) or (peca.cor == "preta" and linha_destino == 7):
novo_tipo = "dama"
capturas.append({
"de": (linha, coluna),
"para": (linha_destino, coluna_destino),
"captura": True,
"captura_posicao": (linha_op, coluna_op),
"novo_tipo": novo_tipo
})
return capturas
def realizar_movimento(self, movimento: Dict) -> 'TabuleiroDeXadrez':
"""Realiza um movimento e retorna o novo tabuleiro"""
novo_tabuleiro = self.model_copy(deep=True)
linha_origem, coluna_origem = movimento["de"]
linha_destino, coluna_destino = movimento["para"]
# Pega a peça de origem
peca = novo_tabuleiro.tabuleiro[linha_origem][coluna_origem]
# Define o tipo correto na posição de destino (pode virar dama)
novo_tabuleiro.tabuleiro[linha_destino][coluna_destino] = Peca(
tipo=movimento["novo_tipo"],
cor=peca.cor
)
# Esvazia a posição de origem
novo_tabuleiro.tabuleiro[linha_origem][coluna_origem] = Peca(tipo="vazia", cor=None)
# Se for uma captura, remove a peça capturada
if movimento["captura"]:
linha_captura, coluna_captura = movimento["captura_posicao"]
novo_tabuleiro.tabuleiro[linha_captura][coluna_captura] = Peca(tipo="vazia", cor=None)
return novo_tabuleiro
# Classe para armazenar informações sobre uma jogada
class Jogada(BaseModel):
numero: int
cor: Literal["branca", "preta"]
modelo: str
de: Tuple[int, int]
para: Tuple[int, int]
captura: bool
captura_posicao: Optional[Tuple[int, int]] = None
tabuleiro_apos: Dict # Dados do tabuleiro após a jogada
resposta_llm: str # Resposta original da LLM
movimento_escolhido: Dict # Movimento que a LLM escolheu
duracao: float # Tempo que levou para a LLM decidir