local ins,rem=table.insert,table.remove local yield=coroutine.yield local seqGenerators={ none=function() end, bag=function(rndGen,seq0) local len=#seq0 local bag={} while true do if #bag==0 then yield(nil) for i=1,len do bag[i]=seq0[len-i+1] end end yield(rem(bag,rndGen:random(#bag))) end end, bagES=function(rndGen,seq0) local len=#seq0 local bag=TABLE.shift(seq0) do-- Get a good first-bag -- Shuffle for i=1,len-1 do ins(bag,rem(bag,rndGen:random(len-i+1))) end -- Skip Uncomfortable minoes for _=1,len-1 do if bag[1]==1 or bag[1]==2 or bag[1]==6 or bag[1]==8 or bag[1]==9 or bag[1]==12 or bag[1]==13 or bag[1]==17 or bag[1]==18 or bag[1]==23 or bag[1]==24 then ins(bag,rem(bag,1)) else break end end -- Finish yield(nil) for i=1,len do yield(bag[i]) end end bag={} while true do if #bag==0 then yield(nil) for i=1,len do bag[i]=seq0[len-i+1] end end yield(rem(bag,rndGen:random(#bag))) end end, his=function(rndGen,seq0) local len=#seq0 local hisLen=math.ceil(len*.5) local history=TABLE.new(0,hisLen) while true 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 end if not rollAgain then break end -- ::CONTINUE_rollAgain:: end if history[1]~=0 then yield(seq0[r]) end rem(history,1) ins(history,r) end end, hisPool=function(rndGen,seq0) local len=#seq0 local hisLen=math.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 -- 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 end weight[maxK]=weight[maxK]/3.5 yield(seq0[maxK]) end end, rnd=function(rndGen,seq0) if #seq0==1 then local i=seq0[1] while true do yield(i) end else local len=#seq0 local last=0 while true do local r=rndGen:random(len-1) if r>=last then r=r+1 end yield(seq0[r]) last=r end end end, mess=function(rndGen,seq0) while true do yield(seq0[rndGen:random(#seq0)]) end end, reverb=function(rndGen,seq0) local bufferSeq,bag={},{} while true do if #bag==0 then yield(nil) 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 yield(rem(bag,rndGen:random(#bag))) end end, loop=function(rndGen,seq0) local len=#seq0 local bag={} while true do if #bag==0 then yield(nil) for i=1,len do bag[i]=seq0[len-i+1] end end yield(rem(bag)) end end, fixed=function(rndGen,seq0) for i=1,#seq0 do yield(seq0[i]) end end, bagP1inf=function(rndGen,seq0) local len=#seq0 local function new() local res={} local higher=nil local higher_dist={} for i=1,len do higher_dist[i]=1 end local remaining=len+1 local unknown={} local extra=-1 local function init() yield(nil) for i=1,len do unknown[i]=1 end remaining=len+1 extra=-1 end init() function res.next_dist() if extra>=0 then return remaining,unknown end local temp={} local temp_sum=0 for i=1,len do local item=higher_dist[i]*(2-unknown[i]) temp[i]=item temp_sum=temp_sum+item end local sum=0 for i=1,len do temp[i]=temp[i]+temp_sum*unknown[i] sum=sum+temp[i] end return sum,temp end function res.update(i) if unknown[i]==0 then assert(extra<0,"extra should be -1") extra=i else unknown[i]=0 end remaining=remaining-1 if remaining>0 then return end if higher==nil then higher=new() end higher.update(extra) local _ _,higher_dist=higher.next_dist() init() end return res end local dist=new() while true do local sum,mydist=dist.next_dist() local r=rndGen:random(sum) for i=1,len do r=r-mydist[i] if r<=0 then yield(seq0[i]) dist.update(i) break end end end end, } 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 return seqGenerators[s] else MES.new('warn', type(s)=='string' and "No sequence mode called "..s or "Wrong sequence generator" ) return seqGenerators.bag,true end end