tetris.py

Created by apocaliips

Created on April 17, 2023

15.6 KB


from math import *
from random import *
from kandinsky import *
from ion import *
from time import *

global wh
wh=color(255,255,255)

def init():
  fill_rect(0,0,320,240,'black')
  global ikicks,bsys,dropspeed,kickdata,scoresys,scoretitles,keys,whiteline,tetraminos,matrix,colors,levelsys
  colors=[(0,255,255),(255,255,0),(200,0,255),(255,150,0),(0,0,255),(255,0,0),(0,255,0)]  
  tetraminos=[
  [[2,3,3,3,3],[0,0,1,2,0,0,1,2,0,0,1,2,0,0,3],[2,2,3,3,3,3],[0,1,2,0,1,2,0,1,2,0,3],0],
  [[0,1,1,2,0,3,3],1],
  [[0,1,2,3,3,3],[0,1,2,0,1,3,2,0,3],[2,3,1,3,2,0,3],[0,1,2,3,1,2,0,3],2],
  [[0,0,1,2,3,3,3],[0,1,2,0,1,2,0,3,3],[2,1,3,3,2,3],[3,1,2,0,1,2,0,3],3],
  [[1,2,3,3,3],[0,1,3,2,0,1,2,0,3],[2,3,3,1,2,0,0,3],[0,1,2,0,1,2,3,3],4],
  [[3,1,2,0,3,3],[0,0,1,2,0,1,3,2,0,3],[2,3,1,2,0,3,3],[0,1,2,1,3,2,3],5],
  [[0,1,3,2,3,3],[0,1,2,0,3,1,2,0,0,3],[2,0,1,3,2,3,3],[1,2,3,1,2,0,3],6]]
  kickdata=[[(-1,0),(-1,-1),(0,2),(-1,2)],[(1,0),(1,1),(0,-2),(1,-2)],[(1,0),(1,-1),(0,2),(1,2)],[(-1,0),(-1,1),(0,-2),(-1,-2)],
  [(-2,0),(1,0),(-2,1),(1,-2)],[(2,0),(-1,0),(2,-1),(-1,2)],[(-1,0),(2,0),(-1,-2),(2,1)],[(1,0),(-2,0),(1,2),(-2,-1)]]
  ikicks=[[0,5,0,7],[4,0,7,0],[0,6,0,4],[6,0,5,0]]
  scoresys=[[0,100,300,500,800],[100,400,1200,1600],[0,1200,1800,2400,1200],[100,200,400,1200],[0,0,600,2400]]
  levelsys=[0,1,3,5,8]
  bsys=[[0,0,0,0,1],[1,1,1,1],[1,1,1,1,1],[0,0,1,1],[0,0,1,1]]
  scoretitles=[["         ","Single","Double","Triple","Tetris"],["M T-S","T-S S","T-S D","T-S T"],
  ["","T-S B","T-S D B","T-S T B","Tetris B"],["M T-S","M T-S S","M T-S D","T-S T"],["","","T-S M D B","T-S T B"]]
  bt=(120,120,120)
  fill_rect(110,0,100,230,wh)
  for ys in range(0,230,10):
    square(100,ys,bt)
    square(210,ys,bt)
  for xs in range(110,210,10):
    square(xs,220,bt)
  fill_rect(110,19,100,1,(255,0,0))
  for ys in range(40,190,10):
    for xs in range(240,300,10):
      square(xs,ys,bt)
  for ys in range(80,140,10):
    for xs in range(240,300,10):
      square(xs-220,ys-40,bt)
  fill_rect(250,50,40,130,'black')
  fill_rect(30,50,40,40,'black')
  if mode%3!=1:
    draw_string("Score :",15,110,wh,'black')
    draw_string("0000000",15,130,wh,'black')
  else:
    draw_string("Lines :",15,110,wh,'black')
    draw_string("00/40",15,130,wh,'black')
  if mode%3==0:
    draw_string("Level :",15,160,wh,'black')
    draw_string("01",65,180,wh,'black')
  else:
    draw_string("Time :",15,160,wh,'black')
    draw_string("00:00.00",15,180,wh,'black')
  for tm in range(3):
    draw_string(str(3-tm),155,110)
    sleep(1)
  draw_string(" ",155,110)
  game()
  
