From b7b02ab5bcf33f92d983d747a3d4a566d7dd5311 Mon Sep 17 00:00:00 2001 From: Imple Lee <80144331+ImpleLee@users.noreply.github.com> Date: Tue, 11 Jul 2023 19:50:52 +0800 Subject: [PATCH 1/4] simplify sequence generator --- parts/bot/bot_cc.lua | 2 +- parts/modes/drought_l.lua | 125 +++++++++--------- parts/player/init.lua | 38 ++++-- parts/player/player.lua | 2 +- parts/player/seqGenerators.lua | 229 +++++++++++++-------------------- 5 files changed, 183 insertions(+), 213 deletions(-) diff --git a/parts/bot/bot_cc.lua b/parts/bot/bot_cc.lua index df694f85..bc4e4ede 100644 --- a/parts/bot/bot_cc.lua +++ b/parts/bot/bot_cc.lua @@ -43,8 +43,8 @@ function bot_cc:revive() self.P:loadAI(self.data) end function bot_cc:pushNewNext(id) - self.ccBot:addNext(rem(self.bufferedNexts,1)) ins(self.bufferedNexts,id) + self.ccBot:addNext(rem(self.bufferedNexts,1)) end function bot_cc:thread() local P,keys=self.P,self.keys diff --git a/parts/modes/drought_l.lua b/parts/modes/drought_l.lua index 515bd92d..618184a3 100644 --- a/parts/modes/drought_l.lua +++ b/parts/modes/drought_l.lua @@ -1,75 +1,74 @@ local ins=table.insert +local yield=coroutine.yield return { env={ drop=20,lock=60, - sequence=function(P) - for _=1,3 do P:getNext(7) end + sequence=function(seqRND) + local field,stat + for _=1,3 do field,stat=yield(7) end while true do - coroutine.yield() - if not P.nextQueue[1] then - local height=TABLE.new(0,10) - 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 + local height=TABLE.new(0,10) + local max=#field + if max>0 then + -- Get heights + for x=1,10 do + local h=max + while field[h][x]==0 and h>1 do + h=h-1 end + height[x]=h end - height[11]=999 - - local wei={1,1,2,2,3,4} - local d=0 - for i=1,10 do - d=d+height[i] + else + for x=1,10 do + height[x]=0 end - if d<40 or P.stat.row>2*42 then-- Low field or almost win, give SZO - for _=1,4 do - ins(wei,1) - ins(wei,2) - ins(wei,6) - end - else - -- Give I when no hole - local tempDeltaHei=-999-- Height difference - for x=2,11 do - local deltaHei=height[x]-height[x-1] - if tempDeltaHei<-2 and deltaHei>2 then - break - elseif x==11 then - for _=1,3 do ins(wei,7) end - else - tempDeltaHei=deltaHei - end - end - - -- Give O when no d=0/give T when no d=1 - local flatCount=0-- d=0 count - local stairCount=0-- d=1 count - for x=2,10 do - local _=height[x]-height[x-1] - if _==0 then - flatCount=flatCount+1 - elseif _==1 or _==-1 then - stairCount=stairCount+1 - end - end - if flatCount<3 then - for _=1,3 do ins(wei,6) end - end - if stairCount<3 then - for _=1,4 do ins(wei,5) end - end - end - P:getNext(wei[P.seqRND:random(#wei)]) end + height[11]=999 + + local wei={1,1,2,2,3,4} + local d=0 + for i=1,10 do + d=d+height[i] + end + if d<40 or stat.row>2*42 then-- Low field or almost win, give SZO + for _=1,4 do + ins(wei,1) + ins(wei,2) + ins(wei,6) + end + else + -- Give I when no hole + local tempDeltaHei=-999-- Height difference + for x=2,11 do + local deltaHei=height[x]-height[x-1] + if tempDeltaHei<-2 and deltaHei>2 then + break + elseif x==11 then + for _=1,3 do ins(wei,7) end + else + tempDeltaHei=deltaHei + end + end + + -- Give O when no d=0/give T when no d=1 + local flatCount=0-- d=0 count + local stairCount=0-- d=1 count + for x=2,10 do + local _=height[x]-height[x-1] + if _==0 then + flatCount=flatCount+1 + elseif _==1 or _==-1 then + stairCount=stairCount+1 + end + end + if flatCount<3 then + for _=1,3 do ins(wei,6) end + end + if stairCount<3 then + for _=1,4 do ins(wei,5) end + end + end + field,stat=yield(wei[seqRND:random(#wei)]) end end, nextCount=1,holdCount=0, diff --git a/parts/player/init.lua b/parts/player/init.lua index 50e15a39..604747f6 100644 --- a/parts/player/init.lua +++ b/parts/player/init.lua @@ -328,19 +328,37 @@ local function _applyGameEnv(P)-- Finish gameEnv processing ENV.nextPos=false end - P.newNext=coroutine.wrap(getSeqGen(P)) - P:newNext(P.gameEnv.seqData) - if ENV.noInitSZO then - for _=1,5 do - local C=P.nextQueue[1] - if C and (C.id==1 or C.id==2 or C.id==6) then - table.remove(P.nextQueue,1) - else - break - end + local seqGen=coroutine.create(getSeqGen(P)) + local seqCalled=false + function P:newNext() + local status,piece + if seqCalled then + status,piece=coroutine.resume(seqGen,P.field,P.stat) + else + status,piece=coroutine.resume(seqGen,P.seqRND,P.gameEnv.seqData) end + seqCalled=true + if status and piece then + P:getNext(piece) + elseif not status then + assert(piece=='cannot resume dead coroutine') + end + end + for _=1,ENV.nextCount do P:newNext() end + -- TODO: make noInitSZO work + -- if ENV.noInitSZO then + -- for _=1,5 do + -- local C=P.nextQueue[1] + -- if C and (C.id==1 or C.id==2 or C.id==6) then + -- table.remove(P.nextQueue,1) + -- else + -- break + -- end + -- end + -- P:newNext() + -- end if P.miniMode then ENV.lockFX=false diff --git a/parts/player/player.lua b/parts/player/player.lua index 40380251..2a9e3157 100644 --- a/parts/player/player.lua +++ b/parts/player/player.lua @@ -1433,7 +1433,7 @@ function Player:popNext(ifhold)-- Pop nextQueue to hand if self.nextQueue[1] then self.cur=rem(self.nextQueue,1) - self.newNext() + self:newNext() self.pieceCount=self.pieceCount+1 local pressing=self.keyPressing diff --git a/parts/player/seqGenerators.lua b/parts/player/seqGenerators.lua index 0de68d8f..2f6022dd 100644 --- a/parts/player/seqGenerators.lua +++ b/parts/player/seqGenerators.lua @@ -3,24 +3,19 @@ local yield=coroutine.yield local seqGenerators={ none=function() while true do yield() end end, - bag=function(P,seq0) - local rndGen=P.seqRND + bag=function(rndGen,seq0) local len=#seq0 local bag={} while true do - while #P.nextQueue<10 do - if #bag==0 then - for i=1,len do - bag[i]=seq0[len-i+1] - end + if #bag==0 then + for i=1,len do + bag[i]=seq0[len-i+1] end - P:getNext(rem(bag,rndGen:random(#bag))) end - yield() + yield(rem(bag,rndGen:random(#bag))) end end, - bagES=function(P,seq0) - local rndGen=P.seqRND + bagES=function(rndGen,seq0) local len=#seq0 local bag=TABLE.shift(seq0) do-- Get a good first-bag @@ -40,52 +35,44 @@ local seqGenerators={ end end -- Finish - for i=1,len do P:getNext(bag[i]) end + for i=1,len do yield(bag[i]) end end bag={} while true do - while #P.nextQueue<10 do - if #bag==0 then - for i=1,len do - bag[i]=seq0[len-i+1] - end + if #bag==0 then + for i=1,len do + bag[i]=seq0[len-i+1] end - P:getNext(rem(bag,rndGen:random(#bag))) end - yield() + yield(rem(bag,rndGen:random(#bag))) end end, - his=function(P,seq0) - local rndGen=P.seqRND + his=function(rndGen,seq0) local len=#seq0 local hisLen=math.ceil(len*.5) local history=TABLE.new(0,hisLen) while true do - while #P.nextQueue<10 do - local r - for _=1,hisLen do-- Reroll up to [hisLen] times - r=rndGen:random(len) - local rollAgain - for i=1,hisLen do - if r==history[i] then - rollAgain=true - break-- goto CONTINUE_rollAgain - end + local r + for _=1,hisLen do-- Reroll up to [hisLen] times + r=rndGen:random(len) + local rollAgain + for i=1,hisLen do + if r==history[i] then + rollAgain=true + break-- goto CONTINUE_rollAgain end - if not rollAgain then break end - -- ::CONTINUE_rollAgain:: end - if history[1]~=0 then - P:getNext(seq0[r]) - end - rem(history,1) - ins(history,r) + if not rollAgain then break end + -- ::CONTINUE_rollAgain:: end - yield() + if history[1]~=0 then + yield(seq0[r]) + end + rem(history,1) + ins(history,r) end end, - hisPool=function(P,seq0) - local rndGen=P.seqRND + hisPool=function(rndGen,seq0) local len=#seq0 local hisLen=math.ceil(len*.5) local history=TABLE.new(0,hisLen)-- Indexes of mino-index @@ -126,147 +113,113 @@ local seqGenerators={ end while true do - while #P.nextQueue<10 do - -- print"======================" - -- Pick a mino from pool - local tryTime=0 - local r - repeat-- ::REPEAT_pickAgain:: - local pickAgain - r=_poolPick()-- Random mino-index in pool - for i=1,len do - if r==history[i] then - tryTime=tryTime+1 - if tryTimeweight[maxK] then - maxK=i - end + local maxK=1 + for i=1,len do + weight[i]=weight[i]*.5+rndGen:random() + if weight[i]>weight[maxK] then + maxK=i end - weight[maxK]=weight[maxK]/3.5 - P:getNext(seq0[maxK]) end - yield() + weight[maxK]=weight[maxK]/3.5 + yield(seq0[maxK]) end end, - rnd=function(P,seq0) + rnd=function(rndGen,seq0) if #seq0==1 then local i=seq0[1] while true do - while #P.nextQueue<10 do P:getNext(i) end - yield() + yield(i) end else - local rndGen=P.seqRND local len=#seq0 local last=0 while true do - while #P.nextQueue<10 do - local r=rndGen:random(len-1) - if r>=last then - r=r+1 - end - P:getNext(seq0[r]) - last=r + local r=rndGen:random(len-1) + if r>=last then + r=r+1 end - yield() + yield(seq0[r]) + last=r end end end, - mess=function(P,seq0) - local rndGen=P.seqRND + mess=function(rndGen,seq0) while true do - while #P.nextQueue<10 do - P:getNext(seq0[rndGen:random(#seq0)]) - end - yield() + yield(seq0[rndGen:random(#seq0)]) end end, - reverb=function(P,seq0) - local rndGen=P.seqRND + reverb=function(rndGen,seq0) local bufferSeq,bag={},{} while true do - while #P.nextQueue<10 do - if #bag==0 then - for i=1,#seq0 do bufferSeq[i]=seq0[i] end + if #bag==0 then + for i=1,#seq0 do bufferSeq[i]=seq0[i] end + repeat + local r=rem(bufferSeq,rndGen:random(#bag)) + local p=1 repeat - local r=rem(bufferSeq,rndGen:random(#bag)) - local p=1 - repeat - ins(bag,r) - p=p-.15-rndGen:random() - until p<0 - until #bufferSeq==0 - for i=1,#bag do - bufferSeq[i]=bag[i] - end + ins(bag,r) + p=p-.15-rndGen:random() + until p<0 + until #bufferSeq==0 + for i=1,#bag do + bufferSeq[i]=bag[i] end - P:getNext(rem(bag,rndGen:random(#bag))) end - yield() + yield(rem(bag,rndGen:random(#bag))) end end, - loop=function(P,seq0) + loop=function(rndGen,seq0) local len=#seq0 local bag={} while true do - while #P.nextQueue<10 do - if #bag==0 then - for i=1,len do - bag[i]=seq0[len-i+1] - end + if #bag==0 then + for i=1,len do + bag[i]=seq0[len-i+1] end - P:getNext(rem(bag)) end - yield() + yield(rem(bag)) end end, - fixed=function(P,seq0) - local seq={} + fixed=function(rndGen,seq0) for i=#seq0,1,-1 do - ins(seq,seq0[i]) - end - while true do - while #P.nextQueue<10 do - if seq[1] then - P:getNext(rem(seq)) - else - break - end - end - yield() + yield(seq0[i]) end end, } From c25e7a3d5bf03f73e7c5eaab6ce352a074e47257 Mon Sep 17 00:00:00 2001 From: Imple Lee <80144331+ImpleLee@users.noreply.github.com> Date: Tue, 11 Jul 2023 20:05:31 +0800 Subject: [PATCH 2/4] fix noInitSZO --- parts/player/init.lua | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/parts/player/init.lua b/parts/player/init.lua index 604747f6..1108b400 100644 --- a/parts/player/init.lua +++ b/parts/player/init.lua @@ -330,15 +330,24 @@ local function _applyGameEnv(P)-- Finish gameEnv processing local seqGen=coroutine.create(getSeqGen(P)) local seqCalled=false + local initSZOcount=0 function P:newNext() local status,piece if seqCalled then status,piece=coroutine.resume(seqGen,P.field,P.stat) else status,piece=coroutine.resume(seqGen,P.seqRND,P.gameEnv.seqData) + seqCalled=true end - seqCalled=true if status and piece then + if ENV.noInitSZO and initSZOcount<5 then + initSZOcount=initSZOcount+1 + if piece==1 or piece==2 or piece==6 then + return self:newNext() + else + initSZOcount=5 + end + end P:getNext(piece) elseif not status then assert(piece=='cannot resume dead coroutine') @@ -347,18 +356,6 @@ local function _applyGameEnv(P)-- Finish gameEnv processing for _=1,ENV.nextCount do P:newNext() end - -- TODO: make noInitSZO work - -- if ENV.noInitSZO then - -- for _=1,5 do - -- local C=P.nextQueue[1] - -- if C and (C.id==1 or C.id==2 or C.id==6) then - -- table.remove(P.nextQueue,1) - -- else - -- break - -- end - -- end - -- P:newNext() - -- end if P.miniMode then ENV.lockFX=false From 8304cf655b3d0bb6323d6dbfd94d5247d56d4a17 Mon Sep 17 00:00:00 2001 From: Imple Lee <80144331+ImpleLee@users.noreply.github.com> Date: Wed, 12 Jul 2023 07:27:22 +0800 Subject: [PATCH 3/4] make sequence generator independent of player --- parts/player/init.lua | 2 +- parts/player/seqGenerators.lua | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/parts/player/init.lua b/parts/player/init.lua index 1108b400..063abb6b 100644 --- a/parts/player/init.lua +++ b/parts/player/init.lua @@ -328,7 +328,7 @@ local function _applyGameEnv(P)-- Finish gameEnv processing ENV.nextPos=false end - local seqGen=coroutine.create(getSeqGen(P)) + local seqGen=coroutine.create(getSeqGen(ENV.sequence)) local seqCalled=false local initSZOcount=0 function P:newNext() diff --git a/parts/player/seqGenerators.lua b/parts/player/seqGenerators.lua index 2f6022dd..30359d6d 100644 --- a/parts/player/seqGenerators.lua +++ b/parts/player/seqGenerators.lua @@ -223,8 +223,7 @@ local seqGenerators={ end end, } -return function(P)-- Return a piece-generating function for player P - local s=P.gameEnv.sequence +return function(s)-- Return a piece-generating function for player P if type(s)=='function' then return s elseif type(s)=='string' and seqGenerators[s] then @@ -235,7 +234,6 @@ return function(P)-- Return a piece-generating function for player P "No sequence mode called "..s or "Wrong sequence generator" ) - P.gameEnv.sequence='bag' return seqGenerators.bag end end From 7e00a7d764a910024bd8f62f28aa934b4c655f87 Mon Sep 17 00:00:00 2001 From: Imple Lee <80144331+ImpleLee@users.noreply.github.com> Date: Wed, 12 Jul 2023 07:42:50 +0800 Subject: [PATCH 4/4] use `trueNextCount` as replay-visible next count --- parts/modes/drought_l.lua | 2 +- parts/player/gameEnv0.lua | 2 +- parts/player/init.lua | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/parts/modes/drought_l.lua b/parts/modes/drought_l.lua index 618184a3..e1a3b50e 100644 --- a/parts/modes/drought_l.lua +++ b/parts/modes/drought_l.lua @@ -71,7 +71,7 @@ return { field,stat=yield(wei[seqRND:random(#wei)]) end end, - nextCount=1,holdCount=0, + trueNextCount=1,nextCount=1,holdCount=0, ospin=false, freshLimit=15, eventSet='checkLine_100', diff --git a/parts/player/gameEnv0.lua b/parts/player/gameEnv0.lua index 81fac4e1..85fef2dc 100644 --- a/parts/player/gameEnv0.lua +++ b/parts/player/gameEnv0.lua @@ -33,7 +33,7 @@ return { bone=false, lockout=false, fieldH=20,heightLimit=1e99, - nextCount=6,nextStartPos=1, + trueNextCount=10,nextCount=6,nextStartPos=1, holdMode='hold',holdCount=1, infHold=false,phyHold=false, ospin=true,deepDrop=false, diff --git a/parts/player/init.lua b/parts/player/init.lua index 063abb6b..37af538b 100644 --- a/parts/player/init.lua +++ b/parts/player/init.lua @@ -353,7 +353,7 @@ local function _applyGameEnv(P)-- Finish gameEnv processing assert(piece=='cannot resume dead coroutine') end end - for _=1,ENV.nextCount do + for _=1,ENV.trueNextCount do P:newNext() end