monopoly_mignified.py

Created by elnix91

Created on September 28, 2025

14.5 KB

debug version monopoly, feel free to finish it; the last version is available here


_N='Get out of jail'
_M='Advance to Go'
_L='Free from jail'
_K='Go to jail!'
_J='hyp'
_I='code'
_H='case'
_G='Chance'
_F='Community Chest'
_E='name'
_D='money'
_C='terrains'
_B=False
_A=True
from kandinsky import fill_rect as rect,draw_string as txt,set_pixel as pix
from random import randint,choice
from ion import keydown as k
import time
SKY=0,0,0
TXT=(255,)*3
IMP=0,0,255
SEL=255,255,0
PC=[(200,0,200),(0,255,255),(255,0,255),(255,200,0),(255,0,0),(255,255,0),(0,150,0),(0,0,255)]
savefile='monopoly.sav'
CASES=[['Start',1,20],['Mediterranean Ave',0,0,0,6,.2,1,3,9,16,25],[_F,5],['Baltic Avenue',0,1,0,6,.4,2,6,18,32,45],['Income Tax',1,-20],['Reading RR',0,22,1,20,2.5],['Oriental Avenue',0,2,1,10,.6,3,9,27,40,55],[_G,4],['Vermont Avenue',0,3,1,10,.6,3,9,27,40,55],['Connecticut Ave',0,4,1,12,.8,4,10,30,45,60],['Jail',6],['St Charles Place',0,5,2,14,1,5,15,45,62.5,75],['Electric Company',0,26,5,15],['States Avenue',0,6,2,14,1,5,15,45,62.5,75],['Virginia Avenue',0,7,2,16,1.2,6,18,50,70,90],['Pennsylvania RR',0,23,1,20,2.5],['St. James Place',0,8,3,18,1.4,7,20,55,75,95],[_F,5],['Tennessee Avenue',0,9,3,18,1.4,7,20,55,75,95],['New York Avenue',0,10,3,20,1.6,8,22,60,80,100],['Free Parking',8],['Kentucky Avenue',0,11,4,22,1.8,9,25,70,87.5,105],[_G,4],['Indiana Avenue',0,12,4,22,1.8,9,25,70,87.5,105],['Illinois Avenue',0,13,4,24,2,10,30,75,92.5,110],['B&O RR',0,24,1,20,2.5],['Atlantic Avenue',0,14,5,26,2.2,11,33,80,97.5,115],['Ventnor Avenue',0,15,5,26,2.2,11,33,80,97.5,115],['Water Works',0,27,5,15],['Marvin Gardens',0,16,5,28,2.4,12,36,85,102.5,120],['Go to Jail',7],['Pacific Avenue',0,17,6,30,2.6,13,39,90,110,127.5],['North Carolina Ave',0,18,6,30,2.6,13,39,90,110,127.5],[_F,5],['Pennsylvania Ave',0,19,6,32,2.8,15,45,100,120,140],['Short Line',0,25,1,20,2.5],[_G,4],['Park Place',0,20,7,35,3.5,17.5,50,110,130,150],['Luxury Tax',1,-10],['Boardwalk',0,21,7,40,5,20,60,140,170,200]]
CHANCES=[[[_K],5],[[_L],0],[['Advance to Boardwalk'],2,21],[[_M],2,0],[['Advance to Illinois Ave'],2,19],[['Advance to St. Charles'],2,5],[['Bank pays you'],1,5],[[_N],0],[['Go back 3 spaces'],4],[['Go to Reading RR'],2,22],[['Make repairs'],3,[2.5,10]],[['Pay poor tax'],1,-15],[['Trip to Pennsylvania RR'],2,24],[['Building loan matures'],1,15],[['Win crossword contest'],1,10]]
CHESTS=[[[_K],5],[[_L],0],[[_M],2,0],[['Bank error, collect'],1,20],[['Doctor fees, pay'],1,-10],[['Stock sale, get'],1,5],[[_N],0],[['Grand Opera Night'],1,5],[['Holiday fund matures'],1,10],[['Tax refund, collect'],1,2],[['Birthday, collect'],6,1],[['Life insurance matures'],1,10],[['Pay hospital fees'],1,-10],[['Pay school fees'],1,-5],[['Consultancy fee'],1,25],[['You inherit'],1,10]]
def shuffle(l):
  n=len(l)
  for i in range(len(l)-1,0,-1):j=randint(0,i);l[i],l[j]=l[j],l[i]
  return l
