makeclass('player')
makeclass('light')

freqcolor={ azure=152, black=35200, blue=59300, brown=20000, chocolate=1840, cream=8610,
            crimson=575, fawn=272, gold=17300, green=34200, grey=17300, lemon=445,
	    lilac=1020, mauve=719, ochre=132, olive=1910, orange=22500, peach=3860,
	    pink=27200, purple=13700, red=52200, rose=4310, ruby=994, russet=68,
	    scarlet=315, silver=13200, violet=3590, white=45100, yellow=24400 }
	    
function player:near_iter(rad,kind1,kind2,kind3)
  local lis=tangible.near(self,rad,true,true)
  local i=1
  return function()
    while i<=#lis do
      i=i+1
      if not kind1 or isa(lis[i-1],kind1,kind2,kind3) then return lis[i-1] end end end
  end

function tandist(t1,t2)
  local _,t1p,t1x,t1y=tangible.animstate(t1)
  local _,t2p,t2x,t2y=tangible.animstate(t2)
  return math.sqrt((t1x-t2x)*(t1x-t2x)+(t1y-t2y)*(t1y-t2y))
  end

function player:radius_iter(rad,kind)
  local lis=tangible.near(self,rad,true,true)
  local i=1
  return function()
    while i<=#lis do
      i=i+1
      if (not kind or isa(lis[i-1],kind)) and tandist(self,lis[i-1])<=rad then return lis[i-1] end end end
  end

function player:interface(place)
    gui.menu_item("cb_dir0"          ,"Go North")
    gui.menu_item("cb_dir180"        ,"Go South")
    gui.menu_item("cb_dir270"        ,"Go West")
    gui.menu_item("cb_dir90"         ,"Go East")
    gui.menu_item("cb_map"           ,"Map")
    gui.menu_item("cb_spectra"       ,"Show Spectra")
    end

function player:cb_spectra()
  for k,v in pairs(self.spectra) do print(string.format("%-6.6s:%s",k,string.sub('+++++++++++++++++++++++++',1,v))) end
  end

function player:cb_dir0()   self:move(0)   end
function player:cb_dir45()  self:move(45)  end
function player:cb_dir90()  self:move(90)  end
function player:cb_dir135() self:move(135) end
function player:cb_dir180() self:move(180) end
function player:cb_dir215() self:move(215) end
function player:cb_dir270() self:move(270) end
function player:cb_dir315() self:move(315) end

function player:power()
  local rval=0
  for k,v in pairs(self.spectra) do if v>0 then rval=rval+1 end end
  return rval
  end

function player:respawn()
  tangible.animate(self,{action='warp',plane='main',x=math.random(-40,40),y=math.random(-40,40),z=0})
  self:cb_map()
  print("You just died!") -- 
  end
  
function player:fight(enemy)
  local common={}
  for k,v in pairs(self.spectra) do if enemy.spectra[k]>0 then common[k]=1 end end
  local p0=self:power()
  local p1=enemy:power()
  local winner
  if p0==p1 then
    for k,v in pairs(common) self.spectra[k]=nil enemy.spectra[k]=nil end
  else if p0>p1 then
    for k,v in pairs(common) enemy.spectra[k]=nil end
  else
    for k,v in pairs(common) self.spectra[k]=nil end
    end
  p0=self:power()
  p1=enemy:power()
  if p1==0 then self.kills =self.kills+1  enemy.deaths=enemy.deaths+1 enemy:respawn() end
  if p0==0 then self.deaths=self.deaths+1 enemy.kills =enemy.kills+1  self:respawn()  end
  end
  

function player:newlocation()
  for lt in self:radius_iter(3.1,light) do self.spectra[lt.color]=25 end
  for lt in self:radius_iter(3.1,player) do if self.team==lt.team then
    local nspec={} setmetatable(nspec,NilIsZero)
    for k,v in pairs(self.spectra) do nspec[k]=v end
    for k,v in pairs(lt.spectra)   do nspec[k]=math.max(v,nspec[k]) end
    for k,v in pairs(nspec) do self.spectra[k]=v lt.spectra[k]=v end
    end end
  for lt in self:radius_iter(3.1,player) do if self.team~=lt.team then p1:fight(p2) end end
  for k,v in pairs(self.spectra) do self.spectra[k]=self.spectra[k]-1 if self.spectra[k]<=0 then self.spectra[k]=nil end end
  end
  
  
function player:move(degrees)
  dx= math.cos((90-degrees)*math.pi/180)
  dy=-math.sin((90-degrees)*math.pi/180)
  tangible.animate(self,{action='walk',dx=dx,dy=dy})
  self:newlocation()
  self:map(12)
  end

function wrcolor()
  local acc=0
  local rval
  for k,v in pairs(freqcolor) do acc=acc+v if math.random(1,acc)<=v then rval=k end end
  return rval
  end

function makemap()
  for i=1,100 do
    local x=math.random(-50,50)
    local y=math.random(-50,50)
    local nt=tangible.build{class='light',x=x,y=y,z=0,plane='main',graphic='light'}
    nt.color=wrcolor()
    end
  end

function setcell(array,x,y,val)
  if not array[y] then array[y]={} end
  array[y][x]=val
  return array
  end

function player:cb_map(place,dialog)
  self:map(10)
  end

teamcolor={ red='\27[91m', green='\27[92m', yellow='\27[93m', blue='\27[94m', magenta='\27[95m', cyan='\27[96m' }

function player:map(radius)
  local radius=10
  radius=radius or 10
  local cells={}
  local px,py=tangible.xyz(tangible.actor())
  for lt in self:near_iter(1.5*radius,light,player) do
    local lx,ly=tangible.xyz(lt)
    lx=lx-px+radius
    ly=ly-py+radius
    if seq(0,ly,1+2*radius) and seq(0,lx,1+2*radius) then
      local celltext
      if isa(lt,light) then celltext=string.format("%-6.6s",lt.color)
        elseif isa(lt,player) then celltext=teamcolor[lt.team].."Pl:"..string.format("%-3.0f",lt:power()).."\27[0m"
	end
      setcell(cells,math.floor(0.5+lx),math.floor(0.5+ly),celltext) end
    end
  setcell(cells,radius,radius,teamcolor[self.team]..string.format("Me:%-3.0f",self:power()).."\27[0m")
  for ly=0,1+2*radius do
    local line='|'
    for lx=0,1+2*radius do
      if cells[ly] and cells[ly][lx] then line=line..cells[ly][lx]..'|' else line=line..'      |' end
      end
    print(line)
    end
  end

