Cet automate cellulaire ou Jeu de la vie (Game of Life), dont le principe vient de John Horton Conway, simule l’évolution d’une colonie de cellules. Le plateau se comporte comme un tore, les bords se recollent. Le menu permet de choisir la forme des cellules, l’espacement entre les cellules, un placement initial aléatoire ou au choix de l’utilisateur, l’affichage en couleur du vieillissement des cellules, le nombre de cycles à effectuer et afficher, faire une pause à la fin de chaque cycle… Il permet également de modifier (avec les flèches haut et bas) les règles de naissance et de survie.
from kandinsky import draw_string,set_pixel,fill_rect from random import randint from ion import * from time import sleep kd = keydown KL = KEY_LEFT KR = KEY_RIGHT KU = KEY_UP KD = KEY_DOWN KO = KEY_OK KE = KEY_EXE KS = KEY_SHIFT def menu(chaine,var,dec,mode,choix1,choix2): draw_string(chaine,10,v,'orange') draw_string("<"+" "*(5+dec)+">",10+len(chaine)*10,v,'blue') while not (kd(KE) or kd(KO)): if mode == "nombre": sleep(0.08) var = (var-mini+kd(KR)-kd(KL)+10*kd(KU)-10*kd(KD))%(maxi-mini+1)+mini draw_string(" "+str(var)+" "+"px "*(dec>0),(len(chaine)+2)*10+5*dec-5*len(str(var))+15*(dec==0),v,'purple') else:#mode booléen draw_string([choix2,choix1][var],(len(chaine)+3)*10,v,'purple') if kd(KL) or kd(KR): var = not var while kd(KL) or kd(KR):True while kd(KE) or kd(KO):True return var def curseur(couleur): for pos in [0,1]: fill_rect(dg+d*col+pos*(c+(s==3))+(s==1)+4*(s==2)-(s==3),dh+d*lig-2*(s==0)+5*(s==1)+2*(s==2)-(s==3),1,c+(s==3),couleur) fill_rect(dg+d*col+(s==1)+4*(s==2)-(s==3),dh+d*lig+pos*(c-(s==1)+(s==3))-2*(s==0)+5*(s==1)+2*(s==2)-(s==3),1+c+(s==3),1,couleur) def carre(i,j,couleur): if rapide: for u in D: for v in D: set_pixel(dg+d*j+u,dh+d*i+v,couleur) else: fill_rect(dg+d*j,dh+d*i,c,c,couleur) def init(): global v,mini,maxi,dg,dh,col,lig,a,b,A,B,d,D,c,e,s,S,alea,clr,N,Naissance,Survie,Liste,rapide,pause v = 10 S = ['o',chr(215),chr(176),' '] s = 3 draw_string("Forme des cellules : ",10,v,'orange') draw_string("< >",22*10,v,'blue') while not (kd(KE) or kd(KO)): if s == 3: fill_rect(24*10+3,v+6,5,5,'purple') if kd(KL) or kd(KR): s = (s+kd(KR)-kd(KL))%len(S) draw_string(S[s],24*10-2*(s==2),v+4*(s==2)-2*(s==0),'purple') while kd(KL) or kd(KR):True while kd(KE) or kd(KO):True vv = 23-4*(s==3) v += vv alea = menu("Disposition : ",True,6,"booléen","aléatoire","à choisir") v += vv clr = menu("Vieillissement : ",True,7,"booléen","en couleur","monochrome") c = 9-2*s mini = (s+2)%4+1+(s==2) if s == 3: v += 20 rapide = menu("Placement : ",True,3,"booléen","rapide","fluide") v += 20 mini = 1 maxi = 15 c = menu("Taille des cellules : ",7,2,"nombre","","") mini = max(0,5-c) #espacement minimal sans avoir d'erreur de mémoire saturée maxi = 9 v += vv e = menu("Espacement : ",4,1,"nombre","","") Naissance = [3] Survie = [2,3] v += vv draw_string("Nombre de voisins pour",10,v,'orange') for k in [0,1]: etape = [Naissance,Survie][k] v += 20-2*(s==3) draw_string(["naître : ","survivre : "][k],20,v,'orange') for n in range(9): draw_string(str(n),130+20*n,v,['grey','purple'][n in etape]) pos = 3 while not (kd(KE) or kd(KO)): if kd(KL) or kd(KR): for m in [-1,1]: draw_string(" ",130+20*pos+10*m,v) pos = (pos+(kd(KR)-kd(KL)))%9 draw_string("[",130+20*pos-10,v,'blue') draw_string("]",130+20*pos+10,v,'blue') sleep(0.08) if kd(KU) or kd(KD): if pos in etape: etape.remove(pos) else: etape.append(pos) draw_string(str(pos),130+20*pos,v,['grey','purple'][pos in etape]) while kd(KU) or kd(KD):True while kd(KE) or kd(KO):True v += vv mini = 1 maxi = 999 N = menu("Nombre de cycles : ",50,0,"nombre","","") v += vv pause = menu("Pause en fin de cycle : ",False,0,"booléen","oui","non") d = c+e D = range(c) a = 222//d b = 320//d A = range(a) B = range(b) dg = (320%d+e)//2-2*(s==1)-4*(s==2) dh = (222%d+e)//2-5*(s==1)-2*(s==2)+(s==0) Liste = [[0 for col in B] for lig in A] fill_rect(1,1,320,222,'white') if alea: for lig in A: for col in B: Liste[lig][col] = 2*randint(0,1) if Liste[lig][col] == 2: if s < 3: draw_string(S[s],dg+d*col,(dh+d*lig)*(1-2*(s==0))+207*(s==0),'blue') else: carre(lig,col,'blue') else: col = b//2 lig = a//2 while not (kd(KU) or kd(KD) or kd(KL) or kd(KR) or kd(KE) or kd(KO) or kd(KS)): draw_string("Flèches pour se déplacer",40,30,'orange') draw_string("EXE ou OK pour afficher/cacher",10,48,'orange') draw_string("SHIFT pour lancer la partie",25,66,'orange') fill_rect(10,30,300,84,'white') while not kd(KS): sleep(0.08) curseur('orange') K = kd(KR)-kd(KL) L = kd(KD)-kd(KU) if K != 0 or L != 0: curseur('white') lig = (lig+L)%a col = (col+K)%b if s == 3 and e == 0: for rangl in [-2,-1,0,1,2]: for rangc in [-2,-1,0,1,2]: if Liste[(lig+rangl)%a][(col+rangc)%b] > 0: carre(lig+rangl,col+rangc,'blue') if kd(KE) or kd(KO): Liste[lig*(1-2*(s==0))+(a-1)*(s==0)][col*(1-2*(s==2))+(b-1)*(s==2)] = 2-Liste[lig*(1-2*(s==0))+(a-1)*(s==0)][col*(1-2*(s==2))+(b-1)*(s==2)] couleur = ['white','blue'][Liste[lig*(1-2*(s==0))+(a-1)*(s==0)][col*(1-2*(s==2))+(b-1)*(s==2)] > 0] if s < 3: draw_string(S[s],dg+d*col,dh+d*lig-7*(s==0),couleur) if s == 0 and e < 5 and lig > 0: for rang in range(a-lig,a): if Liste[rang][col] == 0:break draw_string(S[s],dg+d*col,dh+d*(a-rang-1)-7*(s==0),'blue') if s == 1 and e < 5: for rang in range(lig+1,a): if Liste[rang][col] == 0:break draw_string(S[s],dg+d*col,dh+d*rang,'blue') if s == 2: for rangc in range(b-col-1,b-col*(e>3)): for rangl in range(lig,a): if Liste[rangl][rangc] > 0: draw_string(S[s],dg+d*(b-1-rangc),dh+d*rangl,'blue') else: carre(lig,col,couleur) while kd(KE) or kd(KO):True curseur('white') def main(): for gen in range(N): for i in A: for j in B: Voisins = 0 for k in [-1,0,1]: for l in [-1,0,1]: if [k,l] != [0,0] and Liste[(i+k)%a][(j+l)%b]**2 > 3: Voisins += 1 if (Liste[i][j] == 0 and Voisins in Naissance) or (Liste[i][j] > 0 and Voisins in Survie): Liste[i][j] += 1 couleur = (clr*min(25*Liste[i][j]-25,255),0,max(0,255+clr*(25-25*Liste[i][j]))) else: Liste[i][j] *= -1 couleur = 'white' if Liste[i][j] != 0: if s < 3: draw_string(S[s],dg+d*j*(1-2*(s==2))+d*(b-1)*(s==2),(dh+d*i)*(1-2*(s==0))+207*(s==0),couleur) else: carre(i,j,couleur) for i in A: for j in B: Liste[i][j] = 2*((max(0,Liste[i][j])+1)//2) aff = 0 while kd(KS) or (pause and not (kd(KE) or kd(KO))): draw_string(str(gen+N*relance+1)*kd(KS),160,110,'red') aff = max(aff,kd(KS)) draw_string(" "*len(str(gen+N*relance+1))*aff,160,110) choix = 0 while 1: if choix == 0: init() relance = -1 relance += 1 main() while not (kd(KE) or kd(KO)):True while kd(KE) or kd(KO): draw_string("Maintenir SHIFT en pleine partie",0,30,'orange') draw_string("pour mettre en pause et afficher",0,48,'orange') draw_string("le numéro du cycle terminé.",0,64,'orange') draw_string(" Cycle : "+str(N*(relance+1))+" ",110-5*len(str(N*(relance+1))),102,'red') draw_string(" Poursuivre ",80,122,'purple') draw_string(" Retour au menu ",60,140,'purple') while not (kd(KE) or kd(KO)): draw_string("[",70+20*choix,140-18*choix,'blue') draw_string("]",240-20*choix,140-18*choix,'blue') if kd(KD) or kd(KU): draw_string(" ",70+20*choix,140-18*choix) draw_string(" ",240-20*choix,140-18*choix) choix = 1-choix while kd(KD) or kd(KU):True while kd(KE) or kd(KO):True fill_rect(0,30*choix,320,222-158*choix,'white') fill_rect(90,102,180,56,'white')