
local _config = {
  max_rafts = 3,
  prob_rafts = 0.3, -- /100
  
  max_birds = 10,
  prob_birds = 0.3, -- /100
  
  max_moai = 3,
  prob_moai = 1, -- multiplicator
}

if config then
  for k,v in pairs(_config) do
    if not config[k] then
      config[k] = v
    end
  end
else
  config = _config
end

local scrw, scrh = srfsize()
local bots, birds, smoke, moai = {}, {}, {}, {}
local rpls, wavs = {}, {}

local drk, lit, nrm = {}, {}, {}

function _init()
  spritesheet("sheet")
  
  target("sheet")
  clipboard(expsrf());
  target()
  
  init_window()
  
  for i=0,15 do
    drk[i] = sget(i, 6)
    lit[i] = sget(i, 4)
    nrm[i] = i
  end

  pal()

  winda = rnd(1)
  nwinda = winda
  
  new_player(32,32)
  
  cls(16)
  
  sugar_step()
end

local ff
function _update()
  dt = delta()
  
  pal()
  fillp()
  clip()
  
  if btn(0) and btnp(5) then dbg = not dbg end

  if chance(1) then
    nwinda=rnd(1)
  end
  
  local dw=warp(nwinda,winda)
  if abs(dw)>0.1 then
    winda = winda-0.02*dw
  end

  if #bots < config.max_rafts and chance(config.prob_rafts) then
    new_bot()
  end
  
  if #birds < config.max_birds and chance(config.prob_birds) then
    new_birds()
  end
  
  if #moai < config.max_moai and chance(max(0.1-#moai*0.09, 0.001)*config.prob_moai) then
    new_moai()
  end

  upd_player(player)
  
  foreach(bots, upd_bot)
  foreach(birds, upd_bird)
  foreach(moai, upd_moai)
  foreach(smoke, upd_smoke)
  --foreach(sparkles, update_sparkle)
  
end

function _draw()

  cls(16)
  sprgrid(8,8)
  
  do -- water effects
    -- ripples from rafts
    local f1,f2 = 0xefbf,0xbfef
    --if time()%2<1 then
    --  f1,f2 = 0xefbf,0xbfef
    --else
    --  f2,f1 = 0xefbf,0xbfef
    --end
    
    for _,r in ipairs(rpls) do
      local rr=flr(min(r.l*.5+5,7))
      fillp(f1, true)
      circ(r.x,r.y,rr,3)
      fillp(f2, true)
      circ(r.x,r.y,rr,7)
    
      r.l=r.l+0.125
     
      if r.l+4>14 then
       del(rpls,r)
      end
    end
    fillp()
    
    -- waves + fish
    if chance(5) then
      local x=player.x+rnd(128)-64
      local y=player.y+rnd(128)-64
      local d=dist(x-player.x, y-player.y)
      if d < 64 then
        add(wavs,{l=0.2,x=x-4,y=y,w=sgn(got(1)),f=chance(5)})
      end
    end
    
    local tdel={}
    for i,w in ipairs(wavs) do
      if w.f then
        spr(flr(120+w.l-0.2),flr(w.x)+w.w*w.l,w.y,1,1,w.w<0)
        w.l=w.l+.15
      else
        spr(flr(104+w.l-0.2),w.x,w.y)
        w.l=w.l+.1
      end
      
      if w.l>=8 then add(tdel,i) end
    end
    
    for _,i in pairs(tdel) do
      deli(wavs,i)
    end
  
  end
  
  fillp()

  drw_chr(player)

  foreach(bots, drw_chr)
  
  pal(11,0)
  foreach(birds, drw_bird)
  pal(14,14)
  pal(6,6)
  
  foreach(moai, drw_moai)
  pal(11,11)
  
  fillp(0x5a5a,true)
  foreach(smoke, drw_smoke)
  fillp()
  
  if dbg then
    print(aft(),0,0,5)
  end
end


do -- init stuff
  function init_window()
    local minw = config.min_resolution or 300
    
    local xa,ya,xb,yb = winspec("display")
    local w,h = xb-xa, yb-ya
    local k = flr(min(w/minw, h/minw))
    
    local nw = ceil(w/k)
    local nh = ceil(h/k)
    
    winspec("wmode", "borderless")
    winspec("lay", xa-(w-nw*k)/2, ya-(h-nh*k)/2, nw*k, nh*k)
    winspec("screen", nw, nh)
    winspec("smode", "intscale")
    winspec("top", true)
    
    scrw, scrh = nw, nh
    
    winspec("title", "My Pet Explorer")
    
    winspec("trsp", 16, true)
    
    clip()
    target()
  end