try:import os;OS=_A
except:OS=_B
clean=lambda:rect(0,0,320,222,SKY)
txtc=lambda t,y,fc,bc:txt(t,160-len(t)*5,y,fc,bc)
s=lambda:k(0)|k(1)|k(2)|k(3)
v=lambda:k(4)|k(52)
def popup(x,y,w,h,xso,yso,c,title,opt,types,result=[],frame=_A,padding=2,back=_B,retname=_B):
  if frame:rect(x,y,w,h,c[0]);rect(x+3,y+3,w-6,h-6,SKY);y+=2
  else:rect(x,y,w,h,SKY)
  for(i,j)in enumerate(title):txtc(j,y+2+(18+padding)*i,c[1],SKY)
  ntv=_B
  for(i,o)in enumerate(opt):
    txt(o,xso,yso+(18+padding)*i,c[2],SKY)
    if types[i][0]==0:switch(types[i][1],yso+(18+padding)*i,result[i]);ntv=_A
    elif types[i][0]==1:rect(types[i][1],yso+(18+padding)*i+17,10*types[i][2],1,IMP);ntv=_A
    elif types[i][0]==2:txt('<   >',types[i][1]-20,yso+(18+padding)*i,IMP,SKY)
  if ntv:txt('VALIDATE',xso,yso+(18+padding)*(i+1),(0,255,0),SKY);types.append([3])
  r=0;first=_A;lastAct=-1
  while v():0
  while 1:
    if s()|first:
      lastAct=r;r=(r-k(1)+k(2))%len(types)
      if types[r][0]==2:result[r]=(result[r]-k(0)+k(3))%(types[r][3]-types[r][2]+1);txt(str(result[r]+types[r][2]),types[r][1],yso+(18+padding)*r,IMP,SKY)
      rect(xso-20,yso+(18+padding)*lastAct,10,18,SKY);txt('',xso-20,yso+(18+padding)*r,SEL,SKY)
      if first:first=_B
      while s():0
    elif v():
      if not ntv:
        if retname:return opt[r]
        return r
      if types[r][0]==0:
        result[r]=not result[r];switch(types[r][1],yso+(18+padding)*r,result[r])
        while v():0
      elif types[r][0]==1:result[r]=kinput(types[r][1],yso+(18+padding)*r,types[r][2],types[r][3],types[r][4])
      elif types[r][0]==3:
        if retname:return opt[r]
        return tuple(result)
    elif k(17)&back:return-1
def switch(x,y,on):
  rect(x,y,18,18,(200,)*3);rect(x+1,y+1,16,16,SKY)
  if on:c=0,255,0
  else:c=(100,)*3
  rect(x+3,y+3,12,12,c)
def kinput(x,y,maxLenght=4,minLenght=4,onlynumbers=_A,ct=TXT):
  letters={29:'l',30:'m',31:'n',32:'o',33:'p',34:'q',36:'r',37:'s',38:'t',39:'u',40:'v',42:'w',43:'x',44:'y',45:'z',18:'a',19:'b',20:'c',21:'d',22:'e',23:'f',24:'g',25:'h',26:'i',27:'j',28:'k'};numbers={30:'7',31:'8',32:'9',42:'1',43:'2',44:'3',36:'4',37:'5',38:'6',48:'0'};Input='';rect(x,y,10*maxLenght,18,SKY);rect(x,y+17,10*maxLenght,1,IMP);rect(x,y+2,1,14,TXT)
  while v():0
  while 1:
    for i in range(17,49):
      if k(i):
        if onlynumbers:
          if(i in numbers.keys())&(len(Input)<maxLenght):Input+=numbers[i]
        elif(i in letters.keys())&(len(Input)<maxLenght):Input+=letters[i]
        if(i==17)&(len(Input)>0):Input=Input[:-1];rect(x+len(Input)*10,y,12,18,SKY)
        rect(x,y+17,10*maxLenght,1,IMP);rect(x+len(Input)*10+1,y+2,1,14,TXT);txt(Input,x,y,ct,SKY)
        while k(i):0
    if v():
      if len(Input)>=minLenght:rect(x+len(Input)*10+1,y+2,1,14,SKY);return Input
      else:txt(Input,x,y,(255,0,0),SKY);time.sleep(.5);txt(Input,x,y,ct,SKY)