def game():
  x,y,px,py=140,20,150,10
  t=randrange(0,7)
  wait=-1
  rot=0
  poutline=[400,0]
  plowest=500
  next=[[0,0,0,0,0,0,0,0],[-1,0,0,0,0,0,0,0],[-1]]
  next[0]=randombag()
  next=nextt(next)
  hold,holdtemp,holdallowed=-1,0,True
  mov_allowed=[True,True]
  score,combo=0,0
  level= 1 if mode==0 else speed
  xp=0
  btob=0
  end=False
  mono=monotonic()
  mt=monotonic()
  coolr=0
  lines=0
  coolh=monotonic()
  while end==False:
    px,py,prot=x,y,rot
    move=[0,0,0,0]
    if keydown(KEY_EXE):
      while keydown(KEY_EXE):
        pass
      while not keydown(KEY_EXE):
        draw_string("Paused",240,205,wh,'black')
        draw_string("7-Restart",5,5,wh,'black')
        draw_string("Menu-9",240,5,wh,'black')
        if keydown(KEY_SEVEN):
          init()
        if keydown(KEY_NINE):
          menu(mode,speed)
      draw_string("      ",240,205,wh,'black')
      draw_string("         ",5,5,wh,'black')
      draw_string("      ",240,5,wh,'black')
      while keydown(KEY_EXE):
        pass
      for tm in range(3):
        draw_string(str(3-tm),10,200,wh,'black')
        sleep(1)
      draw_string(" ",10,200,wh,'black')
    if (mt+(0.8-(level-1)*0.007)**(level-1)<=monotonic() and not keydown(KEY_DOWN)) or (mt+0.03<=monotonic() and keydown(KEY_DOWN)):
      y+=10
      mt=monotonic()
      move[1]=1
      
    if keydown(KEY_BACKSPACE) and holdallowed:
      if hold==-1:
        hold=next[0][0]
        next=nextt(next)
      refresh(t,px,py,prot)
      refresh(t,px,plowest,prot)
      holdtemp=hold
      hold=t
      fill_rect(30,50,40,40,'black')
      tetra(30,60,hold,0)
      t=holdtemp
      holdallowed=False
      x,y,rot,px,py,prot,plowest=140,10,0,140,10,0,500
    if keydown(KEY_LEFT) and coolh<=monotonic():
      x-=10
      coolh=monotonic()+0.13
      move[0]=1
    if not (keydown(KEY_RIGHT) or keydown(KEY_LEFT)):
      coolh=monotonic()
    if keydown(KEY_RIGHT) and coolh<=monotonic():
      x+=10
      coolh=monotonic()+0.13
      move[0]=1
    if keydown(KEY_UP):
      move[3]=1
      y=plowest
      wait=monotonic()
      
    if keydown(KEY_5):
      coolr+=1
    else:
      coolr=0
    if coolr==1:
      rot=(rot+(1-2*int(keydown(KEY_SHIFT))))%(len(tetraminos[t])-1)
      move[2]=1
    timer=monotonic()-mono
    timems=str(int((timer-floor(timer))*100))
    timem=floor(int(timer)/60)
    times=str(int(timer)-60*timem)
    if mode!=0:
      draw_string(timems,75,180,wh,'black')
      draw_string(str(timem),25-len(str(timem)),180,wh,'black')
      draw_string(times,65-len(times)*10,180,wh,'black')
    if (mode==1 and lines>=40) or (mode==2 and timem>=3):
      while keydown(KEY_5):
        pass
      draw_string("Victory",125,60)
      draw_string("[5] Back to menu",75,80)
      while not keydown(KEY_5):
        pass
      menu(mode,speed)
    if px!=x or py!=y or prot!=rot:
      refresh(t,px,py,prot)
      refresh(t,px,plowest,prot)
      fill_rect(110,19,100,1,(255,0,0))
      x_,y_=x,y
      for tests in range(7-int(prot==rot)*4):
        cur=tetraminos[t][rot]
        tempx,tempy=x_,y_
        for i in range(len(cur)):
          if cur[i]==0:
            tempx+=10
          if cur[i]==1 or cur[i]==3:
            if not get_pixel(tempx,tempy)==wh:
              if tests==0:
                y,y_,move[1]=py,py,0
              elif tests==1:
                x,x_,move[0]=px,px,0
              elif 6>tests>=2 and prot!=rot:
                if tests<5:
                  iskicked=True
                else:
                  iskicked=False
                x_,y_=x,y
                if t==0:
                  ikick=ikicks[rot][prot]
                  x_+=kickdata[ikick][tests-2][0]*10
                  y_+=kickdata[ikick][tests-2][1]*10
                elif t>=2:
                  if prot==0 or prot==2:
                    x_+=kickdata[rot-1][tests-2][0]*10
                    y_+=kickdata[rot-1][tests-2][1]*10
                  else:
                    x_+=kickdata[prot][tests-2][0]*10
                    y_+=kickdata[prot][tests-2][1]*10
                elif t==1 or (prot==rot and t==2):
                  tests=6
              elif tests==6:
                rot,move[2]=prot,0
              break
            tempx+=10
          if cur[i]==2:
            tempy+=10
            tempx=x_
      if prot!=rot:
        x,y=x_,y_
      hasmoved=True
      if move[3]==1:
        lastmove=3
        hasmoved=False
      elif move[2]==1:
        lastmove=2
      elif move[1]==1:
        lastmove=1
      elif move[0]==1:
        lastmove=0
      else:
        lastmove=-1
        hasmoved=False
      cur=tetraminos[t][rot]
      tempx,tempy=x+2,y+2
      for i in range(len(cur)):
        if cur[i]<=1:
          tempx+=10
        if cur[i]==3:
          if not get_pixel(tempx,tempy+10)==wh:
            if wait==-1 or hasmoved:
              wait=monotonic()+.5
            py=y
            if wait<=monotonic():
              wait=-1
              tetra(x,y,t,rot)
              holdallowed=True
              #line
              sline=0
              for ys_ in range(20):
                ys=20-ys_
                line=0
                for xs in range(112,212,10):
                  if get_pixel(xs,12+ys*10)!=wh:
                    line+=1
                if line==10:
                  pass
                  sline+=1
                  temp_y=10+ys*10
              scoring=0
              if sline==0:
                combo=0
              else:
                score+=combo*50*level
                combo+=1
              if t==2 and lastmove==2:
                c=0
                for adj in range(4):
                  ads=get_pixel(5+x+floor(adj%2)*20,5+y+floor(adj/2)*20)
                  if ads!=wh:
                    c+=1
                  else:
                    if (rot%2==0 and (adj==rot or adj==rot+1)) or (rot%2==1 and (adj==1-(rot-1)/2) or adj==3-(rot-1)/2):
                      scoring=3
                if c>=3:
                  if scoring!=3:
                    scoring=1
                  if iskicked:
                    scoring=3
                elif scoring==3:
                  scoring=0
              xp+=levelsys[sline]
              if xp>=10 and mode%3==0:
                if level<15:
                  level+=1
                xp=0
              if bsys[scoring][sline]==1:
                btob+=1
              elif sline!=0:
                btob=0
              if btob>=2:
                if scoring!=3:
                  scoring=2
                else:
                  scoring=4
              lines+=sline
              if mode==0:
                score+=scoresys[scoring][sline]*level
              else:
                score+=scoresys[scoring][sline]
              title=scoretitles[scoring][sline]
              if mode!=1:
                draw_string(str(score),85-ceil(len(str(score)))*10,130,wh,'black')
              else:
                draw_string(str(lines),35-ceil(len(str(lines)))*10,130,wh,'black')
              if mode==0:
                draw_string(str(level),85-ceil(len(str(level)))*10,180,'white','black')
              draw_string(scoretitles[0][0],5,5,wh,'black')
              draw_string(title,5,5,wh,'black')
              if bsys[scoring][sline]==1:
                btob=1
              if sline != 0 or scoring != 0:
                sleep(0.5)
              for ys_ in range(20):
                ys=20-ys_
                line=0
                for xs in range(112,212,10):
                  if get_pixel(xs,12+ys*10)!=wh:
                    line+=1
                if line==10:
                  fill_rect(110,10+ys*10,100,10,wh)
                if not line==0:
                  a=0
                  temp_y=10+ys*10
                  temp_line=[0,0,0,0,0,0,0,0,0,0]
                  for xs in range(10):
                    temp_line[xs]=get_pixel(114+10*xs,temp_y+4)
                  
                  while a<10:
                    a=0
                    for xs in range(10):
                      if not get_pixel(112+10*xs,temp_y+12)==wh:
                        a+=1
                    if a==0:
                      fill_rect(110,temp_y,100,10,wh)
                      temp_y+=10
                    else:
                      for xs_ in range(10):
                        if not temp_line[xs_]==wh:
                          square(110+10*xs_,temp_y,temp_line[xs_])
                      a=10                         
              for xd in range(112,212,10):
                if get_pixel(xd,12)!=wh:
                  #ded
                  end=True
              x,y,rot=140,0,0
              t=next[0][0]
              iskicked=False
              px,py,prot=x,y,rot
              next=nextt(next)
              sleep(0.2)
              break
          tempx+=10
        if cur[i]==2:
          tempy+=10
          tempx=x    


      plowest=getlowest(x,y,t,rot)
      outline(x,plowest,t,rot)
      
    tetra(x,y,t,rot)
  draw_string("GAME OVER",115,60)
  draw_string("[5] Back to menu",75,80)
  while not keydown(KEY_5):
    pass

