local ins,rem=table.insert,table.remove local ceil=math.ceil local yield=YIELD local seqGenerators={ none=function()while true do yield()end end, bag=function(P,seq0) local rndGen=P.seqRND 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,rndGen:random(#bag))) end yield() end end, his=function(P,seq0) local rndGen=P.seqRND local len=#seq0 local hisLen=ceil(len*.5) local history=TABLE.new(0,hisLen) while true do while #P.nextQueue<6 do local r for _=1,hisLen do--Reroll up to [hisLen] times r=rndGen:random(len) for i=1,hisLen do if r==history[i]then goto CONTINUE_rollAgain end end do break end ::CONTINUE_rollAgain:: end if history[1]~=0 then P:getNext(r)end rem(history,1)ins(history,r) end yield() end end, hisPool=function(P,seq0) local rndGen=P.seqRND local len=#seq0 local hisLen=ceil(len*.5) local history=TABLE.new(0,hisLen)--Indexes of mino-index local poolLen=5*len local droughtTimes=TABLE.new(len,len)--Drought times of seq0 local pool={}for i=1,len do for _=1,5 do ins(pool,i)end end--5 times indexes of seq0 local function poolPick() local r=rndGen:random(poolLen) local res=pool[r] --Find droughtest(s) minoes local droughtList={1}--Droughtst minoes' indexes of seq0 local maxTime=droughtTimes[1] for i=2,len do if droughtTimes[i]>maxTime then maxTime=droughtTimes[i] if #droughtList==1 then droughtList[1]=i else droughtList={i}end elseif droughtTimes[i]==maxTime then ins(droughtList,i) end end --Update droughtTimes for i=1,len do droughtTimes[i]=droughtTimes[i]+1 end droughtTimes[res]=0 --Update pool -- print("Rem "..res) pool[r]=droughtList[rndGen:random(#droughtList)] -- print("Add "..pool[r]) return res end while true do while #P.nextQueue<6 do -- print"======================" --Pick a mino from pool local tryTime=0 ::REPEAT_pickAgain:: local 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 end weight[maxK]=weight[maxK]/3.5 P:getNext(seq0[maxK]) end yield() end end, rnd=function(P,seq0) if #seq0==1 then local i=seq0[1] while true do P:getNext(i)yield()end else local rndGen=P.seqRND local len=#seq0 local last=0 while true do while #P.nextQueue<6 do local r=rndGen:random(len-1) if r>=last then r=r+1 end P:getNext(seq0[r]) last=r end yield() end end end, mess=function(P,seq0) local rndGen=P.seqRND while true do while #P.nextQueue<6 do P:getNext(seq0[rndGen:random(#seq0)]) end yield() end end, reverb=function(P,seq0) local rndGen=P.seqRND 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,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 end P:getNext(rem(bag,rndGen:random(#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 seq[1]then P:getNext(rem(seq)) else if not(P.cur or P.nextQueue[1]or P.holdQueue[1])then P:lose(true) end break end end yield() end end, } return function(P)--Return a piece-generating function for player P local s=P.gameEnv.sequence if type(s)=='function'then return s elseif type(s)=='string'and seqGenerators[s]then return seqGenerators[s] else MES.new( type(s)=='string'and "No sequence mode called "..s or "Wrong sequence generator", 'warn') P.gameEnv.sequence='bag' return seqGenerators.bag end end