-------------------------------------------------- local int,ceil,abs,rnd,max,min=math.floor,math.ceil,math.abs,math.random,math.max,math.min local ins,rem=table.insert,table.remove local gc=love.graphics local Timer=love.timer.getTime local format=string.format local scr=scr--screen camera -------------------------------------------------- -------------------------------------------------- local gameEnv0={ das=10,arr=2, sddas=2,sdarr=2, quickR=true,swap=true, ghost=true,center=true, grid=false,swap=true, _20G=false,bone=false, drop=60,lock=60, wait=0,fall=0, next=6,hold=true,oncehold=true, sequence="bag7", block=true, visible="show",--keepVisible=visile~="show" Fkey=NULL,puzzle=false,ospin=true, freshLimit=1e99,easyFresh=true, fine=false,fineKill=false, target=1e99,dropPiece="null", bg="none",bgm="race" } local renATK={[0]=0,0,0,1,1,2,2,3,3,4,4}--3 else local b2bPoint={50,100,180} local b2bATK={3,5,8} local clearSCR={80,200,400} local spinSCR={--[blockName][row] {200,750,1600},--Z {200,750,1600},--S {220,700,1600},--L {220,700,1600},--J {250,800,1500},--T {300,1000,2200},--O {300,1000,1800},--I }--MUL:1.2,2.0 --Techrash:1K;MUL:1.3,1.8 --Mini*=.5 local visible_opt={show=1e99,time=300,fast=20,none=5} local reAtk={0,0,1,1,1,2,2,3,3} local reDef={0,1,1,2,3,3,4,4,5} local blockName={"Z","S","L","J","T","O","I"} local clearName={"single","double","triple"} local spin_n={[0]="spin_0","spin_1","spin_2","spin_3"} local clear_n={"clear_1","clear_2","clear_3","clear_4"} local ren_n={}for i=1,11 do ren_n[i]="ren_"..i end local blockPos={4,4,4,4,4,5,4} local TMP1,TMP2,TMP3,TMP4={1,2},{2,1},{2,2},{1.5,1.5}----------save cache local scs={ {[0]=TMP1,TMP2,TMP3,TMP3}, {[0]=TMP1,TMP2,TMP3,TMP3}, {[0]=TMP1,TMP2,TMP3,TMP3}, {[0]=TMP1,TMP2,TMP3,TMP3}, {[0]=TMP1,TMP2,TMP3,TMP3}, {[0]=TMP4,TMP4,TMP4,TMP4}, {[0]={0.5,2.5},{2.5,0.5},{1.5,2.5},{2.5,1.5}}, } local CCblockID={4,3,5,6,1,2,0} TMP1={0,0} local TRS={ [1]={ [01]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2},{0,1} }, [10]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2}, {0,-1} }, [03]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-1}, {1,-2} }, [30]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2}, {0,-1}}, [12]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2} }, [21]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2} }, [32]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2} }, [23]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2} }, [02]={TMP1,{1,0}, {-1,0}, {0,-1}, {0,1} }, [20]={TMP1,{-1,0}, {1,0}, {0,1}, {0,-1} }, [13]={TMP1,{0,-1}, {0,1}, {-1,0}, {0,-2} }, [31]={TMP1,{0,1}, {0,-1}, {1,0}, {0,2} }, },--Z [2]={ [01]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-1},{-1,-2} }, [10]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2}, {0,-1}}, [03]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2}, {0,1} }, [30]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2}, {0,-1} }, [12]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2} }, [21]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2} }, [32]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2} }, [23]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2} }, [02]={TMP1,{-1,0}, {1,0}, {0,-1}, {0,1} }, [20]={TMP1,{1,0}, {-1,0}, {0,1}, {0,-1} }, [13]={TMP1,{0,1}, {0,-1}, {-1,0}, {0,2} }, [31]={TMP1,{0,-1}, {0,1}, {1,0}, {0,-2} }, },--S [3]={ [01]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2},{0,1}, {-1,-1} }, [10]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2}, {0,-1}, {1,1} }, [03]={TMP1,{1,0}, {1,1}, {0,-2}, {-1,1} }, [30]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2} }, [12]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2}, {1,1} }, [21]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2},{-1,-1} }, [32]={TMP1,{-1,0}, {-1,-1},{1,0}, {0,2}, {-1,2} }, [23]={TMP1,{1,0}, {1,1}, {-1,0}, {0,-2}, {1,-2} }, [02]={TMP1,{1,0}, {-1,0}, {0,-1}, {0,1} }, [20]={TMP1,{-1,0}, {1,0}, {0,1}, {0,-1} }, [13]={TMP1,{0,1}, {1,0}, {0,-1} }, [31]={TMP1,{0,-1}, {-1,0}, {0,1} }, },--L [4]={ [01]={TMP1,{-1,0}, {-1,1}, {0,-2}, {1,1} }, [10]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2} }, [03]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2}, {0,1}, {1,-1} }, [30]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2}, {0,-1}, {-1,1} }, [12]={TMP1,{1,0}, {1,-1}, {-1,0}, {0,2}, {1,2} }, [21]={TMP1,{-1,0}, {-1,1}, {1,0}, {0,-2}, {-1,-2} }, [32]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2}, {-1,1} }, [23]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2}, {1,-1} }, [02]={TMP1,{-1,0}, {1,0}, {0,-1}, {0,1} }, [20]={TMP1,{1,0}, {-1,0}, {0,1}, {0,-1} }, [13]={TMP1,{0,-1}, {1,0}, {0,1} }, [31]={TMP1,{0,1}, {-1,0}, {0,-1} }, },--J [5]={ [01]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2},{-1,-1} }, [10]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2}, {0,-1}, {1,1}}, [03]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2} }, [30]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2}, {0,-1} }, [12]={TMP1,{1,0}, {1,-1}, {0,-1}, {0,2}, {1,2}, {-1,-1}}, [21]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2},{1,1} }, [32]={TMP1,{-1,0}, {-1,-1},{0,-1}, {0,2}, {-1,2}, {1,-1}}, [23]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2}, {-1,1} }, [02]={TMP1,{-1,0}, {1,0}, {0,1} }, [20]={TMP1,{1,0}, {-1,0}, {0,-1} }, [13]={TMP1,{0,-1}, {0,1}, {1,0}, {0,-2}, {0,2}}, [31]={TMP1,{0,-1}, {0,1}, {-1,0}, {0,-2}, {0,2}}, },--T [6]={},--O(special) [7]={ [01]={TMP1,{0,1}, {1,0}, {-2,0}, {-2,-1},{1,2} }, [03]={TMP1,{0,1}, {-1,0}, {2,0}, {2,-1}, {-1,2} }, [10]={TMP1,{2,0}, {-1,0}, {-1,-2},{2,1}, {0,2} }, [30]={TMP1,{-2,0}, {1,0}, {1,-2}, {-2,1}, {0,2} }, [12]={TMP1,{-1,0}, {2,0}, {-1,2}, {2,-1} }, [32]={TMP1,{1,0}, {-2,0}, {1,-2}, {-2,-1} }, [21]={TMP1,{-2,0}, {1,0}, {1,-2}, {-2,1} }, [23]={TMP1,{2,0}, {-1,0}, {-1,-2},{2,1} }, [02]={TMP1,{-1,0}, {1,0}, {0,-1}, {0,1} }, [20]={TMP1,{1,0}, {-1,0}, {0,1}, {0,-1} }, [13]={TMP1,{0,-1}, {-1,0}, {1,0}, {0,1} }, [31]={TMP1,{1,0}, {-1,0}}, } } local AIRS={{ [01]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2} }, [10]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2} }, [03]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2} }, [30]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2} }, [12]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2} }, [21]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2} }, [32]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2} }, [23]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2} }, }}for i=2,6 do AIRS[i]=AIRS[1]end AIRS[7]={ [01]={TMP1,{-2,0}, {1,0}, {-2,-1},{1,2} }, [10]={TMP1,{2,0}, {-1,0}, {2,1}, {-1,-2} }, [12]={TMP1,{-1,0}, {2,0}, {-1,2}, {2,-1} }, [21]={TMP1,{1,0}, {-2,0}, {1,-2}, {-2,1} }, [23]={TMP1,{2,0}, {-1,0}, {2,1}, {-1,-2} }, [32]={TMP1,{-2,0}, {1,0}, {-2,-1},{1,2} }, [30]={TMP1,{1,0}, {-2,0}, {1,-2}, {-2,1} }, [03]={TMP1,{-1,0}, {2,0}, {-1,2}, {2,-1} }, } local TMP1={ [1]={ {1,2,1,0,1,2,2,1}, {2,2,3,1,1,2,3,2,2}, },--Z [3]={ {1,2,1,0,1,2,2,1}, {2,2,3,2,1,2,3,3,2}, {3,4,3,2,3,4,4,3}, {2,3,2,1,2,3,3,2,2}, },--L [6]={ {1,2,2,1,0,1,2,2,1}, },--O [7]={ {1,2,1,0,1,2,1}, {2,2,2,2,1,1,2,2,2,2}, },--I }--SZI逆态视为顺态,JLT算法相同 TMP1[2]=TMP1[1] TMP1[4]=TMP1[3] TMP1[5]=TMP1[3] local finesseCtrlPar=TMP1 TMP1,TMP2,TMP3,TMP4=nil----------release local CCblockID={4,3,5,6,1,2,0} local freshMethod={ none=NULL, bag7=function(P) if #P.next<6 then local bag={1,2,3,4,5,6,7} ::L::P:newNext(rem(bag,rnd(#bag))) if bag[1]then goto L end end end, his4=function(P) if #P.next<6 then local j,i=0 repeat i,j=rnd(7),j+1 until i~=P.his[1]and i~=P.his[2]and i~=P.his[3]and i~=P.his[4] P:newNext(i) rem(P.his,1)P.his[4]=i end end, rnd=function(P) ::L::local i=rnd(7) if i==P.next[5]then goto L end P:newNext(i) end,--random drought1=function(P) if #P.next<6 then local bag={1,2,3,4,5,6} ::L::P:newNext(rem(bag,rnd(#bag))) if bag[1]then goto L end end end, drought2=function(P) if #P.next<6 then local bag={1,1,1,1,2,2,2,2,6,6,6,6,3,3,4,4,5,7} ::L::P:newNext(rem(bag,rnd(#bag))) if bag[1]then goto L end end end, } -------------------------------------------------- local frameColor={ [0]=color.white, color.lightGreen, color.lightBlue, color.lightPurple, color.lightOrange, } local attackColor={ {color.darkGrey,color.white}, {color.grey,color.white}, {color.lightPurple,color.white}, {color.lightRed,color.white}, {color.darkGreen,color.cyan}, } local function drawPixel(y,x,id) gc.draw(blockSkin[id],30*x-30,600-30*y) end local function drawDial(x,y,speed) gc.setColor(1,1,1) mStr(int(speed),x,y-18) gc.draw(dialCircle,x,y,nil,nil,nil,32,32) gc.setColor(1,1,1,.6) gc.draw(dialNeedle,x,y,2.094+(speed<=175 and .02094*speed or 4.712-52.36/(speed-125)),nil,nil,5,4) end local mesDisp={ --Default:font=35,white sprint=function(P) setFont(60) local r=max(P.gameEnv.target-P.stat.row,0) mStr(r,-82,265) if r<21 and r>0 then gc.setLineWidth(4) gc.setColor(1,r>10 and 0 or rnd(),.5) gc.line(0,600-30*r,300,600-30*r) end end, marathon=function(P) setFont(50) mStr(P.stat.row,-82,320) mStr(P.gameEnv.target,-82,370) gc.rectangle("fill",-125,375,90,4) end, master=function(P) setFont(50) mStr(P.modeData.point,-82,320) mStr((P.modeData.event+1)*100,-82,370) gc.rectangle("fill",-125,375,90,4) end, classic=function(P) setFont(80) local r=P.gameEnv.target*.1 mStr(r<11 and 18 or r<22 and r+8 or r==22 and"00"or r==23 and"0a"or format("%x",r*10-220),-82,210) mDraw(drawableText.speedLV,-82,290) setFont(50) mStr(P.stat.row,-82,320) mStr(P.gameEnv.target,-82,370) gc.rectangle("fill",-125,375,90,4) end, zen=function(P) setFont(75) mStr(max(200-P.stat.row,0),-82,280) end, infinite=function(P) setFont(50) mStr(P.stat.atk,-82,310) mStr(format("%.2f",P.stat.atk/P.stat.row),-82,420) mDraw(drawableText.atk,-82,363) mDraw(drawableText.eff,-82,475) end, tsd=function(P) setFont(80) mStr(P.modeData.event,-82,330) mDraw(drawableText.tsd,-82,407) end, blind=function(P) mDraw(drawableText.line,-82,300) mDraw(drawableText.techrash,-82,420) if curMode.lv==6 then mDraw(drawableText.grade,-82,170) setFont(60) mStr(P.modeData.event,-82,110) end setFont(80) mStr(P.stat.row,-82,220) mStr(P.stat.clear_4,-82,340) end, dig=function(P) setFont(70) mStr(P.modeData.event,-82,310) mDraw(drawableText.wave,-82,375) end, survivor=function(P) setFont(70) mStr(P.modeData.event,-82,310) mDraw(drawableText.wave,-82,375) end, defender=function(P) setFont(60) mStr(P.modeData.point,-82,315) mDraw(drawableText.rpm,-82,375) end, attacker=function(P) setFont(60) mStr(P.modeData.point,-82,315) mDraw(drawableText.rpm,-82,375) end, tech=function(P) setFont(50) mStr(P.stat.atk,-82,310) mStr(format("%.2f",P.stat.atk/P.stat.row),-82,420) mDraw(drawableText.atk,-82,363) mDraw(drawableText.eff,-82,475) end, c4wtrain=function(P) setFont(50) mStr(max(100-P.stat.row,0),-82,220) mStr(P.combo,-82,310) mStr(P.modeData.point,-82,400) mDraw(drawableText.combo,-82,358) mDraw(drawableText.mxcmb,-82,450) end, pctrain=function(P) setFont(80) mStr(P.stat.pc,-82,330) mDraw(drawableText.pc,-82,412) end, pcchallenge=function(P) setFont(50) mStr(max(100-P.stat.row,0),-82,250) setFont(80) mStr(P.stat.pc,-82,350) mDraw(drawableText.pc,-82,432) gc.setColor(.5,.5,.5) if frame>179 then local y=72*(7-(P.stat.piece+(P.hd.id>0 and 2 or 1))%7)-36 gc.line(320,y,442,y) end end, techmino49=function(P) setFont(40) mStr(#players.alive.."/49",-82,175) mStr(P.ko,-70,215) gc.draw(drawableText.ko,-127,225) setFont(25) gc.setColor(1,.5,0,.6) gc.print(P.badge,-47,227) gc.setColor(1,1,1) setFont(30) gc.print(up0to4[P.strength],-132,290) for i=1,P.strength do gc.draw(badgeIcon,16*i-138,260) end end, techmino99=function(P) setFont(40) mStr(#players.alive.."/99",-82,175) mStr(P.ko,-70,215) gc.draw(drawableText.ko,-127,225) setFont(25) gc.setColor(1,.5,0,.6) gc.print(P.badge,-47,227) gc.setColor(1,1,1) setFont(30) gc.print(up0to4[P.strength],-132,290) for i=1,P.strength do gc.draw(badgeIcon,16*i-138,260) end end, drought=function(P) setFont(75) mStr(max(100-P.stat.row,0),-82,280) end, custom=function(P) if P.gameEnv.puzzle or P.gameEnv.target>1e10 then setFont(60) mStr(P.stat.row,-82,225) mDraw(drawableText.line,-82,290) else setFont(60) mStr(max(P.gameEnv.target-P.stat.row,0),-82,240) end if P.gameEnv.puzzle and P.modeData.event==0 then gc.setLineWidth(3) for y=1,preField.h do for x=1,10 do local B=preField[y][x] if B>7 then gc.setColor(blockColor[B]) gc.rectangle("line",30*x-23,607-30*y,16,16) elseif B>0 then local c=blockColor[B] gc.setColor(c[1],c[2],c[3],.6) gc.rectangle("line",30*x-25,605-30*y,20,20) gc.rectangle("line",30*x-20,610-30*y,10,10) elseif B==-1 then gc.setColor(1,1,1,.4) gc.line(30*x-25,605-30*y,30*x-5,625-30*y) gc.line(30*x-25,625-30*y,30*x-5,605-30*y) end end end end end } --------------Used in draw player↑ player={}local player=player function newDemoPlayer(id,x,y,size) local P={id=id}players[id]=P P.invincible=true for k,v in next,player do P[k]=v end players.alive[#players.alive+1]=P P.x,P.y,P.size=x,y,size P.fieldOffX,P.fieldOffY=0,0 P.small,P.keyRec=false,false P.centerX,P.centerY=P.x+300*P.size,P.y+670*P.size P.absFieldX=P.x+150*P.size P.absFieldY=P.y+60*P.size P.alive=true P.control=true P.timing=false P.stat={ time=0,score=0, key=0,extraPiece=0,extraRate=0, rotate=0,hold=0,piece=0,row=0, atk=0,send=0,recv=0,pend=0, clear_1=0,clear_2=0,clear_3=0,clear_4=0, spin_0=0,spin_1=0,spin_2=0,spin_3=0, pc=0,b2b=0,b3b=0, } P.modeData={point=0,event=0} P.keyTime={}for i=1,10 do P.keyTime[i]=-1e5 end P.keySpeed=0 P.dropTime={}for i=1,10 do P.dropTime[i]=-1e5 end P.dropSpeed=0 P.atker={} P.strength=0 P.field,P.visTime={},{} P.atkBuffer={sum=0} P.gameEnv={ das=5,arr=2, sddas=2,sdarr=2, _20G=false,bone=false, drop=1e99,lock=1e99, wait=10,fall=20, next=6,hold=true,oncehold=true, sequence="bag7", block=true, visible="show", Fkey=NULL,puzzle=false,ospin=true, freshLimit=1e99,easyFresh=true, target=1e99,dropPiece="null", } P.cur={bk={{}},id=0,color=0,name=0} P.sc,P.dir,P.r,P.c={0,0},0,0,0 P.curX,P.curY,P.y_img=0,0,0 P.hd={bk={{}},id=0,color=0,name=0} P.holded=false P.next={} P.dropDelay,P.lockDelay=1e99,1e99 P.freshTime=0 P.spinLast,P.lastClear=false,nil P.spinSeq=0 P.ctrlCount=0 local bag1={1,2,3,4,5,6,7} for _=1,7 do P:newNext(rem(bag1,rnd(#bag1))) end P.freshNext=freshMethod.bag7 if P.gameEnv.sequence==1 then P.bag={}--Bag7 elseif P.gameEnv.sequence==2 then P.his={}for i=1,4 do P.his[i]=P.next.id[i+3]end--History4 elseif P.gameEnv.sequence==3 then--Pure random end P.human=false P.AI_mode="CC" P.AI_stage=1 P.AI_needFresh=false P.AI_keys={} P.AI_delay,P.AI_delay0=3,3 P.AIdata={next=5,hold=true,_20G=false,bag7=true,node=80000} if not BOT then P.AI_mode="9S"end if P.AI_mode=="CC"then P.RS=AIRS local opt,wei=BOT.getConf() BOT.setHold(opt,P.AIdata.hold) BOT.set20G(opt,P.AIdata._20G) BOT.setBag(opt,P.AIdata.bag7) BOT.setNode(opt,P.AIdata.node) P.AI_bot=BOT.new(opt,wei) BOT.free(opt)BOT.free(wei) local CCBID={4,3,5,6,1,2,0} for i=1,5 do BOT.addNext(P.AI_bot,CCBID[P.next[i].id]) end elseif P.AI_mode=="9S"then P.RS=TRS end P.showTime=1e99 P.keepVisible=true P.keyPressing={}for i=1,12 do P.keyPressing[i]=false end P.moving,P.downing=0,0 P.waiting,P.falling=-1,-1 P.clearing,P.cleared={},{} P.combo,P.b2b=0,0 P.fieldBeneath=0 P.shade={} P.score1,P.b2b1=0,0 P.bonus={}--texts P:resetblock() PTC.dust[1]=PTC.dust0:clone() end function newPlayer(id,x,y,size,AIdata) players[id]={id=id} local P=players[id] for k,v in next,player do P[k]=v end--Class function players.alive[#players.alive+1]=P P.x,P.y,P.size=x,y,size or 1 P.fieldOffX,P.fieldOffY=0,0--for Shake fx P.small=P.size<.1--if draw in small mode P.keyRec=not P.small--if calculate keySpeed if P.small then P.centerX,P.centerY=P.x+300*P.size,P.y+600*P.size P.canvas=love.graphics.newCanvas(60,120) P.frameWait=rnd(30,120) else P.centerX,P.centerY=P.x+300*P.size,P.y+670*P.size P.absFieldX=P.x+150*P.size P.absFieldY=P.y+60*P.size end P.alive=true P.control=false P.timing=false P.stat={ time=0,score=0, key=0,extraPiece=0,extraRate=0, rotate=0,hold=0,piece=0,row=0, atk=0,send=0,recv=0,pend=0, clear_1=0,clear_2=0,clear_3=0,clear_4=0, spin_0=0,spin_1=0,spin_2=0,spin_3=0, pc=0,b2b=0,b3b=0, }--Current gamestat P.modeData={point=0,event=0}--data use by mode P.keyTime={}for i=1,10 do P.keyTime[i]=-1e5 end P.keySpeed=0 P.dropTime={}for i=1,10 do P.dropTime[i]=-1e5 end P.dropSpeed=0 P.field,P.visTime={},{} P.atkBuffer={sum=0} P.ko,P.badge,P.strength=0,0,0 P.atkMode,P.swappingAtkMode=1,20 P.atker,P.atking,P.lastRecv={} --Royale-related P.gameEnv={}--Current game setting environment for k,v in next,gameEnv0 do if modeEnv[k]~=nil then P.gameEnv[k]=modeEnv[k] elseif setting[k]~=nil then P.gameEnv[k]=setting[k] else P.gameEnv[k]=v end end--reset current game settings P.cur={bk={{}},id=0,color=0,name=0} P.sc,P.dir,P.r,P.c={0,0},0,0,0 P.curX,P.curY,P.y_img=0,0,0 P.hd={bk={{}},id=0,color=0,name=0} P.holded=false P.next={} P.dropDelay,P.lockDelay=P.gameEnv.drop,P.gameEnv.lock P.freshTime=0 P.spinLast,P.lastClear=false,nil P.spinSeq=0--for Ospin,each digit mean a spin P.ctrlCount=0--key press time,for finesse check P.his={rnd(7),rnd(7),rnd(7),rnd(7)} local s=P.gameEnv.sequence if s=="bag7"or s=="his4"then local bag1={1,2,3,4,5,6,7} for _=1,7 do P:newNext(rem(bag1,rnd(#bag1))) end elseif s=="rnd"then for _=1,6 do local r=rnd(7) P:newNext(r) end elseif s=="drought1"then local bag1={1,2,3,4,5,6} for _=1,6 do P:newNext(rem(bag1,rnd(#bag1))) end elseif s=="drought2"then local bag1={1,2,3,4,6,6} for _=1,6 do P:newNext(rem(bag1,rnd(#bag1))) end end P.freshNext=freshMethod[P.gameEnv.sequence] if P.gameEnv.sequence==1 then P.bag={}--Bag7 elseif P.gameEnv.sequence==2 then P.his={}for i=1,4 do P.his[i]=P.next.id[i+3]end--History4 elseif P.gameEnv.sequence==3 then--Pure random end if AIdata then P.human=false P.AI_mode=AIdata.type P.AI_stage=1 P.AI_needFresh=false P.AI_keys={} P.AI_delay=min(int(P.gameEnv.drop*.8),2*AIdata.delta) P.AI_delay0=AIdata.delta P.AIdata={ next=AIdata.next, hold=AIdata.hold, _20G=P.gameEnv._20G, bag7=AIdata.bag7=="bag7", node=AIdata.node, } if not BOT then P.AI_mode="9S"end if P.AI_mode=="CC"then P.RS=AIRS local opt,wei=BOT.getConf() BOT.setHold(opt,P.AIdata.hold) BOT.set20G(opt,P.AIdata._20G) BOT.setBag(opt,P.AIdata.bag7) BOT.setNode(opt,P.AIdata.node) P.AI_bot=BOT.new(opt,wei) BOT.free(opt)BOT.free(wei) for i=1,AIdata.next do BOT.addNext(P.AI_bot,CCblockID[P.next[i].id]) end elseif P.AI_mode=="9S"then P.RS=TRS P.AI_keys={} end else P.human=true P.RS=TRS players.human=players.human+1 end P.showTime=visible_opt[P.gameEnv.visible] P.keepVisible=P.gameEnv.visible=="show" P.keyPressing={}for i=1,12 do P.keyPressing[i]=false end P.moving,P.downing=0,0 P.waiting,P.falling=-1,-1 P.clearing,P.cleared={},{} P.combo,P.b2b=0,0 P.fieldBeneath=0 P.shade={} P.score1,P.b2b1=0,0 P.bonus={}--texts P.endCounter=0--used after gameover P.counter=0--many usage P.result=nil--string:win/lose end function player.update(P,dt) if P.timing then P.stat.time=P.stat.time+dt end if P.alive then if P.keyRec then local v=0 for i=2,10 do v=v+i*(i-1)*7.2/(frame-P.keyTime[i])end P.keySpeed=P.keySpeed*.99+v*.1 v=0 for i=2,10 do v=v+i*(i-1)*7.2/(frame-P.dropTime[i])end P.dropSpeed=P.dropSpeed*.99+v*.1 --Update speeds if modeEnv.royaleMode then if P.keyPressing[9]then P.swappingAtkMode=min(P.swappingAtkMode+2,30) else P.swappingAtkMode=P.swappingAtkMode+((#P.field>15 and P.swappingAtkMode>4 or P.swappingAtkMode>8)and -1 or 1) end end end if not P.human and P.control and P.waiting==-1 then local C=P.AI_keys P.AI_delay=P.AI_delay-1 if not C[1]then P.AI_stage=AI_think[P.AI_mode][P.AI_stage](P,C) elseif P.AI_delay<=0 then P:pressKey(C[1])P:releaseKey(C[1]) local k=#C for i=1,k do C[i]=C[i+1]end--table.remove(C,1) P.AI_delay=P.AI_delay0*2 end end if not P.keepVisible then for j=1,#P.field do for i=1,10 do if P.visTime[j][i]>0 then P.visTime[j][i]=P.visTime[j][i]-1 end end end end--Fresh visible time if P.moving<0 then if P.keyPressing[1]then if -P.moving<=P.gameEnv.das then P.moving=P.moving-1 elseif P.waiting==-1 then local x=P.curX if P.gameEnv.arr>0 then P.act.moveLeft(P,true) else P.act.insLeft(P,true) end if x~=P.curX then P.moving=P.moving+P.gameEnv.arr-1 end end else P.moving=0 end elseif P.moving>0 then if P.keyPressing[2]then if P.moving<=P.gameEnv.das then P.moving=P.moving+1 elseif P.waiting==-1 then local x=P.curX if P.gameEnv.arr>0 then P.act.moveRight(P,true) else P.act.insRight(P,true) end if x~=P.curX then P.moving=P.moving-P.gameEnv.arr+1 end end else P.moving=0 end end if P.keyPressing[7]and not P.keyPressing[9]then local d=abs(P.downing)-P.gameEnv.sddas P.downing=P.downing+1 if d>1 then if P.gameEnv.sdarr>0 then if d%P.gameEnv.sdarr==0 then P.act.down1(P) end else P.act.insDown(P) end end else P.downing=0 end if P.falling>=0 then P.falling=P.falling-1 if P.falling>=0 then goto stop else local L=#P.clearing if P.human and P.gameEnv.fall>0 and #P.field+L>P.clearing[L]then SFX("fall")end P.clearing,P.cleared={},{} end end if not P.control then goto stop end if P.waiting>=0 then P.waiting=P.waiting-1 if P.waiting==-1 then P:resetblock()end goto stop end if P.curY~=P.y_img then if P.dropDelay>=0 then P.dropDelay=P.dropDelay-1 if P.dropDelay>0 then goto stop end end P.curY=P.curY-1 P.spinLast=false if P.y_img~=P.curY then P.dropDelay=P.gameEnv.drop elseif P.AI_mode=="CC"then P.AI_needFresh=true if not P.AIdata._20G and P.gameEnv.drop=0 then goto stop end P:drop() if P.AI_mode=="CC"then P.AI_needFresh=true end end ::stop:: if P.b2b1==P.b2b then elseif P.b2b1=0 then P.falling=P.falling-1 if P.falling>=0 then goto stop else local L=#P.clearing if P.human and P.gameEnv.fall>0 and #P.field+L>P.clearing[L]then SFX("fall")end P.clearing,P.cleared={},{} end end::stop:: if P.endCounter<40 then for j=1,#P.field do for i=1,10 do if P.visTime[j][i]<20 then P.visTime[j][i]=P.visTime[j][i]+.5 end end end--Make field visible end if P.b2b1>0 then P.b2b1=max(0,P.b2b1*.92-1)end --Dead end if P.stat.score>P.score1 then if P.stat.score-P.score1<10 then P.score1=P.score1+1 else P.score1=int(min(P.score1*.9+P.stat.score*.1+1)) end end for i=#P.shade,1,-1 do local S=P.shade[i] S[1]=S[1]-1+setting.dropFX*.25 if S[1]<=0 then rem(P.shade,i) end end if P.fieldOffY>0 then P.fieldOffY=P.fieldOffY-(P.fieldOffY>3 and 2 or 1) end if P.fieldOffX~=0 then P.fieldOffX=P.fieldOffX-(P.fieldOffX>0 and 1 or -1) end for i=#P.bonus,1,-1 do local b=P.bonus[i] if b.inf then if b.t<30 then b.t=b.t+.5 end else b.t=b.t+b.speed if b.t>=60 then rem(P.bonus,i)end end end for i=#P.atkBuffer,1,-1 do local A=P.atkBuffer[i] A.time=A.time+1 if not A.sent then if A.countdown>0 then A.countdown=max(A.countdown-garbageSpeed,0) end else if A.time>20 then rem(P.atkBuffer,i) end end end if P.fieldBeneath>0 then P.fieldBeneath=max(P.fieldBeneath-pushSpeed,0)end if not P.small then PTC.dust[P.id]:update(dt) end end function player.draw(P) if P.small then P.frameWait=P.frameWait-1 if P.frameWait==0 then P.frameWait=8 gc.setCanvas(P.canvas) gc.clear(0,0,0,.4) gc.push("transform") gc.origin() gc.setColor(1,1,1,P.result and max(20-P.endCounter,0)*.05 or 1) local F=P.field for j=1,#F do for i=1,10 do if F[j][i]>0 then gc.draw(blockSkinmini[F[j][i]],6*i-6,120-6*j) end end end--Field if P.alive then gc.setLineWidth(2) gc.setColor(frameColor[P.strength])gc.rectangle("line",1,1,58,118) end--Draw boarder if modeEnv.royaleMode then gc.setColor(1,1,1) for i=1,P.strength do gc.draw(badgeIcon,12*i-7,4,nil,.5) end end if P.result then gc.setColor(1,1,1,min(P.endCounter,60)*.01) setFont(22)mStr(P.result,32,47) setFont(20)mStr(P.rank,30,82) end gc.pop() gc.setCanvas() --draw content end gc.setColor(1,1,1) gc.draw(P.canvas,P.x,P.y,nil,P.size*10) if P.killMark then gc.setLineWidth(3) gc.setColor(1,0,0,min(P.endCounter,25)*.04) gc.circle("line",P.centerX,P.centerY,(840-20*min(P.endCounter,30))*P.size) end --draw Canvas else gc.push("transform") gc.translate(P.x,P.y)gc.scale(P.size) --Camera gc.setColor(0,0,0,.6)gc.rectangle("fill",0,0,600,690) gc.setLineWidth(7)gc.setColor(frameColor[P.strength])gc.rectangle("line",0,0,600,690,3) --Frame gc.translate(150+P.fieldOffX,70+P.fieldOffY) if P.gameEnv.grid then gc.setLineWidth(1) gc.setColor(1,1,1,.2) for x=1,9 do gc.line(30*x,-10,30*x,600)end for y=0,19 do y=30*(y-int(P.fieldBeneath/30))+P.fieldBeneath gc.line(0,y,300,y) end end--Grid gc.translate(0,P.fieldBeneath) gc.setScissor(scr.x+P.absFieldX*scr.k,scr.y+P.absFieldY*scr.k,300*P.size*scr.k,610*P.size*scr.k) if P.falling==-1 then for j=int(P.fieldBeneath/30+1),#P.field do for i=1,10 do if P.field[j][i]>0 then gc.setColor(1,1,1,min(P.visTime[j][i]*.05,1)) drawPixel(j,i,P.field[j][i]) end end end else--field block only local dy,stepY=0,setting.smo and(P.falling/(P.gameEnv.fall+1))^2.5*30 or 30 local A=P.falling/P.gameEnv.fall local h,H=1,#P.field for j=int(P.fieldBeneath/30+1),H do while j==P.clearing[h]do h=h+1 dy=dy+stepY gc.translate(0,-stepY) gc.setColor(1,1,1,A) gc.rectangle("fill",0,630-30*j,300,stepY) end for i=1,10 do if P.field[j][i]>0 then gc.setColor(1,1,1,min(P.visTime[j][i]*.05,1)) drawPixel(j,i,P.field[j][i]) end end end gc.translate(0,dy) end--Field with falling animation for i=1,#P.shade do local S=P.shade[i] gc.setColor(1,1,1,S[1]*.12) for x=S[3],S[5]do for y=S[6],S[4]do drawPixel(y,x,S[2]) end end end--shade FX if P.waiting==-1 then if P.gameEnv.ghost then gc.setColor(1,1,1,.3) for i=1,P.r do for j=1,P.c do if P.cur.bk[i][j]then drawPixel(i+P.y_img-1,j+P.curX-1,P.cur.color) end end end end--Ghost -- local dy=setting.smo and(P.y_img~=P.curY and or 1)^4*30 or 0 local dy if setting.smo then if P.y_img~=P.curY then dy=(min(P.dropDelay,1e99)/P.gameEnv.drop-1)*30 else dy=0 end --[[ if P.y_img~=P.curY then dy=(min(P.dropDelay,8e98)/P.gameEnv.drop)^4*30 else dy=(min(P.lockDelay,8e98)/P.gameEnv.lock)^(P.gameEnv._20G and 3 or 7)*30 end ]] else dy=0 end gc.translate(0,-dy) local trans=P.lockDelay/P.gameEnv.lock if P.gameEnv.block then gc.setColor(1,1,1,trans) for i=1,P.r do for j=1,P.c do if P.cur.bk[i][j]then gc.rectangle("fill",30*(j+P.curX-1)-33,597-30*(i+P.curY-1),36,36) end end end--BlockShade(lockdelay indicator) gc.setColor(1,1,1) for i=1,P.r do for j=1,P.c do if P.cur.bk[i][j]then drawPixel(i+P.curY-1,j+P.curX-1,P.cur.color) end end end--Block end if P.gameEnv.center then gc.setColor(1,1,1,trans) local x=30*(P.curX+P.sc[2]-1)-15 gc.draw(spinCenter,x,600-30*(P.curY+P.sc[1]-1)+15,nil,nil,nil,4,4) gc.translate(0,dy) gc.setColor(1,1,1,.5) gc.draw(spinCenter,x,600-30*(P.y_img+P.sc[1]-1)+15,nil,nil,nil,4,4) goto E end--Rotate center gc.translate(0,dy) end ::E:: gc.setScissor()--In-playField things gc.setColor(1,1,1) gc.draw(PTC.dust[P.id]) gc.translate(0,-P.fieldBeneath) gc.setBlendMode("replace","alphamultiply")--SPEED UPUP(?) gc.setLineWidth(2) gc.rectangle("line",-1,-11,302,612)--Draw boarder gc.rectangle("line",301,0,15,601)--Draw atkBuffer boarder local h=0 for i=1,#P.atkBuffer do local A=P.atkBuffer[i] local bar=A.amount*30 if h+bar>600 then bar=600-h end if not A.sent then if A.time<20 then bar=bar*(20*A.time)^.5*.05 --Appear end if A.countdown>0 then gc.setColor(attackColor[A.lv][1]) gc.rectangle("fill",303,599-h,11,-bar+3) gc.setColor(attackColor[A.lv][2]) gc.rectangle("fill",303,599-h+(-bar+3),11,-(-bar+3)*(1-A.countdown/A.cd0)) --Timing else local t=math.sin((Timer()-i)*30)*.5+.5 local c1,c2=attackColor[A.lv][1],attackColor[A.lv][2] gc.setColor(c1[1]*t+c2[1]*(1-t),c1[2]*t+c2[2]*(1-t),c1[3]*t+c2[3]*(1-t)) gc.rectangle("fill",303,599-h,11,-bar+3) --Warning end else gc.setColor(attackColor[A.lv][1]) bar=bar*(20-A.time)*.05 gc.rectangle("fill",303,599-h,11,-bar+2) --Disappear end h=h+bar end--Buffer line local a,b=P.b2b,P.b2b1 if a>b then a,b=b,a end gc.setColor(.8,1,.2) gc.rectangle("fill",-14,599,11,-b*.5) gc.setColor(P.b2b<40 and color.white or P.b2b<=1e3 and color.lightRed or color.lightBlue) gc.rectangle("fill",-14,599,11,-a*.5) gc.setColor(1,1,1) if Timer()%.5<.3 then gc.rectangle("fill",-15,b<40 and 578.5 or 98.5,13,3) end gc.rectangle("line",-16,-3,15,604)--Draw b2b bar boarder --B2B indictator gc.translate(-P.fieldOffX,-P.fieldOffY) gc.setBlendMode("alpha") if P.gameEnv.hold then mDraw(drawableText.hold,-82,-10) if P.holded then gc.setColor(.6,.5,.5)end local B=P.hd.bk for i=1,#B do for j=1,#B[1]do if B[i][j]then drawPixel(i+17.5-#B*.5,j-2.7-#B[1]*.5,P.hd.color) end end end end--Hold gc.setColor(1,1,1) mDraw(drawableText.next,381,-10) local N=1 ::L:: if N<=P.gameEnv.next and P.next[N]then local b,c=P.next[N].bk,P.next[N].color for i=1,#b do for j=1,#b[1] do if b[i][j]then drawPixel(i+20-2.4*N-#b*.5,j+12.7-#b[1]*.5,c) end end end N=N+1 goto L end --Next gc.setColor(.8,.8,.8) gc.draw(drawableText.modeName,-135,-65) gc.draw(drawableText.levelName,437-drawableText.levelName:getWidth(),-65) gc.setColor(1,1,1) if frame<180 then local count=179-frame gc.push("transform") gc.translate(155,220) setFont(100) if count%60>45 then gc.scale(1+(count%60-45)^2*.01,1)end mStr(int(count/60+1),0,0) gc.pop() end--Draw starting counter for i=1,#P.bonus do P.bonus[i]:draw(min((30-abs(P.bonus[i].t-30))*.05,1)*(not P.bonus[i].inf and #P.field>(9-P.bonus[i].dy*.0333)and .7 or 1)) end--Effects setFont(30) gc.setColor(1,1,1) mStr(format("%.2f",P.stat.time),-82,518)--Time mStr(P.score1,-82,560)--Score gc.draw(drawableText.bpm,390,490) gc.draw(drawableText.kpm,350,583) setFont(30) drawDial(360,520,P.dropSpeed) drawDial(405,575,P.keySpeed) --Speed dials gc.setColor(1,1,1) if mesDisp[curMode.id]then mesDisp[curMode.id](P)end--Other messages if modeEnv.royaleMode then if P.atkMode then gc.setColor(1,.8,0,P.swappingAtkMode*.02) gc.rectangle("fill",RCPB[2*P.atkMode-1],RCPB[2*P.atkMode],90,35,8,4) end gc.setColor(1,1,1,P.swappingAtkMode*.025) gc.draw(royaleCtrlPad) end gc.pop() end end function player.demoDraw(P) gc.push("transform") gc.translate(P.x,P.y)gc.scale(P.size)gc.translate(P.fieldOffX,P.fieldOffY) --Camera gc.setColor(.1,.1,.1,.8)gc.rectangle("fill",0,0,300,600) gc.setLineWidth(2)gc.setColor(1,1,1)gc.rectangle("line",-1,-1,302,602) --Frame if P.falling==-1 then for j=int(P.fieldBeneath/30+1),#P.field do for i=1,10 do if P.field[j][i]>0 then gc.setColor(1,1,1,min(P.visTime[j][i]*.05,1)) drawPixel(j,i,P.field[j][i]) end end end else--field block only local dy,stepY=0,setting.smo and(P.falling/(P.gameEnv.fall+1))^2.5*30 or 30 local A=P.falling/P.gameEnv.fall local h,H=1,#P.field for j=int(P.fieldBeneath/30+1),H do while j==P.clearing[h]do h=h+1 dy=dy+stepY gc.translate(0,-stepY) gc.setColor(1,1,1,A) gc.rectangle("fill",0,630-30*j,300,stepY) end for i=1,10 do if P.field[j][i]>0 then gc.setColor(1,1,1,min(P.visTime[j][i]*.05,1)) drawPixel(j,i,P.field[j][i]) end end end gc.translate(0,dy) end--Field with falling animation for i=1,#P.shade do local S=P.shade[i] gc.setColor(1,1,1,S[1]*.12) for x=S[3],S[5]do for y=S[6],S[4]do drawPixel(y,x,S[2]) end end end--shade FX if P.waiting==-1 then gc.setColor(1,1,1,.3) for i=1,P.r do for j=1,P.c do if P.cur.bk[i][j]then drawPixel(i+P.y_img-1,j+P.curX-1,P.cur.color) end end end --Ghost draw gc.setColor(1,1,1) for i=1,P.r do for j=1,P.c do if P.cur.bk[i][j]then drawPixel(i+P.curY-1,j+P.curX-1,P.cur.color) end end end--Block end gc.setColor(1,1,1,.3) local N=miniBlock[P.hd.id] if N then gc.draw(N,15,30,nil,16,nil,0,N:getHeight()*.5) end local N=1 ::L:: if N<=P.gameEnv.next and P.next[N]then local p=miniBlock[P.next[N].id] gc.draw(p,285,40*N-10,nil,16,nil,p:getWidth(),p:getHeight()*.5) N=N+1 goto L end --Next gc.setColor(1,1,1) gc.draw(PTC.dust[P.id]) gc.translate(-P.fieldOffX,-P.fieldOffY) for i=1,#P.bonus do P.bonus[i]:draw(min((30-abs(P.bonus[i].t-30))*.05,1)*(not P.bonus[i].inf and #P.field>(9-P.bonus[i].dy*.0333)and .7 or 1)) end--Effects gc.pop() end -------------------------------------------------- function player:showText(text,type,font,dy,spd,inf) if not self.small then self.bonus[#self.bonus+1]={t=0,text=text,draw=textFX[type],font=font,dy=dy or 0,speed=spd or 1,inf=inf} end end function player:createShade(x1,y1,x2,y2)--x1y2 if self.gameEnv.block and y1>=y2 then self.shade[#self.shade+1]={5,self.cur.color,x1,y1,x2,y2} end end function player:createBeam(R,send,time,target,color,clear,spin,mini,combo) local x1,y1,x2,y2 if self.small then x1,y1=self.centerX,self.centerY else x1,y1=self.x+(30*(self.curX+self.sc[2]-1)-30+15+150)*self.size,self.y+(600-30*(self.curY+self.sc[1]-1)+15+70)*self.size end if R.small then x2,y2=R.centerX,R.centerY else x2,y2=R.x+308*R.size,R.y+450*R.size end local radius,corner local a,r,g,b=1,unpack(blockColor[color]) if clear>10 then radius=10+3*send+100/(target+4) local t=clear%10 if t==1 then corner=3 r=.3+r*.4 g=.3+g*.4 b=.3+b*.4 elseif t==2 then corner=5 r=.5+r*.5 g=.5+g*.5 b=.5+b*.5 elseif t<6 then corner=6 r=.6+r*.4 g=.6+g*.4 b=.6+b*.4 else r=.8+r*.2 g=.8+g*.2 b=.8+b*.2 corner=20 end else if combo>3 then radius=min(15+combo,30) corner=3 else radius=30 corner=4 end r=1-r*.3 g=1-g*.3 b=1-b*.3 end if modeEnv.royaleMode and not(self.human or R.human)then radius=radius*.4 a=.35 end FX_attack[#FX_attack+1]={ x=x1,y=y1,--current pos x1=x1,y1=y1,--start pos x2=x2,y2=y2,--end pos rad=radius*(setting.atkFX+2)*.2, corner=corner, type=type==1 and"fill"or"line", r=r,g=g,b=b,a=a*(setting.atkFX+1)*.25, t=0, drag={},--Afterimage coordinate list } end -------------------------------------------------- -------------------------------------------------- local function ifoverlap(P,bk,x,y) local C=#bk[1] if x<1 or x+C>11 or y<1 then return true end if y>#P.field then return end for i=1,#bk do if P.field[y+i-1]then for j=1,C do if bk[i][j]and P.field[y+i-1][x+j-1]>0 then return true end end end end end local function ckfull(P,i) for j=1,10 do if P.field[i][j]<=0 then return end end return true end local function checkrow(P,start,height)--(cy,r) local c=0 local h=start for i=1,height do if ckfull(P,h)then ins(P.clearing,h) ins(P.cleared,h+c) removeRow(P.field,h) removeRow(P.visTime,h) c=c+1 if not P.small then local S=PTC.dust[P.id] for _=1,100 do S:setPosition(rnd(300),630-30*(h+c)+rnd(30)) S:emit(2) end end else h=h+1 end end h=#P.field for i=c,1,-1 do if P.clearing[i]>h then P.clearing[i]=nil end end return c end local function solid(P,x,y) if x<1 or x>10 or y<1 then return true end if y>#P.field then return false end return P.field[y][x]>0 end local function getBlockDirection(P) return(P.curX+P.sc[2]-6.5)*.15 end function player:fineError(rate) self.stat.extraPiece=self.stat.extraPiece+1 self.stat.extraRate=self.stat.extraRate+rate if self.human then if self.gameEnv.fineKill then SFX("error_long") Event.lose(self) elseif setting.fine then SFX("error") end elseif self.gameEnv.fineKill then Event.lose(self) end end function player:garbageSend(R,send,time,...) if setting.atkFX>0 then self:createBeam(R,send,time,...) end R.lastRecv=self if R.atkBuffer.sum<20 then local B=R.atkBuffer if B.sum+send>20 then send=20-B.sum end--no more then 20 local m,k=#B,1 while k<=m and time>B[k].countdown do k=k+1 end for i=m,k,-1 do B[i+1]=B[i] end B[k]={ pos=rnd(10), amount=send, countdown=time, cd0=time, time=0, sent=false, lv=min(int(send^.69),5), }--Sorted insert(by time) B.sum=B.sum+send R.stat.recv=R.stat.recv+send if R.human then SFX(send<4 and "blip_1"or"blip_2",min(send+1,5)*.1) end end end function player:garbageRelease() local n,flag=1 ::L:: local A=self.atkBuffer[n] if A and A.countdown<=0 and not A.sent then self:garbageRise(8+A.lv,A.amount,A.pos) self.atkBuffer.sum=self.atkBuffer.sum-A.amount A.sent,A.time=true,0 self.stat.pend=self.stat.pend+A.amount n=n+1 flag=true else goto E end goto L ::E:: if flag and self.AI_mode=="CC"then CC_updateField(self)end end function player:garbageRise(color,amount,pos) local t=self.showTime*2 for _=1,amount do ins(self.field,1,getNewRow(color)) ins(self.visTime,1,getNewRow(t)) self.field[1][pos]=0 end self.fieldBeneath=self.fieldBeneath+amount*30 self.curY=self.curY+amount self:freshgho() for i=1,#self.clearing do self.clearing[i]=self.clearing[i]+amount end for i=1,#self.shade do local S=self.shade[i] S[4],S[6]=S[4]+amount,S[6]+amount end if #self.field>40 then Event.lose(self)end end function player:freshTarget() if self.atkMode==1 then if not self.atking or not self.atking.alive or rnd()<.1 then self:changeAtk(randomTarget(self)) end elseif self.atkMode==2 then self:changeAtk(self~=mostBadge and mostBadge or secBadge or randomTarget(self)) elseif self.atkMode==3 then self:changeAtk(self~=mostDangerous and mostDangerous or secDangerous or randomTarget(self)) elseif self.atkMode==4 then for i=1,#self.atker do if not self.atker[i].alive then rem(self.atker,i) return end end end end function player:changeAtkMode(m) if self.atkMode==m then return end self.atkMode=m if m==1 then self:changeAtk(randomTarget(self)) elseif m==2 then self:freshTarget() elseif m==3 then self:freshTarget() elseif m==4 then self:changeAtk() end ::L:: end function player:changeAtk(R) -- if not self.human then R=players[1]end--Delete first "--" to enable 1vALL mode if self.atking then local K=self.atking.atker for i=1,#K do if K[i]==self then rem(K,i) goto L end end end ::L:: if R then self.atking=R R.atker[#R.atker+1]=self else self.atking=nil end end function player:freshgho() self.y_img=min(#self.field+1,self.curY) if self.gameEnv._20G or self.keyPressing[7]and self.gameEnv.sdarr==0 then while not ifoverlap(self,self.cur.bk,self.curX,self.y_img-1)do self.y_img=self.y_img-1 self.spinLast=false end if self.curY>self.y_img then if not self.small then if setting.dropFX>0 then self:createShade(self.curX,self.curY+1,self.curX+self.c-1,self.y_img+self.r-1) end if setting.shakeFX>0 then self.fieldOffY=2*setting.shakeFX+1 end end self.curY=self.y_img end else while not ifoverlap(self,self.cur.bk,self.curX,self.y_img-1)do self.y_img=self.y_img-1 end end end function player:freshLockDelay() if self.lockDelay if self.cur.id==6 then if self.gameEnv.easyFresh then self:freshLockDelay() end if self.gameEnv.ospin then if self.curY==self.y_img then self.spinSeq=self.spinSeq%100*10+d local x,y=self.curX,self.curY local id if self.spinSeq==313 then--Z if solid(self,x-1,y)and solid(self,x+2,y)then if solid(self,x-1,y+2)and not solid(self,x-1,y+1)then--嵌 self.curX=x-1 self.dir=2 id=1 elseif not solid(self,x+1,y-1)and not solid(self,x+2,y-1)then--压 self.curY=y-1 self.dir=2 id=1 end end elseif self.spinSeq==131 then--S if solid(self,x-1,y)and solid(self,x+2,y)then if solid(self,x+2,y+2)and not solid(self,x+2,y+1)then--嵌 self.dir=2 id=2 elseif not solid(self,x,y-1)and not solid(self,x-1,y-1)then--压 self.curY=y-1 self.curX=x-1 self.dir=2 id=2 end end elseif self.spinSeq==331 then--L if solid(self,x-1,y+1)and solid(self,x+2,y+1)then if solid(self,x+2,y)and not solid(self,x-1,y)then--钩 self.curX=x-1 self.dir=0 id=3 elseif not solid(self,x,y-1)and not solid(self,x+2,y)then--扣 self.curY=y-1 self.dir=2 id=3 end end elseif self.spinSeq==113 then--J if solid(self,x+2,y+1)and solid(self,x-2,y+1)then if solid(self,x-2,y)and not solid(self,x+2,y)then--钩 self.dir=0 id=4 elseif not solid(self,x+1,y-1)and not solid(self,x-1,y)then--扣 self.curX=x-1 self.curY=y-1 self.dir=2 id=4 end end elseif self.spinSeq==111 then--T-R if solid(self,x+2,y+1)and solid(self,x-1,y+1)and solid(self,x+2,y)and not solid(self,x-1,y)then if solid(self,x,y-1)then--钩 self.curX=x-1 self.dir=0 id=5 else--转 self.curY=y-1 self.dir=1 id=5 end end elseif self.spinSeq==333 then--T-L if solid(self,x-1,y+1)and solid(self,x-1,y)and solid(self,x+2,y+1)and not solid(self,x+2,y)then if solid(self,x+1,y-1)then--钩 self.dir=0 id=5 else--转 self.curY=y-1 self.dir=3 id=5 end end elseif self.spinSeq==222 then--I if solid(self,x+2,y+1)and solid(self,x-1,y+1)then if not solid(self,x-1,y)then if not solid(self,x+2,y)then self.curX=x-1 self.dir=2 id=7 elseif not solid(self,x-2,y)then self.curX=x-2 self.dir=2 id=7 end elseif not solid(self,x+2,y)and not solid(self,x+3,y)then self.dir=2 id=7 end end end if id then--Transform successed local C=self.cur C.id=id C.bk=blocks[id][self.dir] self.r,self.c=#C.bk,#C.bk[1] self.sc=scs[id][self.dir] self.spinLast=2 self.stat.rotate=self.stat.rotate+1 self:freshgho() SFX("rotatekick",nil,getBlockDirection(self)) return end else self.spinSeq=0 end end if self.human then SFX(ifpre and"prerotate"or"rotate",nil,getBlockDirection(self)) end return end -- local icb=blocks[self.cur.id][idir] local isc=scs[self.cur.id][idir] local ir,ic=#icb,#icb[1] local ix,iy=self.curX+self.sc[2]-isc[2],self.curY+self.sc[1]-isc[1] local t--succssful test local iki=self.RS[self.cur.id][self.dir*10+idir] for i=1,self.freshTime<=1.2*self.gameEnv.freshLimit and #iki or 1 do if not ifoverlap(self,icb,ix+iki[i][1],iy+iki[i][2])then ix,iy=ix+iki[i][1],iy+iki[i][2] t=i goto spin end end do return end ::spin:: if not self.small and setting.dropFX>0 then self:createShade(self.curX,self.curY+self.r-1,self.curX+self.c-1,self.curY) end local y0=self.curY self.curX,self.curY,self.dir=ix,iy,idir self.sc,self.cur.bk=scs[self.cur.id][idir],icb self.r,self.c=ir,ic self.spinLast=t==2 and 0 or 1 if not ifpre then self:freshgho()end if self.gameEnv.easyFresh or y0>self.curY then self:freshLockDelay()end if self.human then SFX(ifpre and"prerotate"or ifoverlap(self,self.cur.bk,self.curX,self.curY+1)and ifoverlap(self,self.cur.bk,self.curX-1,self.curY)and ifoverlap(self,self.cur.bk,self.curX+1,self.curY)and"rotatekick"or"rotate",nil,getBlockDirection(self)) end self.stat.rotate=self.stat.rotate+1 end function player:hold(ifpre) if not self.holded and self.waiting==-1 and self.gameEnv.hold then --Finesse check local H,B=self.hd,self.cur if H and H.id==B.id and H.name==B.name then self:fineError(1.5) elseif self.ctrlCount>1 then self:fineError(2) end self.holded=self.gameEnv.oncehold self.spinLast=false self.ctrlCount=0 self.spinSeq=0 self.cur,self.hd=self.hd,self.cur self.hd.bk=blocks[self.hd.id][0] if self.cur.id==0 then self.cur=rem(self.next,1) self:freshNext() if self.AI_mode=="CC"then BOT.addNext(self.AI_bot,CCblockID[self.next[self.AIdata.next].id])end end self.sc,self.dir=scs[self.cur.id][0],0 self.r,self.c=#self.cur.bk,#self.cur.bk[1] self.curX,self.curY=blockPos[self.cur.id],21+ceil(self.fieldBeneath/30)-self.r+min(int(#self.field*.2),2) if abs(self.moving)>self.gameEnv.das and not ifoverlap(self,self.cur.bk,self.curX+(self.moving>0 and 1 or -1),self.curY)then self.curX=self.curX+(self.moving>0 and 1 or -1) end --IMS self:freshgho() self.dropDelay,self.lockDelay,self.freshTime=self.gameEnv.drop,self.gameEnv.lock,max(self.freshTime-5,0) if ifoverlap(self,self.cur.bk,self.curX,self.curY)then self:lock()Event.lose(self)end if self.human then SFX(ifpre and"prehold"or"hold") end self.stat.hold=self.stat.hold+1 end end function player:newNext(n) self.next[#self.next+1]={bk=blocks[n][0],id=n,color=self.gameEnv.bone and 8 or n,name=n} end function player:resetblock() self.holded=false self.spinLast=false self.spinSeq=0 self.ctrlCount=0 self.cur=rem(self.next,1) self:freshNext() if self.AI_mode=="CC"then BOT.addNext(self.AI_bot,CCblockID[self.next[self.AIdata.next].id])end self.sc,self.dir=scs[self.cur.id][0],0--spin center/direction self.r,self.c=#self.cur.bk,#self.cur.bk[1]--row/column self.curX,self.curY=blockPos[self.cur.id],21+ceil(self.fieldBeneath/30)+min(int(#self.field*.15)-self.r,0)--初始高度:7格+1,14格+2(非I) self.dropDelay,self.lockDelay,self.freshTime=self.gameEnv.drop,self.gameEnv.lock,0 if self.keyPressing[8]then self:hold(true)end if self.keyPressing[3]then self:spin(1,true)end if self.keyPressing[4]then self:spin(3,true)end if self.keyPressing[5]then self:spin(2,true)end if abs(self.moving)>self.gameEnv.das and not ifoverlap(self,self.cur.bk,self.curX+(self.moving>0 and 1 or -1),self.curY)then self.curX=self.curX+(self.moving>0 and 1 or -1) end --Initial SYSs if ifoverlap(self,self.cur.bk,self.curX,self.curY)then self:lock()Event.lose(self)end self:freshgho() if self.keyPressing[6]then self.act.hardDrop(self)self.keyPressing[6]=false end end function player:drop()--Place piece self.dropTime[11]=ins(self.dropTime,1,frame)--update speed dial self.waiting=self.gameEnv.wait local dospin=0 if self.spinLast then if self.cur.id<6 then local x,y=self.curX+self.sc[2]-1,self.curY+self.sc[1]-1 local c=0 if solid(self,x-1,y+1)then c=c+1 end if solid(self,x+1,y+1)then c=c+1 end if c==0 then goto NTC end if solid(self,x-1,y-1)then c=c+1 end if solid(self,x+1,y-1)then c=c+1 end if c>2 then dospin=dospin+1 end end--Three point ::NTC:: if self.cur.id~=6 and ifoverlap(self,self.cur.bk,self.curX-1,self.curY)and ifoverlap(self,self.cur.bk,self.curX+1,self.curY)and ifoverlap(self,self.cur.bk,self.curX,self.curY+1)then dospin=dospin+2 end--Immobile end self:lock() local CHN=getFreeVoiceChannel() local cc,send,exblock=checkrow(self,self.curY,self.r),0,0--Currect clear&send&sendTime if self.clearing[1]then self.falling=self.gameEnv.fall end local cscore,sendTime=0,0 local mini if self.spinLast then if cc>0 then if dospin>0 then dospin=dospin+self.spinLast if dospin<2 then mini=self.cur.id<6 and cc<3 and cc18 then goto 通过测试 end--高处易误判 do local y0=self.curY local x,c=self.curX,self.c local B=self.cur.bk for x=1,c do local y for i=#B,1,-1 do if B[i][x]then y=i;goto 继续 end end goto 操作判断法 ::继续:: if y then x=self.curX+x-1 for y=y0+y,#self.field do if solid(self,x,y)then goto 通过测试 end end end end--遮挡暂时都算最简 ::操作判断法:: if dospin then self.ctrlCount=self.ctrlCount-2 end--对无遮挡spin宽松两步 local id=self.cur.id local dir=self.dir+1 if id<3 or id==7 then if dir>2 then dir=dir-2 end end--SZI的逆态视为顺态 local R,I=self.ctrlCount,finesseCtrlPar[id][dir][self.curX]--Real key/Ideal key local d=R-I if d<=0 then goto 通过测试 end if I==0 then I=1 end local rate=R/I if rate>2.5 then rate=2.5 end self:fineError(rate) end ::通过测试:: if cc>0 then self.combo=self.combo+1 if cc==4 then cscore=1000 if self.b2b>1000 then self:showText(text.techrashB3B,"fly",80,-30) send=6 sendTime=100 exblock=exblock+1 cscore=cscore*1.8 self.stat.b3b=self.stat.b3b+1 if self.human then VOICE("b3b",CHN) end elseif self.b2b>=50 then self:showText(text.techrashB2B,"drive",80,-30) sendTime=80 send=5 cscore=cscore*1.3 self.stat.b2b=self.stat.b2b+1 if self.human then VOICE("b2b",CHN) end else self:showText(text.techrash,"stretch",80,-30) sendTime=60 send=4 end self.b2b=self.b2b+120 self.lastClear=74 self.stat.clear_4=self.stat.clear_4+1 if self.human then VOICE("tts",CHN) end elseif cc>0 then local clearKey=clear_n if dospin then cscore=spinSCR[self.cur.name][cc] if self.b2b>1000 then self:showText(text.b3b..text.spin[self.cur.name]..text.clear[cc],"spin",40,-30) send=b2bATK[cc]+1 exblock=exblock+1 cscore=cscore*2 self.stat.b3b=self.stat.b3b+1 if self.human then VOICE("b3b",CHN) end elseif self.b2b>=50 then self:showText(text.b2b..text.spin[self.cur.name]..text.clear[cc],"spin",40,-30) send=b2bATK[cc] cscore=cscore*1.2 self.stat.b2b=self.stat.b2b+1 if self.human then VOICE("b2b",CHN) end else self:showText(text.spin[self.cur.name]..text.clear[cc],"spin",50,-30) send=2*cc end sendTime=20+send*20 if mini then self:showText(text.mini,"appear",40,-80) send=ceil(send*.5) sendTime=sendTime+60 cscore=cscore*.5 self.b2b=self.b2b+b2bPoint[cc]*.5 if self.human then VOICE("mini",CHN) end else self.b2b=self.b2b+b2bPoint[cc] end self.lastClear=self.cur.id*10+cc clearKey=spin_n if self.human then SFX(spin_n[cc]) VOICE(blockName[self.cur.name],CHN) VOICE("spin_",CHN) end elseif #self.field>0 then self.b2b=max(self.b2b-250,0) self:showText(text.clear[cc],"appear",32+cc*3,-30,(8-cc)*.3) send=cc-1 sendTime=20+send*20 cscore=cscore+clearSCR[cc] self.lastClear=cc end self.stat[clearKey[cc]]=self.stat[clearKey[cc]]+1 if self.human then VOICE(clearName[cc],CHN) end end send=send+(renATK[self.combo]or 3) if #self.field==0 then self:showText(text.PC,"flicker",70,-80) send=min(send,3)+min(6+self.stat.pc,10) exblock=exblock+2 sendTime=sendTime+60 if self.stat.row>4 then self.b2b=1200 cscore=cscore+500*min(6+self.stat.pc,10) else cscore=cscore+500 end self.stat.pc=self.stat.pc+1 self.lastClear=self.cur.id*10+5 if self.human then SFX("perfectclear") VOICE("pc",CHN) end end if self.combo>2 then self:showText(text.cmb[min(self.combo,20)],self.combo<10 and"appear"or"flicker",20+min(self.combo,25)*3,60) cscore=cscore+min(20*self.combo,300)*cc end sendTime=sendTime+25*self.combo if self.human then SFX(clear_n[cc]) SFX(ren_n[min(self.combo,11)]) if self.combo>14 then SFX("ren_mega",(self.combo-10)*.1)end VIB(cc+1) end if self.b2b>1200 then self.b2b=1200 end if modeEnv.royaleMode then local i=min(#self.atker,9) if i>1 then send=send+reAtk[i] exblock=exblock+reDef[i] end end--Counter attack if send>0 then self.stat.atk=self.stat.atk+send --ATK statistics if exblock then exblock=int(exblock*(1+self.strength*.25))end send=send*(1+self.strength*.25) if mini then send=send*.8 end send=int(send) --Badge Buff if send==0 then goto L end self:showText(send,"zoomout",40,70) if exblock==0 then goto L end self:showText(exblock,"zoomout",20,115) ::L:: send=send+exblock local k=0 ::R:: if self.atkBuffer.sum>0 and send>0 then ::F:: k=k+1 local A=self.atkBuffer[k] if not A then goto E end if A.sent then goto F end if send>=A.amount then send=send-A.amount self.atkBuffer.sum=self.atkBuffer.sum-A.amount A.sent,A.time=true,0 if send>0 then goto R end else A.amount=A.amount-send self.atkBuffer.sum=self.atkBuffer.sum-send send=0 end end ::E:: send=send-exblock if send>0 then local T if modeEnv.royaleMode then if self.atkMode==4 then local M=#self.atker if M>0 then for i=1,M do self:garbageSend(self.atker[i],send,sendTime,M,self.cur.color,self.lastClear,dospin,mini,self.combo) end else T=randomTarget(self) end else self:freshTarget() T=self.atking end elseif #players.alive>1 then T=randomTarget(self) end if T then self:garbageSend(T,send,sendTime,1,self.cur.color,self.lastClear,dospin,mini,self.combo) end self.stat.send=self.stat.send+send if self.human and send>3 then SFX("emit",min(send,8)*.1)end end end else self.combo=0 if dospin then self:showText(text.spin[self.cur.name],"appear",50,-30) self.b2b=self.b2b+20 self.stat.spin_0=self.stat.spin_0+1 if self.human then SFX("spin_0") VOICE(blockName[self.cur.name],CHN) VOICE("spin",CHN) end cscore=cscore+30 end cscore=cscore+10 if self.b2b>1000 then self.b2b=max(self.b2b-40,1000) end self:garbageRelease() end self.stat.score=self.stat.score+cscore self.stat.piece,self.stat.row=self.stat.piece+1,self.stat.row+cc Event[self.gameEnv.dropPiece](self) if self.human then SFX("lock",nil,getBlockDirection(self))end end function player:pressKey(i) self.keyPressing[i]=true if self.id==1 then virtualkeyDown[i]=true virtualkeyPressTime[i]=10 end if self.alive then self.act[actName[i]](self) self.keyTime[11]=ins(self.keyTime,1,frame) self.stat.key=self.stat.key+1 end --ins(rec,{i,frame}) end function player:releaseKey(i) self.keyPressing[i]=false if self.id==1 then virtualkeyDown[i]=false end -- if recording then ins(rec,{-i,frame})end end -------------------------------------------------- -------------------------------------------------- player.act={} function player.act.moveLeft(P,auto) if not auto then P.ctrlCount=P.ctrlCount+1 end if P.keyPressing[9]then if P.gameEnv.swap then P:changeAtkMode(1) end elseif P.control and P.waiting==-1 then if not ifoverlap(P,P.cur.bk,P.curX-1,P.curY)then P.curX=P.curX-1 local y0=P.curY P:freshgho() if P.gameEnv.easyFresh or y0~=P.curY then P:freshLockDelay()end if P.human and P.curY==P.y_img then SFX("move")end P.spinLast=false if not auto then P.moving=-1 end else P.moving=-P.gameEnv.das-1 end else P.moving=-1 end end function player.act.moveRight(P,auto) if not auto then P.ctrlCount=P.ctrlCount+1 end if P.keyPressing[9]then if P.gameEnv.swap then P:changeAtkMode(2) end elseif P.control and P.waiting==-1 then if not ifoverlap(P,P.cur.bk,P.curX+1,P.curY)then P.curX=P.curX+1 local y0=P.curY P:freshgho() if P.gameEnv.easyFresh or y0~=P.curY then P:freshLockDelay()end if P.human and P.curY==P.y_img then SFX("move")end P.spinLast=false if not auto then P.moving=1 end else P.moving=P.gameEnv.das+1 end else P.moving=1 end end function player.act.rotRight(P) if P.control and P.waiting==-1 then P.ctrlCount=P.ctrlCount+1 P:spin(1) P.keyPressing[3]=false end end function player.act.rotLeft(P) if P.control and P.waiting==-1 then P.ctrlCount=P.ctrlCount+1 P:spin(3) P.keyPressing[4]=false end end function player.act.rotFlip(P) if P.control and P.waiting==-1 then P.ctrlCount=P.ctrlCount+2 P:spin(2) P.keyPressing[5]=false end end function player.act.hardDrop(P) if P.keyPressing[9]then if P.gameEnv.swap then P:changeAtkMode(3) end P.keyPressing[6]=false elseif P.control and P.waiting==-1 then if P.curY~=P.y_img then if not P.small then if setting.dropFX>0 then P:createShade(P.curX,P.curY+1,P.curX+P.c-1,P.y_img+P.r-1) end if setting.shakeFX>0 then P.fieldOffY=2*setting.shakeFX+1 end end P.curY=P.y_img P.spinLast=false if P.human then SFX("drop",nil,getBlockDirection(P)) VIB(1) end end P.lockDelay=-1 P:drop()------------------------------------BUG:drop==number? P.keyPressing[6]=false end end function player.act.softDrop(P) if P.keyPressing[9]then if P.gameEnv.swap then P:changeAtkMode(4) end else P.downing=1 if P.control and P.waiting==-1 then if P.curY~=P.y_img then P.curY=P.curY-1 P.spinLast=false end end end end function player.act.hold(P) if P.control and P.waiting==-1 then P:hold() end end function player.act.func(P) P.gameEnv.Fkey(P) end function player.act.restart(P) if P.gameEnv.quickR or frame<180 then clearTask("play") resetPartGameData() end end function player.act.insLeft(P,auto) local x0,y0=P.curX,P.curY while not ifoverlap(P,P.cur.bk,P.curX-1,P.curY)do P.curX=P.curX-1 if not P.small and setting.dropFX>0 then P:createShade(P.curX+1,P.curY+P.r-1,P.curX+1,P.curY) end P:freshgho() end if x0~=P.curX then if P.human and setting.shakeFX>0 then P.fieldOffX=-2*setting.shakeFX end if P.gameEnv.easyFresh or y0~=P.curY then P:freshLockDelay()end end if auto then if P.ctrlCount==0 then P.ctrlCount=1 end else P.ctrlCount=P.ctrlCount+1 end end function player.act.insRight(P,auto) local x0,y0=P.curX,P.curY while not ifoverlap(P,P.cur.bk,P.curX+1,P.curY)do P.curX=P.curX+1 if not P.small and setting.dropFX>0 then P:createShade(P.curX+P.c-1,P.curY+P.r-1,P.curX+P.c-1,P.curY) end P:freshgho() end if x0~=P.curX then if P.human and setting.shakeFX>0 then P.fieldOffX=2*setting.shakeFX end if P.gameEnv.easyFresh or y0~=P.curY then P:freshLockDelay()end end if auto then if P.ctrlCount==0 then P.ctrlCount=1 end else P.ctrlCount=P.ctrlCount+1 end end function player.act.insDown(P) if P.curY~=P.y_img then if not P.small then if setting.dropFX>0 then P:createShade(P.curX,P.curY+1,P.curX+P.c-1,P.y_img+P.r-1) end if setting.shakeFX>0 then P.fieldOffY=2*setting.shakeFX end end P.curY,P.lockDelay,P.spinLast=P.y_img,P.gameEnv.lock,false end end function player.act.down1(P) if P.curY~=P.y_img then P.curY=P.curY-1 P.spinLast=false end end function player.act.down4(P) for _=1,4 do if P.curY~=P.y_img then P.curY=P.curY-1 P.spinLast=false else break end end end function player.act.down10(P) for _=1,10 do if P.curY~=P.y_img then P.curY=P.curY-1 P.spinLast=false else break end end end function player.act.dropLeft(P) P.act.insLeft(P) P.act.hardDrop(P) end function player.act.dropRight(P) P.act.insRight(P) P.act.hardDrop(P) end function player.act.addLeft(P) P.act.insLeft(P) P.act.insDown(P) P.act.insRight(P) P.act.hardDrop(P) end function player.act.addRight(P) P.act.insRight(P) P.act.insDown(P) P.act.insLeft(P) P.act.hardDrop(P) end --------------------------------------------------