def menu(mm, sm):
  global mode,speed
  mode,speed=mm,sm
  modetext=["Marathon (default)","Sprint 40 lines   ","Ultra 3 min        "]
  i=0
  logo=[
  [1,1,1,0,2,2,2,0,3,3,3,0,4,4,4,0,5,0,6,6,6],
  [0,1,0,0,2,0,0,0,0,3,0,0,4,0,4,0,0,0,6,0,0],
  [0,1,0,0,2,2,0,0,0,3,0,0,4,4,0,0,5,0,0,6,0],
  [0,1,0,0,2,0,0,0,0,3,0,0,4,0,4,0,5,0,0,0,6],
  [0,1,0,0,2,2,2,0,0,3,0,0,4,0,0,4,5,0,6,6,6],
  ]
  logocolors=[(0,0,100),(255,0,0),(255,150,0),(255,255,0),(0,255,0),(0,255,255),(255,0,255)]
  draw_logo()
  for ym in range(5):
    for xm in range(21):
      fill_rect(65+xm*9,32+ym*9,9,9,logocolors[logo[ym][xm]])
  while True:
    if i==0:
      draw_string("Press [EXE] to start",60,170,wh,'black')
      draw_string("[0] Options",105,190,wh,'black')
      if keydown(KEY_ZERO):
        i=1
        fill_rect(0,0,320,240,'black')
        while keydown(KEY_ZERO):
          pass
      if keydown(KEY_EXE):
        init()
        draw_logo()
        for ym in range(5):
          for xm in range(21):
            fill_rect(65+xm*9,32+ym*9,9,9,logocolors[logo[ym][xm]])
  

    if i==1:
      draw_string("[Options]",10,10,wh,'black')
      draw_string("Mode : ",30,40,wh,'black')
      if mm%3!=0:
        draw_string("Speed : ",30,60,wh,'black')
        draw_string(str(speed) +"   ",120,60,wh,'black')
      else:
        draw_string("               ",30,60,wh,'black')
      draw_string(modetext[mode%3],110,40,wh,'black')
      if keydown(KEY_5):
        mm+=1
        mode=mm%3
        while keydown(KEY_5):
          pass
      sm+=int(keydown(KEY_UP))*int(speed<15)-int(keydown(KEY_DOWN)*int(speed>1))
      speed=sm
      sleep(0.12)
      if keydown(KEY_ZERO):
        i=0
        draw_logo()
        for ym in range(5):
          for xm in range(21):
            fill_rect(65+xm*9,32+ym*9,9,9,logocolors[logo[ym][xm]])
        while keydown(KEY_ZERO):
          pass
