Jeu Leaves, adapté pour calculatrice par Afyu.
Le jeu Leaves a été imaginé par IsawU : Présentation en anglais : https://www.youtube.com/watch?v=RQx2V76qQfg Présentation en français : https://www.youtube.com/watch?v=gjh7OLO0V3Y Modèle d’impression 3D : https://www.printables.com/model/72515-abstract-strategy-game-leaves/files )
Chacun des deux joueurs commence la partie avec 10 feuilles, qu’il faut placer autour des 5 branches initiales. À tour de rôle, chacun des joueur place 2 de ses feuilles. Chaque placement de feuille est suivi d’une poussée des tuiles adjacentes (toutes celles qui sont alignées et jointives), dans une direction. La poussée de la 2ème feuille posée doit être effectuée perpendiculairement à la poussée de la 1ère feuille posée, avec une rotation d’un quart de tour dans le sens des aiguilles d’une montre. Il est interdit de placer une feuille entre deux tuiles puis de pousser vers une des deux tuiles qui encadrent (on ne coupe pas l’arbre en deux) mais au contraire, on peut pousser depuis l’extérieur vers l’intérieur dans le but de réduire la taille d’un espace entre deux tuiles.
Le but est d’avoir le plus grand nombre possible de feuilles encore accrochées à une branche à la fin de la partie (après le placement de toutes les feuilles des joueurs) : c’est-à-dire les feuilles qui sont à côté d’une branche, mais pas en diagonale. Ensuite, les feuilles qui ne sont pas (ou plus) accrochées tombent et on compte le nombre de feuilles encore accrochées.
# jeu Leaves, adapté pour calculatrice par Afyu du jeu Leaves initialement imaginé par IsawU (https://www.youtube.com/watch?v=RQx2V76qQfg # https://www.youtube.com/watch?v=gjh7OLO0V3Y # Modèle d'impression 3D : https://www.printables.com/model/72515-abstract-strategy-game-leaves/files ) from kandinsky import * from ion import * from time import * from random import randint def dessine_curseur(x,y,clr,mode_mini=0): dX=65+(15-4*mode_mini)*x-1 dY=25+(15-4*mode_mini)*y-1 for i in range(2): fill_rect(dX,dY+(14-4*mode_mini)*i,15-4*mode_mini,1,clr) fill_rect(dX+(14-4*mode_mini)*i,dY,1,15-4*mode_mini,clr) def efface_case(i,j,mode_mini,clr=(230,230,230)): dX=int(65+1+(15-4*mode_mini)*i) dY=int(25+1+(15-4*mode_mini)*j) fill_rect(dX-1,dY-1,13-4*mode_mini,13-4*mode_mini,clr) def dessine_case(i,j,nom=" ",mode_mini=0): dX=int(65+1+(15-4*mode_mini)*i) dY=int(25+1+(15-4*mode_mini)*j) efface_case(i,j,mode_mini) #fill_rect(dX-1,dY-1,13-4*mode_mini,13-4*mode_mini,(220,220,220)) if nom==" ": nom=("","branche","chene","erable")[Plateau[j][i]] if nom=="branche": if mode_mini: motif=("MFFFFMF","MMFFMMM","FMFMMFF","FMMMFFM","FMMMMMF","FMMFFFF","MMFFFFF") else: motif=("FFFFMFFFFMF","FMFFMMFMMMF","FMFFFMFMFFF","FMMFFMMMMMM","FFMFFMMMFFF","FFMFMMFFFFF","FFMMMFFFMMF","FFMMMFFMMFF","FFMMMMMMFFF","FMMMFFFFFFF","MMMFFFFFFFF") elif nom=="chene": if mode_mini: motif=("FFFFVVV","FFFVVVV","FFVVVVV","FVVVVVF","FVVVVFF","VVVVFFF","VVFFFFF") else: motif=("FFFFFFFVVVV","FFFFFVVVVVV","FFFFFVVVVVV","FFFVVVVVVVV","FFFVVVVVVVF","FVVVVVVVVVF","FVVVVVVVFFF","FVVVVVVVFFF","FVVVVVFFFFF","VVVVVVFFFFF","VVFFFFFFFFF") elif nom=="erable": if mode_mini: motif=("FFFRFFF","FFRRRFF","RRRRRRR","FRRRRRF","FFRRRFF","FRRRRRF","RRFRFRR") else: motif=("FFFFFRFFFFF","FFFFRRRFFFF","FFFFRRRFFFF","RRRFRRRFRRR","RRRRRRRRRRR","FRRRRRRRRRF","FFRRRRRRRFF","FFFRRRRRFFF","FFRRRRRRRFF","FRRRFRFRRRF","FFFFFRFFFFF") else: motif=("F"*(11-4*mode_mini),)*(11-4*mode_mini) for ligne in range(11-4*mode_mini): for colonne in range(11-4*mode_mini): clr=("w","brown",(50,150,30),"r")[("F","M","V","R").index(motif[ligne][colonne])] if clr != "w": set_pixel(dX+colonne,dY+ligne,clr) def coup_valide(direction): if direction=="droite": return sum(Plateau[Yc][:Xc])==0 and Plateau[Yc][Xc+1]!=0 #and any(Plateau[Yc+i][Xc+1]==1 for i in (-1,0,1)) if direction=="gauche": return sum(Plateau[Yc][Xc+1:])==0 and Plateau[Yc][Xc-1]!=0 #and any(Plateau[Yc+i][Xc-1]==1 for i in (-1,0,1)) if direction=="haut": return sum(Plateau[i][Xc] for i in range(Yc+1,H))==0 and Plateau[Yc-1][Xc]!=0 #and any(Plateau[Yc-1][Xc+i]==1 for i in (-1,0,1)) if direction=="bas": return sum(Plateau[i][Xc] for i in range(0,Yc))==0 and Plateau[Yc+1][Xc]!=0 #and any(Plateau[Yc+1][Xc+i]==1 for i in (-1,0,1)) # dessin du plateau, avec les 5 branches initiales def dessine_plateau(): for i in range(L): for j in range(H): dessine_case(i,j," ",mode_mini) def dessine_motif(motif,clr=""): if motif=="|": for j in range(11,16): if clr=="w": efface_case(20,j,1,"w") # mode_mini else: dessine_case(20,j,"branche",1) # mode_mini if motif=="U": for (i,j) in ((19,14),(19,15),(20,15),(21,15),(21,14)): if clr=="w": efface_case(i,j,1,"w") # mode_mini else: dessine_case(i,j,"branche",1) # mode_mini if motif=="+": for (i,j) in ((19,14),(20,14),(21,14),(20,13),(20,15)): if clr=="w": efface_case(i,j,1,"w") # mode_mini else: dessine_case(i,j,"branche",1) # mode_mini # arbre en forme de coeur #for i in range(4): # dessine_case(-1.6,4+i,"branche") # dessine_case(-2.6,3+i,"erable") # dessine_case(-0.6,3+i,"chene") # dessine_case(-3.6,4+i%2,"erable") # dessine_case(0.4,4+i%2,"chene") # arbres des côtés for j in (0,1): for i in range(8): dessine_case(-2.6+17*j,1.8+i,"branche") for i in range(6): dessine_case(-3.6+2*j+(2-4*j)*(i%2==1)+17*j,1.8+i,("chene","erable")[i%2]) # feuilles en haut et en bas for j in (0,1): for k in range(j,11+j): dessine_case(0.9+k-j,-0.8+11.25*j+k%2,("chene","erable")[k%2]) L=13 H=13 Plateau=[[0]*L for k in range(H)] motif_initial=2 # | ou U ou + mode_mini=0 draw_string("Leaves",130,70,"purple") draw_string("(feuilles)",110,95,"purple") draw_string("Valider avec OK",85,135,"purple") for k in range(2): fill_rect(60,55+k*111,200,1,"g") while not (keydown(KEY_OK) or keydown(KEY_EXE)): for k in range(1,20): draw_string("Valider avec OK",85,135,(140+10*abs(10-k),25*abs(10-k),200)) if keydown(KEY_OK) or keydown(KEY_EXE):break sleep(0.1) while keydown(KEY_OK) or keydown(KEY_EXE):1 fill_rect(0,0,320,222,"w") draw_string("Présentation",100,10,(80,150,50)) Regles=(("Le jeu débute avec 5 branches","( ) placées sur le plateau.","Chaque joueur a 10 feuilles.","","A tour de rôle, les joueurs","placent puis poussent 2 de","leurs feuilles, en tentant de","les maintenir accrochées aux","branches (pas en diagonale)."),\ ("La poussée de la 2ème feuille","placée s'effectue perpendi-","culairement à la poussée de","la 1ère feuille placée, en","tournant dans le sens des","aiguilles d'une montre.","","On ne peut pas placer une","feuille entre deux tuiles."),\ ("En fin de partie, toutes les","feuilles qui ne sont plus","accrochées aux branches","tombent et sont retirées du","jeu. Le gagnant est le joueur","qui a le plus de feuilles","encore accrochées.","","Choix du motif initial : ")) for i in range(3): for k in range(len(Regles[i])): draw_string(Regles[i][k],20,33+18*k,"b") draw_string("Page "+str(i+1)+"/3 → OK",120,200,(80,150,50)) if i==0: dessine_case(-2.1,1.9,"branche") for k in range(10): dessine_case(-3.33+0.94*k,4.3,"chene") dessine_case(6.8+0.94*k,4.3,"erable") if i==2: draw_string("< >",260,177,"orange") chg=1 while not (keydown(KEY_EXE) or keydown(KEY_OK)): if i==2: if chg: dessine_motif("|U+"[motif_initial],"w") #draw_string("|U+"[motif_initial],285,177,"w") motif_initial=(motif_initial+chg)%3 dessine_motif("|U+"[motif_initial]) #draw_string("|U+"[motif_initial],285,177,"purple") sleep(0.2) chg=keydown(KEY_RIGHT)-keydown(KEY_LEFT) while keydown(KEY_EXE) or keydown(KEY_OK):1 fill_rect(0,30,320,222,"w") fill_rect(0,0,320,30,"w") # dessin des 10 feuilles de chaque joueur for joueur in (0,1): for i in range(10): dessine_case(-3+(i%2)+17*joueur,3+(i//2),("chene","erable")[joueur]) dessine_case(2+2*(i%5),11*joueur,"branche") motif="|U+"[motif_initial] if motif=="|": for i in range(5): Plateau[i+L//2-2][H//2]=1 # branche if motif=="U": for (i,j) in ((19,14),(19,15),(20,15),(21,15),(21,14)): Plateau[j-9][i-14]=1 # branche if motif=="+": for (i,j) in ((19,14),(20,14),(21,14),(20,13),(20,15)): Plateau[j-8][i-14]=1 # branche Xc,Yc=L//2+1,H//2 chgX,chgY=-1,0 joueur=0 tour=1 # 0 ou 1 precedente_direction="gauche" #mode_mini=0 dessine_plateau() while sum([Plateau[n].count(2) for n in range(H)])<10: # tant qu'on n'a pas placé 10 feuilles vertes # passage en mode compact, lorsque nécessaire if sum(Plateau[1])!=0 or sum(Plateau[-2])!=0 or sum(Plateau[k][1] for k in range(H))!=0 or sum(Plateau[k][-2] for k in range(H))!=0: mode_mini=1 fill_rect(65,25,13*15,13*15,"w") if sum(Plateau[1])!=0: # il va manquer des lignes en haut Plateau=[[0]*L for k in range(2)]+Plateau H+=2 Yc+=1 if sum(Plateau[-2])!=0: # il va manquer des lignes en bas Plateau=Plateau+[[0]*L for k in range(2)] H+=2 Yc+=1 if sum(Plateau[k][1] for k in range(H))!=0: for ligne in range(H): # il va manquer des colonnes à gauche Plateau[ligne]=[0]*2+Plateau[ligne] L+=2 Xc+=1 if sum(Plateau[k][-2] for k in range(H))!=0: for ligne in range(H): # il va manquer des colonnes à droite Plateau[ligne]=Plateau[ligne]+[0]*2 L+=2 # Plateau=[[0]*(L+10) for k in range(5)]+Plateau+[[0]*(L+10) for k in range(5)] dessine_plateau() Nrestant=9-sum([Plateau[n].count(2+joueur) for n in range(H)]) dessine_curseur(-3+Nrestant%2+17*joueur,3+Nrestant//2,"b") if tour==0 and Nrestant>0: # curseur autour de la 2ème feuille à jouer dessine_curseur(-3+(Nrestant-1)%2+17*joueur,3+(Nrestant-1)//2,"b") # choix de l'emplacement draw_string(" Choix de l'emplacement ",40,5,"b") if chgX or chgY: dessine_curseur(Xc,Yc,"w",mode_mini) Xc=(Xc+chgX-1)%(L-2)+1 # on évite les bords de Plateau pour éviter les conflits avec des voisins hors bornes Yc=(Yc+chgY-1)%(H-2)+1 dessine_curseur(Xc,Yc,"rb"[Plateau[Yc][Xc]==0 and (((tour==0 or sum([Plateau[n].count(2) for n in range(H)])==0) and any(coup_valide(direction) for direction in ("droite","gauche","haut","bas"))) or (tour==1 and coup_valide(("haut","droite","bas","gauche")[("gauche","haut","droite","bas").index(precedente_direction)]) ))],mode_mini) # 4 directions possibles pour le tout premier coup et le premier coup de chaque joueur, et seulement les directions perpendiculaires au premier coup pour le deuxième coup de chaque joueur sleep(0.2) chgX=keydown(KEY_RIGHT)-keydown(KEY_LEFT) chgY=keydown(KEY_DOWN)-keydown(KEY_UP) if (keydown(KEY_OK) or keydown(KEY_EXE)) and Plateau[Yc][Xc]==0 and (((tour==0 or sum([Plateau[n].count(2) for n in range(H)])==0) and any(coup_valide(direction) for direction in ("droite","gauche","haut","bas"))) or (tour==1 and coup_valide(("haut","droite","bas","gauche")[("gauche","haut","droite","bas").index(precedente_direction)]) )):#and any(Plateau[Yc+j][Xc+i]==1 for i in (-1,0,1) for j in (-1,0,1)):#(Plateau[Yc+1][Xc]==1 or Plateau[Yc-1][Xc]==1 or Plateau[Yc][Xc+1]==1 or Plateau[Yc][Xc-1]==1): # on est sur une case vide, adjacente à une branche draw_string(" Choix de la direction ",45,5,"b") Plateau[Yc][Xc]=joueur+2 # 2 ou 3 dessine_case(Xc,Yc," ",mode_mini) # on efface la feuille de la réserve du joueur concerné dessine_curseur(-3+Nrestant%2+17*joueur,3+Nrestant//2,"w") dessine_case(-3+Nrestant%2+17*joueur,3+Nrestant//2,"") while keydown(KEY_OK) or keydown(KEY_EXE):1 while 1: if keydown(KEY_RIGHT) and coup_valide("droite") and (tour==0 or sum([Plateau[n].count(3) for n in range(H)])==0 or (tour==1 and precedente_direction=="haut")):#sum(Plateau[Yc][:Xc])==0 and Plateau[Yc][Xc+1]!=0 and any(Plateau[Yc+i][Xc+1]==1 for i in (-1,0,1)): for k in range(Plateau[Yc].index(0,Xc),Xc,-1): Plateau[Yc][k]=Plateau[Yc][k-1] dessine_case(k,Yc," ",mode_mini) Plateau[Yc][Xc]=0 dessine_case(Xc,Yc," ",mode_mini) precedente_direction="droite" joueur=(joueur+tour%2)%2 tour=(tour+1)%2 break if keydown(KEY_LEFT) and coup_valide("gauche") and (tour==0 or sum([Plateau[n].count(3) for n in range(H)])==0 or (tour==1 and precedente_direction=="bas")):#sum(Plateau[Yc][Xc+1:])==0 and Plateau[Yc][Xc-1]!=0 and any(Plateau[Yc+i][Xc-1]==1 for i in (-1,0,1)): for k in range(L-1-Plateau[Yc][::-1].index(0,L-1-Xc),Xc): Plateau[Yc][k]=Plateau[Yc][k+1] dessine_case(k,Yc," ",mode_mini) Plateau[Yc][Xc]=0 dessine_case(Xc,Yc," ",mode_mini) precedente_direction="gauche" joueur=(joueur+tour%2)%2 tour=(tour+1)%2 break if keydown(KEY_UP) and coup_valide("haut") and (tour==0 or sum([Plateau[n].count(3) for n in range(H)])==0 or (tour==1 and precedente_direction=="gauche")):#sum(Plateau[i][Xc] for i in range(Yc+1,H))==0 and Plateau[Yc-1][Xc]!=0 and any(Plateau[Yc-1][Xc+i]==1 for i in (-1,0,1)): for k in range(H-1-[Plateau[i][Xc] for i in range(H)][::-1].index(0,H-1-Yc),Yc): Plateau[k][Xc]=Plateau[k+1][Xc] dessine_case(Xc,k," ",mode_mini) Plateau[Yc][Xc]=0 dessine_case(Xc,Yc," ",mode_mini) precedente_direction="haut" joueur=(joueur+tour%2)%2 tour=(tour+1)%2 break if keydown(KEY_DOWN) and coup_valide("bas") and (tour==0 or sum([Plateau[n].count(3) for n in range(H)])==0 or (tour==1 and precedente_direction=="droite")):#sum(Plateau[i][Xc] for i in range(0,Yc))==0 and Plateau[Yc+1][Xc]!=0 and any(Plateau[Yc+1][Xc+i]==1 for i in (-1,0,1)): for k in range([Plateau[i][Xc] for i in range(H)].index(0,Yc),Yc,-1): Plateau[k][Xc]=Plateau[k-1][Xc] dessine_case(Xc,k," ",mode_mini) Plateau[Yc][Xc]=0 dessine_case(Xc,Yc," ",mode_mini) precedente_direction="bas" joueur=(joueur+tour%2)%2 tour=(tour+1)%2 break dessine_curseur(Xc,Yc,"w",mode_mini) # fin de partie, on va déterminer combien de feuilles sont attachées à une branche # et combien de feuilles vont tomber draw_string(" Partie terminée ",45,5,"b") while not (keydown(KEY_OK) or keydown(KEY_EXE)):1 while keydown(KEY_OK) or keydown(KEY_EXE):1 draw_string(" Les feuilles tombent ",50,5,"orange") for i in range(H): for j in range(L): if Plateau[i][j] in (2,3) and not any(Plateau[i+k][j+l]==1 and k%2 != l%2 for k in (-1,0,1) for l in (-1,0,1)): dessine_curseur(j,i,"k",mode_mini) sleep(3) feuilles_tombees=[0,0] for i in range(H): for j in range(L): if Plateau[i][j] in (2,3) and not any(Plateau[i+k][j+l]==1 and k%2 != l%2 for k in (-1,0,1) for l in (-1,0,1)): dessine_curseur(j,i,"w",mode_mini) joueur=Plateau[i][j]-2 feuilles_tombees[joueur]+=1 # on dessine la feuille en la rendant au joueur concerné Plateau[i][j]=0 dessine_case(j,i," ",mode_mini) dessine_case(-3+(feuilles_tombees[joueur]-1)%2+17*joueur,3+(feuilles_tombees[joueur]-1)//2,("chene","erable")[joueur]) #draw_string(str(feuilles_tombees),150,200,"b") sleep(1) if feuilles_tombees[0]==feuilles_tombees[1]: draw_string(" Egalité ! ",45,5,"b") else: draw_string("Les feuilles "+("vertes","rouges")[feuilles_tombees[1]<feuilles_tombees[0]]+" ont gagné !",5,5,((50,150,30),"r")[feuilles_tombees[1]<feuilles_tombees[0]])