local game={} game.__index=game local sounds=require"sounds" local gemtypes=require"gemtypes" local gem_type_max=#gemtypes function game:new(w,h) local obj=setmetatable({ w=w,h=h, gem_tc=3, board={}, falling={}, tofall={}, fpcache={}, pfx={}, dbg={}, toenerg=0, batt={display=1,real=1}, grabs={}, },self) for x=1,w do for y=1,h do self:spawn_gem(x) end end return obj end function game:pti(x,y) return y+(x-1)*self.h end function game:get(x,y) if not self.board[x] then return end return self.board[x][y] end local function eqgem(a,b) if not a or not b then return end return a.t==b.t end local scandirs={ {-1,0,1},{1,0,1}, {0,-1,2},{0,1,2} } local function scanrows(hot,get,o) local rows={} local seen={} for _,pos in pairs(hot) do local row={hot=pos} local gem = get(o,x,y) local i=pti(x,y) if not seen[i] then seen[i]=true for _,dir in pairs(scandirs) do local axis=dirs[3] row[axis]=row[axis] or {} local off=0 local ox,oy=x,y repeat off=off+1 ox=ox+dir[1]*off oy=oy+dir[2]*off seen[pti(ox,oy)]=true until not eqgem(gem,get(o,ox,oy)) row[axis][dir[axis]*0.5+1.5]=pos[axis]+(off-1)*dir[axis] end end for _,axis in ipairs(row) do axis[3]=axis[2]-axis[1]+1 end rows[row]=true end local finrows={} for row,_ in pairs(rows) do local mar=0 for i,axis in ipairs(row) do mar=math.max(mar,axis[3]) row[i]=axis[3]>=3 and axis end row.mar=mar if mar<3 then rows[row]=nil end end return rows end function game:init_fpcache(x) if self.fpcache[x] then return end local falls={} local dead={} for fall,_ in pairs(self.falling) do if not fall.die then falls[#falls+1]=fall else dead[fall]=true end end table.sort(falls,function(a,b) return a.y=y and miy-#fall.gems0 then local fall={y=0,vel=0,gems={}} self.falling[x][fall]=true self.fpcache[x]=nil self:init_fpcache(x) end local i=#topfall.gems+1 local gtc=math.floor(self.gem_tc) local infgem=math.random(1,gtc) local fgem=infgem repeat fgem=(fgem)%gtc+1 topfall.gems[i]=fgem until fgem==infgem or not next(scanrows({{x,y}},self.get_fall_predict,o)) end function game:kill(posl) local kc=0 for _,pos in pairs(posl) do self.board[pos.x][pos.y]=nil self.tofall[pos.x]=math.min(self.tofall[pos.x] or self.h,pos.y) kc=kc+1 end end function game:check(hot,swaps) local rows=scanrows(hot,get,self) local for row,_ in pairs(rows) do end end function game:grab(id,x,y) grabs[id]={ pos={x,y}, ipos={math.floor(x+.5),math.floor(y+.5)}, off={0,0}, } end function game:grabmove(id,x,y) local g=grabs[id] if not grabs[id] then return end local dx,dy=x-g.pos[1],y-g.pos[2] if math.abs(dx)>math.abs(dy) then dy=0 else dx=0 end dx=math.min(1,math.max(-1,math.floor(dx+.5))) dy=math.min(1,math.max(-1,math.floor(dy+.5))) off[1],off[2]=dx,dy end function game:ungrab(id,x,y) end function game:update(dt) dt=math.min(dt,0.2) end