def draw_case(x,y,id,rot=0):
  t=CASES[id][1];rect(x,y,20,20,TXT);rect(x+1,y+1,18,18,SKY)
  if t==0:
    if 21<CASES[id][2]<26:rect(x+2,y+2,16,16,(50,)*3);rect(x+4,y+4,12,12,SKY);rect(x+6,y+6,8,8,(50,)*3)
    elif CASES[id][2]>25:
      if CASES[id][2]==0:c=0,0,200
      else:c=SEL
      txt('S',x+5,y+1,c,SKY)
    else:
      xs1,ys1,w1,h1,xs2,ys2,w2,h2=x+1,y+1,18,5,x+1,y+7,18,12
      if rot==1:xs1,w1,h1,ys2,w2,h2=x+14,5,18,y+1,12,18
      elif rot==2:ys1,ys2=y+14,y+1
      elif rot==3:w1,h1,xs2,ys2,w2,h2=5,18,x+7,y+1,12,18
      rect(xs1,ys1,w1,h1,PC[CASES[id][3]])
      for i in range(N):
        if id in A[i][_C]:rect(xs2,ys2,w2,h2,PC[i])
      if 0<A[-2][CASES[id][2]]<5:
        xi,yi=0,0
        if w1>h1:xi=4
        else:yi=4
        for i in range(A[-2][CASES[id][2]]):rect(xs1+1+xi*i,ys1+1+yi*i,3,3,SKY)
      elif A[-2][CASES[id][2]]==5:rect(xs1+1,ys1+1,3,3,TXT)
  elif t==1:
    if CASES[id][2]>0:c=0,200,0
    else:c=200,0,0
    rect(x+2,y+2,16,16,c)
  elif 3<t<6:
    if t==4:c=0,0,255
    else:c=255,0,0
    txt('C',x+5,y+1,c,SKY)
  elif t==6:rect(x+1,y+1,18,18,(255,100,0));rect(x+1,y+7,12,12,(70,)*3)
  elif t==7:rect(x+3,y+3,14,14,(255,100,0))
  elif t==8:rect(x+2,y+2,16,16,(0,255,0));rect(x+4,y+4,12,12,(0,180,0))
  np=[]
  for i in range(N):
    if A[i][_H]==id:np.append(i)
  if len(np)>0:
    rect(x+5,y+7,10,6,SKY)
    for _ in range(2):
      for __ in range(4):
        if _*4+__ in np:rect(x+6+__*2,y+8+_*2,2,2,PC[_*4+__])
def menu():
  global A;clean();c=0
  if OS:
    if savefile in os.listdir():
      c=popup(0,0,320,222,135,150,[PC[0],PC[3],IMP],['Savefile found!','Do you want to','continue the game?'],['YES','NO'],[[3],[3]])
      if c==0:
        with open(savefile,'r')as f:
          A=eval(f.read())
          if _I in A[0].keys():Password=_A
          else:Password=_B
        return len(A)-6,Password,_A
  opt=['Number of players:','Password protection:'];types=[[2,260,2,8],[0,260]]
  if OS:opt.append('Enable saving:');types.append([0,260])
  params=popup(0,0,320,222,30,70,[PC[1],PC[3],IMP],['MONOPOLY - Made by Elnix'],opt,types,[0,_B,_B],padding=22);N=params[0]+2;A=[{_E:'',_D:150000,_C:[],_J:[],_H:0,'free':_B}for i in range(N)]
  for i in range(N):
    clean();txt('Player '+str(i+1),30,20,PC[i],SKY);txt(', enter your name:',110,20,TXT,SKY);A[i][_E]=kinput(110,70,10,_B)
    if params[1]:
      txt('Please set a up a pin code:',25,110,TXT,SKY)
      while 1:
        code=kinput(140,140)
        if len(code)<4:txt('Too short!',110,170,(255,0,0),SKY)
        else:A[i][_I]=code;break
  A.append([33,11]);A.append(shuffle([i for i in range(18)]));A.append(shuffle([i for i in range(18)]));A.append([i for i in range(22)]);A.append([0 for i in range(22)]);A.append(0);return N,params[1],params[2]
def getHousePrice(id):
  if id<10:return 5000
  elif id<20:return 10000
  elif id<30:return 15000
  else:return 20000
