diff --git a/SFX/rotatekick.ogg b/SFX/rotatekick.ogg index 7a69f010..8850fc4e 100644 Binary files a/SFX/rotatekick.ogg and b/SFX/rotatekick.ogg differ diff --git a/ai.lua b/ai.lua index 2785d9d9..b84b09d6 100644 --- a/ai.lua +++ b/ai.lua @@ -8,7 +8,7 @@ FilledLines TetrisShape BlockedWells; ]] -spinNeed={2,2,4,4,4,1,2} +dirCount={1,1,3,3,3,0,1} spinOffset={ {1,0,0},--S {1,0,0},--Z @@ -19,44 +19,27 @@ spinOffset={ {2,0,1},--I }for i=1,7 do spinOffset[i][0]=0 end - -local count=0 -RowFree={}for i=1,16 do RowFree[i]={}end -function getNewRow(len) - count=count+1 - if count==17 then count=1 end - for i=1,len do - RowFree[count][i]=0 - end - return RowFree[count] -end ---Cache manage - -function ifoverlapAI(field,bk,x,y) - if x<1 or x+#bk[1]>11 or y<1 then return true end - if y>#field then return nil end +function ifoverlapAI(f,bk,x,y) + if y<1 then return true end + if y>#f then return nil end for i=1,#bk do for j=1,#bk[1]do - if field[y+i-1]and bk[i][j]>0 and field[y+i-1][x+j-1]>0 then return true end + if f[y+i-1]and bk[i][j]>0 and f[y+i-1][x+j-1]>0 then return true end end end end -function resetField(f0,start,ifOrigion) - while field[start]do - rem(field,start) +function resetField(f0,f,start) + while f[start]do + removeRow(f,start) end for i=start,#f0 do - if ifOrigion then - field[i]=f0[i] - else - field[i]={} - for j=1,10 do - field[i][j]=f0[i][j] - end + f[i]=getNewRow() + for j=1,10 do + f[i][j]=f0[i][j] end end end function getScore(field,cb,cx,cy) local highest=0 - local height=getNewRow(0) + local height=getNewRow() local rough=0 local clear=0 local hole=0 @@ -67,7 +50,7 @@ function getScore(field,cb,cx,cy) if field[i][j]==0 then f=false;break end end if f then - rem(field,i) + removeRow(field,i) clear=clear+1 end end @@ -81,62 +64,67 @@ function getScore(field,cb,cx,cy) if x>3 and x<8 and h>highest then highest=h end if h>1 then for h=h-1,1,-1 do - if field[h][x]==0 then hole=hole+1 end + if field[h][x]==0 then hole=hole+1 if hole>5 then break end end end end end for x=1,9 do local dh=abs(height[x]-height[x]) if dh>1 then - rough=rough+dh^1.5 + rough=rough+min(dh^2,10) end end + ins(freeRow,height) return -highest*5 - -rough*20 - -cy*15 + -rough*15 + -cy*20 + -#cb*10 +clear^2*4 - -hole*20 + -hole*15 end --controlname:mL,mR,rR,rL,rF,hD,sD,H,LL,RR function AI_getControls(ctrl) - local field_org,cb,cx,cy={} - for i=1,#field do - field_org[i]={} + local Tfield={}--test field + local field_org=field + for i=1,#field_org do + Tfield[i]=getNewRow() for j=1,10 do - field_org[i][j]=field[i][j] + Tfield[i][j]=field_org[i][j] end end local best={x=1,dir=0,hold=false,score=-9e99} for ifhold=0,1 do local bn=ifhold==0 and bn or hn>0 and hn or nxt[1] - for dir=0,spinNeed[bn]-1 do--for each direction - cb=blocks[bn][dir] + for dir=0,dirCount[bn] do--for each direction + local cb=blocks[bn][dir] for cx=1,11-#cb[1]do--for each positioon - cy=#field+1 - while not ifoverlapAI(field,cb,cx,cy-1)do + local cy=#Tfield+1 + while not ifoverlapAI(Tfield,cb,cx,cy-1)do cy=cy-1 end--move to bottom for i=1,#cb do local y=cy+i-1 - if not field[y]then field[y]=getNewRow(10)end + if not Tfield[y]then Tfield[y]=getNewRow()end for j=1,#cb[1]do if cb[i][j]~=0 then - field[y][cx+j-1]=1 + Tfield[y][cx+j-1]=1 end end end--simulate lock - local score=getScore(field,cb,cx,cy) + local score=getScore(Tfield,cb,cx,cy) if score>best.score then best={bn=bn,x=cx,dir=dir,hold=ifhold==1,score=score} end - resetField(field_org,cy) + resetField(field_org,Tfield,cy) end end - end--ifHold - resetField(field_org,cy,true)--True reset,no temp pointer + end--ifHold loop + + while #Tfield>0 do + removeRow(Tfield,1) + end--Release cache - cb,cx,cy=cb_org,cx_org,cy_org if best.hold then ins(ctrl,8) end @@ -146,7 +134,7 @@ function AI_getControls(ctrl) ins(ctrl,5) elseif best.dir==3 then ins(ctrl,4) - end--rotate + end--hold&rotate best.x=best.x-spinOffset[best.bn][best.dir] local n=blockPos[best.bn]0 do + removeRow(f,1) + removeRow(f2,1) + end + end +end +--to save cache,all rows pruduced and removed here! function sortByTime(a,b) return a.time>b.time @@ -10,7 +44,7 @@ end ww,wh=gc.getWidth(),gc.getHeight() -Timer=tm.getTime +Timer=tm.getTime--Easy get time mx,my,mouseShow=-10,-10,true pause=0--pause countdown(frame) focus=true @@ -26,7 +60,10 @@ languages={"eng"} prevMenu={ load=love.event.quit, ready="mode", - play="mode", + play=function() + restockRow() + gotoScene("mode") + end, mode="main", help="main", stat="main", @@ -199,38 +236,30 @@ color={ } attackColor={ {color.red,color.yellow}, - {color.red,color.cyan}, + {color.red,color.purple}, {color.blue,color.white}, animate={ function(t) gc.setColor(1,t,0) end, function(t) - gc.setColor(1-t,t,t) + gc.setColor(1,0,t) end, function(t) gc.setColor(t,t,1) end, - } + }--3 animation-colorsets of attack buffer bar } -- for k,v in pairs(color) do -- v[1],v[2],v[3]=255*v[1],255*v[2],255*v[3] -- end -loseReason={"Finished","Block out"} -blockName={"Z","S","L","J","T","O","I"} -clearName={"Single","Double","Triple"} -actName={"moveLeft","moveRight","rotRight","rotLeft","rotFlip","hardDrop","softDrop","hold","restart","toLeft","toRight"} -actName_show={"move left","move right","rotate right","rotate left","rotate flip","hard drop","soft drop","hold","restart","toLeft","toRight"} -blockPos={4,4,4,4,4,5,4} -renATK={[0]=0,0,0,1,1,2,2,3,3,3}--4 else -b2bATK={3,5,8} require("TRS")--load block&TRS kick - -marathon_drop={[0]=60,48,40,30,24,18,15,12,10,8,7,6,5,4,3,2,1,1,0,0} +require("lists") gameEnv0={ - das=6,arr=1, + das=10,arr=2, + sddas=0,sdarr=2, ghost=true,center=true, drop=30,lock=45, wait=0,fall=20, @@ -239,6 +268,7 @@ gameEnv0={ _20G=false,target=9e99, freshLimit=9e99, key={"left","right","x","z","c","up","down","space","LEFT","RIGHT"}, + gamepad={"dpleft","dpright","a","b","y","dpup","dpdown","rightshoulder","leftshoulder","LEFT","RIGHT"}, reach=function()end,--Called when reach row target } randomMethod={ @@ -341,7 +371,7 @@ loadmode={ curBG="game2" BGM("push") end, - tetris25=function() + tetris21=function() modeEnv={ wait=1, fall=1, @@ -444,30 +474,17 @@ Event={ end end, death_reach=function() - if gameEnv.target==50 then - gameEnv.lock=9 - gameEnv.wait=5 - gameEnv.fall=8 - showText("STAGE 2","fly",80,-100) - elseif gameEnv.target==100 then - gameEnv.lock=8 - gameEnv.wait=4 - gameEnv.fall=6 - showText("STAGE 3","fly",80,-100) - elseif gameEnv.target==150 then - gameEnv.lock=7 - gameEnv.wait=3 - gameEnv.fall=5 - showText("STAGE 4","fly",80,-100) - elseif gameEnv.target==200 then - gameEnv.lock=6 - gameEnv.wait=2 - gameEnv.fall=4 - showText("STAGE 5","fly",80,-100) - gameEnv.target=250 + if gameEnv.target==250 then + Event.gameover.win() + else + gameEnv.target=gameEnv.target+50 + local t=gameEnv.target/50 + gameEnv.lock=death_lock[t] + gameEnv.wait=death_wait[t] + gameEnv.fall=death_fall[t] + showText("STAGE "..t,"fly",80,-120) + SFX("reach") end - gameEnv.target=gameEnv.target+50 - SFX("reach") end, task={ win=function() @@ -522,7 +539,7 @@ mesDisp={ death=function() mStr(P.cstat.row.."/"..gameEnv.target,-75,250) end, - tetris25=function() + tetris21=function() gc.print("Remain",-140,450) gc.print("Attack",-130,305) setFont(80) @@ -554,9 +571,11 @@ setting={ sfx=true,bgm=true, fullscreen=false, lang="eng", - das=5,arr=0, + das=10,arr=2, + sddas=0,sdarr=2, ghost=true,center=true, key={"left","right","x","z","c","up","down","space","r","LEFT","RIGHT"}, + gamepad={"dpleft","dpright","a","b","y","dpup","dpdown","rightshoulder","leftshoulder","LEFT","RIGHT"}, } stat={ run=0, @@ -612,11 +631,35 @@ function mouseConvert(x,y) return x*1280/ww,360+(y-wh*.5)*1280/ww end end +function sysSFX(s,v) + if setting.sfx then + local n=1 + while sfx[s][n]:isPlaying()do + n=n+1 + if not sfx[s][n]then + sfx[s][n]=sfx[s][n-1]:clone() + sfx[s][n]:seek(0) + end + end + sfx[s][n]:setVolume(v or 1) + sfx[s][n]:play() + end +end function SFX(s,v) if setting.sfx then - sfx[s]:stop() - sfx[s]:setVolume(v or 1) - sfx[s]:play() + local n=1 + while sfx[s][n]:isPlaying()do + n=n+1 + if not sfx[s][n]then + sfx[s][n]=sfx[s][n-1]:clone() + sfx[s][n]:seek(0) + end + end + if P.id>1 then + v=1/(#players.alive-1) + end + sfx[s][n]:setVolume(v or 1) + sfx[s][n]:play() end end function BGM(s) @@ -640,6 +683,7 @@ function gotoScene(s,style) end end function resetGameData() + if players then restockRow()end--Avoid first start game error players={alive={}} loadmode[gamemode]() @@ -652,6 +696,11 @@ function resetGameData() PTC.dust[i]:start() end stat.game=stat.game+1 + + freeRow={} + for i=1,50*#players do + freeRow[i]={0,0,0,0,0,0,0,0,0,0} + end collectgarbage() end function startGame(mode) @@ -691,9 +740,9 @@ function loaddata() for i=#v+1,8 do v[i]="N/A"end setting.key=v --Settings - elseif t=="das"or t=="arr"then + elseif t=="das"or t=="arr"or t=="sddas"or t=="sdarr"then v=toN(v)if not v or v<0 then v=0 end - setting[t]=v + setting[t]=int(v) elseif t=="ghost"or t=="center"then setting[t]=v=="true" elseif t=="run"or t=="game"or t=="gametime"or t=="piece"or t=="row"or t=="atk"or t=="key"or t=="rotate"or t=="hold"or t=="spin"then @@ -723,6 +772,8 @@ function savedata() t=t..stringPack("spin=",stat.spin) t=t..stringPack("das=",setting.das) t=t..stringPack("arr=",setting.arr) + t=t..stringPack("sddas=",setting.sddas) + t=t..stringPack("sdarr=",setting.sdarr) t=t..stringPack("keyset=",string.concat(setting.key)) --t=love.math.compress(t,"zlib"):getString() userdata:open("w") @@ -1081,7 +1132,7 @@ end function lock() for i=1,r do local y=cy+i-1 - if not P.field[y]then P.field[y],P.visTime[y]={0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0}end + if not P.field[y]then P.field[y],P.visTime[y]=getNewRow(),getNewRow()end for j=1,c do if cb[i][j]~=0 then P.field[y][cx+j-1]=P.bn @@ -1106,8 +1157,8 @@ function garbageRelease() local atk=P.atkBuffer[i] if not atk.sent and atk.countdown==0 then for j=1,atk.amount do - ins(P.field,1,{13,13,13,13,13,13,13,13,13,13}) - ins(P.visTime,1,{t,t,t,t,t,t,t,t,t,t}) + ins(P.field,1,getNewRow(13)) + ins(P.visTime,1,getNewRow(t)) for k=1,#atk do P.field[1][atk[k]]=0 end @@ -1138,10 +1189,13 @@ end function keyDown.setting2(key) if key=="escape"then back() + keysetting,gamepadsetting=nil elseif keysetting then setting.key[keysetting]=key + keysetting,gamepadsetting=nil + else + buttonControl_key(key) end - keysetting=nil end keyUp={} function keyUp.play(key) @@ -1153,7 +1207,40 @@ function keyUp.play(key) end end end +gamepadDown={} +function gamepadDown.play(key) + local k=players[1].gameEnv.gamepad + for i=1,11 do + if key==k[i]then + pressKey(i,players[1]) + break + end + end + if key=="escape"then back()end +end +function gamepadDown.setting2(key) + if key=="back"then + back() + keysetting,gamepadsetting=nil + elseif gamepadsetting then + setting.gamepad[gamepadsetting]=key + keysetting,gamepadsetting=nil + else + buttonControl_gamepad(key) + end +end +gamepadUp={} +function gamepadUp.play(key) + local k=players[1].gameEnv.gamepad + for i=1,10 do + if key==k[i]then + releaseKey(i,players[1]) + break + end + end +end wheelmoved={} +--Warning,these are not system callbacks! require("BGblock")--BG block module require("ai")--AI module @@ -1252,7 +1339,10 @@ function love.draw() numFont(20)gc.setColor(1,1,1) gc.print(tm.getFPS(),0,700) - gc.print(gcinfo(),0,670) + gc.print(gcinfo(),0,680) + -- numFont(80) + -- gc.print(gcinfo(),400,370) + --if gcinfo()>500 then collectgarbage()end end function love.resize(x,y) @@ -1283,7 +1373,7 @@ function love.run() tm.step() love.resize(1280,720) game.load()--Launch - math.randomseed(os.time()*626)--true ultheur's naim! + math.randomseed(os.time()*626)--true ultheur's I D! -- while true do return function() love.event.pump() diff --git a/paint.lua b/paint.lua index fa986339..0de65d61 100644 --- a/paint.lua +++ b/paint.lua @@ -109,7 +109,7 @@ end function Pnt.main() gc.setColor(1,1,1) setFont(30) - gc.print("Alpha 0.1.19727",370,150) + gc.print("Alpha 0.1+",370,150) gc.draw(img.title[setting.lang],30,30) end function Pnt.play() @@ -266,17 +266,18 @@ function Pnt.play() setmetatable(_G,nil) end function Pnt.setting2() + gc.setColor(1,1,1) + setFont(18) + mStr("softdropDAS:"..setting.sddas,828,138) + mStr("softdropARR:"..setting.sdarr,1043,138) setFont(35) - gc.setColor(1,1,1) - mStr("DAS:"..setting.das,830,72) - mStr("ARR:"..setting.arr,1045,72) - gc.setColor(1,1,1) + mStr("DAS:"..setting.das,828,73) + mStr("ARR:"..setting.arr,1043,73) for i=1,9 do - gc.printf(actName_show[i]..":",100,60*i-8,200,"right") + gc.printf(actName_show[i]..":",0,60*i-8,180,"right") end - if keysetting then - setFont(35) - gc.print("<<",550,60*keysetting-10) + if keysetting or gamepadsetting then + gc.print("<<",keysetting and 380 or 670,60*(keysetting or gamepadsetting)-10) end end function Pnt.help() diff --git a/timer.lua b/timer.lua index 1d8494e8..7947cd19 100644 --- a/timer.lua +++ b/timer.lua @@ -22,7 +22,7 @@ function Tmr.load() end elseif loading==3 then if loadnum<=#sfx then - sfx[sfx[loadnum]]=love.audio.newSource("/SFX/"..sfx[loadnum]..".ogg","static") + sfx[sfx[loadnum]]={love.audio.newSource("/SFX/"..sfx[loadnum]..".ogg","static")} loadprogress=loadnum/#sfx loadnum=loadnum+1 else @@ -59,7 +59,7 @@ function Tmr.play(dt) count=count-1 if count==0 then count=nil - SFX("start") + sysSFX("start") for P=1,#players do P=players[P] _G.P=P @@ -70,7 +70,7 @@ function Tmr.play(dt) end setmetatable(_G,nil) elseif count%60==0 then - SFX("ready") + sysSFX("ready") end if count then @@ -116,7 +116,6 @@ function Tmr.play(dt) end end --Fresh visible time if keyPressing[1]or keyPressing[2]then - P.moving=moving+sgn(moving) local d=abs(moving)-gameEnv.das if d>1 then if gameEnv.arr>0 then @@ -127,11 +126,21 @@ function Tmr.play(dt) act[moving>0 and"toRight"or"toLeft"]() end end + P.moving=moving+sgn(moving) else P.moving=0 end if keyPressing[7]then - act.softDrop() + local d=abs(downing)-gameEnv.sddas + if d>1 then + if gameEnv.sdarr>0 then + if d%gameEnv.sdarr==0 then + act.down1() + end + else + act.toDown() + end + end P.downing=downing+1 else P.downing=0 @@ -141,8 +150,8 @@ function Tmr.play(dt) if falling<=0 then if #field>clearing[1]then SFX("fall")end for i=1,#clearing do - rem(field,clearing[i]) - rem(visTime,clearing[i]) + removeRow(field,clearing[i]) + removeRow(visTime,clearing[i]) end P.clearing={} end @@ -176,8 +185,8 @@ function Tmr.play(dt) if falling<=0 then if #field>clearing[1]then SFX("fall")end for i=1,#clearing do - rem(field,clearing[i]) - rem(visTime,clearing[i]) + removeRow(field,clearing[i]) + removeRow(visTime,clearing[i]) end P.clearing={} end @@ -206,7 +215,7 @@ function Tmr.play(dt) end end end - if fieldBeneath>0 then P.fieldBeneath=fieldBeneath-2 end + if fieldBeneath>0 then P.fieldBeneath=fieldBeneath-3 end P.b2b1=P.b2b1*.95+P.b2b*.05 PTC.dust[p]:update(dt) end diff --git a/user_actions.lua b/user_actions.lua index 4e367f0a..1228dfc8 100644 --- a/user_actions.lua +++ b/user_actions.lua @@ -31,7 +31,7 @@ act={ end end, softDrop=function() - act.toDown() + if cy~=y_img then P.cy=cy-1 end P.downing=1 end, rotRight=function()spin(1)end, @@ -43,8 +43,8 @@ act={ resetGameData() count=60+26--Althour'z neim end, - down1=function()drop()end, - down4=function()for i=1,4 do if cy~=y_img then drop()else break end end end, + down1=function()if cy~=y_img then P.cy=cy-1 end end, + down4=function()for i=1,4 do if cy~=y_img then P.cy=cy-1 else break end end end, toDown=function()if cy~= y_img then P.cy,P.lockDelay,P.spinLast=y_img,gameEnv.lock,false end end, toLeft=function()while not ifoverlap(cb,cx-1,cy)do P.cx,P.lockDelay=cx-1,gameEnv.lock;freshgho()end end, toRight=function()while not ifoverlap(cb,cx+1,cy)do P.cx,P.lockDelay=cx+1,gameEnv.lock;freshgho()end end,