end

do -- rafts
  local hair = {2,4,5,8,9,12,13,14,15}
  local skin = {15,4,5,6,7}
  local tunics = {14,13,12,2,3,9,10,11}
  
  function upd_player(s)
    local mx, my = btnv(6), btnv(7)
    local dx, dy = mx-s.x, my-s.y
    
    local d = dist(dx, dy)
    
    if s.stop then
      s.stop = s.stop - 0.0166
      if s.stop <= 0 then
        s.stop = nil
      end
    else
      if d > 64 then
        upd_chr(s, dx/d, dy/d)
      elseif d < 48 then
        upd_chr(s, -0.5*dx/d, -0.5*dy/d)
      else
        upd_chr(s, 0, 0)
      end
    end
    
    for _,b in pairs(bots) do
      if not b.talked then
        local sd = sqrdist(s.x-b.x, s.y-b.y)
        if sd < sqr(16) then
          b.talked = true
          b.stop = 10
          s.stop = 10
          b.vx, b.vy = 0,0
          s.vx, s.vy = 0,0
          s.fleft=s.x>b.x
          b.fleft=not s.fleft
        end
      end
    end
    
    make_rpls(s)
  end

  function upd_bot(s)
    s.dirt = s.dirt-delta()
    
    if s.dirt<0 then
      s.dir = s.dir + got(0.15)
      s.dir = s.dir%1
      s.dirt = 2+rnd(3)
    end
    
    if s.stop then
      s.stop = s.stop - 0.0166
      if s.stop <= 0 then
        s.stop = nil
      end
    else
      if s.dir >= 0 then
        upd_chr(s, 0.5*cos(s.dir), 0.5*sin(s.dir))
      else
        upd_chr(s, 0, 0)
      end
    end
    
    make_rpls(s)
    
    s.life = s.life + 0.0166
    if s.life > 15 and (s.x < -24 or s.y < -24 or s.x > scrw+24 or s.y > scrh+24) then
      del(bots, s)
    end
  end

  function upd_chr(s,accx,accy)
    local acc=0.05+(_dbg and 1 or 0)
    
    s.vx=s.vx+accx*acc
    s.vy=s.vy+accy*acc
    
    s.x = s.x + s.vx + 0.1*cos(winda)
    s.y = s.y + s.vy + 0.1*sin(winda)
    
    s.vx=s.vx*0.95
    s.vy=s.vy*0.95
    
    local ma=0.75+(_dbg and 40 or 0)
    local dv=dist(s.vx,s.vy)
    if dv>ma then
      s.vx = s.vx * ma/dv
      s.vy = s.vy * ma/dv
    end
    
    if abs(s.vx)>0.1 then
      s.fleft=s.vx<0
    end
  end
  
  function make_rpls(s)
    s.rdt=s.rdt-0.25
    if s.rdt<0 then
      add(rpls,{x=s.x,y=s.y,l=rnd(1)})
      s.rdt=2
    end
  end
  
  
  function drw_chr(s)
    drw_raft(s)
     
    draw_oanim(s.idle,s.x-6,s.y-6,time()+s.k,s.fleft,s.plt)

    all_colors_to()
  end

  function drw_sail(x,y,coa,sia,col,var)
    pal(14,col)
    pal(15,drk[col])
    
    local mx=(14+var)*8
    for i=30,1,-1 do
      local y=flr(y)+(i/4)
      local si=sin(i/60)
      local w=5-2*si
      local f=(6+2*cos(t()/2))*si
      
      local ax,ay = x-w*coa+f*sia, y-w*sia-f*coa
      local bx,by = x+w*coa+f*sia, y+w*sia-f*coa
      
      local my=i/4
      if ay<by then
        ax,ay,bx,by=bx,by,ax,ay
      end
      
      --pal(13,5)
      --tline(ax,ay+1,bx,by+1,mx,my,.5/w,0)
      --pal(13,13)
      --tline(ax,ay,bx,by,mx,my,.5/w,0)
      
      local d=dist(bx-ax,by-ay)
      for i=0,1,1/d do
        local x=lerp(ax,bx,i)
        local y=lerp(ay,by,i)
        local c=sget(mx+i*7.999,my)
        
        if c>0 then
          pal(13,5)
          pset(x,y-1,c)
          pal(13,13)
          pset(x,y,c)
        end
      end

    end
    
    pal(14,14)
    pal(15,15)
  end

  function drw_raft(s)
    local coa,sia = cos(winda+.25), 0.5*sin(winda+.25)
   
    spr(0x1e, s.x-8, s.y-4, 2, 1)
   
    if coa>=-0.1 then
     spr(0x0d, s.x-4, s.y-12, 1, 2)
    end
    
    drw_sail(flr(s.x), s.y-12, coa, sia, s.col, s.var)
   
    if coa<-0.1 then
     spr(0x0d, s.x-4, s.y-12, 1, 2)
    end
  end


  function new_player(x,y)
    local s={
      x=x,y=y,
      vx=0,
      vy=0,
      col=14,
      rdt=0,
      var=1,
      tc=14,
      hr=2,
      k=0,
      raftcol=14,
      idle="idle1",
      skn=rnd(skin),
      items={2},
      update=upd_player,
      draw=drw_chr,
      regs="to_update,to_draw2"
    }
   
    s.plt={[6]=s.skn,[2]=s.hr,[3]=lit[s.hr],[14]=s.tc}
   
    player = s
    --return register_object(s)
  end
  
  function new_bot()
    local x,y
    if chance(50) then
      x = rnd(scrw)
      y = -24 + irnd(2) * (scrh+48)
    else
      x = -24 + irnd(2) * (scrw+48)
      y = rnd(scrh)
    end
  
    local s={
      x=x,y=y,
      vx=0,vy=0,
      var=irnd(2),
      dir=-atan2(scrw/2-x, scrh/2-y)+got(0.1),
      dirt=0,
      idle=rnd{"idle1","idle2","idle3"},
      skn=rnd(skin),
      tone=irnd(20),
      k=rnd(999),
      rdt=0,
      life=0,
      
      update=upd_bot,
      draw=drw_chr,
      regs="to_update,to_draw2,bot"
    }
    
    repeat s.hr=rnd(hair) until s.hr~=s.skn
    
    s.tc = chance(25) and s.skn or rnd(tunics)
    s.col=s.tc
    
    s.plt={[6]=s.skn,[2]=s.hr,[3]=lit[s.hr],[14]=s.tc}
    
    add(bots, s)
    --return register_object(s)
  end

