Commit c1e812c8 authored by Antoine Rollet's avatar Antoine Rollet

Upload New File

parent f227c421
import pygame as pg
import numpy as np
from numpy import cos,sin
from time import time,sleep
from random import shuffle
continuer=1
wd_width = 600
wd_height = 600
random=np.random.random
# color_set =[]
# c=open("C:/Users/Antoine/Desktop/colors.csv").read()
# for c1 in c.replace("\n","\t").split("\t"):
# print(c1)
# if c1!= '':
# color_set.append(tuple([int(e) for e in c1.split(', ')]))
# shuffle(color_set)
def collisionDroiteSeg(A,B,O,P):
# Soit une droite AB et un segment OP
# On cherche à savoir si il y a collision entre les deux
ABx = B[0] - A[0]
ABy = B[1] - A[1]
APx = P[0] - A[0]
APy = P[1] - A[1]
AOx = O[0] - A[0]
AOy = O[1] - A[1]
if ((ABx*APy - ABy*APx)*(ABx*AOy - ABy*AOx)) < 0:
return True
else:
return False
def collisionSegSeg(A,B,O,P):
return collisionDroiteSeg(A,B,O,P) and collisionDroiteSeg(O,P,A,B)
def collisionPolygPolyg(P1,P2):
for i in range(len(P1)):
A1=P1[i]
if i==len(P1)-1:
B1=P1[0]
else:
B1=P1[i+1]
for j in range(len(P2)):
A2=P2[j]
if j==len(P2)-1:
B2=P2[0]
else:
B2=P2[j+1]
if collisionSegSeg(A1,B1,A2,B2):
return True
return False
def pointInPolyg(P,poly):
for i in range(len(poly)):
A=poly[i]
if i==len(poly)-1:
B=poly[0]
else:
B=poly[i+1]
Dx=B[0]-A[0]
Dy=B[1]-A[1]
Tx=P[0]-A[0]
Ty=P[1]-A[1]
d=Dx*Ty-Dy*Tx
if d<0:
return False
return True
def activationFunctionNotVect(x):
if 1/(1+np.exp(-x))>0.6:
return 1
else:
return 0
activationFunction = np.vectorize(activationFunctionNotVect)
class Agent:
def __init__(self,x,y,dir, id=1,color=(255,255,255)):
self.x=x
self.y=y
self.taille=12
self.dir=dir
self.id=id
self.alive=True
self.color=color
self.n_kills=0
pied_gauche=self.x+self.taille/2*cos(np.pi/2+self.dir), self.y+self.taille/2*sin(np.pi/2+self.dir)
pied_droit=self.x+self.taille/2*cos(np.pi/2-self.dir), self.y-self.taille/2*sin(np.pi/2-self.dir)
self.tete=self.x+self.taille*cos(self.dir),self.y+self.taille*sin(self.dir)
self.hitbox=[self.tete,pied_gauche,pied_droit]
self.set_brain_structure(9,5)
self.vision = np.zeros((9))
angles= [ np.pi/21*i for i in range(-7,8,2)]
def __str__(self):
return "Agent " + str(self.id)
def watch(self,storm_center,storm_radius,other_players):
# Pour l'instant la "vue" est aléatoire sauf la vision de l'orage
# vue à 120°, 7 champs de vision
dist_to_storm=(np.sqrt((self.x-storm_center[0])**2+(self.y-storm_center[1])**2))/storm_radius
ang_to_storm=np.arctan2(self.x-storm_center[0],self.y-storm_center[1])
self.vision=np.zeros(9)
self.vision[0]=dist_to_storm
self.vision[1]=ang_to_storm
self.watch_other_players(other_players)
# print(self.vision)
def watch_other_players(self,other_players):
for player in other_players:
if player!=self:
if (self.x-player.x)**2 + (self.y-player.y)**2<= (6*self.taille)**2:
angle=(self.dir - np.arctan2(self.y-player.y,self.x-player.x)-np.pi)%(2*np.pi)
if angle>=5/3*np.pi or angle <= np.pi/3:
if angle>=5/3*np.pi:
angle-=2*np.pi
dist_to_other_player=1-np.sqrt((self.x-player.x)**2+(self.y-player.y)**2)/6/self.taille
i=1
while angle >= np.pi/3*(2*i/7-1):
i+=1
# En % de 6 x taille (distance maximale)
self.vision[i-1+2]=dist_to_other_player
# print(self.id,"is seeing", player.id)
def take_action(self,fenetre,storm_center,storm_radius,other_players):
self.watch(storm_center,storm_radius,other_players)
actions=self.vision.dot(self.weights_1.dot(self.weights_2))
actions = activationFunction(actions)
# print(actions)
for i in range(len(actions)):
if i==0 and actions[i]:
self.move_forward()
if i==1 and actions[i]:
self.move_backward()
if i==2 and actions[i]:
self.turn_left()
if i==3 and actions[i]:
self.turn_right()
if i==4 and actions[i]:
return self.shoot(fenetre)
def set_brain_structure(self,input_size,output_size):
self.weights_1 = np.random.randint(-2,2,(input_size,12))
self.weights_2 = np.random.randint(-2,2,(12,output_size))
self.brain=[self.weights_1,self.weights_2]
def is_shot(self,shot):
for i in range(len(self.hitbox)):
A=self.hitbox[i]
if i==len(self.hitbox)-1:
B=self.hitbox[0]
else:
B=self.hitbox[i+1]
if collisionSegSeg(A,B,shot[1][0],shot[1][1]):
self.alive=False
print(self.id," was shot by ",shot[0],".")
return True
return False
def shoot(self,fenetre):
# Un tir est un segment
depart=self.hitbox[0] # Début du tir au niveau de la tête
arrivee = depart[0]+2*self.taille*cos(self.dir), depart[1]+2*self.taille*sin(self.dir) # Arrivée après deux fois la taille du bonhomme
if fenetre!=None:
pg.draw.line(fenetre,(255,0,0),depart,arrivee)
# self.afficher(fenetre)
pg.display.update()
return (self.id,[depart,arrivee])
def refresh_hitbox(self):
pied_gauche=self.x+self.taille/2*cos(np.pi/2+self.dir), self.y+self.taille/2*sin(np.pi/2+self.dir)
pied_droit=self.x+self.taille/2*cos(np.pi/2-self.dir), self.y-self.taille/2*sin(np.pi/2-self.dir)
tete=self.x+self.taille*cos(self.dir),self.y+self.taille*sin(self.dir)
self.hitbox=[tete,pied_gauche,pied_droit]
def check_in_storm(self,storm_center,storm_radius):
if (self.x-storm_center[0])**2 + (self.y-storm_center[1])**2<=storm_radius**2:
self.alive=True
else:
self.alive=False
print(self.id, " died in the storm.")
def move_forward(self,speed=2):
self.x+=speed*cos(self.dir)
self.y+=speed*sin(self.dir)
self.refresh_hitbox()
def move_backward(self,speed=2):
self.x-=speed*cos(self.dir)
self.y-=speed*sin(self.dir)
self.refresh_hitbox()
def turn_left(self):
self.dir-=np.pi/50
self.refresh_hitbox()
def turn_right(self):
self.dir+=np.pi/50
self.refresh_hitbox()
def afficher(self,fenetre,color=None):
self.refresh_hitbox() #à supprimer
x,y=self.x,self.y
direction_joueur=self.dir
taille=50
if color==None:
color=self.color
# print(x,y,direction_joueur)
# Détermination des trois "extrémités"=membres du joueur
tete,pied_gauche,pied_droit=self.hitbox
# Affichage des membres
pg.draw.circle(fenetre,(255,0,0),(int(tete[0]),int(tete[1])),taille//25)
# pg.draw.circle(fenetre,(0,255,0),(int(pied_gauche[0]), int(pied_gauche[1])), taille//25)
# pg.draw.circle(fenetre,(0,0,255),(int(pied_droit[0]),int(pied_droit[1])),taille//25)
pg.draw.circle(fenetre,(255,255,0),(int(x),int(y)),taille//20)
# Affichage du "corps" du joueur
pg.draw.polygon(fenetre,color,self.hitbox)
# Affichage de l'id du joueur
# pg.font.init()
# font=pg.font.SysFont(None,20)
# font_image=font.render(str(self.id),True,(0,0,0))
# fenetre.blit(font_image,(self.x,self.y))
# pg.display.flip()
class Storm:
def __init__(self):
self.center=(wd_width//2,wd_height//2)
self.max_radius = (max(wd_width,wd_height)/np.sqrt(2))*1.2
self.radius = self.max_radius
self.adv_quantum = self.radius / 30 # ici le cercle ce sera réduit en le dénominateur secondes
def storm_push(self,time_elapsed):
self.radius = self.max_radius - time_elapsed*self.adv_quantum
def afficher_storm(self,fenetre):
pg.draw.circle(fenetre,(238,130,238),(wd_width//2,wd_height//2),
int(self.radius),2)
# pg.display.update()
class BR_Game(Storm,Agent):
def __init__(self,agents,display=True,hurry=1):
self.player_colors=[(np.random.randint(256),np.random.randint(256),np.random.randint(256)) for i in range(len(agents))]
self.alive_players=list(agents.values())
# self.alive_players.append(p[0])
self.dead_players=[]
self.storm = Storm()
self.start_time=time()
self.time_elapsed=0
self.hurry=hurry
self.game_ongoing=True
self.display=display
self.fenetre=None
if display:
self.fenetre=pg.display.set_mode((wd_width,wd_height))
def play(self):
# if self.display:
# pg.display.flip()
while self.game_ongoing:
self.time_elapsed = (time() - self.start_time)*self.hurry
self.storm.storm_push(self.time_elapsed)
shots=[]
for player in self.alive_players:
player.check_in_storm(self.storm.center,self.storm.radius)
for player in self.alive_players: #On va avoir des problemes ici si on ne veut pas de display
shoot=player.take_action(self.fenetre,self.storm.center,self.storm.radius,self.alive_players)
if shoot != None:
shots.append(shoot)
for shot in shots:
for player in self.alive_players:
if player.is_shot(shot):
for shooter in self.alive_players:
if shooter.id==shot[0]:
shooter.n_kills+=1
if self.display:
self.fenetre.fill((0,0,0))
self.storm.afficher_storm(self.fenetre)
for player in self.alive_players:
if player.alive and self.display:
player.afficher(self.fenetre)
elif not(player.alive):
self.dead_players.append(player)
self.alive_players.remove(player)
# Code qui détermine si deux joueurs se touchent
# for player_1 in self.alive_players:
# for player_2 in self.alive_players:
# if player_1.id != player_2.id:
# col=collisionPolygPolyg(player_1.hitbox,player_2.hitbox)
# if col:
# player_1.afficher(self.fenetre,(255,0,0))
# player_2.afficher(self.fenetre,(255,0,0))
if self.display:
pg.event.pump()
# pg.display.update()
pg.display.flip()
for event in pg.event.get(): #On parcours la liste de tous les événements reçus
if event.type == pg.QUIT: #Si un de ces événements est de type QUIT
self.game_ongoing= False #On arrête la boucle
pg.display.quit()
if event.type == pg.MOUSEBUTTONDOWN:
sleep(3)
self.game_ongoing=len(self.alive_players)>1
self.dead_players.append(self.alive_players[0])
print("Player ",self.dead_players[-1]," won the game!")
pg.quit()
def leaderboard(self):
self.scores=dict()
for i in range(len(self.dead_players)):
self.scores[self.dead_players[i].id]=i+self.dead_players[i].n_kills*2
print("#",len(self.dead_players)-i,". "+str(self.dead_players[i]), "with", self.dead_players[i].n_kills, "kills!")
leaderboard=[assoc[0] for assoc in sorted(self.scores.items(),key=lambda tupl: tupl[1])]
return leaderboard,[agent.id for agent in self.dead_players]
class AgentPool(Agent):
def __init__(self,new_agents=True,n_agents=20,agents=None):
if new_agents:
self.agents=dict()
for i in range(n_agents):
self.agents[i]=Agent(random()*wd_width,random()*wd_height,random()*2*np.pi,id=i)
else:
self.agents=agents
self.max_id=max(self.agents.keys())
self.n_agents=n_agents
print(self.max_id+1,"agents in the pool.")
def make_them_fight(self,n_fights=1,display=False,hurry=1):
for id,agent in self.agents.items():
agent.n_kills=0
leaderboards=[]
for i in range(n_fights):
print("This is fight number",i+1,"!")
for id,agent in self.agents.items():
agent.x=random()*wd_width
agent.y=random()*wd_height
agent.dir=random()*2*np.pi
game=BR_Game(agents=self.agents,display=display,hurry=hurry)
game.play()
leaderboards.append(game.leaderboard()[1])
scores=dict()
for id,agent in self.agents.items():
scores[id]=sum([lb.index(id) for lb in leaderboards])+agent.n_kills
self.leaderboard=[assoc[0] for assoc in sorted(scores.items(),key=lambda tupl: tupl[1])]
print(scores)
print(self.leaderboard)
def kill_the_weakest(self,n_to_kill):
for dead in self.leaderboard[:n_to_kill]:
self.agents.pop(dead)
def make_a_baby(self):
father_id=np.random.choice(list(self.agents.keys()))
father=self.agents.get(father_id)
mother_id=np.random.choice(list(self.agents.keys()))
mother=self.agents.get(mother_id)
n,p=father.brain[0].shape
mix1=np.ones((n,1)).dot(np.random.choice(2,(1,p))) #select random columns
mix1+=np.random.normal(size=mix1.shape)
new_brain_1=father.brain[0]*mix1+mother.brain[0]*(1-mix1)
n,p=father.brain[1].shape
mix2=np.ones((n,1)).dot(np.random.choice(2,(1,p)))
mix2+=np.random.normal(size=mix2.shape)
new_brain_2=father.brain[1]*mix2+mother.brain[1]*(1-mix2)
#no mutation yet
new_brain=[new_brain_1,new_brain_2]
baby=Agent(random()*wd_width,random()*wd_height,random()*2*np.pi,id=self.max_id+1)
baby.brain=new_brain
self.agents[baby.id]=baby
self.max_id+=1
def loop(self,n_loops=1,fights_per_loop=1):
for i in range(n_loops):
self.make_them_fight(n_fights=fights_per_loop,display=False,hurry=2)
self.kill_the_weakest(self.n_agents//2)
for e in range(self.n_agents-len(self.agents)):
self.make_a_baby()
game=BR_Game(AgentPool().agents)
game.play()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment