diff --git a/document/mode.txt b/document/mode.txt index 8aeca1ef..930c0dde 100644 --- a/document/mode.txt +++ b/document/mode.txt @@ -52,9 +52,8 @@ highCam:是否开启超屏视野 nextPos:是否开启生成预览 - sequence:序列模式,可以使用默认的几个函数用字符串表示,也可以自己写 - freshMethod=放一块后对next序列的刷新函数,不使用默认sequence的话就要自己写 - bag:一包的方块(本质是基准序列,不一定是包) + sequence=序列模式,是放一块后对next序列的刷新函数,可以使用默认的几个函数用字符串表示。也可以自己写一个,注意:使用协程技术 + seqData:序列模式使用的"包"数据(本质是生成序列用的数据,会作为参数传进序列生成函数,不一定是包) mission:包含任务的table,说明暂时略 life:生命数, diff --git a/parts/ai.lua b/parts/ai.lua index 4c0ae8a0..24bbdb21 100644 --- a/parts/ai.lua +++ b/parts/ai.lua @@ -1,6 +1,6 @@ local int,ceil,min,abs,rnd,modf=math.floor,math.ceil,math.min,math.abs,math.random,math.modf local ins,rem=table.insert,table.remove -local YIELD=YIELD +local resume,yield=coroutine.resume,coroutine.yield -- controlname: -- 1~5:mL,mR,rR,rL,rF, -- 6~10:hD,sD,H,A,R, @@ -75,7 +75,7 @@ if _CC then P.cur=rem(P.nextQueue,1) P.curX,P.curY=blockPos[P.cur.id],int(P.gameEnv.fieldH+1-modf(P.cur.sc[1]))+ceil(P.fieldBeneath/30) - P:newNext() + assert(resume(P.newNext)) local id=CCblockID[P.nextQueue[P.AIdata.next].id] if id then CC.addNext(P.AI_bot,id) @@ -201,7 +201,7 @@ return{ ["9S"]=function(P,keys) while true do --Thinking - YIELD() + yield() local Tfield={}--Test field local best={x=1,dir=0,hold=false,score=-1e99}--Best method local field_org=P.field @@ -268,7 +268,7 @@ return{ ins(keys,6) --Check if time to change target - YIELD() + yield() if P:RND()<.00126 then P:changeAtkMode(rnd()<.85 and 1 or #P.atker>3 and 4 or rnd()<.3 and 2 or 3) end @@ -277,13 +277,13 @@ return{ ["CC"]=CC and function(P,keys) while true do --Start thinking - YIELD() + yield() if not pcall(CC.think,P.AI_bot)then break end --Poll keys local success,result,dest,hold,move repeat - YIELD() + yield() success,result,dest,hold,move=pcall(CC.getMove,P.AI_bot) until not success or result==0 or result==2 if not success then break end @@ -308,7 +308,7 @@ return{ end --Check if time to change target - YIELD() + yield() if P:RND()<.00126 then P:changeAtkMode(rnd()<.85 and 1 or #P.atker>3 and 4 or rnd()<.3 and 2 or 3) end diff --git a/parts/gametoolfunc.lua b/parts/gametoolfunc.lua index 195b85e5..effd12a7 100644 --- a/parts/gametoolfunc.lua +++ b/parts/gametoolfunc.lua @@ -583,9 +583,9 @@ function applyCustomGame()--Apply CUSTOMENV, BAG, MISSION GAME.modeEnv[k]=v end if BAG[1]then - GAME.modeEnv.bag=BAG + GAME.modeEnv.seqData=BAG else - GAME.modeEnv.bag=nil + GAME.modeEnv.seqData=nil end if MISSION[1]then GAME.modeEnv.mission=MISSION diff --git a/parts/modes/drought_l.lua b/parts/modes/drought_l.lua index 0428ea6b..70b6622a 100644 --- a/parts/modes/drought_l.lua +++ b/parts/modes/drought_l.lua @@ -5,90 +5,91 @@ return{ drop=20,lock=60, sequence=function(P) for _=1,3 do P:getNext(7)end - end, - freshMethod=function(P) - if not P.nextQueue[1] then - local height=FREEROW.get(0) - local max=#P.field - if max>0 then - --Get heights - for x=1,10 do - local h=max - while P.field[h][x]==0 and h>1 do - h=h-1 + while true do + YIELD() + if not P.nextQueue[1] then + local height=FREEROW.get(0) + local max=#P.field + if max>0 then + --Get heights + for x=1,10 do + local h=max + while P.field[h][x]==0 and h>1 do + h=h-1 + end + height[x]=h + end + else + for x=1,10 do + height[x]=0 end - height[x]=h end - else - for x=1,10 do - height[x]=0 - end - end - height[11]=999 + height[11]=999 - local res={1,1,2,2,3,4} - local d=0 - local A - for i=1,10 do - d=d+height[i] - end - if d<40 or P.stat.row>2*42 then - A=#res+1 - for _=1,4 do - res[A]=1 - res[A+1]=2 + local res={1,1,2,2,3,4} + local d=0 + local A + for i=1,10 do + d=d+height[i] + end + if d<40 or P.stat.row>2*42 then + A=#res+1 + for _=1,4 do + res[A]=1 + res[A+1]=2 + res[A+2]=6 + A=A+3 + end + goto END + end + + --Give I when no hole + d=-999--Height difference + --A=hole mark + for x=2,11 do + local _=height[x]-height[x-1] + if d<-2 and _>2 then + A=true + end + d=_ + end + if not A then + A=#res+1 + res[A]=7 + res[A+1]=7 + res[A+2]=7 + end + + --Give O when no d=0/give T when no d=1 + d=0--d=0 count + A=0--d=1 count + for x=2,10 do + local _=height[x]-height[x-1] + if _==0 then + d=d+1 + elseif _==1 or _==-1 then + A=A+1 + end + end + if d<3 then + A=#res+1 + res[A]=6 + res[A+1]=6 res[A+2]=6 - A=A+3 end - goto END - end - - --Give I when no hole - d=-999--Height difference - --A=hole mark - for x=2,11 do - local _=height[x]-height[x-1] - if d<-2 and _>2 then - A=true + if A<3 then + A=#res+1 + res[A]=5 + res[A+1]=5 + res[A+2]=5 + res[A+3]=5 + res[A+4]=5 end - d=_ - end - if not A then - A=#res+1 - res[A]=7 - res[A+1]=7 - res[A+2]=7 - end - --Give O when no d=0/give T when no d=1 - d=0--d=0 count - A=0--d=1 count - for x=2,10 do - local _=height[x]-height[x-1] - if _==0 then - d=d+1 - elseif _==1 or _==-1 then - A=A+1 - end + ::END:: + FREEROW.discard(height) + P:getNext(res[P:RND(#res)]) end - if d<3 then - A=#res+1 - res[A]=6 - res[A+1]=6 - res[A+2]=6 - end - if A<3 then - A=#res+1 - res[A]=5 - res[A+1]=5 - res[A+2]=5 - res[A+3]=5 - res[A+4]=5 - end - - ::END:: - FREEROW.discard(height) - P:getNext(res[P:RND(#res)]) end end, target=100,dropPiece=PLY.check_lineReach, diff --git a/parts/modes/drought_n.lua b/parts/modes/drought_n.lua index 8ed0dd60..3a711daf 100644 --- a/parts/modes/drought_n.lua +++ b/parts/modes/drought_n.lua @@ -4,7 +4,7 @@ return{ env={ drop=20,lock=60, sequence="bag", - bag={1,1,2,2,3,3,4,4,5,5,6,6}, + seqData={1,1,2,2,3,3,4,4,5,5,6,6}, target=100,dropPiece=PLY.check_lineReach, nextCount=3, ospin=false, diff --git a/parts/modes/sprintPenta.lua b/parts/modes/sprintPenta.lua index c0228bcd..8173c719 100644 --- a/parts/modes/sprintPenta.lua +++ b/parts/modes/sprintPenta.lua @@ -2,7 +2,7 @@ return{ color=COLOR.green, env={ drop=60,lock=60, - sequence="bag",bag={8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25}, + sequence="bag",seqData={8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25}, target=40,dropPiece=PLY.check_lineReach, bg="aura",bgm="waterfall", }, diff --git a/parts/player/gameEnv0.lua b/parts/player/gameEnv0.lua index 2f699427..2144026a 100644 --- a/parts/player/gameEnv0.lua +++ b/parts/player/gameEnv0.lua @@ -37,8 +37,7 @@ return{ ospin=true,deepDrop=false, RS="TRS", sequence="bag", - freshMethod=NULL, - bag={1,2,3,4,5,6,7}, + seqData={1,2,3,4,5,6,7}, face=NULL,skin=NULL, mission=NULL, diff --git a/parts/player/init.lua b/parts/player/init.lua index f6779ced..47d9a333 100644 --- a/parts/player/init.lua +++ b/parts/player/init.lua @@ -142,7 +142,6 @@ local function newEmptyPlayer(id,mini) P.holdQueue={} P.holdTime=0 P.nextQueue={} - P.seqData={} P.freshTime=0 P.spinLast=false @@ -296,10 +295,11 @@ local function applyGameEnv(P)--Finish gameEnv processing if ENV.sequence~="bag"and ENV.sequence~="loop"then ENV.bagLine=false else - ENV.bagLen=#ENV.bag + ENV.bagLen=#ENV.seqData end if ENV.nextCount==0 then ENV.nextPos=false end + prepareSequence(P) if P.mini then ENV.lockFX=false @@ -355,7 +355,6 @@ function PLY.newDemoPlayer(id) GAME.modeEnv=DemoEnv loadGameEnv(P) applyGameEnv(P) - prepareSequence(P) P:loadAI{ type="CC", next=5, @@ -385,7 +384,6 @@ function PLY.newRemotePlayer(id,mini,playerData) loadRemoteEnv(P,playerData.conf) applyGameEnv(P) - prepareSequence(P) end function PLY.newAIPlayer(id,AIdata,mini) @@ -397,7 +395,6 @@ function PLY.newAIPlayer(id,AIdata,mini) ENV.face={0,0,0,0,0,0,0} ENV.skin={1,7,11,3,14,4,9} applyGameEnv(P) - prepareSequence(P) P:loadAI(AIdata) end function PLY.newPlayer(id,mini) @@ -407,7 +404,6 @@ function PLY.newPlayer(id,mini) loadGameEnv(P) applyGameEnv(P) - prepareSequence(P) end ---------------------------------------------------- return PLY \ No newline at end of file diff --git a/parts/player/player.lua b/parts/player/player.lua index 61a6f10b..81c015e3 100644 --- a/parts/player/player.lua +++ b/parts/player/player.lua @@ -1,13 +1,13 @@ ------------------------------------------------------ --Notice: anything in this file or in any other file, ---var P stands for Player object. Don't forget that. +--local var P stands for Player object. Don't forget it. ------------------------------------------------------ local Player={}--Player class local int,ceil,rnd=math.floor,math.ceil,math.random local max,min,modf=math.max,math.min,math.modf local ins,rem=table.insert,table.remove -local YIELD=YIELD +local resume,yield=coroutine.resume,coroutine.yield local kickList=require"parts.kickList" @@ -147,7 +147,7 @@ end local function task_movePosition(P,x,y,size) local x1,y1,size1=P.x,P.y,P.size while true do - YIELD() + yield() if (x1-x)^2+(y1-y)^2<1 then P:setPosition(x,y,size) return true @@ -750,7 +750,7 @@ function Player.popNext(P,ifhold)--Pop nextQueue to hand P.ctrlCount=0 P.cur=rem(P.nextQueue,1) - P:newNext() + assert(resume(P.newNext)) if P.cur then P.pieceCount=P.pieceCount+1 if P.AI_mode=="CC"then @@ -1516,7 +1516,7 @@ end ---------------------------------------------------- local function tick_throwBadge(ifAI,sender,time) while true do - YIELD() + yield() time=time-1 if time%4==0 then local S,R=sender,sender.lastRecv @@ -1544,7 +1544,7 @@ local function tick_throwBadge(ifAI,sender,time) end local function tick_finish(P) while true do - YIELD() + yield() P.endCounter=P.endCounter+1 if P.endCounter<40 then --Make field visible @@ -1558,7 +1558,7 @@ local function tick_finish(P) end local function tick_lose(P) while true do - YIELD() + yield() P.endCounter=P.endCounter+1 if P.endCounter<40 then --Make field visible @@ -1591,7 +1591,7 @@ end function tick_autoPause() local time=0 while true do - YIELD() + yield() time=time+1 if SCN.cur~="play"or GAME.frame<180 then return diff --git a/parts/player/prepareSequence.lua b/parts/player/prepareSequence.lua index c224bb80..b44283d6 100644 --- a/parts/player/prepareSequence.lua +++ b/parts/player/prepareSequence.lua @@ -1,132 +1,130 @@ local rnd=math.random local ins,rem=table.insert,table.remove +local yield=coroutine.yield -local freshMethod -local freshPrepare={ - rnd=function(P) - local bag=P.gameEnv.bag - P:getNext(bag[rnd(#bag)]) - freshMethod.rnd(P) - end, - fixed=function(P) - local bag=P.gameEnv.bag - local L=#bag - for i=1,L do - P.seqData[i]=bag[L+1-i] - end - while #P.nextQueue<6 do - if P.seqData[1]then - P:getNext(rem(P.seqData)) - else - break +local sequenceModes={ + none=function() while true do yield()end end, + bag=function(P,seq0) + local len=#seq0 + local bag={} + while true do + while #P.nextQueue<6 do + if #bag==0 then + for i=1,len do + bag[i]=seq0[len-i+1] + end + end + P:getNext(rem(bag,rnd(#bag))) end + yield() end end, -} -freshMethod={ - none=NULL, - bag=function(P) - local bag=P.seqData - while #P.nextQueue<6 do - if #bag==0 then--Copy a new bag - local bag0=P.gameEnv.bag - for i=1,#bag0 do bag[i]=bag0[i]end - end - P:getNext(rem(bag,P:RND(#bag))) - end - end, - his4=function(P) - while #P.nextQueue<6 do - local bag=P.gameEnv.bag - local L=#bag - for n=1,4 do - local j,i=0 - repeat - i=bag[P:RND(L)] - j=j+1 - until i~=P.seqData[1]and i~=P.seqData[2]and i~=P.seqData[3]and i~=P.seqData[4]or j==4 - P.seqData[n]=i - P:getNext(i) - end - end - end, - rnd=function(P) - while #P.nextQueue<6 do - local bag=P.gameEnv.bag - local L=#bag - for i=1,4 do - local count=0 - repeat - i=bag[P:RND(L)] - count=count+1 - until i~=P.nextQueue[#P.nextQueue].id or count>=L - P:getNext(i) - end - end - end, - reverb=function(P) - local seq=P.seqData - while #P.nextQueue<6 do - if #seq==0 then - local bag0=P.gameEnv.bag - for i=1,#bag0 do seq[i]=bag0[i]end - local bag={} - repeat - local r=rem(seq,P:RND(#bag)) - local p=1 + his4=function(P,seq0) + local len=#seq0 + while true do + while #P.nextQueue<6 do + for n=1,4 do + local j,i=0 repeat - ins(bag,r) - p=p-.15-P:RND() - until p<0 - until #seq==0 - for i=1,#bag do - seq[i]=bag[i] + i=seq0[P:RND(len)] + j=j+1 + until i~=seq0[1]and i~=seq0[2]and i~=seq0[3]and i~=seq0[4]or j==4 + seq0[n]=i + P:getNext(i) end end - P:getNext(rem(seq)) + yield() end end, - loop=function(P) - while #P.nextQueue<6 do - if #P.seqData==0 then - local bag=P.gameEnv.bag - local L=#bag - for i=1,L do - P.seqData[i]=bag[L+1-i] + rnd=function(P,seq0) + P:getNext(seq0[rnd(#seq0)]) + while true do + while #P.nextQueue<6 do + local len=#seq0 + for i=1,4 do + local count=0 + repeat + i=seq0[P:RND(len)] + count=count+1 + until i~=P.nextQueue[#P.nextQueue].id or count>=len + P:getNext(i) end end - P:getNext(rem(P.seqData)) + yield() end end, - fixed=function(P) - while #P.nextQueue<6 do - if P.seqData[1]then - P:getNext(rem(P.seqData)) - else - if not(P.cur or P.holdQueue[1])then P:lose(true)end - return + reverb=function(P,seq0) + local bufferSeq,bag={},{} + while true do + while #P.nextQueue<6 do + if #bag==0 then + for i=1,#seq0 do bufferSeq[i]=seq0[i]end + repeat + local r=rem(bufferSeq,P:RND(#bag)) + local p=1 + repeat + ins(bag,r) + p=p-.15-P:RND() + until p<0 + until #bufferSeq==0 + for i=1,#bag do + bufferSeq[i]=bag[i] + end + end + P:getNext(rem(bag,rnd(#bag))) end + yield() + end + end, + loop=function(P,seq0) + local len=#seq0 + local bag={} + while true do + while #P.nextQueue<6 do + if #bag==0 then + for i=1,len do + bag[i]=seq0[len-i+1] + end + end + P:getNext(rem(bag)) + end + yield() + end + end, + fixed=function(P,seq0) + local seq={} + for i=#seq0,1,-1 do + ins(seq,seq0[i]) + end + while true do + while #P.nextQueue<6 do + if not(seq[1]or P.cur or P.holdQueue[1])then + P:lose(true) + break + end + P:getNext(rem(seq)) + end + yield() end end, } -local function prepareSequence(P)--Call freshPrepare and set newNext +return function(P)--Set newNext funtion for player P local ENV=P.gameEnv + ::tryAgain:: if type(ENV.sequence)=="string"then - P.newNext=freshMethod[ENV.sequence] - if freshPrepare[ENV.sequence]then - freshPrepare[ENV.sequence](P) + if sequenceModes[ENV.sequence]then + P.newNext=coroutine.create(sequenceModes[ENV.sequence]) else - P:newNext() - end - else - if type(ENV.freshMethod)=="function"then - if ENV.sequence then ENV.sequence(P)end - P.newNext=ENV.freshMethod - else - LOG.print("Wrong sequence generator code","warn") + LOG.print("No sequence mode called "..ENV.sequence,"warn") ENV.sequence="bag" - prepareSequence(P) + goto tryAgain end + elseif type(ENV.sequence)=="function"then + P.newNext=coroutine.create(ENV.sequence) + else + LOG.print("Wrong sequence generator","warn") + ENV.sequence="bag" + goto tryAgain end -end -return prepareSequence \ No newline at end of file + assert(coroutine.resume(P.newNext,P,ENV.seqData)) +end \ No newline at end of file