end

do -- birds
  local hair = {2,4,5,8,9,11,12,13,14,15}
  
  function upd_bird(s)
    local mx, my = btnv(6), btnv(7)
    local dx, dy = mx-s.x, my-s.y
    
    local d = sqrdist(dx, dy)
    
    if d < sqr(24) then
      s.vx = s.vx - 0.15 * sgn(dx) * (1-abs(dx)/24)
      s.vy = s.vy - 0.15 * sgn(dy) * (1-abs(dy)/24)
    end
    
    s.x = s.x + s.vx*0.5
    s.y = s.y + s.vy*0.5
    
    s.vx = lerp(s.vx, s.ovx, 0.01)
    s.vy = lerp(s.vy, s.ovy, 0.01)
    
    if s.x < -24 or s.y < -24 or s.x > scrw+24 or s.y > scrh+24 then
      if s.in_screen then
        del(birds, s)
      end
    else
      s.in_screen = true
    end
  end
  
  local frames = {0x53,0x52,0x51,0x50,0x52}
  function drw_bird(s)
    pal(14, s.col)
    pal(6, lit[s.col])
    spr(frames[flr(time()*20+s.k)%#frames+1], s.x-4, s.y-4, 1, 1, s.vx<0)
  end

  function new_birds()
    local x,y,vx,vy
    if chance(33) then
      x = rnd(scrw)
      y = scrh+24
      vx = -sgn(x-scrw/2)*1+got(0.5)
      vy = -2+got(0.5)
    else
      x = -24 + irnd(2) * (scrw+48)
      y = rnd(scrh)
      vx = -sgn(x-scrw/2)*2+got(0.5)
      vy = -1+got(1)
    end
    
    local col = rnd(hair)
    local k = chance(75) and (irnd(5)+1) or 1
    
    for i=1,k do
      local s = {
        x=x+got(16),
        y=y+got(16),
        vx = vx,
        vy = vy,
        ovx = vx,
        ovy = vy,
        col = col,
        k = rnd(999)
      }
      
      add(birds, s)
    end
  end
end

do -- moai

  function upd_moai(s)
    if s.leave then
      s.move = true
      s.burried = s.burried + 0.25
      if s.burried >= 32 then
        del(moai,s)
        return
      end
    elseif s.burried > 0 then
      s.burried = max(s.burried - 0.25, 0)
      s.move = true
    else
      s.move = false
    end
    
    local mx,my = btnv(6), btnv(7)
    if my > scrh-40 and my <= scrh and abs(s.x-mx) < 20 then
      s.x = s.x + 0.25 * sgn(s.x-mx)
      s.move = true
    end
    
    s.stay = s.stay - 0.01666
    if s.stay <= 0 then
      s.leave = true
    end
    
    if s.move then
      new_smoke(s.x+got(4), scrh)
    end
  end
  
  function drw_moai(s)
    local dx,dy = 0,0
    if s.move then
      dx,dy = got(1), rnd(1)
    end
    
    --sspr(s.sp*24, 64, 24, 32, s.x-24+dx, scrh-64+s.burried*2+dy, 48, 64)
    spr(0x80+s.sp*3, s.x-12+dx, scrh-32+s.burried+dy, 3, 4, s.flip)
  end

  function new_moai()
    local x = 16+rnd(scrw-32)
  
    local sp,b = irnd(4), #moai == 0 or #moai >= 4
    while not b do
      sp = irnd(4)
      b = true
      for _,o in pairs(moai) do
        b = b and sp ~= o.sp
      end
    end
    
    local s = {
      x = x,
      sp = sp,
      burried = 32,
      move = true,
      stay = 60 + rnd(240),
      flip = chance(50)
    }
    
    add(moai,s)
  end
end

do -- smoke
  local colors = {15, 4, 5}
  
  function upd_smoke(s)
    s.x = s.x + s.vx
    s.y = s.y + s.vy
    
    s.vx = lerp(s.vx, 0, 0.03)
    s.vy = lerp(s.vy, -0.2, 0.03)
    
    s.r = s.r - 0.05
    if s.r <= 0 then
      del(smoke, s)
    end
  end
  
  function drw_smoke(s)
    circfill(s.x, s.y, s.r, s.col)
  end

  function new_smoke(x,y)
    local a,spd=rnd(1),rnd(1)
    local s={
      x=x+got(8),
      y=y+got(4),
      vx=spd*cos(a),
      vy=spd*sin(a)*0.5,
      r=1+rnd(3),
      col = rnd(colors)
    }
    
    add(smoke, s)
  end
end

do -- anim stuff
  local anims={
   run={s=0x20,n=16,spd=20},
   idle0={spd=2, sprs={16,16,16,21}},
   idle1={spd=5, sprs={16,16,17,18,19,18,17,18,19,20}},
   idle2={spd=12, sprs={16,16,48,49,50,50,50,51,51,52,53,54,55,48,48,16}},
   idle3={spd=12, sprs={16,16,56,57,57,58,58,58,59,59,60,60,59,59,59,61,61,59,59,59,60,59,61,59,60,60,59,59,59,59,62,63,48,49}}
  }
  
  function draw_oanim(name,x,y,t,flip,plt)
   local nfo=anims[name]
   local s
   local t=t*nfo.spd
  
   if nfo.sprs then
    local n=flr(t%#nfo.sprs)
    s=nfo.sprs[n+1]
   else
    local n=t%nfo.n
    s=nfo.s+n
   end
   
   all_colors_to(0)
   spr(s,x-1,y,1,1,flip)
   spr(s,x+1,y,1,1,flip)
   spr(s,x,y-1,1,1,flip)
   spr(s,x,y+1,1,1,flip)
   all_colors_to()
   if plt then pal(plt) end
   spr(s,x,y,1,1,flip)
  end
end

do -- utilities

  function all_colors_to(c)
    for i=0,15 do
      pal(i,c or i)
    end
  end

  add = table.insert
  deli = table.remove
  function foreach(tab, foo) for _,v in pairs(tab) do foo(v) end end
  function del(tab, v) for i,w in pairs(tab) do if w==v then deli(tab,i) return end end end
  
  function invsqr(a) return 1-sqr(1-a) end
  function range(a,b,v) return (v-a)/(b-a) end
  function chance(a) return rnd(100)<a end
  function got(a) return rnd(a*2)-a end
  function lerp(a,b,i) return (1-i)*a+i*b end
 -- function dist(x,y) return sqrt(x*x,y*y) end
end