0,]']>S}Wup8dH)6o;]AsVl3'mm m m m mm m m m mm m mm mM mM mm mM mm mM m``````````````````````````8'l l;'l l Ll L l l llLll L Ll L l l llLll l l l ll ll ll ll ll l  l Mm M m m mmMmm M Mm M m l mmMmm m m m mm mm mm mm mm m  m`````````````````L l lV(l  Ll lT)lLlL[)L L LL])L 8bbbb b bbbBb bb bbb Bb bB bbbbb````````````````````` bb bb bb bbbbbbBbb Bbb bb bb bb bbbbbbBbb B   QQP,D1e5@T9@T94=4=aaeeeu~  Yi@@@˦00?   ݎ      DDNDNNDD NNNN NNDNN  NNNN NNDNŇ      ̌     033  033  0##  02"  ""  ""  033233233  ݎ 033233233   0##2##2##Ѝ  02"22"22"  """"""""  """"""""            숈̌ ݎ ̈ ݎ   ݎ       NDDDNDDDND NNNN ݎNDNDDNDNN NDDDNDDND        ̌ DD4DD4 DD4DD4 Ȍ DC3DC3ݎ Ȍ 443443 Ȍ  333333Ȍ 333333  DD4DD433#DD4DD4 ̌ DD4DD433#DD4DD4 DC3DC332"DC3DC3 Ȍ443443##"443443 333333"""333333 333333"""333333 ""33#33#33#UUeDD4DD4 ""33#33#33#UUeDD4DD4"!32"32"32"UVfDC3DC3##"##"##"eef443443ݎ"""""""""fff333333ݎNDNDNDDND"""""""""fff333333NNNN""""DD4DD4wwUUeUUeNDDNDDNNNNND""""DD4DD4wwUUeUUeNNNNNNN"!"!DC3DC3wqUVfUVfNDNDNNDNNNND443443eefeefNNN333333ffffffNDDDDDDND333333ffffff""DD4DD4wwwwUUe ̌ ""DD4DD4wwwwUUe ̀ "!DC3DC3wqwqUVf  443443eef 333333fff  333333fff   bfffffff    ݎ ݎw-- title: The Master of Blocks -- author: Phoenix Flare -- desc: Tet*** TGM Port -- script: lua -- input: gamepad -- saveid: The Master of Blocks -- Licensed under zlib -- Copyright 2021 Phoenix Flare version="v1.7" -- initialize records function initRecordSave() for x=0,19 do pmem(x,5400) pmem(x+100,5400) end for x=20,99 do pmem(x,0) pmem(x+100,0) end for x=1,9 do local y=({20,23,26,30,33,36,40,43,46})[x] pmem(y,x<7 and 1 or 0) pmem(y+100,x<7 and 1 or 0) end for x=1,9 do local y=({22,25,28,32,35,38,42,45,48})[x] pmem(y,54000) pmem(y+100,54000) end end function initMenuSave() pmem(201,0xFF0C) end if pmem(255)~=120 then initMenuSave() initRecordSave() pmem(255,120) end function save() local save=(sound*0x1000)+(bgm*0x0100)+(secret4 and 128 or 0)+(secret3 and 64 or 0)+(secret2 and 32 or 0)+(secret and 16 or 0)+(hqBlock and 8 or 0)+(bga and 4 or 0)+(reverse and 2 or 0)+rule-1 pmem(201,save) end playfield={} function initPlayfield() playfield={} for y=-2,bigMode and 10 or 20 do playfield[y]={} for x=1,bigMode and 5 or 10 do playfield[y][x]={0, false, 0} end end end -- Speed Data gravtable = { levels={30, 35, 40, 50, 60, 70, 80, 90, 100, 120, 140, 160, 170, 200, 220, 230, 233, 236, 239, 243, 247, 251, 300, 330, 360, 400, 420, 450, 500}, values={4, 6, 8, 10, 12, 16, 32, 48, 64, 80, 96, 112, 128, 144, 4, 32, 64, 96, 128, 160, 192, 224, 256, 512, 768, 1024, 1280, 1024, 768} } function getGravityValue(x) if maxSpeed then return 5120 end if mode==3 and level==999 then return amulet and 128 or 256 end if mode~=3 then for n=1,#gravtable.levels do if x1 then return linec and 67 or 27 end return linec and 71 or 30 end function getDASValue(x) if curse==3 then return 0 end return 16 end function getLockDelayValue(x) return 30 end modeNames={"STANDARD","EXTRA","INDIGNATION"} gradeScores={400, 800, 1400, 2000, 3500, 5500, 8000, 12000, 16000, 22000, 30000, 40000, 52000, 66000, 82000, 100000, 120000} ordinals={"1st", "2nd", "3rd"} worldBlocks={ --I tetromino { {{-1,1},{0,1},{1,1},{2,1}}, {{1,2},{1,1},{1,0},{1,-1}}, {{-1,0},{0,0},{1,0},{2,0}}, {{0,2},{0,1},{0,0},{0,-1}} }, --T tetromino { {{0,0},{0,1},{-1,0},{1,0}}, {{0,0},{0,1},{1,0},{0,-1}}, {{0,0},{-1,0},{1,0},{0,-1}}, {{0,0},{0,1},{-1,0},{0,-1}} }, --J tetromino { {{0,0},{-1,1},{-1,0},{1,0}}, {{0,0},{0,1},{1,1},{0,-1}}, {{0,0},{-1,0},{1,0},{1,-1}}, {{0,0},{0,1},{-1,-1},{0,-1}} }, --L tetromino { {{0,0},{1,1},{-1,0},{1,0}}, {{0,0},{0,1},{0,-1},{1,-1}}, {{0,0},{-1,0},{1,0},{-1,-1}}, {{0,0},{-1,1},{0,1},{0,-1}} }, --S tetromino { {{0,0},{0,1},{1,1},{-1,0}}, {{0,0},{0,1},{1,0},{1,-1}}, {{0,0},{1,0},{-1,-1},{0,-1}}, {{0,0},{-1,1},{-1,0},{0,-1}} }, --Z tetromino { {{0,0},{-1,1},{0,1},{1,0}}, {{0,0},{1,1},{1,0},{0,-1}}, {{0,0},{-1,0},{0,-1},{1,-1}}, {{0,0},{0,1},{-1,0},{-1,-1}} }, --O tetromino { {{0,0},{0,1},{1,1},{1,0}}, {{0,0},{0,1},{1,1},{1,0}}, {{0,0},{0,1},{1,1},{1,0}}, {{0,0},{0,1},{1,1},{1,0}} }, --L5 pentomino { {{-1,0},{0,0},{1,0},{2,0},{2,1}}, {{0,2},{0,1},{0,0},{0,-1},{1,-1}}, {{-1,1},{0,1},{1,1},{2,1},{-1,0}}, {{1,2},{1,1},{1,0},{1,-1},{0,2}} }, --J5 pentomino { {{-1,0},{0,0},{1,0},{2,0},{-1,1}}, {{0,3},{0,2},{0,1},{0,0},{1,3}}, {{-1,1},{0,1},{1,1},{2,1},{2,0}}, {{1,3},{1,2},{1,1},{1,0},{0,0}} }, --S5 pentomino { {{0,1},{-1,2},{-1,1},{1,1},{1,0}}, {{0,1},{0,2},{1,2},{0,0},{-1,0}}, {{0,1},{-1,1},{1,1},{1,0},{-1,2}}, {{0,1},{0,2},{-1,0},{0,0},{1,2}} }, --Z5 pentomino { {{0,1},{1,2},{-1,1},{1,1},{-1,0}}, {{0,1},{-1,2},{0,2},{0,0},{1,0}}, {{0,1},{1,2},{-1,1},{1,1},{-1,0}}, {{0,1},{-1,2},{0,2},{0,0},{1,0}} }, --I5 pentomino { {{0,1},{2,1},{-1,1},{1,1},{-2,1}}, {{0,3},{0,2},{0,1},{0,0},{0,-1}}, {{0,1},{2,1},{-1,1},{1,1},{-2,1}}, {{0,3},{0,2},{0,1},{0,0},{0,-1}}, }, --T5 pentomino { {{0,1},{-1,2},{-1,1},{1,1},{-1,0}}, {{0,1},{0,2},{1,2},{0,0},{-1,2}}, {{0,1},{-1,1},{1,1},{1,0},{1,2}}, {{0,1},{0,2},{-1,0},{0,0},{1,0}} }, --X pentomino { {{0,1},{0,2},{-1,1},{1,1},{0,0}}, {{0,1},{0,2},{-1,1},{1,1},{0,0}}, {{0,1},{0,2},{-1,1},{1,1},{0,0}}, {{0,1},{0,2},{-1,1},{1,1},{0,0}} }, --F pentomino { {{0,1},{0,2},{-1,1},{1,1},{1,0}}, {{0,1},{0,2},{1,1},{0,0},{-1,0}}, {{0,1},{-1,1},{1,1},{0,0},{-1,2}}, {{0,1},{0,2},{-1,1},{0,0},{1,2}} }, --F' pentomino { {{0,1},{0,2},{-1,1},{1,1},{-1,0}}, {{0,1},{0,2},{1,1},{0,0},{-1,2}}, {{0,1},{-1,1},{1,1},{0,0},{1,2}}, {{0,1},{0,2},{-1,1},{0,0},{1,0}} }, --Y pentomino { {{-1,0},{0,0},{1,0},{2,0},{1,1}}, {{0,2},{0,1},{0,0},{0,-1},{1,0}}, {{-1,1},{0,1},{1,1},{2,1},{0,0}}, {{1,2},{1,1},{1,0},{1,-1},{0,1}} }, --Y' pentomino { {{-1,0},{0,0},{1,0},{2,0},{0,1}}, {{0,2},{0,1},{0,0},{0,-1},{1,1}}, {{-1,1},{0,1},{1,1},{2,1},{1,0}}, {{1,2},{1,1},{1,0},{1,-1},{0,0}} }, --N pentomino { {{-1,1},{0,0},{1,0},{2,0},{0,1}}, {{1,2},{0,1},{0,0},{0,-1},{1,1}}, {{-1,1},{0,1},{1,1},{2,0},{1,0}}, {{1,2},{1,1},{1,0},{0,-1},{0,0}} }, --N' pentomino { {{-1,0},{0,0},{1,0},{2,1},{1,1}}, {{0,2},{0,1},{0,0},{1,-1},{1,0}}, {{-1,0},{0,1},{1,1},{2,1},{0,0}}, {{0,2},{1,1},{1,0},{1,-1},{0,1}} }, --P pentomino { {{0,0},{0,1},{-1,0},{1,0},{-1,1}}, {{0,0},{0,1},{1,0},{0,-1},{1,1}}, {{0,0},{-1,0},{1,0},{0,-1},{1,-1}}, {{0,0},{0,1},{-1,0},{0,-1},{-1,-1}} }, --Q pentomino { {{0,0},{0,1},{-1,0},{1,0},{1,1}}, {{0,0},{0,1},{1,0},{0,-1},{1,-1}}, {{0,0},{-1,0},{1,0},{0,-1},{-1,-1}}, {{0,0},{0,1},{-1,0},{0,-1},{-1,1}} }, --U pentomino { {{0,0},{1,1},{-1,0},{1,0},{-1,1}}, {{0,0},{0,1},{0,-1},{1,-1},{1,1}}, {{0,0},{-1,0},{1,0},{-1,-1},{1,-1}}, {{0,0},{-1,1},{0,1},{0,-1},{-1,-1}} }, --V pentomino { {{-1,2},{-1,1},{-1,0},{0,0},{1,0}}, {{-1,2},{0,2},{1,2},{-1,1},{-1,0}}, {{-1,2},{0,2},{1,2},{1,1},{1,0}}, {{1,2},{1,1},{-1,0},{0,0},{1,0}} }, --W pentomino { {{-1,2},{-1,1},{0,1},{0,0},{1,0}}, {{0,1},{0,2},{1,2},{-1,1},{-1,0}}, {{-1,2},{0,2},{0,1},{1,1},{1,0}}, {{1,2},{1,1},{-1,0},{0,0},{0,1}} } } classicBlocks={ --I tetromino { {{-1,1},{0,1},{1,1},{2,1}}, {{1,2},{1,1},{1,0},{1,-1}}, {{-1,1},{0,1},{1,1},{2,1}}, {{1,2},{1,1},{1,0},{1,-1}} }, --T tetromino { {{0,0},{0,1},{-1,0},{1,0}}, {{0,1},{0,2},{1,1},{0,0}}, {{0,1},{-1,1},{1,1},{0,0}}, {{0,1},{0,2},{-1,1},{0,0}} }, --J tetromino { {{0,0},{-1,1},{-1,0},{1,0}}, {{0,1},{0,2},{1,2},{0,0}}, {{0,1},{-1,1},{1,1},{1,0}}, {{0,1},{0,2},{-1,0},{0,0}} }, --L tetromino { {{0,0},{1,1},{-1,0},{1,0}}, {{0,1},{0,2},{0,0},{1,0}}, {{0,1},{-1,1},{1,1},{-1,0}}, {{0,1},{-1,2},{0,2},{0,0}} }, --S tetromino { {{0,0},{0,1},{1,1},{-1,0}}, {{0,1},{-1,2},{-1,1},{0,0}}, {{0,0},{0,1},{1,1},{-1,0}}, {{0,1},{-1,2},{-1,1},{0,0}}, }, --Z tetromino { {{0,0},{-1,1},{0,1},{1,0}}, {{0,1},{1,2},{1,1},{0,0}}, {{0,0},{-1,1},{0,1},{1,0}}, {{0,1},{1,2},{1,1},{0,0}} }, --O tetromino { {{0,0},{0,1},{1,1},{1,0}}, {{0,0},{0,1},{1,1},{1,0}}, {{0,0},{0,1},{1,1},{1,0}}, {{0,0},{0,1},{1,1},{1,0}} }, --L5 pentomino { {{-1,1},{0,1},{1,1},{2,1},{-1,0}}, {{1,3},{1,2},{1,1},{1,0},{0,3}}, {{-1,0},{0,0},{1,0},{2,0},{2,1}}, {{0,3},{0,2},{0,1},{0,0},{1,0}} }, --J5 pentomino { {{-1,0},{0,0},{1,0},{2,0},{-1,1}}, {{0,2},{0,1},{0,0},{0,-1},{1,2}}, {{-1,1},{0,1},{1,1},{2,1},{2,0}}, {{1,2},{1,1},{1,0},{1,-1},{0,-1}} }, --S5 pentomino { {{0,1},{0,2},{1,2},{0,0},{-1,0}}, {{0,1},{-1,2},{-1,1},{1,1},{1,0}}, {{0,1},{0,2},{-1,0},{0,0},{1,2}}, {{0,1},{-1,1},{1,1},{1,0},{-1,2}} }, --Z5 pentomino { {{0,1},{-1,2},{0,2},{0,0},{1,0}}, {{0,1},{1,2},{-1,1},{1,1},{-1,0}}, {{0,1},{-1,2},{0,2},{0,0},{1,0}}, {{0,1},{1,2},{-1,1},{1,1},{-1,0}} }, --I5 pentomino { {{0,1},{2,1},{-1,1},{1,1},{-2,1}}, {{0,3},{0,2},{0,1},{0,0},{0,-1}}, {{0,1},{2,1},{-1,1},{1,1},{-2,1}}, {{0,3},{0,2},{0,1},{0,0},{0,-1}}, }, --T5 pentomino { {{0,1},{0,2},{1,2},{0,0},{-1,2}}, {{0,1},{-1,1},{1,1},{1,0},{1,2}}, {{0,1},{0,2},{-1,0},{0,0},{1,0}}, {{0,1},{-1,2},{-1,1},{1,1},{-1,0}} }, --X pentomino { {{0,1},{0,2},{-1,1},{1,1},{0,0}}, {{0,1},{0,2},{-1,1},{1,1},{0,0}}, {{0,1},{0,2},{-1,1},{1,1},{0,0}}, {{0,1},{0,2},{-1,1},{1,1},{0,0}} }, --F pentomino { {{0,1},{0,2},{-1,1},{0,0},{1,2}}, {{0,1},{0,2},{-1,1},{1,1},{1,0}}, {{0,1},{0,2},{1,1},{0,0},{-1,0}}, {{0,1},{-1,1},{1,1},{0,0},{-1,2}} }, --F' pentomino { {{0,1},{0,2},{1,1},{0,0},{-1,2}}, {{0,1},{-1,1},{1,1},{0,0},{1,2}}, {{0,1},{0,2},{-1,1},{0,0},{1,0}}, {{0,1},{0,2},{-1,1},{1,1},{-1,0}} }, --Y pentomino { {{-1,1},{0,1},{1,1},{2,1},{0,0}}, {{1,3},{1,2},{1,1},{1,0},{0,2}}, {{-1,0},{0,0},{1,0},{2,0},{1,1}}, {{0,3},{0,2},{0,1},{0,0},{1,1}} }, --Y' pentomino { {{-1,1},{0,1},{1,1},{2,1},{1,0}}, {{1,3},{1,2},{1,1},{1,0},{0,1}}, {{-1,0},{0,0},{1,0},{2,0},{0,1}}, {{0,3},{0,2},{0,1},{0,0},{1,2}} }, --N pentomino { {{-1,1},{0,1},{1,1},{2,0},{1,0}}, {{1,3},{1,2},{1,1},{0,0},{0,1}}, {{-1,1},{0,0},{1,0},{2,0},{0,1}}, {{1,3},{0,2},{0,1},{0,0},{1,2}} }, --N' pentomino { {{-1,0},{0,1},{1,1},{2,1},{0,0}}, {{0,3},{1,2},{1,1},{1,0},{0,2}}, {{-1,0},{0,0},{1,0},{2,1},{1,1}}, {{0,3},{0,2},{0,1},{1,0},{1,1}} }, --P pentomino { {{0,1},{-1,1},{1,1},{0,0},{1,0}}, {{0,1},{0,2},{-1,1},{0,0},{-1,0}}, {{0,0},{0,1},{-1,0},{1,0},{-1,1}}, {{0,1},{0,2},{1,1},{0,0},{1,2}} }, --Q pentomino { {{0,1},{-1,1},{1,1},{0,0},{-1,0}}, {{0,1},{0,2},{-1,1},{0,0},{-1,2}}, {{0,0},{0,1},{-1,0},{1,0},{1,1}}, {{0,1},{0,2},{1,1},{0,0},{1,0}}, }, --U pentomino { {{0,1},{-1,1},{1,1},{-1,0},{1,0}}, {{0,1},{-1,2},{0,2},{0,0},{-1,0}}, {{0,0},{1,1},{-1,0},{1,0},{-1,1}}, {{0,1},{0,2},{0,0},{1,0},{1,2}} }, --V pentomino { {{-1,2},{0,2},{1,2},{1,1},{1,0}}, {{1,2},{1,1},{-1,0},{0,0},{1,0}}, {{-1,2},{-1,1},{-1,0},{0,0},{1,0}}, {{-1,2},{0,2},{1,2},{-1,1},{-1,0}} }, --W pentomino { {{-1,2},{0,2},{0,1},{1,1},{1,0}}, {{1,2},{1,1},{-1,0},{0,0},{0,1}}, {{-1,2},{-1,1},{0,1},{0,0},{1,0}}, {{0,1},{0,2},{1,2},{-1,1},{-1,0}} } } worldColors={{11,10,224},{7,1,225},{9,8,226},{3,2,227},{5,6,228},{2,1,229},{4,3,230},{12,13,231}} classicColors={worldColors[6],worldColors[1],worldColors[3],worldColors[4],worldColors[2],worldColors[5],worldColors[7],worldColors[8]} pentColors={4,3,5,6,1,6,2,3,4,5,6,6,3,7,3,5,2,1} for x=25,8,-1 do worldColors[x]=worldColors[pentColors[x-7]] classicColors[x]=classicColors[pentColors[x-7]] end function randDraw() drawn=false rolls=0 while not drawn and rolls<4 do ptd=math.random(7) if curse==4 and math.random(100)>85 then ptd=math.random(18)+7 end drawn=true for x=1,4 do if ptd==lastFour[x] then drawn=false end end rolls=rolls+1 end next=ptd for x=1,3 do lastFour[x]=lastFour[x+1] end lastFour[4]=next end next=0 lastFour={} level=0 sectionThreshold=0 curse=0 frames=0 function gameInit() pIndex=1 garbageCounter=0 if mode==3 then curse=0 end dropped=false score=0 scorecombo=1 pieceframes=0 soft=0 maxsoft=0 firstBlock=true lastKey=0 maxY=0 initPlayfield() next={0,0,0} lastFour={5,6,5,6} randDraw() grade=mode~=3 and 1 or 0 level=0 sectionThreshold=100 GMEligible=mode~=3 frames=0 blockActive=false ct={} rollSurvived=false checkedMusic=false timer=0 lastGradeTime=0 sectionStop=false combo=0 maxCombo=0 bravo=0 end gameInit() saveOffset=0 moves=0 rotations=0 maxY=0 gameState=-3 grav=0 are=0 lineClearFrames=0 markedLines={} lockDelay=30 blockActive=false ct={} kicked=false classicLock=false rollSurvived=false checkedMusic=false timer=0 sectionStop=false combo=0 maxCombo=0 minRecordDiff=601 quadClears=0 oldQuads=0 bravo=0 track=0 rot=0 -- menu init menu=1 submenu=1 mode=1 detail=false rule=(pmem(201)&0x0001)+1 reverse=pmem(201)&0x0002==2 bga=(pmem(201)&0x0004)==4 hqBlock=pmem(201)&0x0008==8 secret=pmem(201)&0x0010==16 secret2=pmem(201)&0x0020==32 secret3=pmem(201)&0x0040==64 secret4=pmem(201)&0x0080==128 bgm=(pmem(201)&0x0F00)>>8 sound=(pmem(201)&0xF000)>>12 bigMode=false frames=1 -- menu descriptions function getDescription(s,m) if s==1 then return ({"Start the game.","Game options.\nSet the gamemode,\ncontrols, and\nrotation rules.","Change the volume\nand graphics\nquality.","View the credits\nagain, in case\nyou missed them\nthe first time.","Special cheats!\nUsing these will\ndisable the\nleaderboards."})[m] end if s==2 then if m==1 then return ({"Go for top rank!\nFor all players","Ranking up is\nharder with\ngarbage in field!\nFor experts","Accursed mode.\nGood luck.\nFor masochists"})[mode] end if m==2 then if curse==9 then return "Unusable rule\nwith no kicks.\nFor chosen ones" end return ({"Unique rule\nwith powerful\nkicks.\nFor all players","Challenging rule\nwith restricted\nkicks.\nFor experts"})[rule] end if m==3 then return reverse and "Rotation buttons\nare reversed\nA/X: CW\nB: CCW" or "Rotation buttons\nare standard\nA/X: CCW\nB: CW" end if m==4 then return "Magic amulet.\nIt's not much,\nbut it should\nhelp." end end if s==3 then return ({"Toggle detailed\nblock sprites.","Toggle background\nanimations.","Music volume.","Sound volume."})[m] end if s==5 then if m<4 then return ({"Make blocks four\ntimes as large!","Blocks will spawn\nat their lowest\npoint!","The guide block\nwill never go\naway!"})[m] end if m==4 then if curse==0 then return "Forbidden Magic." else return ({"You can only see\nthe stack's\noutline.","Sounds will play\nat random.","There is no delay\nbefore the block\ngoes flying.","Pentominoes have\na chance to\nappear.","Each block has a\nchance to vanish.","I blocks locked\nvertically stop\nexisting.","The next queue\nleaves.","Your active block\nwill fade away.","Only one rotation\ndirection is\navailable, and\nkicks disabled!!!"})[curse] end end end end -- center text function printcenter(string, y, color, smallfont) width=print(string,0,-10,0,false,1,smallfont) print(string,(240-width)/2,y,color,false,1,smallfont) end -- main loop function TIC() if curse==2 and math.random(30)==math.random(30) then sfx(math.random(36)-1,nil,-1,soundChan) end cls() drawBackground() for x=0,3 do if soundChan==x then if peek(0xFF9D+18*x)&0xF0~=0 then poke(0xFF9D+18*x, (peek(0xFF9D+18*x)&0x0F)+(math.floor((peek(0xFF9D+18*x)&0xF0)*sound/15)&0xF0)) end else if peek(0xFF9D+18*x)&0xF0~=0 then poke(0xFF9D+18*x, (peek(0xFF9D+18*x)&0x0F)+(math.floor((peek(0xFF9D+18*x)&0xF0)*bgm/15)&0xF0)) end end end if gameState~=-2 then rect(85,3,70,130,14) rect(86,4,68,128,curse==9 and mode+1 or amulet and 15 or ({13,9,0})[mode]) rect(89,7,62,122,14) rect(90,8,60,120,0) if curse~=9 or mode==3 then spr(188-rule, 64, 4, 0, 2) else spr(188, 64, 4, 0, 2) end if not (maxSpeed or alwaysGhost or bigMode) then for x=1,3 do font(ordinals[x]..".",2,28*x-26) v=24 if pmem(saveOffset+x*3-3)==0 then v=8 end drawGrade(2,28*x-18,pmem(saveOffset+x*3-3)-1) font("Lv"..pmem(saveOffset+x*3-2),v,28*x-18) font(formatTime(pmem(saveOffset+x*3-1)),v,28*x-10) end end end if gameState==0 then soundChan=0 rect(160,20,71,28,0) rectb(160,20,71,28,12) print(getDescription(submenu,menu),162,22,12,true,1,true) if submenu==1 then spr(241,92,112,0,1,0,0,5,1) else spr(246,92,112,0,1,0,0,6,1) spr(252,92,120,0,1,0,0,4,1) end if btnp(2) or btnp(3) then if submenu~=1 then sfx(14,nil,-1,soundChan) end if submenu==2 then if menu==1 then if btnp(2) then mode=mode-1 if mode<1 then mode=secret2 and 3 or secret and 2 or 1 end elseif btnp(3) then mode=mode+1 if mode>(secret2 and 3 or secret and 2 or 1) then mode=1 end end end if menu==2 then rule=rule+1 if rule==3 then rule=1 end end if menu==3 then reverse=not reverse end if menu==4 then amulet=not amulet end end if submenu==3 then if menu==1 then hqBlock=not hqBlock end if menu==2 then bga=not bga end if menu==3 then if btnp(2) then bgm=math.max(0,bgm-1) end if btnp(3) then bgm=math.min(15,bgm+1) end end if menu==4 then if btnp(2) then sound=math.max(0,sound-1) end if btnp(3) then sound=math.min(15,sound+1) end end end if submenu==5 then if menu==1 then bigMode=not bigMode end if menu==2 then maxSpeed=not maxSpeed end if menu==3 then alwaysGhost=not alwaysGhost end if menu==4 then if btnp(2) then curse=(curse-1)%(secret4 and 10 or 9) end if btnp(3) then curse=(curse+1)%(secret4 and 10 or 9) end end end end submenus={5, (amready or amulet) and 4 or 3, 4, nil, secret3 and 4 or 3} if btnp(0) then sfx(14,nil,-1,soundChan) menu=menu-1 amready=false if menu==0 then menu=submenus[submenu] end if submenu==2 and not amulet then menu=math.min(menu,3) end end if btnp(1) then sfx(14,nil,-1,soundChan) menu=menu+1 if menu>submenus[submenu] then menu=1 amready=submenu==2 end end if mode~=3 then amready=false amulet=false else curse=0 end if curse==9 then rule=2 end if submenu==1 then printcenter("START",15,menu==1 and 4 or 12) printcenter("OPTIONS",30,13) printcenter("GAME",45,menu==2 and 4 or 12) printcenter("GFX & SFX",60,menu==3 and 4 or 12) printcenter("CREDITS",75,menu==4 and 4 or 12) printcenter("SPECIAL",90,menu==5 and 4 or 12) end if submenu==2 then printcenter("MODE",15,menu==1 and 4 or 12) printcenter(modeNames[mode],21,13,mode==3) printcenter("ROTATION",30,menu==2 and 4 or 12) printcenter(curse==9 and mode~=3 and "SIMIZU" or rule==1 and "DELUXE" or "CLASSIC",36,curse==9 and 2 or 13) printcenter("CONTROL",45,menu==3 and 4 or 12) printcenter(reverse and "REVERSE" or "STANDARD",51,13) if menu==4 or amulet then printcenter("AMULET",75,menu==4 and 4 or 11) printcenter(amulet and "USE" or "DON'T USE",81,amulet and 9 or 13) end end if submenu==3 then printcenter("GRAPHICS",15,menu==1 and 4 or 12) printcenter(hqBlock and "NORMAL" or "SIMPLE",21,13) printcenter("BG ANIMS",30,menu==2 and 4 or 12) printcenter(bga and "ON" or "OFF",36,13) printcenter("MUSIC",45,menu==3 and 4 or 12) printcenter(bgm.."/15",51,13) printcenter("SOUND",60,menu==4 and 4 or 12) printcenter(sound.."/15",66,13) end if submenu==5 then printcenter("BIG BLOCK",15,menu==1 and 4 or 12) printcenter(bigMode and "ON" or "OFF",21,13) printcenter("20G MODE",30,menu==2 and 4 or 12) printcenter(maxSpeed and "ON" or "OFF",36,13) printcenter("TLS MODE",45,menu==3 and 4 or 12) printcenter(alwaysGhost and "ON" or "OFF",51,13) if secret3 then printcenter("CURSE",60,menu==4 and 4 or 12) printcenter(({[0]="NONE","SHADOW","SOUND","ICE","SUPER","VANISH","DECAY","NEXIT","FADING","SIMIZU"})[curse],66,curse==9 and 2 or 13) end end if submenu==2 then if btn(7) and frames==0 then print("DELETED",2,110,2) elseif btn(7) then print("HOLD Y TO\nDELETE DATA",2,110,frames%2==0 and 3 or 2) frames=frames-1 else frames=180 end else frames=180 end if frames==0 then initRecordSave() initMenuSave() mode=1 secret=false secret2=false secret3=false end stRecordOffset=10*mode-10 saveOffset=10*mode+100*rule-90 if btnp(5) then if submenu~=1 then menu=submenu submenu=1 end end if btnp(4) then if submenu==1 and menu==1 then save() gameInit() gameState=1 frames=90 cRoll=false sfx(15,"C-5",60,soundChan) elseif submenu==1 and menu~=4 then submenu=menu menu=1 elseif submenu==1 and menu==4 then gameState=-2 return end end elseif gameState==1 then drawGame() checkLastKey() frames=frames-1 if not cRoll then if frames>45 then printcenter("READY",64,12) else if mode~=3 then printcenter("GO",64,12) end end end if mode==3 and frames==46 then gameState=10 markedLines={} lineClearFrames=-1 track=1 end if frames<1 then gameState=cRoll and 3 or 2 if mode~=3 then music(0) end markedLines={} lineClearFrames=-1 track=1 end elseif gameState==2 then drawGame() if btnp(7) then sfx(8,"C-5",20,soundChan) gameState=-1 cRoll=false end if level%100>=85 and not checkedMusic then checkMusic() end are=are-1 lineClearFrames=lineClearFrames-1 timer=timer+1 if btnp(1) then dropped=true end if lineClearFrames==0 then clearLines() if delLines then sfx(35,nil,30,soundChan) end end if are<1 and not blockActive then dealBlock() firstBlock=false if next<8 then sfx(next,"C-4",30,soundChan) else sfx(next+8,"C-4",30,soundChan) end justDealt=true if delLines then recover() delLines=false end else justDealt=false end checkLastKey() blockManipulation() if level+1==sectionThreshold and not sectionStop then sfx(9,"C-7",30,soundChan) sectionStop=true end if delLines and lineClearFrames<1 then rect(90,bigMode and 80 or 104,60,bigMode and 48 or 24,9) for x=1,4+math.random(3) do local y=math.random(bigMode and 48 or 24) line(90,128-y,150,128-y,11) end end elseif gameState==3 then drawGame() if btnp(7) then sfx(8,"C-5",20,soundChan) gameState=-1 cRoll=true end are=are-1 lineClearFrames=lineClearFrames-1 frames=frames-1 if btnp(1) then dropped=true end if lineClearFrames==0 then clearLines() end if are<1 and not blockActive then dealBlock() if next<8 then sfx(next,"C-4",30,soundChan) else sfx(next+8,"C-4",30,soundChan) end justDealt=true else justDealt=false end checkLastKey() blockManipulation() if mode==3 then rollSurvived=true end if frames<1 then rollSurvived=true gameState=6 end elseif gameState==4 then music() printcenter("GAME OVER",32,2) printcenter("YOUR RANK",72,12) drawGrade(112,80) if rollSurvived then printcenter(modeNames[mode],48,12,mode==3) printcenter("ALL CLEAR!!!",56,12,true) else printcenter("LEVEL REACHED",48,12,true) printcenter(level,56,12) end if btnp(4) then curse=0 if mode==3 then lastGradeTime=timer end local place=4 for x=3,1,-1 do if grade>pmem(saveOffset-3+x*3) then place=x elseif grade==pmem(saveOffset-3+x*3) then if level>pmem(saveOffset-2+x*3) then place=x elseif level==pmem(saveOffset-2+x*3) then if lastGradeTime=500 and GMEligible or level==999) then gameState=9 secret2=true end if not secret3 and mode==3 and grade>0 then secret3=true end if not secret4 and mode==3 and grade>9 then secret4=true end save() end elseif gameState==5 then markedLines={} lineClearFrames=-1 music() frames=frames-1 width=print("EXCELLENT",0,-10) for x=-1,1 do for y=-1,1 do print("EXCELLENT",(240-width)/2+x,48+y,14) end end printcenter("EXCELLENT",48,12) if frames<300 then print("but... let's go",97,60,12,false,1,true) print("better next time",92,67,12,false,1,true) end if frames==0 then gameState=4 end elseif gameState==6 or gameState==7 then music() drawGame() if not curtain then for y=1,20 do for x=1,10 do if playfield[y] and playfield[y][x] then playfield[y][x][3]=240 end end end end curtain=curtain and curtain+(btn(4) and 2 or 1) or -60 rect(90,8+(120-math.min(120,math.max(0,curtain))),60,math.min(120,math.max(0,curtain)),0) if curtain>=150 then curtain=nil gameState=gameState-2 end elseif gameState==8 then cls(0) printcenter("CONGRATULATIONS ON STANDARD GM!",60,3+time()%2) printcenter("TRY TO EXTRA MODE!",70,3+time()%2) spr(76,103,100,0,1,0,0,4,1) spr(241,130,100,0) if btnp(4) then gameState=0 mode=2 end elseif gameState==9 then local w1=print("INDIGNATION MODE UNLOCKED")/2 local w2=print("GOOD LUCK")/2 cls(0) for x=-1,1 do for y=-1,1 do print("INDIGNATION MODE UNLOCKED",120-w1+x,58+y,2) print("GOOD LUCK",120-w2+x,70+y,2) end end printcenter("INDIGNATION MODE UNLOCKED",58,0) printcenter("GOOD LUCK",70,0) spr(76,103,100,0,1,0,0,4,1) spr(241,130,100,0) if btnp(4) then gameState=0 mode=3 end elseif gameState==10 then music() printcenter("GAME OVER",32,2) printcenter("YOUR RANK",72,12) spr(38,112,80,0,1,0,0,2,2) spr(58,122,88,0) printcenter("LEVEL REACHED",48,12,true) printcenter(0,56,12) if btnp(4) then gameState=1 track=1 music(0) poke(0x13FFC, 160) -- YOUR BUGFIXES AND API CHANGES -- HAVEN'T BEATEN ME YET, NESBOX!~ soundChan=1 end elseif gameState==-1 then drawGame() rect(103,62,3+print("PAUSE",0,-10),9,15) printcenter("PAUSE",64,12) if btnp(7) then gameState=cRoll and 3 or 2 end end if gameState==-2 then printcenter("The Master of Blocks",10,12) printcenter("PROGRAM & MUSIC - Phoenix Flare",17,12) printcenter("GRAPHICS - MarkGamed7794",24,12) printcenter("SPECIAL THANKS TO:",36,12) printcenter("Tetra Legends Discord Server",46,12) printcenter("TAP Discord Server",53,12) printcenter("Badger eSports",60,12) printcenter("All Playtesters",67,12) spr(76,103,100,0,1,0,0,4,1) spr(241,130,100) if btnp(4) then gameState=0 end elseif gameState==-3 then cls() timer=timer+1 local fade=math.max(math.min(math.min(timer, 300-timer), 45), 0) poke(0x3FD2, 0x1E*fade/45+0x1A) poke(0x3FD3, 0x9B*fade/45+0x1C) poke(0x3FD4, 0x38*fade/45+0x2C) spr(384, 86, 26, 8, 1, 0, 0, 8, 8) printcenter("GREEN ALPACA", 94, 6) printcenter("SOFT", 100, 6) if timer>315 then gameState=-2 poke(0x3FD2, 0x38) poke(0x3FD3, 0xB7) poke(0x3FD4, 0x64) cls() timer=0 end return else if bigMode then spr(208,2,2,0,1,0,0,9,1) end if maxSpeed then spr(106,2,10,0,1,0,0,5,1) end if alwaysGhost then spr(122,2,18,0,1,0,0,5,1) end end print(version,240-print(version,0,-8,0,true,1,true),129,15,true,1,true) end -- game logic functions function checkLastKey() if btn(2) and not btn(3) then lastKey=1 elseif btn(3) and not btn(2) then lastKey=2 else if btnp(2) then lastKey=1 end if btnp(3) then lastKey=2 end end end function blockManipulation() if blockActive then pieceframes=pieceframes+1 grav=grav+math.max(getGravityValue(level), btn(1) and 256 or 0) if btn(1) then soft=soft+1 maxsoft=math.max(soft,maxsoft) else soft=0 end if mode~=3 then dropped=true end if (btn(1) and dropped or btnp(1)) and not checkPos(0,1) then classicLock=true end if checkPos(0,1) then while grav>(bigMode and 511 or 255) do if checkPos(0,1) then ct.y=ct.y+1 spin=false grav=grav-256 ldReset(1) else break end end else grav=0 lockDelay=lockDelay-1 if lockDelay<1 or classicLock then lock() end end if btnp(2,getDASValue(level),1) and lastKey==1 then if checkPos(-1,0) then ct.x=ct.x-1 spin=false if not checkPos(0,1) then ldReset(2) end end end if btnp(3,getDASValue(level),1) and lastKey==2 then if checkPos(1,0) then ct.x=ct.x+1 spin=false if not checkPos(0,1) then ldReset(2) end end end if blockActive and not justDealt then local r=false if not r and btnp(reverse and 5 or 4) then r=rotLeft() end if not r and btnp(reverse and 4 or 5) then r=rotRight() end if not r and btnp(6) then if reverse then r=rotRight() else r=rotLeft() end end end if moves==0 or rotations==0 then classicLock=true end end end function ldReset(type) if type==1 then lockDelay=getLockDelayValue(level) elseif rule==1 then if type==2 and moves>0 then lockDelay=getLockDelayValue(level) moves=moves-1 if moves==0 then classicLock=true end end if type==3 and rotations>0 then lockDelay=getLockDelayValue(level) rotations=rotations-1 if rotations==0 then classicLock=true end end end end function lockFlash() for x=1,4 do b=(rule==1 and worldBlocks or classicBlocks)[ct.block][ct.rot][x] s=bigMode and 2 or 1 if ct.y-b[2]>0 then if not playfield[ct.y-b[2]-1][ct.x+b[1]][2] then line((bigMode and 77 or 83)+6*(ct.x+b[1])*s, (bigMode and -5 or 1)+6*(ct.y-b[2])*s, 90+6*(ct.x+b[1])*s, (bigMode and -5 or 1)+6*(ct.y-b[2])*s, 12) end if ct.y-b[2]<(bigMode and 10 or 20) and not playfield[ct.y-b[2]+1][ct.x+b[1]][2] then line((bigMode and 77 or 83)+6*(ct.x+b[1])*s, 8+6*(ct.y-b[2])*s, 90+6*(ct.x+b[1])*s, 8+6*(ct.y-b[2])*s, 12) end if ct.x+b[1]>1 and not playfield[ct.y-b[2]][ct.x+b[1]-1][2] then line((bigMode and 77 or 83)+6*(ct.x+b[1])*s, (bigMode and -5 or 1)+6*(ct.y-b[2])*s, (bigMode and 77 or 83)+6*(ct.x+b[1])*s, 8+6*(ct.y-b[2])*s, 12) end if ct.x+b[1]<(bigMode and 5 or 10) and not playfield[ct.y-b[2]][ct.x+b[1]+1][2] then line(90+6*(ct.x+b[1])*s, (bigMode and -5 or 1)+6*(ct.y-b[2])*s, 90+6*(ct.x+b[1])*s, 8+6*(ct.y-b[2])*s, 12) end end end end function lock() sfx(0,nil,30,soundChan) if curse==6 and ct.block==1 and ct.rot%2==0 then else local visibility=(curse==5 and math.random(5)==5) and 0 or 240 for x=1,#worldBlocks[ct.block][ct.rot] do b=(rule==1 and worldBlocks or classicBlocks)[ct.block][ct.rot][x] playfield[ct.y-b[2]][ct.x+b[1]]={(rule==1 and worldColors or classicColors)[ct.block],true,visibility} end end lockFlash() blockActive=false dropped=false lines=checkLines() if mode==3 and level==999 then checkSGrade() if lines>0 then frames=frames+({30,120,300,600})[lines] end end local b=false if checkBravo() then if gameState==2 then bravo=bravo+1 end b=true end if lines==0 and mode==2 then garbageCounter=garbageCounter+1 if garbageCounter>=13-math.floor(level/100) then patternGarbage() garbageCounter=0 end end if gameState==2 then if lines>0 then scorecombo=scorecombo+lines*2-2 else scorecombo=1 end level=level+lines if level>=sectionThreshold then sfx(15,"C-5",60,soundChan) sectionEnd() end if lines>0 then score=score+((math.ceil(level/4)+maxsoft)*lines*scorecombo*(b and 4 or 1)) end if lines>0 and mode<3 then while gradeScores[grade] and score>=gradeScores[grade] do grade=grade+1 lastGradeTime=timer end end maxsoft=0 if lines>1 then combo=combo+1 elseif lines==0 then combo=0 end end are=getAREValue(level,lines>0) lineClearFrames=getLineClearFrames(level,lines>0) if combo>maxCombo then maxCombo=combo end pieceframes=0 end function checkLines() lines=0 for y=0,bigMode and 10 or 20 do filled=0 for x=1,bigMode and 5 or 10 do if playfield[y][x][2] then filled=filled+1 end end if filled==(bigMode and 5 or 10) then table.insert(markedLines, y) lines=lines+1 end end if lines==4 then quadClears=quadClears+1 end return lines end function clearLines() for b, y in pairs(markedLines) do for dy=y,-1,-1 do for x=1,bigMode and 5 or 10 do playfield[dy][x]=playfield[dy-1][x] end end for x=1,bigMode and 5 or 10 do playfield[-2][x]={0,false,0} end end markedLines={} if mode==3 and level==999 then checkSGrade() end end function checkRecovery() local blocks=0 for y=-2,(bigMode and 10 or 20) do for x=1,(bigMode and 5 or 10) do if playfield[y][x][2] then blocks=blocks+1 end end end if blocks>=(bigMode and 37 or 150) then canRecover=true elseif canRecover and blocks-(lines*(bigMode and 5 or 10))<=(bigMode and 17 or 70) then canRecover=false recoveries=recoveries+1 end end function checkBravo() endline=nil for y=-2,(bigMode and 10 or 20) do for x=1,(bigMode and 5 or 10) do if playfield[y][x][2] and not endline then endline=y break end end end if not endline or lines+endline==(bigMode and 11 or 21) then return true else return false end end function checkMusic() checkedLevel=level+100 if mode==1 then if checkedLevel>500 and track==1 then music() end end if mode==2 then if (checkedLevel>500 and track==1) or (checkedLevel>700 and track==2) or (checkedLevel>900 and track==3) or level>984 then music() end end if mode==3 then if (checkedLevel>100 and track==1) or (checkedLevel>500 and track==2) or (checkedLevel>700 and track==3) or (checkedLevel>900 and track==4) then music() end end checkedMusic=true end function sectionEnd() checkedMusic=false if mode==3 then if amulet then delLines=true end curse=sectionThreshold/100 if sectionThreshold==999 then curse=9 end if sectionThreshold==900 then curse=0 end end if GMEligible then if mode==3 then GMEligible=false end if sectionThreshold==300 then GMEligible=score>=12000 and timer<=255*60 elseif sectionThreshold==500 then GMEligible=score>=40000 and timer<=450*60 elseif sectionThreshold==999 then GMEligible=score>=126000 and timer<=810*60 end end if sectionThreshold==900 then sectionThreshold=999 elseif sectionThreshold==999 then if GMEligible then grade=grade+1 end lastGradeTime=timer level=999 cRoll=true soundChan=0 frames=2968 music(6) if mode==3 then frames=1800 music(7) end gameState=3 else sectionThreshold=sectionThreshold+100 end if mode==1 then if track==1 and level>=500 then music(2) track=2 end end if mode==2 then if track==1 and level>=500 then music(1) track=2 elseif track==2 and level>=700 then music(2) track=3 elseif track==3 and level>=900 then music(3) track=4 end end if mode==3 then if track==1 and level>=100 then music(0) poke(0x13FFC, 200) track=2 soundChan=3 elseif track==2 and level>=500 then music(0) poke(0x13FFC, 218) track=3 soundChan=1 elseif track==3 and level>=700 then music(0) poke(0x13FFC, 145) track=4 soundChan=3 end end if level~=999 then sectionStop=false end end pattern={ [false]={0x1FF,0x1FF,0x1FF,0x1FF,0x3FE,0x3FE,0x3FE,0x3FE,0x0FF,0x1FF,0x1FF,0x3FC,0x3FE,0x3FE,0x37F,0x27F,0x2FF,0x3FB,0x3F9,0x3FD,0x3CF,0x3CF,0x3DF,0x38F}, [true]={0x0F,0x0F,0x0F,0x0F,0x1E,0x1E,0x1E,0x1E,0x07,0x0F,0x0F,0x1C,0x1E,0x1E,0x17,0x13,0x1B,0x1D,0x19,0x1B,0x19,0x19,0x1B,0x11} } function patternGarbage() sfx(14,"C-6",30,soundChan) for y=-2,(bigMode and 9 or 19) do for x=1,(bigMode and 5 or 10) do playfield[y][x]=playfield[y+1][x] end end y=bigMode and 10 or 20 playfield[y]={} for x=1,(bigMode and 5 or 10) do playfield[y][x]={} playfield[y][x][1]={12,13,231} playfield[y][x][2]=(pattern[bigMode][(pIndex-1)%#pattern[bigMode]+1]&((bigMode and 1<<5 or 1<<10)>>x))~=0 playfield[y][x][3]=300 end pIndex=pIndex+1 end function recover() markedLines=bigMode and {7,8,9,10} or {17,18,19,20} clearLines() end function dealBlock() maxY=0 ct={block=next,x=bigMode and 3 or 5,y=2,rot=math.floor(rule*1.5)} if mode~=4 then pent=0 end randDraw() kicked=false classicLock=false grav=0 blockActive=true rotations=8 moves=10 ldReset(1) if level+1~=sectionThreshold and not firstBlock and gameState==2 then level=level+1 end if btn(reverse and 5 or 4) then rotLeft(true) elseif btn(reverse and 4 or 5) then rotRight(true) elseif btn(6) then if reverse then rotRight(true) else rotLeft(true) end end if not checkPos(0,0) then gameState=6 toppedOut=true blockActive=false end end function rotRight(noKick) if curse==9 and mode~=3 then return rotLeft() end if rule==1 then kicked=false end canWallKick=not checkPos(-1,0) canFloorKick=not checkPos(0,1) oldrot=ct.rot ct.rot=ct.rot+1 if ct.rot>4 then ct.rot=1 end if checkPos(0,0) then if canFloorKick then ldReset(3) end spin=true return true end if not noKick then if rule==1 then if worldKick(true) then if canFloorKick or kicked then ldReset(3) end spin=true return true end end if rule==2 then if classicKick() then spin=true return true end end end ct.rot=oldrot return false end function rotLeft(noKick) if mode~=3 and curse==9 then noKick=true end if rule==1 then kicked=false end canWallKick=not checkPos(-1,0) canFloorKick=not checkPos(0,1) oldrot=ct.rot ct.rot=ct.rot-1 if ct.rot<1 then ct.rot=4 end if checkPos(0,0) then if canFloorKick then ldReset(3) end spin=true return true end if not noKick then if rule==1 then if worldKick(false) then if canFloorKick or kicked then ldReset(3) end spin=true return true end end if rule==2 then if classicKick() then spin=true return true end end end ct.rot=oldrot return false end function checkCenterColumn() if ct.block==1 or ct.block>4 then return true end for y=-2,0 do for x=-1,1 do if playfield[ct.y+y][ct.x+x] and playfield[ct.y+y][ct.x+x][2] then return x~=0 end end end return true end function classicKick() if not checkCenterColumn() and ct.block<8 or ct.block==1 then return false end if checkPos(1,0) then ct.x=ct.x+1 return true elseif checkPos(-1,0) then ct.x=ct.x-1 return true end if ct.block>7 then if checkPos(2,0) then ct.x=ct.x+2 return true elseif checkPos(-2,0) then ct.x=ct.x-2 return true elseif checkPos(0,-1) then ct.y=ct.y-1 return true end end end offsetscw={ {{-1,0},{-1,-1},{1,0},{1,-1}}, {{-1,0},{-1,1},{1,0},{1,-1}}, {{1,0},{1,1},{-1,0},{-1,-1}}, {{1,0},{1,-1},{-1,0},{-1,1}} } offsetsccw={ {{1,0},{1,-1},{-1,0},{-1,1}}, {{-1,0},{-1,-1},{1,0},{1,1}}, {{-1,0},{-1,1},{1,0},{1,-1}}, {{1,0},{1,1},{-1,0},{-1,-1}} } offsetsVWcw={ {{-1,0},{2,0},{-2,0}}, {{0,1},{0,-2},{0,2}}, {{1,0},{-2,0},{2,0}}, {{0,-1},{0,2},{0,-2}} } offsetsVWccw={ {{0,-1},{0,2},{0,-2}}, {{-1,0},{2,0},{-2,0}}, {{0,1},{0,-2},{0,2}}, {{1,0},{-2,0},{2,0}} } function worldKick(clockwise) if ct.block>23 then if clockwise then for x=({1,3})[ct.block-23],2,({1,-1})[ct.block-23] do if checkPos(offsetsVWcw[ct.rot][x][1],-offsetsVWcw[ct.rot][x][2]) then ct.x=ct.x+offsetsVWcw[ct.rot][x][1] ct.y=ct.y-offsetsVWcw[ct.rot][x][2] if offsetsVWcw[ct.rot][x][2]>0 then kicked=true end return true end end else for x=({1,3})[ct.block-23],2,({1,-1})[ct.block-23] do if checkPos(offsetsVWccw[ct.rot][x][1],-offsetsVWccw[ct.rot][x][2]) then ct.x=ct.x+offsetsVWccw[ct.rot][x][1] ct.y=ct.y-offsetsVWccw[ct.rot][x][2] if offsetsVWccw[ct.rot][x][2]>0 then kicked=true end return true end end end else kicktable=({4,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,2,2,2})[ct.block] if clockwise then for x=1,kicktable do if checkPos(offsetscw[ct.rot][x][1],-offsetscw[ct.rot][x][2]) then ct.x=ct.x+offsetscw[ct.rot][x][1] ct.y=ct.y-offsetscw[ct.rot][x][2] if offsetscw[ct.rot][x][2]>0 then kicked=true end return true end end else for x=1,kicktable do if checkPos(offsetsccw[ct.rot][x][1],-offsetsccw[ct.rot][x][2]) then ct.x=ct.x+offsetsccw[ct.rot][x][1] ct.y=ct.y-offsetsccw[ct.rot][x][2] if offsetsccw[ct.rot][x][2]>0 then kicked=true end return true end end end end end function checkPos(dx, dy) for n, b in pairs((rule==1 and worldBlocks or classicBlocks)[ct.block][ct.rot]) do if ct.x+b[1]+dx>(bigMode and 5 or 10) or ct.x+b[1]+dx<1 then return false end if ct.y-b[2]+dy>(bigMode and 10 or 20) or ct.y-b[2]+dy<-2 then return false end if playfield[ct.y-b[2]+dy][ct.x+b[1]+dx][2] then return false end end return true end gPattern={ [false]={0x1FF,0x2FF,0x37F,0x3BF,0x3DF,0x3EF,0x3F7,0x3FB,0x3FD,0x3FE,0x3FD,0x3FB,0x3F7,0x3EF,0x3DF,0x3BF,0x37F,0x2FF,0x1FF}, [true]={0x0F,0x17,0x1B,0x1D,0x1E,0x1D,0x1B,0x17,0x0F}, } function checkSGrade() local g=0 local row=0 for y=1,(bigMode and 9 or 19) do row=0 for x=1,(bigMode and 5 or 10) do if playfield[21-y][x][2] then row=row+(1<<((bigMode and 5 or 10)-x)) end end if row==gPattern[bigMode][y] then if y<(bigMode and 6 or 11) then if playfield[20-y][y][2] then g=g+1 else break end else if playfield[20-y][20-y][2] then g=g+1 else break end end else break end end frames=frames+900*(g-grade) grade=g return {g,row} end -- draw functions function drawGame() if curse==7 then nexit=(nexit or 0)+0.3 else nexit=math.min(85,(nexit or 0)-0.3) end if nexit<0 then nexit=0 end if bga then rect(159+nexit,19,32,18,0) end if curse~=0 then print(({"SHADOWS","HALLUCINATIONS","ICE LEVEL","SUPER BLOCKS","DISAPPEARANCES","DECAYING PILLARS","NEXIT","FADING SENSE OF SELF",mode==3 and "ANCIENT TECHNIQUE" or "SIMIZU NO NOROI"})[curse],160,40,2,true,1,true) end TLS=0 if blockActive and (level<100 or alwaysGhost) then while checkPos(0,TLS+1) do TLS=TLS+1 end drawTLS(ct.block, (bigMode and 78 or 84)+6*ct.x*s, (bigMode and -4 or 2)+6*(ct.y+TLS)*s, ct.rot) end if mode~=3 then drawGrade(200,12) end spr(150,165+nexit,10,0,1,0,0,3,1) rectb(160+nexit,20,30,18,13) rectb(159+nexit,19,32,20,13) if nexit>0 then for x=1,6 do spr(170+math.floor((nexit/2+x)%6),155+5*x+nexit,39,0) end end if next<8 then drawBlock(next,169+nexit,29,math.floor(rule*1.5)) else font("???",166+nexit,25) end if bravo>0 then spr(128,210,48,0,1,0,0,2,1) font(bravo,218,48) end s=bigMode and 2 or 1 lastrow={1,1,1,1,1,1,1,1,1,1} for y=1,bigMode and 10 or 20 do lastblock=1 for x=1,bigMode and 5 or 10 do if playfield[y][x][2] then if playfield[y][x][3]>0 and playfield[y][x][1][3]<232 then if lastblock==0 then line((bigMode and 77 or 83)+6*x*s, (bigMode and -5 or 1)+6*y*s, (bigMode and 77 or 83)+6*x*s, 8+6*y*s, 14) end if lastrow[x]==0 then line((bigMode and 77 or 83)+6*x*s, (bigMode and -5 or 1)+6*y*s, 90+6*x*s, (bigMode and -5 or 1)+6*y*s, 14) end lastblock=2 lastrow[x]=2 else lastblock=1 lastrow[x]=1 end else if lastblock==2 then line((bigMode and 78 or 84)+6*x*s, (bigMode and -5 or 1)+6*y*s, (bigMode and 78 or 84)+6*x*s, 8+6*y*s, 14) end if lastrow[x]==2 then line((bigMode and 77 or 83)+6*x*s, (bigMode and -4 or 2)+6*y*s, 90+6*x*s, (bigMode and -4 or 2)+6*y*s, 14) end lastblock=0 lastrow[x]=0 end end end for y=1,(bigMode and 10 or 20) do for x=1,(bigMode and 5 or 10) do if playfield[y][x][2] and playfield[y][x][3]>0 then if curse~=1 then if hqBlock then spr(playfield[y][x][1][3], (bigMode and 78 or 84)+6*x*s, (bigMode and -4 or 2)+6*y*s, 0, s) else rect((bigMode and 78 or 84)+6*x*s,(bigMode and -4 or 2)+6*y*s,6*s,6*s,playfield[y][x][1][1]) --rect((bigMode and 78 or 84)+6*x*s,(bigMode and -4 or 2)+6*y*s,5*s,4*s,playfield[y][x][1][1]) end else rect((bigMode and 78 or 84)+6*x*s,(bigMode and -4 or 2)+6*y*s,6*s,6*s,0) end if cRoll then spr(100-math.min(4,math.ceil(playfield[y][x][3]/6)), (bigMode and 78 or 84)+6*x*s, (bigMode and -4 or 2)+6*y*s, 12, s) end end end end if #markedLines>0 and lineClearFrames%2==0 then for b, y in pairs(markedLines) do rect(90, (bigMode and -4 or 2)+6*y*(bigMode and 2 or 1), 60, (bigMode and 12 or 6), 12) end end if blockActive or gameState>5 and toppedOut then drawBlock(ct.block, (bigMode and 78 or 84)+6*ct.x*s, (bigMode and -4 or 2)+6*ct.y*s, ct.rot, true) end spr(134,160,61,0,1,0,0,4,1) font(score,160,70,0,6,6,true) font(mode~=3 and gradeScores[grade] or "???",160,80,0,6,6,true) line(159,78,197,78,12) spr(102,160,91,0,1,0,0,4,1) print(level,160,100,12) print(sectionThreshold,160,110,12) line(160,107,176,107,6) line(160,107,160+16*(getGravityValue(level)/5120),107,2) spr(118,40,90,0,1,0,0,4,1) font(formatTime(timer),40,99,0,6,6,false) end function formatTime(t) return (((t/3600)<10) and "0" or "").. math.floor(t/3600)..":".. (((t/60)%60<10) and "0" or "").. (math.floor(t/60)%60)..".".. (((t%60)*(100/60)<10) and "0" or "").. math.floor(t%60*(100/60)) end function drawBlock(block, x, y, rot, activeBlock) if curse==8 and activeBlock and pieceframes>19 then return end blockType=rule==1 and worldBlocks or classicBlocks blockColor=rule==1 and worldColors or classicColors blockSize=(activeBlock and bigMode) and 2 or 1 for n,b in pairs(blockType[block][rot]) do bx=x+b[1]*6*blockSize by=y-b[2]*6*blockSize if hqBlock then spr(blockColor[block][3],bx,by,0,blockSize) else rect(bx,by,6*blockSize,6*blockSize,blockColor[block][1]) --rect(bx,by,5*blockSize,4*blockSize,blockColor[block][1]) end if activeBlock and curse==8 then spr(96+math.floor(pieceframes/5),bx,by,12,blockSize) end end end function drawTLS(block, x, y, rot) if curse==8 then return end blockType=rule==1 and worldBlocks or classicBlocks blockSize=bigMode and 2 or 1 for n,b in pairs(blockType[block][rot]) do bx=x+b[1]*6*blockSize by=y-b[2]*6*blockSize if hqBlock then spr(240,bx,by,0,blockSize) else rect(bx,by,6*blockSize,6*blockSize,15) --rect(bx,by,5*blockSize,4*blockSize,14) end end end function drawGrade(x, y, rank) local canmonke=false if not rank then rank=grade-1 canmonke=true end if mode==1 then if rank<7 then spr1=2*(rank+1) elseif rank<9 then spr1=16+2*(rank+1) elseif rank<18 then spr1=36 else spr1=38 end if rank<9 then spr2=0 elseif rank<17 then spr2=31+rank elseif rank<18 then spr2=56 else spr2=57 end end if mode==2 then if rank<9 then spr1=64 elseif rank<18 then spr1=66 else spr1=68 end if rank<5 then spr2=70+rank elseif rank<9 then spr2=81+rank elseif rank<14 then spr2=61+rank elseif rank<18 then spr2=72+rank else spr2=90 end end if mode==3 then if rank==-1 then spr1=gameState==4 and canmonke and 114 or 116 spr2=0 elseif rank<5 then spr1=144 spr2=176+rank elseif rank<9 then spr1=144 spr2=187+rank elseif rank<14 then spr1=146 spr2=167+rank elseif rank<18 then spr1=146 spr2=178+rank else spr1=148 spr2=196 end end spr(spr1,x,y,0,1,0,0,2,2) spr(spr2,x+10,y+8,0) end function drawBackground() if gameState==-2 or not bga then return nil end if mode==3 then for x=1,10+math.random(10) do local x={math.random(240),math.random(240)} local y={math.random(138),math.random(138)} line(x[1],y[1],x[2],y[2],2) end return end if gameState==0 then rot=rot+100 for x=1,18 do local ang=math.rad(20*x+rot/1000) line(120,68,120+200*math.cos(ang),68+200*math.sin(ang),13) end else rot=rot+level+100 for x=1,18 do local ang=math.rad(20*x+rot/1000) line(120,68,120+200*math.cos(ang),68+200*math.sin(ang),8) end for x=0,7 do local rad=32*(x+(rot%10000)/10000) circb(120,68,rad,8) end end end