def draw_terrain():
  id=0
  for i in range(10):draw_case(1+i*20,1,id,0);id+=1
  for i in range(10):draw_case(201,1+i*20,id,1);id+=1
  for i in range(10):draw_case(201-i*20,201,id,2);id+=1
  for i in range(10):draw_case(1,201-i*20,id,3);id+=1
  txt('Total in',70,50,IMP,SKY);txt('Free park:',60,70,IMP,SKY);txt(str(A[-1]),110-len(str(A[-1]))*5,90,IMP,SKY)
def calc_rent(id,All=_B,owner=None):
  global DR;p=[5000,2500,5000,10000,20000]
  if CASES[id][2]<26:
    if All:
      if CASES[id][2]<22:return CASES[id][4:]
      return p
    elif CASES[id][2]<22:return CASES[id][4+A[-2][CASES[id][2]]]
    else:
      nbts=0
      for i in range(22,26):
        if i in A[owner][_C]:nbts+=1
      return p[nbts+1]
  else:
    if All:return
    nbs=0
    if 28 in A[owner][_C]:nbs+=1
    if 27 in A[owner][_C]:nbs+=1
    if nbs==1:return 400*DR
    return 1000*DR
def draw_rent(x,y,id):
  r=calc_rent(id,_A)
  if CASES[id][2]<26:
    for(i,j)in enumerate(r):
      if i==0:txt('Base Price:',x,y,TXT,SKY)
      if CASES[id][2]<22:
        if i==1:txt('Terrain:',x,y+20,TXT,SKY)
        elif i==6:txt('Hotel:',x,y+120,TXT,SKY)
        elif i>0:txt(str(i-1)+' houses',x,y+20*i,TXT,SKY)
        txt(str(j),x+120,y+20*i,PC[4],SKY)
      else:
        if i>0:txt(str(i)+' stations:',x,y+20*i,TXT,SKY)
        txt(str(j),x+120,y+20*i,PC[4],SKY)
  else:txt('1 serv: 400*Dices',x,y,TXT,SKY);txt('2 serv: 1000*Dices',x,y+20,TXT,SKY)
def selectP(l):
  clean();txtc('Select a propriety:',10,IMP,SKY);act=0;first=_A
  while v():0
  while not v():
    if s()|first:
      act=(act-k(0)+k(3))%len(l);clean();rect(0,40,320,18,SKY);txtc('< '+CASES[l[act]][0]+' >',40,TXT,SKY);draw_case(20,100,l[act]);draw_rent(110,75,l[act])
      if first:first=_B
      while s():0
    elif k(17):return-1
  return l[act]
def drawC(P,t):
  clean()
  if t:id=-5;txtc('CHANCE',10,IMP,SKY)
  else:id=-4;txtc('COMMUNITY CHEST',10,IMP,SKY)
  for(i,j)in enumerate(CHANCES[A[id][0]][0]):txtc(j,35+i*20,TXT,SKY)
  c=A[id][0][1]
  if c==0:A[P]['free']=_A
  elif c==1:
    if t:amount=CHANCES[A[-5][0]][2]
    else:amount=CHESTS[A[-4][0]][2]
    if amount>0:A[P][_D]+=amount
    else:pay(P,-1,amount,_A)
  elif c==2:0
  elif c==3:
    nbhouses=0;nbhotels=0
    for i in A[P][_C]:
      n=A[-2][CASES[i][2]]
      if 0<n<5:nbhouses+=n
      else:nbhotels=+n
    amount=nbhouses*CHANCES[A[-5][0]][2]+nbhotels*CHANCES[A[-5][0]][3];rp=pay(P,-1,amount)
  elif c==4:0
  elif c==5:0
  if c:A[id].append(A[id][0])
  del[id][0];return rp
def pay(p,r,amount,middle=_B,canCancel=_B):
  C='Mortgage';B='Sell houses'
  while A[p][_D]<amount:
    opt=[];houses={}
    for i in A[p][_C]:
      if CASES[i][2]<22:houses[i]=A[-2][CASES[i][2]]
      else:houses[i]=0
    if sum(houses.values())>0:opt.append(B)
    if 0 in houses.values():opt.append(C)
    if len(opt)==0:
      if lose(p):return 1
      else:return 2
    code=popup(10,10,300,202,40,90,[PC[4],PC[4],IMP],['Warning! Not enough money!','Your money: '+str(A[p][_D]),'To pay: '+str(amount)],opt,[[3]for i in range(len(opt))],back=canCancel,retname=_A)
    if code==B:
      htcbs=[i for(i,j)in houses.items()if j>0];s=selectP(htcbs)
      if s==-1:continue
      else:A[-2][CASES[s][2]]-=1;A[p][_D]+=getHousePrice(s)//2;continue
    elif code==C:
      htcbs=[i for(i,j)in houses.items()if j==0];s=selectP(htcbs)
      if s==-1:continue
      else:A[p][_C].remove(s);A[p][_J].append(s);A[p][_D]+=CASES[s][4]//2
    else:return-1
  A[p][_D]-=amount
  if middle:A[-1]+=amount
  if r!=-1:A[r][_D]+=amount
  return 0