def draw_logo():
  bc=(0,0,150)
  fill_rect(0,0,320,240,'black')
  fill_rect(55,20,210,70,bc)
  fill_rect(125,90,70,70,bc)
  fill_rect(60,25,200,60,(0,0,100))
  fill_rect(130,75,60,80,(0,0,100))

def outline(xt,yt,t,r):
  cur=tetraminos[t][r]    
  xl=xt
  c=colors[tetraminos[t][len(tetraminos[t])-1]]
  cl=list(c)
  for i in range(3):
    cl[i]=(cl[i]+255*5)/6

  c=tuple(cl)
  for i in range(len(cur)):       
    if cur[i]==0:
      xl+=10
    if cur[i]==1 or cur[i]==3:
      square(xl,yt,c)
      xl+=10
    if cur[i]==2:
      yt+=10
      xl=xt

      
def refresh(t,px,py,prot):  
  cur=tetraminos[t][prot]
  xtemp=px
  for i in range(len(cur)):
    if cur[i]==0:
      px+=10
    if cur[i]==1 or cur[i]==3:
      fill_rect(px,py,10,10,wh)
      px+=10
    if cur[i]==2:
      py+=10
      px=xtemp
def tetra(xt,yt,t,r):
  cur=tetraminos[t][r]
  xl=xt
  for i in range(len(cur)):       
    if cur[i]==0:
      xl+=10
    if cur[i]==1 or cur[i]==3:
      square(xl,yt,colors[tetraminos[t][len(tetraminos[t])-1]])
      xl+=10
    if cur[i]==2:
      yt+=10
      xl=xt

