Adaptation du jeu Orlog (jeu de dés et de jetons) à partir du mini-jeu éponyme dans le jeu Assassin’s Creed® : Valhalla.
Version avec une IA basique et un résumé du plateau affiché en bas lors du choix de la divinité pour la prochaine manche mais avec le nom des sorts réduit au nom de la divinité.
Une version avec le nom complet des sorts mais sans l’affichage du résumé du plateau est disponible ici : https://my.numworks.com/python/florian-allard/orlog2023
from random import choice from kandinsky import set_pixel,fill_rect as fr,draw_string as ds from ion import keydown as kd,KEY_EXE as KE,KEY_LEFT as KL,KEY_RIGHT as KR,KEY_DOWN as KD,KEY_UP as KU from time import sleep as sp inf={"Thrymr":(1,"Niveau d'invocation adverse\n réduit.",3,6,9,"-",1,2,3," niv"," "),\ "Var":(1,"Soin par Jeton adverse\n dépensé.",10,14,18,"+",1,2,3," / ","<J"),\ "Freyja":(2,"Dés supplémentaires lancés.",2,4,6,"+",1,2,3," ","v "),\ "Frigg":(2,"Dés à soi et/ou adverses au\n choix relancés.",2,3,4,"",2,3,4," ","v "),\ "Loki":(2,"Dés adverses au choix\n bannis.",3,6,9,"-",1,2,3," ","v "),\ "Skuld":(3,"Jetons adverses détruits\n par face flèche.",4,6,8,"-",2,3,4," / ","Jf"),\ "Tyr":(3,"Jetons adverses détruits\n par PV sacrifié.",4,6,8,"",-2,-3,-4," / ","J<"),\ "Baldr":(4,"Multiplie casques et\n boucliers.",3,6,9,"",2,3,4,"x( & )","cb"),\ "Bragi":(4,"Jetons gagnés par face main.",4,8,12,"+",2,3,4," / ","Jm"),\ "Brunehilde":(4,"Multiplie les haches.",6,10,18," ",1.5,2,3,"x( )"," h"),\ "Freyr":(4,"Ajout de faces majoritaires.",4,6,8,"+",2,3,4," majoritaire","v "),\ "Heimdal":(4,"Soin par attaque bloquée.",4,7,10,"+",1,2,3," /blocage","< "),\ "Hel":(4,"Soin par coup de hache\n infligé.",6,12,18,"+",1,2,3," / infligée","<h"),\ "Mimir":(4,"Jetons gagnés par coup subi.",3,5,7,"+",1,2,3," /coup subi","J "),\ "Skadi":(4,"Multiplie les flèches.",6,10,14,"",2,3,4,"x( )","f "),\ "Ullr":(4,"Boucliers adverses ignorés.",2,3,4,"-",2,3,6," ","b "),\ "Vidar":(4,"Casques adverses enlevés.",2,4,6,"-",2,4,6," ","c "),\ "Thor":(8,"Dégâts infligés après la\n phase de résolution.",4,8,12,"-",2,5,8," ","< "),\ "Idunn":(9,"Soin après la phase de\n résolution.",4,7,10,"+",2,4,6," ","< "),\ "Odin":(9,"Gain de Jetons par PV\n sacrifié.",6,8,10,"+",3,4,5," / ","J<")} def AffDv(Dv): fr(15,42,290,136,"w") fr(0,41,320,1,"purple") ds("< >",5,126,"b") if Dv=="aucune": ds("Ne pas choisir\n de divinité.",90,80,"r") else: ds(Dv,160-5*len(Dv),45,"g") # nom ds(str(inf[Dv][0]),155,62,"r") # priorité ds(inf[Dv][1],29,76,"b") # description dess("d",305,5,"purple") for niv in (0,1,2): Y=115+22*niv Cout=inf[Dv][2+niv] ds(str(Cout)+" : "+inf[Dv][5]+str(inf[Dv][6+niv])+inf[Dv][-2],55+10*(Cout<10),Y,"purple") ds(" >"[niv==NvDv[Jr]],40,Y,"r") dess("J",85,Y+3,dore,dore) for k in (2,1): dess(inf[Dv][-1][-k],220-30*k,Y+3,"brown","brown","brown") sp(0.2) def cadre(x,y,l,h,clr): for k in (0,1): fr(x,y+h*k,l+1,1,clr) fr(x+l*k,y,1,h+1,clr) mtfs={"<":(0,0,0,0,252,252,252,252),"":()," ":(),"v":(),"V":(),"h":(8,28,62,111,206,396,768,1536,1024),"f":(15,3,5,9,16,32,64,896,128,128),"c":(120,252,510,1023,1023,819,819,390,390),"b":(120,204,390,891,585,585,891,390,204,120),"m":(168,170,170,682,766,1022,508,248,120,120),"j":(0,462,330,510,72,72,510,330,462),"d":(1799,1022,260,340,260,396,626,1025,1539,1285,1161,1105,1105,1105,2047)} dore=(200,150,0) def dess(ltr,x,y,Mtf="b",Ctr="g",Lsr=dore): mtf=mtfs[ltr.lower()] for lig in range(len(mtf)): elt=mtf[lig] elt="0"*(12+(ltr in ("d","h"))-len(bin(elt)))+bin(elt)[2:] for col in range(len(elt)): set_pixel(x+col,y+lig,(("w",Mtf)[int(elt[col])],"g")[ltr=="<"]) if ltr not in ("<",""," ","d"): cadre(x-4,y-4,17,17,Ctr) cadre(x-2,y-2,13,13,("w",Lsr)[ltr.isupper()]) def ChF(jr,n,DR,Affch,NB=9): L=len(DR) Verr=[0]*L pos=-1 POS=(165-10*len(Affch),180-150*jr)[n>0] ch=1 Num=102+100*jr if IA and not jr and n>0: Verr=[Affch[k] in ("BCFM",("hfF","bBcC")[Vie[0]<Vie[1]])[Jet[1]>5] for k in range(L)] sp(1) else: while not ((kd(KE) and n>0) or n==3 or L*NB==0 or (kd(KE) and n<1 and sum(Verr)<=NB)): ds("^ "[ch],20*pos+POS,Num,"b") sp(0.2*(ch!=0)) pos=(pos+ch)%L while Affch[pos]==" " and ch: pos=(pos+ch)%L ds("^",20*pos+POS,Num,"b") ch=kd(KR)-kd(KL) if kd(KU) or kd(KD): while kd(KU) or kd(KD):1 dess(Affch[pos],20*pos+POS,Num-15,"b","rg"[Verr[pos]]) Verr[pos]=1-Verr[pos] while kd(KE) and n<3:1 Nvl=tuple(Affch[i] for i in range(L) if (Verr[i] or n==3))*(n>0) chs[jr]=(chs[jr]+list(Nvl),list(Nvl)+chs[jr])[jr] fr(0,Num,320,16,"w")#ds(" "*32,0,102+100*jr) # efface les ^ for i in range(L): # efface les faces des nouveaux dés choisis dess(Affch[i]*(Verr[i]>0 or n==3),20*i+POS,Num-15,"kw"[n>0],"kw"[n>0],"kw"[n>0]) if n<1 and Verr[i]>0: chs[jr][i]=(" ",choice(choice(Des)))[n] return DR,Verr def Duel(faces,jr,clrs=("b","r",dore)): symb(faces[jr],0,0,clrs) symb(faces[1-jr],1,faces[jr] in chs[0] or faces[jr].upper() in chs[0] or faces[1-jr] in chs[1] or faces[1-jr].upper() in chs[1],clrs) def AV(Jr,ch): ch=min(max(ch,-Vie[Jr]),15-Vie[Jr]) Vie[Jr]+=ch if ch: #for i in range(Vie[Jr]-ch*(ch>0)): # affV(i,"g",Jr) for (clr1,clr2) in (("r","cyan"),("w","g")): for i in range(Vie[Jr]-ch*(ch>0),Vie[Jr]-ch*(ch<0)): affV(i,(clr1,clr2)[ch>0],Jr) sp(0.7) while min(Vie)==0: ds("Joueur "+"AB"[Vie.index(0)]+" a rejoint Odin...",10,105,"purple") def affV(i,clr,j): fr(255-245*j+10*(i%5),32+100*j+8*(i//5),6,4,clr) def symb(ltr,jr,pause=0,clrs=("b","g",dore),Nb=99,eff=0): L=len(chs[jr]) for i in range(L): if ltr=="tout" or (chs[jr][i].lower()==ltr and Nb>0): dess(chs[jr][i],20*(i%16)+5+(L<17)*(160-10*L),87+100*jr-10*((L-1)//16)+20*(i//16),clrs[0],clrs[1],clrs[2]) Nb -= 1 chs[jr][i]=(chs[jr][i],"vV"[chs[jr][i].isupper()])[eff] if ltr=="tout" and Ulr[1-jr]: symb("b",jr,0,("cyan",clrs[1],clrs[2]),2+(NvDv[1-jr]-1)**2) sp(pause) def calc(ok=True): if ok: (H[:],f[:],F[:],c[:],C[:],b[:],B[:],m[:],M[:],v[:],V[:])=tuple([chs[k].count(ltr) for k in (0,1)] for ltr in "hfFcCbBmMvV") #Sep=(max(H[J],c[K]+C[K]+v[K]+V[K]),max(f[J]+F[J],b[K]+B[K]),max(c[J]+C[J]+v[J]+V[J],H[K]),max(b[J]+B[J],f[K]+F[K])) chs[J]=list("h"*H[J]+" "*(c[K]+C[K]+v[K]+V[K]-H[J])+"f"*f[J]+"F"*F[J]+" "*(b[K]+B[K]-f[J]-F[J])+"v"*v[J]+"V"*V[J]+"c"*c[J]+"C"*C[J]+" "*(H[K]-c[J]-C[J]-v[J]-V[J])+"b"*b[J]+"B"*B[J]+" "*(f[K]+F[K]-b[J]-B[J])+"m"*m[J]+"M"*M[J]+" "*(m[K]+M[K])) chs[K]=list("v"*v[K]+"V"*V[K]+"c"*c[K]+"C"*C[K]+" "*(H[J]-c[K]-C[K]-v[K]-V[K])+"b"*b[K]+"B"*B[K]+" "*(f[J]+F[J]-b[K]-B[K])+"h"*H[K]+" "*(c[J]+C[J]+v[J]+V[J]-H[K])+"f"*f[K]+"F"*F[K]+" "*(b[J]+B[J]-f[K]-F[K])+" "*(m[J]+M[J])+"m"*m[K]+"M"*M[K]) for Jr in (J,K): fr(0,65+100*Jr,320,49,"w") symb("tout",Jr) def AJ(jr,nb=0): Jet[jr]=min(50,max(0,Jet[jr]+nb)) if nb: for clr in ("r",dore): sp(0.7) affJ(jr,clr) def affJ(jr,clr): ds(" "*jr*(Jet[jr]<10)+str(Jet[jr])+" "*(1-jr),32+235*jr,22+100*jr,clr) def plt(): fr(0,0,320,222,"w") for Jr in (J,K): Y=25+100*Jr ds("Joueur "+"AB"[Jr],120,Y+2,"g") for i in range(Vie[Jr]): affV(i,"g",Jr) dess("J",12+285*Jr,Y,dore,dore) affJ(Jr,dore) dess("d",10+285*Jr,Y+20,"purple") def Tt(dv): if inf[dv][0]==NIV: co=inf[dv][NvDv[Jr]+1] ok=DvMch[Jr]==dv and Jet[Jr]>=co Ny=45+100*Jr dess("d"*(DvMch[Jr]==dv),10+285*Jr,Ny,"rb"[ok]) if ok: chn=inf[dv][5]+str(Puiss)+inf[dv][-2] AJ(Jr,-co) AV(1-Jr,Vr[1-Jr]*co*NvDv[1-Jr]) Nx=245*Jr-10*len(chn)*Jr ds(chn,30+Nx,Ny,"b") for k in (2,1): dess(inf[dv][-1][-k],125+Nx-30*k,3+Ny,"brown","brown","brown") sp(DvMch[Jr]==dv) return ok def sacri(): NbPV=Vie[Jr]-1 while not kd(KE): NbPV=max(0,min(NbPV+kd(KR)-kd(KL),Vie[Jr])) for i in range(Vie[Jr]): affV(i,"kg"[i<NbPV],Jr) sp(0.2) #while kd(KE):1 AJ((Jr,1-Jr)[DvMch[Jr]=="Tyr"],(Vie[Jr]-NbPV)*Puiss) AV(Jr,NbPV-Vie[Jr]) # Choix des divinités pour toute la partie ds("Orlog",135,15,"g") ds("Choisir le mode\n\n Joueur vs Joueur\n Joueur vs IA\n\n Valider avec EXE",85,56,"purple") IA=1 for k in range(6): fr(60,40+k//5*145,200,1,"b") dess("hCfbMF"[k],90+25*k,200) while not kd(KE): IA=(IA,1-IA)[kd(KU)-kd(KD)] for k in (0,1): ds(" >"[k==IA],60,94+18*k,"r") sp(0.2) while kd(KE):1 fr(0,0,320,240,"w") DvCh,NvDv=[["Vidar"]*IA,[]],[-3,-3] #DvCh=[[],[]] J=choice((0,1)) K=1-J for Jr in (J,K): if Jr or not IA: rg=-1 ds("Joueur "+"AB"[Jr]+" : Choix des divinités\n ",2,5,"g") chgt=1 while not kd(KE): rg=(rg+chgt)%20 Dv=tuple(sorted(inf.keys()))[rg] if chgt: AffDv(Dv) chgt=kd(KR)-kd(KL) if kd(KU) or kd(KD): if Dv in DvCh[Jr]: DvCh[Jr].remove(Dv) elif len(DvCh[Jr])<3: DvCh[Jr].append(Dv) DvCh[Jr].sort() ds(" ".join(DvCh[Jr])+" ",15,22,"purple") while kd(KU) or kd(KD):1 while kd(KE):1 DvCh[Jr].append("aucune") # Initialisation Vie=[15,15] Jet=[0,0] while 1: plt() # Phase de lancer Des=("ChhFbm","ChhfBm","ChhfbM","chhFBm","chhFbM","chhfBM") Rest=[Des[:]]*2 chs,Vr,Ulr,Hl,Hmdl,Mmr,DvMch=[[],[]],[0,0],[0,0],[0,0],[0,0],[0,0],["",""] ds(" Phase de lancer ",55,5,"orange") for n in (1,2,3): for jr in (J,K): DR=Rest[jr] R=range(len(DR)) Affch=tuple(choice(DR[i]) for i in R) Y=87+100*jr ds("Phase "+str(n),125,Y-45,"g") fr(170-150*jr,Y-25,150,40,"w") for i in R: dess(Affch[i],20*i+180-150*jr,Y) sp(n==3) DR,Verr=ChF(jr,n,DR,Affch) for i in range(len(chs[jr])): dess(chs[jr][i],20*i+30+(270-20*len(chs[jr]))*jr,Y) sp(1) Rest[jr]=tuple(DR[i] for i in R if (Verr[i]==0)*(n<3)) H,f,F,c,C,b,B,m,M,v,V=tuple([0,0] for k in range(11)) calc() ds(" Phase de choix ",50,5,"orange") #while not kd(KE): # ds("Appuyer sur EXE",80,105,"purple") #while kd(KE):1 sp(2) for Jr in (J,K): if IA and not Jr: DvMch[0]=("aucune","Vidar")[Jet[0]>=2] NvDv[0]=1+(Jet[0]>=3) else: fr(0,0,320,222,"w") # efface l'écran ds("Joueur "+"AB"[Jr]+" : Choisir la divinité \n de la prochaine manche ",2,5,"g") fr(0,179,320,1,"purple") for jr in (J,K): Y=183+20*jr #ds("AB"[jr],-35,Y,"g") #for i in range(Vie[jr]):fr(67+8*(i%5),Y+6*(i//5),5,3,"g") dess("<",50,Y+5,"g") ds(str(Vie[jr]),63,Y,"g") dess("J",10,Y+3,dore,dore) ds(str(Jet[jr]),27,Y,dore) L=len(chs[jr]) for i in range(L): dess(chs[jr][i],93+(43-2*L)*i,Y+3) rg=-1 chgt=1 while not kd(KE): rg=(rg+chgt)%len(DvCh[Jr]) Divi=DvCh[Jr][rg] if chgt or kd(KU)+kd(KD): NvDv[Jr]=(NvDv[Jr]-kd(KU)+kd(KD))%3 AffDv(Divi) chgt=kd(KR)-kd(KL) while kd(KE):1 DvMch[Jr]=DvCh[Jr][rg] NvDv[Jr]+=1 # pour avoir un niveau entre 1 et 3 plt() ds("Phase de résolution ",65,5,"orange") calc(False) for NIV in range(1,10): for Jr in (J,K): if DvMch[Jr]!="aucune": Puiss=inf[DvMch[Jr]][5+NvDv[Jr]] # divinité priorité 1 if Tt("Var"): Vr[Jr]=1 if Tt("Thrymr"): dess("d",295-285*Jr,145-100*Jr,"cyan") sp(1) NvDv[1-Jr]=max(0,NvDv[1-Jr]-NvDv[Jr]) DvMch[1-Jr]=(DvMch[1-Jr],"aucune")[NvDv[1-Jr]==0] # divinité priorité 2 if Tt("Freyja"): chs[Jr]+=[choice(choice(Des)) for k in range(NvDv[Jr])] calc() if DvMch[Jr] in ("Frigg","Loki") and Tt(DvMch[Jr]): Nb=sum(ChF(1-Jr,0-(DvMch[Jr]=="Frigg"),chs[1-Jr],chs[1-Jr],Puiss)[1]) ChF(Jr,-1,chs[Jr],chs[Jr],(Puiss-Nb)*(DvMch[Jr]=="Frigg")) sp(1) calc() # divinité priorité 3 if Tt("Skuld"): symb("f",Jr,1,("b","purple",dore)) AJ(1-Jr,-(f[Jr]+F[Jr])*Puiss) #symb("f",Jr) if Tt("Tyr"): sacri() # divinité priorité 4 if Tt("Vidar"): for effacer in (False,True): symb("c",1-Jr,1,("rw"[effacer],"g",dore),Puiss,effacer) calc() if DvMch[Jr] in ("Ullr","Hel","Heimdal","Mimir") and Tt(DvMch[Jr]): (Ulr,Hl,Hmdl,Mmr)[("Ullr","Hel","Heimdal","Mimir").index(DvMch[Jr])][Jr]=1 if DvMch[Jr] in ("Baldr","Brunehilde","Freyr","Skadi") and Tt(DvMch[Jr]): b[Jr]+=(DvMch[Jr]=="Baldr")*NvDv[Jr]*(b[Jr]+B[Jr]) c[Jr]+=(DvMch[Jr]=="Baldr")*NvDv[Jr]*(c[Jr]+C[Jr]) H[Jr]+=(DvMch[Jr]=="Brunehilde")*int((Puiss-1)*H[Jr]+0.51) Liste=(H[Jr],f[Jr]+F[Jr],c[Jr]+C[Jr],b[Jr]+B[Jr],m[Jr]+M[Jr]) (H,f,c,b,m)[choice([k for k in range(5) if Liste[k]==max(Liste)])][Jr]+=(DvMch[Jr]=="Freyr")*int(Puiss) f[Jr]+=(DvMch[Jr]=="Skadi")*(f[Jr]+F[Jr])*NvDv[Jr] calc(False) if Tt("Bragi"): symb("m",Jr,0,("b","purple",dore)) AJ(Jr,(m[Jr]+M[Jr])*Puiss) # action des liserés if F[Jr]+C[Jr]+B[Jr]+M[Jr]+V[Jr] and NIV==5: sp(0.7) symb("tout",Jr,1,"bgr") AJ(Jr,F[Jr]+C[Jr]+B[Jr]+M[Jr]+V[Jr]) symb("tout",Jr,0.5) # Phase d'affrontement des dés k=Jr if NIV==6: Duel(".v",k,"www") Duel("hc",k) MAX=max(0,H[k]-c[1-k]-C[1-k]) AV(1-k,Hmdl[1-k]*min(H[k],c[1-k]+C[1-k])*NvDv[1-k]) AV(1-k,-MAX) AJ(1-k,Mmr[1-k]*MAX*NvDv[1-k]) AV(k,Hl[k]*MAX*NvDv[k]) Duel("hc",k,"www") Duel("fb",k) UU=Ulr[k]*(2+(NvDv[k]-1)**2) symb("b",1-k,0,("cyan","r",dore),UU) MAX=max(0,f[k]+F[k]-b[1-k]-B[1-k]) MIN=min(f[k]+F[k],b[1-k]+B[1-k]) AV(1-k,Hmdl[1-k]*MIN*NvDv[1-k]) AV(1-k,-MAX-min(MIN,UU)) AJ(1-k,Mmr[1-k]*MAX*NvDv[1-k]) Duel("fb",k,"www") if NIV==7: Duel("m.",k) if (m[k]+M[k])*Jet[1-k]: vol=min(m[k]+M[k],Jet[1-k]) AJ(1-k,-vol) AJ(k,vol) Duel("m.",k,"www") # divinité de priorité 6+2 if Tt("Thor"): AV(1-Jr,-Puiss) # divinité de priorité 7+2 if Tt("Idunn"): AV(Jr,Puiss) if Tt("Odin"): sacri() J,K=K,J