def lose(p):
  global N;N-=1
  for i in A[p][_J]:A[-3].append(i)
  rect(20,20,280,182,PC[p]);rect(23,23,274,176,SKY)
  if N>1:txtc(A[p][_E]+' lose!',70,PC[p],SKY);txtc('BUT THE GAME CONTINUE!',110,TXT,SKY)
  del A[p]
  if N==1:
    txtc('Congrat to '+A[0][_E],70,PC[p],SKY);txtc('For winning this game!',110,TXT,SKY)
    while v():0
    while not v():0
    return _B
  else:
    while v():0
    while not v():0
    return _A
def drawDice(x,y,n):rect(x,y,20,20,TXT);rect(x+1,y+1,18,18,SKY);txt(str(n),x+5,y+1,PC[5],SKY)
def game():
  B='You have to pay';global N,DR;N,Password,Save=menu();T=randint(0,N-1);DR=randint(1,6)+randint(1,6);clean();A[0][_C].append(1);A[0][_C].append(3);A[0][_C].append(5);A[0][_C].append(6);A[0][_C].append(12)
  for i in range(22):A[-2][i]=randint(1,5)
  draw_terrain();print(pay(0,1,9899999,canCancel=_A))
  while 1:
    if Password:
      clean();txtc(A[T][_E]+', enter your password:')
      while int(kinput(140,110))!=A[T][_I]:txtc('Wrong password, retry in 3s...',130,PC[4],SKY)
    wasRewarded=0;d1,d2=randint(1,6),randint(1,6);t=time.monotonic()
    while time.monotonic()-t<.2:drawDice(80,150,randint(1,6));drawDice(120,150,randint(1,6))
    drawDice(80,150,d1);drawDice(120,150,d2);DR=d1+d2
    while time.monotonic()-t<.2:0
    for i in range(DR):
      t=time.monotonic();cid=(cid+1)%40
      if cid==0:wasRewarded=20000
      draw_terrain()
      while time.monotonic()-t<.2:0
    if cid==0:wasRewarded=40000;A[T][_D]+=20000
    clean();cid=A[T][_H];a=CASES[cid][1];txt('Landed on '+CASES[cid][0],5,5,TXT,SKY)
    if wasRewarded:txtc('You were rewarded by '+str(wasRewarded),202,(0,255,0),SKY)
    draw_case(cid,295,10);draw_rent(110,60)
    if a==0:
      if cid in A[-3]:
        c=popup(-1,30,0,0,20,140,[0,(0,255,0),IMP],['Want you buy this propriety?','Price:'+str(CASES[cid][4])],['YES','NO'],[[3],[3]],frame=_B)
        if c==0:A[-3].remove(cid);A[T][_C].append(cid)
      elif cid not in A[T][_C]:
        for i in range(N):
          if cid in A[i][_C]:break
        amount=calc_rent(cid,owner=i);txtc(B+A[i][_E],30,(255,150,0),SKY);txtc(str(amount),50,(255,150,0),SKY)
        while v():0
        while not v():0
        rp=pay(T,i,amount)
        if rp!=0:continue
    elif a==1:
      amount=CASES[cid][2]
      if amount>0:txtc('You have been rewarded by',30,IMP,SKY);txtc(str(amount),50,(0,255,0),SKY);A[T][_D]+=amount
      else:
        txtc(B,30,IMP,SKY);txtc(str(amount),50,(255,0,0),SKY);rp=pay(T,-1,amount,_A)
        if rp!=0:continue
    elif 4:txtc('You draw a chance',30,IMP,SKY);drawC(1)
    elif 5:txtc('You draw a community chest',30,IMP,SKY);drawC(0)
    elif a==6:0
    elif a==7:0
    elif a==8:0
    if Save:
      with open(savefile,'w')as f:f.write(str(A))
    T=(T+1)%N
  if OS:os.remove(savefile)
while 1:game()

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.