def square(x,y,c):
  cd=list(c)
  for i in range(3):
    cd[i]/=2
  cd=tuple(cd)
  cl=list(c)
  for i in range(3):
    cl[i]=(cl[i]+255)/2
  fill_rect(x+1,y+1,8,8,c)
  fill_rect(x,y,9,1,cl)
  fill_rect(x,y,1,9,cl)
  fill_rect(x,y+9,9,1,cd)
  fill_rect(x+9,y,1,10,cd)


def getlowest(x,y,t,r):
  cur=tetraminos[t][r]
  for ys in range(y,230,10):
    py,px=ys+5,x+5
    calcdone=False
    for i in range(len(cur)):
      if cur[i]==0:
        px+=10
      if cur[i]==1 or cur[i]==3:
        if not get_pixel(px,py)==wh:
          calcdone=True
          break
        px+=10
      if cur[i]==2:
        py+=10
        px=x+5
    if calcdone==True:
      return ys-10

def nextt(l):
  if l[1][0]==-1:
    l[1]=randombag()
  for i in range(14):
    l[floor(i/7)][i%7]=l[floor((i+1)/7)][(i+1)%7]
  l[2][0]=-1
  fill_rect(250,50,40,130,'black')
  for ns in range(4):
    tetra(250,60+30*ns,l[0][ns],0)
  return l

def randombag():
  bag=[0,0,0,0,0,0,0]
  inbag=[0,1,2,3,4,5,6]
  for i in range(7):
    rand=randrange(0,len(inbag))
    bag[i]=inbag[rand]
    inbag.pop(rand)
  return bag

def start_notice():
  print("Tetris C 1985-2022 Tetris Holding.\nTetris logos, Tetris theme song and Tetriminos are trademarks of Tetris Holding.\nThe Tetris trade dress is owned by Tetris Holding.\nLicensed to The Tetris Company.\nTetris Game Design by Alexey Pajitnov.\nTetris Logo Design by Roger Dean.\nAll Rights Reserved.")
  sleep(.5)

start_notice()
menu(0,2)