-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvisualizador-snake-pddl.py
212 lines (166 loc) · 9.04 KB
/
visualizador-snake-pddl.py
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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# IMPORTANTE QUE O PLANO SEJA CORRESPONDENTE AO PROBLEMA!
# BASEADO NO PLANO GERADO PELO MADAGASCAR, NÃO SEI SE
# OUTROS FUNCIONARIAM SEM ALGUNS AJUSTES.
import os
os.environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "hide"
import pygame, sys, time
# Constantes:
VAZIO_INV = -1
VAZIO = 0
CORPO = 1
CABECA = 2
MACA = 3
LADO_QUADRADO = 50
# Cores:
BRANCO = (255, 255, 255)
PRETO = (0, 0, 0)
VERDE = (0, 180, 0)
VERDE_ESCURO = (0, 64, 0)
VERMELHO = (200, 0, 0)
CINZA = (20, 20, 20)
CINZA_ESCURO = (70, 70, 70)
LARANJA = (200, 100, 0)
# Inicializando pygame:
pygame.init()
pygame.display.set_caption("Visualizador Snake - YOGI")
FONT = pygame.font.SysFont("Segoe UI", 15)
def main():
if len(sys.argv) != 3 and len(sys.argv) != 4:
print("Usage: python [visualizador-snake-pddl.py] [problem-name] [plan-name] [opt-interval]")
return -1
arquivo_problema = open(sys.argv[1], "rt")
arquivo_plano = open(sys.argv[2], "rt")
dimensoes_mapa = {}
mapa, coord_maca, cobra = [], [], []
apos_objects = False
for linha in arquivo_problema.readlines():
x_idx = linha.rfind('s') + 1 # Início da coordenada x
y_idx = linha.rfind('-') + 1 # Início da coordenada y
if not apos_objects and linha.find("objects") != -1:
apos_objects = True # Na linha após objects temos as dimensões do mapa
elif linha.find("goal") != -1:
break
elif apos_objects:
dimensoes_mapa['y'] = int(linha[y_idx:]) + 1
dimensoes_mapa['x'] = int(linha[x_idx:y_idx - 1]) + 1
mapa = [0] * dimensoes_mapa['x'] * dimensoes_mapa['y']
apos_objects = False # Não queremos sobreescrever sem querer as dimensões
elif linha.find("nextsnake") != -1:
mapa[int(linha[x_idx:y_idx - 1]) + int(linha[y_idx:linha.rfind(')')]) * dimensoes_mapa['x']] = CORPO
elif linha.find("headsnake") != -1:
mapa[int(linha[x_idx:y_idx - 1]) + int(linha[y_idx:linha.rfind(')')]) * dimensoes_mapa['x']] = CABECA
elif linha.find("ispoint") != -1:
coord_maca.append(int(linha[x_idx:y_idx - 1]) + int(linha[y_idx:linha.rfind(')')]) * dimensoes_mapa['x'])
# Janela
comprimento = (dimensoes_mapa['x'] + 2) * LADO_QUADRADO
altura = (dimensoes_mapa['y'] + 2) * LADO_QUADRADO
janela = pygame.display.set_mode((comprimento, altura))
# Listas com elementos que serão adicionados e retirados do mapa
passos, novas_cabecas, antigas_cabecas, antigas_caldas, novas_macas = [], [], [], [], []
for linha in arquivo_plano.readlines():
if linha.find("move") != -1:
passos.append(linha.removeprefix("STEP ").removesuffix('\n'))
x_idx = linha.find("pos") + 3
y_idx = x_idx + linha[x_idx:].find('-') + 1
virgula_idx = linha[y_idx:].find(',') + y_idx
antigas_cabecas.append((int(linha[x_idx:y_idx - 1]), int(linha[y_idx:virgula_idx])))
x_idx = y_idx + linha[y_idx:].find("pos") + 3
y_idx = x_idx + linha[x_idx:].find('-') + 1
virgula_parenteses_idx = linha[y_idx:].find(',') + y_idx
if virgula_parenteses_idx == y_idx - 1:
virgula_parenteses_idx = linha.find(')')
novas_cabecas.append((int(linha[x_idx:y_idx - 1]), int(linha[y_idx:virgula_parenteses_idx])))
x_idx = y_idx + linha[y_idx:].find("pos") + 3
y_idx = x_idx + linha[x_idx:].find('-') + 1
virgula_idx = linha[y_idx:].find(',') + y_idx
if linha.find("move-and-eat-spawn") != -1:
novas_macas.append((int(linha[x_idx:y_idx - 1]), int(linha[y_idx:virgula_idx])))
elif linha.find("move-and-eat-no-spawn") == -1:
antigas_caldas.append((int(linha[x_idx:y_idx - 1]), int(linha[y_idx:virgula_idx])))
arquivo_problema.close()
arquivo_plano.close()
rodando = True
qnt_movimentos, pontos = 0, 0
while rodando:
for evento in pygame.event.get():
if evento.type == pygame.QUIT:
rodando = False
break
janela.fill(PRETO)
if qnt_movimentos < len(novas_cabecas): # Cada nova cabeça corresponde à 1 movimento, não excedemos
text = FONT.render(passos[qnt_movimentos], True, BRANCO)
else:
text = FONT.render(f"FIM, TOTAL DE {qnt_movimentos} PASSOS/AÇÕES :)", True, BRANCO)
for i in range(dimensoes_mapa['y']):
for j in range(dimensoes_mapa['x']):
if mapa[j + i * dimensoes_mapa['x']] == 1:
mapa[j + i * dimensoes_mapa['x']] = -1
# Passos
janela.blit(text, (5, 0))
# Posições do mapa
pygame.draw.line(janela, CINZA, (0, LADO_QUADRADO / 2), (comprimento, LADO_QUADRADO / 2), 2)
# Pontos
janela.blit(FONT.render(str(pontos + 2), True, BRANCO),
(comprimento - LADO_QUADRADO / 1.7, LADO_QUADRADO))
# Adiciona as maçãs da lista no mapa se tiver espaço para elas
for coord in coord_maca:
if mapa[coord] == VAZIO:
mapa[coord] = MACA
for i in range(dimensoes_mapa['y']):
janela.blit(FONT.render(str(i), True, CINZA_ESCURO), (LADO_QUADRADO - 20, (i + 1) * LADO_QUADRADO + 3))
for i in range(dimensoes_mapa['x']):
janela.blit(FONT.render(str(i), True, CINZA_ESCURO), ((i + 1) * LADO_QUADRADO + 3, LADO_QUADRADO - 20))
# Itera o mapa pintando cada quadradinho e linhas
for i in range(dimensoes_mapa['y']):
for j in range(dimensoes_mapa['x']):
valor = mapa[j + i * dimensoes_mapa['x']]
x = (j + 1) * LADO_QUADRADO
y = (i + 1) * LADO_QUADRADO
cor = PRETO
if valor == CORPO:
cor = VERDE
elif valor == CABECA:
cor = VERDE_ESCURO
elif valor == MACA:
pygame.draw.rect(janela, PRETO, (x, y, LADO_QUADRADO, LADO_QUADRADO)) # Fundo do mapa
pygame.draw.rect(janela, VERMELHO, (x + LADO_QUADRADO / 3, y + LADO_QUADRADO / 3,
LADO_QUADRADO / 3, LADO_QUADRADO / 3)) # Maçã
pygame.draw.rect(janela, VERDE, (x + LADO_QUADRADO / 3 + 1, y + LADO_QUADRADO / 3 - 6,
LADO_QUADRADO / 6, LADO_QUADRADO / 6)) # Folha
elif valor == VAZIO_INV:
cor = BRANCO
if valor != MACA:
pygame.draw.rect(janela, cor, (x, y, LADO_QUADRADO, LADO_QUADRADO)) # Cobra ou fundo do mapa
pygame.draw.line(janela, CINZA, (x, LADO_QUADRADO),
(x, altura - LADO_QUADRADO), 2) # Linhas verticais
pygame.draw.line(janela, CINZA, (LADO_QUADRADO, (i + 1) * LADO_QUADRADO),
(comprimento - LADO_QUADRADO, (i + 1) * LADO_QUADRADO), 2) # Linhas horizontais
# Linha vertical laranja
pygame.draw.line(janela, LARANJA, ((dimensoes_mapa['x'] + 1) * LADO_QUADRADO, LADO_QUADRADO),
((dimensoes_mapa['x'] + 1) * LADO_QUADRADO, altura - LADO_QUADRADO), 2)
# Linha horizontal laranja
pygame.draw.line(janela, LARANJA, (LADO_QUADRADO, (dimensoes_mapa['y'] + 1) * LADO_QUADRADO),
(comprimento - LADO_QUADRADO, (dimensoes_mapa['y'] + 1) * LADO_QUADRADO), 2)
# Enquanto ainda há passos/movimentos
if qnt_movimentos < len(novas_cabecas):
# Se não comemos uma maçã nesse passo/movimento, deleta a calda antiga
if coord_maca.count(novas_cabecas[qnt_movimentos][0] + novas_cabecas[qnt_movimentos][1] * dimensoes_mapa['x']) == VAZIO:
mapa[antigas_caldas[qnt_movimentos - pontos][0] + antigas_caldas[qnt_movimentos - pontos][1] * dimensoes_mapa['x']] = VAZIO
# Se comemos, deleta a maçã comida e se ainda tiver cria uma nova
else:
coord_maca.remove(novas_cabecas[qnt_movimentos][0] + novas_cabecas[qnt_movimentos][1] * dimensoes_mapa['x'])
if pontos < len(novas_macas):
coord_maca.append(novas_macas[pontos][0] + novas_macas[pontos][1] * dimensoes_mapa['x'])
pontos += 1
mapa[novas_cabecas[qnt_movimentos][0] + novas_cabecas[qnt_movimentos][1] * dimensoes_mapa['x']] = 2 # Cria nova cabeça
mapa[antigas_cabecas[qnt_movimentos][0] + antigas_cabecas[qnt_movimentos][1] * dimensoes_mapa['x']] = 1 # Deleta cabeça antiga
qnt_movimentos += 1
# Velocidade da cobrinha (menor = mais rápido)
if len(sys.argv) == 3:
time.sleep(0.2)
else:
time.sleep(float(sys.argv[3]))
# Atualizar a tela
pygame.display.flip()
if __name__ == '__main__':
main()