BomberMan/iachallenge2024_bomberman_t...

383 lines
16 KiB
Python

# -*- coding: utf-8 -*-
"""
Created on Wed Sep 12 13:52:48 2018
@author: Laurent
"""
TEMPS_BASE = 1
TEMPS_PROPAGATION = 0.01
TEMPS_EXPLOSION = 5.5
TEMPS_PARTIE = 100
E_INSTANT = 0
E_NATURE = 1
EVENEMENT_TOUR_JOUEUR = 1
EVENEMENT_EXPLOSION_BOMBE = 2
EVENEMENT_PROPAGATION = 3
PLATEAU_VIDE = 0
PLATEAU_PIERRE = 1
PLATEAU_BOIS = 2
DIRECTION_NORD = 0
DIRECTION_EST = 1
DIRECTION_SUD = 2
DIRECTION_OUEST = 3
DIRECTION_ATTENTE = 4
B_LIGNE = 0
B_COLONNE = 1
B_LONGUEURFLAMMES = 2
B_JOUEUR = 3
B_INSTANT = 4
J_LIGNE = 0
J_COLONNE = 1
J_DECISION = 2
J_VITESSE = 3
J_NOMBREBOMBES = 4
J_LONGUEURFLAMMES = 5
J_BOMBESRESTANTES = 6
J_DASHSRESTANTS = 7
J_PIEGESRESTANTS = 8
J_TOURSDASH = 9
A_BOMBE = 1
A_DASH = 2
A_PIEGE = 3
POWERUP_VITESSE = 0
POWERUP_NOMBREBOMBES = 1
POWERUP_LONGUEURFLAMMES = 2
POWERUP_DASH = 3
POWERUP_PIEGE = 4
PU_LIGNE = 0
PU_COLONNE = 1
PU_NATURE = 2
from random import randrange
from copy import deepcopy
from tkinter import *
from os import system
def attente(vitesse):
return TEMPS_BASE * 0.9**vitesse
def cree_plateau_initial(lignes, colonnes, nombreDeTrous):
plateau = [[PLATEAU_BOIS for i in range(colonnes+2)] for j in range(lignes+2)]
for i in range(2, lignes+1,2):
for j in range(2, colonnes+1, 2):
plateau[i][j]=PLATEAU_PIERRE
for i in range(0, lignes+2):
plateau[i][0] = PLATEAU_PIERRE
plateau[i][-1] = PLATEAU_PIERRE
for j in range(0, colonnes+2):
plateau[0][j] = PLATEAU_PIERRE
plateau[-1][j] = PLATEAU_PIERRE
plateau[1][1] = plateau[1][2] = plateau[2][1] = PLATEAU_VIDE
plateau[1][-2] = plateau[1][-3] = plateau[2][-2] = PLATEAU_VIDE
plateau[-2][1] = plateau[-2][2] = plateau[-3][1] = PLATEAU_VIDE
plateau[-2][-2] = plateau[-2][-3] = plateau[-3][-2] = PLATEAU_VIDE
for i in range(nombreDeTrous):
i,j=0,0
while plateau[i][j] != PLATEAU_BOIS:
i=randrange(lignes)
j=randrange(colonnes)
plateau[i][j] = PLATEAU_VIDE
return plateau
def affiche_plateau(canvas, plateau, plateauCouleur, bombes, joueurs, powerups):
canvas.delete(ALL)
for i in range(len(plateau)):
for j in range(len(plateau[0])):
if plateau[i][j]==PLATEAU_PIERRE:
canvas.create_rectangle(j*TAILLE_TUILE, i*TAILLE_TUILE, j*TAILLE_TUILE+TAILLE_TUILE, i*TAILLE_TUILE+TAILLE_TUILE, fill="black")
elif plateau[i][j]==PLATEAU_BOIS:
canvas.create_rectangle(j*TAILLE_TUILE, i*TAILLE_TUILE, j*TAILLE_TUILE+TAILLE_TUILE, i*TAILLE_TUILE+TAILLE_TUILE, fill="brown")
else:
if plateauCouleur[i][j]!=-1:
couleurJoueur = COULEURS_JOUEURS[plateauCouleur[i][j]]
canvas.create_rectangle(j*TAILLE_TUILE, i*TAILLE_TUILE, j*TAILLE_TUILE+TAILLE_TUILE, i*TAILLE_TUILE+TAILLE_TUILE, fill=couleurJoueur, outline = couleurJoueur)
if trouve_objet(i,j, bombes)!=None:
canvas.create_oval(j*TAILLE_TUILE+5, i*TAILLE_TUILE+5, j*TAILLE_TUILE+TAILLE_TUILE-5, i*TAILLE_TUILE+TAILLE_TUILE-5, fill="cyan")
if trouve_objet(i,j, joueurs)!=None:
couleurJoueur = COULEURS_JOUEURS[trouve_objet(i,j, joueurs)]
trace_bomberman(canvas, j*TAILLE_TUILE, i*TAILLE_TUILE, couleurJoueur)
if trouve_objet(i,j, powerups)!=None:
couleurPowerup = COULEURS_POWERUPS[powerups[trouve_objet(i,j, powerups)][PU_NATURE]]
canvas.create_polygon(j*TAILLE_TUILE+TAILLE_TUILE/2, i*TAILLE_TUILE, j*TAILLE_TUILE, i*TAILLE_TUILE+TAILLE_TUILE/2, j*TAILLE_TUILE+TAILLE_TUILE/2, (i+1)*TAILLE_TUILE, (j+1)*TAILLE_TUILE, i*TAILLE_TUILE + TAILLE_TUILE/2, fill=couleurPowerup)
def trace_bomberman(canvas, x, y, couleur):
canvas.create_oval(x+15, y+15, x+TAILLE_TUILE-15, y+TAILLE_TUILE, fill=couleur)
canvas.create_oval(x+10, y, x+TAILLE_TUILE-10, y+TAILLE_TUILE-20, fill=couleur)
canvas.create_oval(x+13, y+5, x+TAILLE_TUILE-13, y+TAILLE_TUILE-26, fill="pink")
def compte_couleur(grille, nbJoueurs):
compteurs = [0 for i in range(nbJoueurs)]
for ligne in grille:
for couleur in ligne:
if couleur >= 0:
compteurs[couleur]+=1
return compteurs
def affiche_infos(canvas, joueurs, plateauCouleur):
canvas.delete(ALL)
scores = list(reversed((sorted(zip(compte_couleur(plateauCouleur, len(joueurs)), range(len(joueurs)))))))
for k in range(len(scores)):
i = scores[k][1]
if joueurs[i]!=None:
couleur = COULEURS_JOUEURS[i]
j=2
couleurPowerup = COULEURS_POWERUPS[POWERUP_NOMBREBOMBES]
canvas.create_polygon(j*TAILLE_TUILE+TAILLE_TUILE/2, k*TAILLE_TUILE, j*TAILLE_TUILE, k*TAILLE_TUILE+TAILLE_TUILE/2, j*TAILLE_TUILE+TAILLE_TUILE/2, (k+1)*TAILLE_TUILE, (j+1)*TAILLE_TUILE, k*TAILLE_TUILE + TAILLE_TUILE/2, fill=couleurPowerup)
canvas.create_text((j+1)*TAILLE_TUILE+TAILLE_TUILE/2, (k+0.5)*TAILLE_TUILE, text=joueurs[i][J_NOMBREBOMBES])
j=4
couleurPowerup = COULEURS_POWERUPS[POWERUP_LONGUEURFLAMMES]
canvas.create_polygon(j*TAILLE_TUILE+TAILLE_TUILE/2, k*TAILLE_TUILE, j*TAILLE_TUILE, k*TAILLE_TUILE+TAILLE_TUILE/2, j*TAILLE_TUILE+TAILLE_TUILE/2, (k+1)*TAILLE_TUILE, (j+1)*TAILLE_TUILE, k*TAILLE_TUILE + TAILLE_TUILE/2, fill=couleurPowerup)
canvas.create_text((j+1)*TAILLE_TUILE+TAILLE_TUILE/2, (k+0.5)*TAILLE_TUILE, text=joueurs[i][J_LONGUEURFLAMMES])
j=6
couleurPowerup = COULEURS_POWERUPS[POWERUP_VITESSE]
canvas.create_polygon(j*TAILLE_TUILE+TAILLE_TUILE/2, k*TAILLE_TUILE, j*TAILLE_TUILE, k*TAILLE_TUILE+TAILLE_TUILE/2, j*TAILLE_TUILE+TAILLE_TUILE/2, (k+1)*TAILLE_TUILE, (j+1)*TAILLE_TUILE, k*TAILLE_TUILE + TAILLE_TUILE/2, fill=couleurPowerup)
canvas.create_text((j+1)*TAILLE_TUILE+TAILLE_TUILE/2, (k+0.5)*TAILLE_TUILE, text=joueurs[i][J_VITESSE])
j=8
couleurPowerup = COULEURS_POWERUPS[POWERUP_DASH]
canvas.create_polygon(j*TAILLE_TUILE+TAILLE_TUILE/2, k*TAILLE_TUILE, j*TAILLE_TUILE, k*TAILLE_TUILE+TAILLE_TUILE/2, j*TAILLE_TUILE+TAILLE_TUILE/2, (k+1)*TAILLE_TUILE, (j+1)*TAILLE_TUILE, k*TAILLE_TUILE + TAILLE_TUILE/2, fill=couleurPowerup)
canvas.create_text((j+1)*TAILLE_TUILE+TAILLE_TUILE/2, (k+0.5)*TAILLE_TUILE, text=joueurs[i][J_DASHSRESTANTS])
j=10
couleurPowerup = COULEURS_POWERUPS[POWERUP_PIEGE]
canvas.create_polygon(j*TAILLE_TUILE+TAILLE_TUILE/2, k*TAILLE_TUILE, j*TAILLE_TUILE, k*TAILLE_TUILE+TAILLE_TUILE/2, j*TAILLE_TUILE+TAILLE_TUILE/2, (k+1)*TAILLE_TUILE, (j+1)*TAILLE_TUILE, k*TAILLE_TUILE + TAILLE_TUILE/2, fill=couleurPowerup)
canvas.create_text((j+1)*TAILLE_TUILE+TAILLE_TUILE/2, (k+0.5)*TAILLE_TUILE, text=joueurs[i][J_PIEGESRESTANTS])
j = 12
canvas.create_text((j+1)*TAILLE_TUILE+TAILLE_TUILE/2, (k+0.5)*TAILLE_TUILE, text=joueurs[i][J_DECISION])
else:
couleur = "gray"
trace_bomberman(canvas, 0, HAUTEUR_JOUEUR*k,couleur)
def ajoute_evenement(evenements, evenement):
for i in range(0,len(evenements)):
if evenement[0]<evenements[i][0]:
evenements.insert(i,evenement)
return
evenements.append(evenement)
def prochain(i,j,direction):
if direction == DIRECTION_NORD:
i-=1
elif direction == DIRECTION_SUD:
i+=1
elif direction == DIRECTION_OUEST:
j-=1
elif direction == DIRECTION_EST:
j+=1
return i,j
def trouve_objet(i,j, liste):
for indice in range(len(liste)):
if liste[indice]!=None and liste[indice][0]==i and liste[indice][1]==j:
return indice
def casse(plateau, powerups, i,j):
plateau[i][j]=PLATEAU_VIDE
if randrange(0,3)==0:
powerups.append([i,j, randrange(5)])
return
def execute_evenement(evenements, evenement, plateau, plateauCouleur, bombes, joueurs, powerups, pieges):
if evenement[E_NATURE]==EVENEMENT_TOUR_JOUEUR:
temps, nature, indiceJoueur = evenement
joueur = joueurs[indiceJoueur]
if joueur == None:
return
i, j = joueur[J_LIGNE], joueur[J_COLONNE]
# en cas d'erreur quelconque, on considère que le joueur "passe" son tour
direction,action = decision(joueur[J_DECISION],indiceJoueur, deepcopy(plateau), deepcopy(plateauCouleur), deepcopy(bombes), deepcopy(joueurs), deepcopy(powerups), evenement[E_INSTANT])
if joueurs[indiceJoueur][J_BOMBESRESTANTES]>0 and action == A_BOMBE:
joueur[J_BOMBESRESTANTES]-=1
bombes.append([i,j,joueur[J_LONGUEURFLAMMES],indiceJoueur,evenement[0]+TEMPS_EXPLOSION])
ajoute_evenement(evenements, [evenement[0]+TEMPS_EXPLOSION, EVENEMENT_EXPLOSION_BOMBE, len(bombes)-1])
elif joueurs[indiceJoueur][J_DASHSRESTANTS]>0 and action == A_DASH:
joueurs[J_DASHSRESTANTS]-=1
joueurs[J_TOURSDASH]+=3
elif joueurs[indiceJoueur][J_PIEGESRESTANTS]>0 and action == A_PIEGE:
joueurs[J_PIEGESRESTANTS]-=1
pieges.append([i,j,indiceJoueur])
ip,jp = prochain(i,j,direction)
if plateau[ip][jp]==PLATEAU_VIDE and trouve_objet(ip, jp, bombes)==None:
joueur[J_LIGNE]=ip
joueur[J_COLONNE]=jp
i, j = joueur[J_LIGNE], joueur[J_COLONNE]
indicePiege = trouve_objet(i,j, pieges)
penalite = 0
if indicePiege != None:
if piege[P_JOUEUR] != indiceJoueur:
penalite = 3
piege.pop(indicePiege)
indicePowerup = trouve_objet(i,j,powerups)
if indicePowerup != None:
powerup = powerups.pop(indicePowerup)
if powerup[PU_NATURE]==POWERUP_LONGUEURFLAMMES:
joueur[J_LONGUEURFLAMMES]+=1
elif powerup[PU_NATURE]==POWERUP_NOMBREBOMBES:
joueur[J_NOMBREBOMBES]+=1
joueur[J_BOMBESRESTANTES]+=1
elif powerup[PU_NATURE]==POWERUP_VITESSE:
joueur[J_VITESSE]+=1
elif powerup[PU_NATURE]==POWERUP_DASH:
joueur[J_DASHSRESTANTS]+=1
elif powerup[PU_NATURE]==POWERUP_PIEGE:
joueur[J_PIEGESRESTANTS]+=1
ajoute_evenement(evenements, [temps+attente(joueur[J_VITESSE])*(joueur[J_TOURSDASH]==0)+penalite, EVENEMENT_TOUR_JOUEUR, indiceJoueur])
if joueur[J_TOURSDASH]>0:
joueur[J_TOURSDASH]-=1
elif evenement[E_NATURE]==EVENEMENT_EXPLOSION_BOMBE:
temps, nature, indiceBombe = evenement
if bombes[indiceBombe]==None:
return
i,j,longueurFlammes, indiceJoueur, instant = bombes[indiceBombe]
indJoueur = bombes[indiceBombe][B_JOUEUR]
bombes[indiceBombe] = None
for direction in [DIRECTION_NORD, DIRECTION_SUD, DIRECTION_EST, DIRECTION_OUEST]:
ajoute_evenement(evenements, [evenement[0], EVENEMENT_PROPAGATION, i, j, direction, longueurFlammes, indJoueur])
if joueurs[indiceJoueur]!=None:
joueurs[indiceJoueur][J_BOMBESRESTANTES]+=1
elif evenement[E_NATURE]==EVENEMENT_PROPAGATION:
temps, nature, i, j, direction, longueurFlammes, indJoueur = evenement
if plateau[i][j]==PLATEAU_PIERRE:
# Pierre : indestuctible donc pas d'effet
return
elif plateau[i][j]==PLATEAU_BOIS:
# Bois : destructible, on détruit
casse(plateau, powerups, i,j)
return
else:
# On colore la case avec la couleur du joueur
plateauCouleur[i][j] = indJoueur
# On détruit le powerup s'il y en a un
indicePowerup = trouve_objet(i,j,powerups)
if indicePowerup != None:
powerups.pop(indicePowerup)
# On tue tous les joueurs qui sont à cet endroit
indiceJoueur = trouve_objet(i,j,joueurs)
while indiceJoueur != None:
joueurs[indiceJoueur] = None
indiceJoueur = trouve_objet(i,j,joueurs)
# On fait exploser la bombe s'il y en a une
indiceBombe = trouve_objet(i,j,bombes)
if indiceBombe != None:
ajoute_evenement(evenements, [evenement[0],EVENEMENT_EXPLOSION_BOMBE, indiceBombe])
longueurFlammes = 0
# Si on est pas au bout de la flamme, on propage
if longueurFlammes>0:
ip, jp = prochain(i,j,direction)
ajoute_evenement(evenements, [evenement[0]+TEMPS_PROPAGATION, EVENEMENT_PROPAGATION, ip, jp, direction, longueurFlammes-1, indJoueur])
TAILLE_TUILE = 40
HAUTEUR_JOUEUR = TAILLE_TUILE
LARGEUR_INFOS = 800
COULEURS_JOUEURS = ["red", "blue", "green", "yellow"]
COULEURS_POWERUPS = [ "cyan", "orangered", "yellow", "magenta", "purple"]
def decision(programme, indiceJoueur, plateau, plateauCouleur, bombes, joueurs, powerups, instant):
with open("entrees.txt", "w") as entrees:
print(instant, file=entrees)
print(indiceJoueur, file=entrees)
print(len(plateau), len(plateau[0]), file=entrees)
plateauTotal = [[plateau[i][j] if plateau[i][j]!=0 or plateauCouleur[i][j]==-1 else 3+plateauCouleur[i][j] for j in range(len(plateau[0]))] for i in range(len(plateau))]
for ligne in plateauTotal:
for val in ligne:
print(val, end=" ", file=entrees)
print(file=entrees)
print(len(bombes)-bombes.count(None), file=entrees)
for bombe in bombes:
if bombe!=None:
print(bombe[B_LIGNE], bombe[B_COLONNE], bombe[B_LONGUEURFLAMMES], bombe[B_INSTANT], file=entrees)
print(len(joueurs)-joueurs.count(None), file=entrees)
for j, joueur in enumerate(joueurs):
if joueur!=None:
print(joueur[J_LIGNE], joueur[J_COLONNE], j, joueur[J_VITESSE], joueur[J_NOMBREBOMBES], joueur[J_LONGUEURFLAMMES], joueur[J_DASHSRESTANTS], joueur[J_PIEGESRESTANTS], file=entrees)
print(len(powerups), file=entrees)
for pu in powerups:
print(pu[PU_LIGNE], pu[PU_COLONNE], pu[PU_NATURE], file=entrees)
system("cat entrees.txt | "+programme+" > sortie.txt")
with open("sortie.txt", "r") as sortie:
direction, b = sortie.readline().split()
action = int(b)
return int(direction), action
def simulation(strategies):
def pas_de_jeu():
if len(joueurs) - joueurs.count(None) > 1:
evenement = evenements.pop(0)
if evenement[0]>TEMPS_PARTIE:
return
execute_evenement(evenements, evenement, plateau, plateauCouleur, bombes, joueurs, powerups, pieges)
affiche_plateau(canvas, plateau, plateauCouleur, bombes, joueurs, powerups)
affiche_infos(canvasInfosJoueurs, joueurs, plateauCouleur)
temps = int((evenements[0][0]-evenement[0])/3*1000)
if temps != 0:
fenetre.after(temps, pas_de_jeu)
else:
pas_de_jeu()
dimensions = 13,21
positionsInitiales=[(1, 1), (dimensions[0]-2, dimensions[1]-2), (1, dimensions[1]-2), (dimensions[0]-2, 1)]
plateau = cree_plateau_initial(dimensions[0]-2, dimensions[1]-2, 20)
plateauCouleur = [[-1 for j in range(dimensions[1])] for i in range(dimensions[0])]
evenements = []
bombes = []
joueurs = []
powerups = []
pieges = []
fenetre = Tk()
canvas = Canvas(width=dimensions[1]*TAILLE_TUILE, height=dimensions[0]*TAILLE_TUILE)
canvas.pack()
joueurs = []
for i in range(len(strategies)):
joueur = [positionsInitiales[i][0], positionsInitiales[i][1], strategies[i], 0, 1, 1, 1, 0, 0, 0]
joueurs.append(joueur)
ajoute_evenement(evenements, [0., EVENEMENT_TOUR_JOUEUR, i])
canvasInfosJoueurs = Canvas(width = LARGEUR_INFOS, height=len(joueurs)*HAUTEUR_JOUEUR)
canvasInfosJoueurs.pack()
pas_de_jeu()
fenetre.mainloop()
return
from importlib import import_module
simulation(["./main.ml", "./main.ml","./main.ml", "./main.ml"])