Wa-Tor est une simulation de type proie-prédateur. Dans une mer torique évoluent des thons et des requins. Les uns et les autres se déplacent et se reproduisent. Pour acquérir l'énergie suffisante à sa survie, un requin doit manger un thon régulièrement. Un thon vit éternellement tant qu'il n'est pas mangé par un requin.
Voici les descriptions des entités présente au sein de cette simulation :
La mer : elle est représentée par une grille à deux dimensions torique (cela signifie que les bords droits et gauches sont reliés, et que les bords hauts et bas également). Chaque case possède donc quatre case voisines, une dans chacune des quatre directions cardinales (N, S, E O) et peut-être soit vide, soit occupée par un thon ou par un requin. Dans cette mer évoluent, selon certaines règles, des thons et des requins. On trouve au plus un poisson par case.
Les thons : un thon est caractérisé par son temps de gestation. Ce temps est initialisé à une valeur initiale commune à tous les thons au début de la simulation.
Les requins : un requin est caractérisé par son temps de gestation et son énergie. Ces deux valeurs sont initialisées à une valeur initiale commune à tous les requins au début de la simulation.
À chaque tour de la simulation, une case de la mer est sélectionnée aléatoirement. Si elle est vide, il ne se passe rien. Si elle est occupée par un poisson (thon ou requin), on applique alors son comportement.
Le comportement d'un thon se résumer en deux actions :
Son déplacement : le thon choisit aléatoirement une case libre parmi ses voisines. S'il en existe une, le thon se déplace vers cette case, sinon, il reste sur place.
Sa reproduction : le temps de gestation du thon est diminué de 1 à chaque tour. Si ce temps arrive à 0, le thon donne naissance à un nouveau thon qui naît sur la case qu'il vient de quitter s'il s'est déplacé, sinon aucun thon ne naît. Le temps de gestation est remis à sa valeur initiale.
Le comportement d'un requin se résumer en trois actions :
Son énergie : le requin perd un point d'énergie à chaque tour. Si le niveau d'énergie du requin est à 0, il meurt. Dans ce cas les étapes suivantes n'ont pas lieu.
Son déplacement : le requin choisit aléatoirement parmi ses voisines une case occupée par un thon. S'il en existe une, le requin se déplace vers forcément sur cette case et mange le thon et son niveau d'énergie est remis à sa valeur initiale. Sinon, il cherche à se déplacer vers une case voisine vide choisie au hasard. Il reste sur place s'il n'y en a aucune.
Sa reproduction : le temps de gestation du requin est diminué de 1 à chaque tour. Si ce temps arrive à 0, le requin donne naissance à un nouveau requin sur la case qu'il vient de quitter s'il s'est déplacé, sinon aucun requin ne naît. Son temps de gestation est remis à sa valeur initiale.
Pour une simulation « réussie » il faut que temps gestation des thons
< énergie des requins
< durée gestation des requins
. Les valeurs suggérées sont 2, 3 et 5.
Le but de ce projet est de concevoir un programme en Python permettant de simuler et d'observer l'évolution des populations de requins et de thons au fil des tours de simulation.
Vous aurez une certaine autonomie pour choisir et implémenter les fonctions nécessaires à la réalisation de cette simulation. Toutefois, quelques pistes de réflexion vous sont fournies ci-dessous pour vous guider.
Il est nécessaire de stocker plusieurs informations sur chaque poisson (son type, son énergie, son temps de gestation actuel...). Pour représenter un poisson et toutes ses informations, on peut utiliser un dictionnaire selon le format suivant :
requin = { type:"requin", .... : ... }
thon = { type:"thon", ... : ... }
Pour chaque poisson, il peut être intéressant de réfléchir aux fonctions suivantes :
liste_voisins(x, y)
, qui retourne la liste des cases voisine.deplacement(poisson)
, qui s'occupe de déplacer le poisson.reproduction(poisson)
, qui s'occupe de la reproduction du poisson.mort(poisson)
, qui s'occupe de la mort d'un requin uniquement.La mer est représentée par une liste à deux dimensions (liste de listes) où chaque case de la mer est soit un poisson (de type dict
) ou une case vide (que l'on représentera également par un dictionnaire dont la clé type
sera égale à vide
). La mer est donc une liste de liste, où chaque élément de la liste sont des dictionnaires.
Pour simplifier la création et la gestion de la mer, on pourrait écrire les fonctions suivante :
generer_mer(pourcentage_thon, pourcentage_requin)
, qui s'occupe de créer la mer.afficher_mer(mer)
, qui permet d'afficher la mer dans la console Python.choisir_case_aleatoire(mer)
, qui retourne un tuple (x, y)
où x
et y
sont les coordonnées d'une case de la mer.On peut utiliser des constantes commeDUREE_GESTATION_THON
, DUREE_GESTATION_REQUIN
, ENERGIE_REQUIN
pour définir les valeurs initiales pour les différents poissons.
Pour afficher la mer d'une manière graphique à l'aide d'une interface graphique, vous pourrez utiliser le programme ci-dessous :
from time import sleep
from tkinter import *
class WatorGraphique:
def __init__(self, mer):
self.mer = mer
def start(self):
fen_princ = Tk()
size_x = self.mer.largeur*20
size_y = self.mer.hauteur*20
fen_princ.geometry(str(size_x)+"x"+str(size_y))
canvas = Canvas(fen_princ, width=size_x, height=size_y, bg='ivory')
fen_princ.after(1, self.run, canvas, fen_princ)
fen_princ.mainloop()
def run(self, canvas,fen_princ):
self.afficher_mer(canvas)
a = self.mer.choisir_case_alea()
a.update_comportement(self.mer)
fen_princ.after(1, self.run, canvas,fen_princ)
def afficher_mer(self,canvas):
canvas.delete('all')
for x in range(0, self.mer.largeur):
for y in range(0, self.mer.hauteur):
if type(self.mer.grille[x][y]) is CaseVide :
canvas.create_rectangle(x*20,y*20,x*20+20,y*20+20,width=0,fill="black")
elif type(self.mer.grille[x][y]) is CaseRequin:
canvas.create_rectangle(x*20,y*20,x*20+20,y*20+20,width=0,fill="red")
elif type(self.mer.grille[x][y]) is CaseThon:
canvas.create_rectangle(x*20,y*20,x*20+20,y*20+20,width=0,fill="blue")
canvas.pack(expand="yes")
mer = Mer(20,20t)
mer.generer_mer(30,10)
w = WatorGraphique(mer)
w.start()