Advertisement
Guest User

Untitled

a guest
Jan 10th, 2016
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.95 KB | None | 0 0
  1.  
  2.     losrange = 7
  3.     fielddim = losrange*2
  4.  
  5.     pillardancing = false
  6.    
  7.     dance_direction = nil
  8.     dance_direction_num = nil
  9.     next_move = nil
  10.     pillar_center = {nil,nil}
  11.     walk_path = {[-1]={},[1]={}}
  12.    
  13.     order_diag = { {-1,-1}, {0,-1}, {1,-1}, {1,0}, {1,1}, {0,1}, {-1,1}, {-1,0} }
  14.     moves_diag = { "y", "h", "b", "j", "n", "l", "u", "k" }
  15.     order_adja = { {-1,0}, {0,1}, {1,0}, {0,-1} }
  16.    
  17.     pseudomonsters = { ["fungus"]=true, ["plant"]=true }
  18.  
  19.     function rotate_forward(what) table.insert(what,#what,table.remove(what,1)) end
  20.     function rotate_backward(what) table.insert(what,1,table.remove(what,#what)) end
  21.     function contains(t,what)
  22.         for _,f in pairs(t) do if f ~= nil and f == what then return true end end
  23.         return false
  24.     end
  25.  
  26.     function pv(v) return type(v) == "table" and "("..tostring(v[1])..","..tostring(v[2])..")" or tostring(v) end
  27.     function vector_out_of_bounds(v,range) return math.abs(v[1]) > range or math.abs(v[2]) > range end
  28.     function tile_at_vector(v) return pillar_fov[v[1]][v[2]] end
  29.     function set_tile_at_vector(v,t) pillar_fov[v[1]][v[2]] = t end
  30.     function feature_at_vector(v) return view.feature_at(v[2],v[1]) end
  31.     function monster_at_vector(v) return monster.get_monster_at(v[2],v[1]) end
  32.     function exclude_at_vector(v) travel.set_exclude(v[2],v[1],0) end
  33.     function unexclude_at_vector(v) travel.del_exclude(v[2],v[1]) end
  34.  
  35.     function vector_field(v1,v2)
  36.         vectorfield = {}
  37.         for y=v1[1],v1[2] do for x=v2[1],v2[2] do vectorfield[#vectorfield+1] = {y,x} end end
  38.         return vectorfield
  39.     end
  40.     los_vectorfield = vector_field({-losrange,losrange},{-losrange,losrange})
  41.     field_vectorfield = vector_field({-fielddim,fielddim},{-fielddim,fielddim})
  42.     function vector_field_offset(field,offset)
  43.         vectorfield_new = {}
  44.         for _,v in pairs(field) do
  45.             vectorfield_new[#vectorfield_new+1] = vector_add(v,offset)
  46.         end
  47.         return vectorfield_new
  48.     end
  49.     function vector_equal(v1,v2) return v1[1] == v2[1] and v1[2] == v2[2] end
  50.     function vector_copy(v) return {v[1],v[2]} end
  51.     function vector_neg(v) return {-v[1],-v[2]} end
  52.     function vector_add(v1,v2) return {v1[1]+v2[1],v1[2]+v2[2]} end
  53.     function vector_sub(v1,v2) return {v1[1]-v2[1],v1[2]-v2[2]} end
  54.     function vector_redir(v,dir) return {v[1]*dir[1],v[2]*dir[2]} end
  55.     function vector_cross(v1,v2) return v1[1] * v2[2] - v1[2] * v2[1] end
  56.     function vector_abs(v) return math.sqrt(v[1]^2+v[2]^2) end
  57.     function vector_coordabs(v) return {math.abs(v[1]),math.abs(v[2])} end
  58.     function vector_angle(v1,v2) return math.atan(vector_cross(v1,v2) / (vector_abs(v1) * vector_abs(v2))) end
  59.  
  60.     function all_fields_in(vectorfield,what)
  61.         r = {}
  62.         for _,v in pairs(vectorfield) do if what[tile_at_vector(v)] ~= nil then r[#r+1] = v end end
  63.         return r
  64.     end
  65.  
  66.     function not_fields_in(vectorfield,what)
  67.         r = {}
  68.         for _,v in pairs(vectorfield) do if what[tile_at_vector(v)] == nil then r[#r+1] = v end end
  69.         return r
  70.     end
  71.  
  72.     function get_dance_direction(move,pillar_offset)
  73.         if pillar_offset == nil then pillar_offset = {0,0} end
  74.         rawdir = vector_cross(vector_sub(pillar_center,pillar_offset),move)
  75.         return rawdir ~= 0 and rawdir / math.abs(rawdir) or 0
  76.     end
  77.    
  78.     function init_fov()
  79.         pillar_fov = {}
  80.         for _,v in pairs(vector_field({-fielddim,fielddim},{-fielddim,fielddim})) do
  81.             if pillar_fov[v[1]] == nil then pillar_fov[v[1]] = {} end
  82.             set_tile_at_vector(v,"0")
  83.             if not vector_out_of_bounds(v,losrange) then
  84.                 f = feature_at_vector(v)
  85.                 mon = monster_at_vector(v)
  86.                 if f == nil or not travel.feature_traversable(f) or (mon and pseudomonsters[mon:name()] == true) then set_tile_at_vector(v,"1") end
  87.             end
  88.         end
  89.         set_tile_at_vector({0,0},"x")
  90.     end
  91.  
  92.     function shift_fov(next_move)
  93.         a=crawl.call_dlua("return crawl.millis()")
  94.         set_tile_at_vector({0,0},"p")
  95.         new_fov = {}
  96.         for _,v in pairs(vector_field({-fielddim,fielddim},{-fielddim,fielddim})) do
  97.             vn = vector_sub(v,next_move)
  98.             if not vector_out_of_bounds(vn,fielddim) then
  99.                 if new_fov[vn[1]] == nil then new_fov[vn[1]] = {} end
  100.                 new_fov[vn[1]][vn[2]] = tile_at_vector(v)
  101.             end
  102.         end
  103.         pillar_fov = new_fov
  104.         for _,v in pairs(vector_field({-fielddim,fielddim},{-fielddim,fielddim})) do
  105.             if pillar_fov[v[1]] == nil then pillar_fov[v[1]] = {} end
  106.             if tile_at_vector(v) == nil then set_tile_at_vector(v,"0") end
  107.         end
  108.         set_tile_at_vector({0,0},"x")
  109.         c=crawl.call_dlua("return crawl.millis()")
  110.         p(c-a)
  111.     end
  112.  
  113.     function floodfill(v)
  114.         set_tile_at_vector(v,"?")
  115.         for _,move in pairs(order_adja) do
  116.             vn = vector_add(v,move)
  117.             if vector_out_of_bounds(vn,losrange) then
  118.                 set_tile_at_vector(v,"!")
  119.                 return false
  120.             end
  121.             if tile_at_vector(vn) == "1" and not floodfill(vn) then
  122.                 set_tile_at_vector(v,"!")
  123.                 return false
  124.             end
  125.         end
  126.         if tile_at_vector(v) == "?" then
  127.             set_tile_at_vector(v,"P")
  128.             return true
  129.         end
  130.     end
  131.    
  132.     function path_recursion(step,origin,path)
  133.         neworigin = vector_add(origin,step)
  134.         for _,vn in pairs(all_fields_in(vector_field_offset(order_diag,neworigin),{["p"]=true,["x"]=true})) do
  135.             vn = vector_sub(vn,neworigin)
  136.             if not vector_equal(vn,vector_neg(step)) then
  137.                 continue = vector_copy(vn)
  138.                 dir = get_dance_direction(continue,neworigin)
  139.                 continue[3] = dir
  140.             end
  141.         end
  142.         path[#path+1] = continue
  143.         if tile_at_vector(vector_add(neworigin,continue)) == "x" then
  144.             return path
  145.         else
  146.             return path_recursion(continue,neworigin,path)
  147.         end
  148.     end
  149.    
  150.     function find_dir_of_path(step)
  151.         walk_path = {[-1]={},[1]={}}
  152.         path = path_recursion(step,{0,0},{step})
  153.         dirsum = 0
  154.         for _,step in pairs(path) do dirsum = dirsum + step[3] end
  155.         return dirsum / math.abs(dirsum), path
  156.     end
  157.  
  158.     function draw_path()
  159.         for _,v in pairs(all_fields_in(los_vectorfield,{["P"]=true})) do
  160.             for _,vn in pairs(not_fields_in(vector_field_offset(order_adja,v),{["P"]=true})) do
  161.                 set_tile_at_vector(vn,"p")
  162.             end
  163.         end
  164.         set_tile_at_vector({0,0},"x")
  165.     end
  166.    
  167.     function calculate_path()
  168.         possible_moves = {}
  169.         for i,v in pairs(all_fields_in(order_diag,{["p"]=true})) do
  170.             dir = get_dance_direction(v)
  171.             possible_moves[#possible_moves+1] = {v[1],v[2],dir}
  172.         end
  173.         d1, p1 = find_dir_of_path(possible_moves[1])
  174.         d2, p2 = find_dir_of_path(possible_moves[2])
  175.         if d1 == d2 then
  176.             crawl.mpr("Couldn't determine path directions, this shouldn't happen!")
  177.             StopPillardancing()
  178.         else
  179.             for _,v in pairs(p1) do walk_path[d1][#walk_path[d1]+1] = {v[1],v[2],d1} end
  180.             for _,v in pairs(p2) do walk_path[d2][#walk_path[d2]+1] = {v[1],v[2],d2} end
  181.         end
  182.     end
  183.    
  184.     function fill_pillar()
  185.         for _,v in pairs(all_fields_in(los_vectorfield,{["p"]=true})) do
  186.             surrounded = true
  187.             for _ in pairs(not_fields_in(vector_field_offset(order_adja,v),{["p"]=true,["P"]=true,["x"]=true,["!"]=true})) do surrounded = false break end
  188.             if surrounded then set_tile_at_vector(v,"P") end
  189.         end
  190.     end
  191.    
  192.     function tendril(v,dv)
  193.         for d=1,losrange*2 do
  194.             vn = vector_add(v,vector_redir({d,d},dv))
  195.             if vector_out_of_bounds(vn,losrange-1) then break end
  196.             tile = tile_at_vector(vn)
  197.             if (tile ~= "0" and tile ~= "p") or (tile == "p" and d == 1) then break end
  198.             if tile == "p" then for dn=1,d do
  199.                 set_tile_at_vector(vector_add(v,vector_redir({dn,dn},dv)),"p")
  200.                 return true
  201.             end end
  202.         end
  203.     end
  204.    
  205.     function next_to_pillar()
  206.         for _,v in pairs(all_fields_in(order_diag,{["1"]=true})) do
  207.             if floodfill(v) then return v end
  208.             init_fov()
  209.         end
  210.         return nil
  211.     end
  212.    
  213.     function monsters_at(move)
  214.         ybound = {-losrange,losrange}
  215.         xbound = {-losrange,losrange}
  216.  
  217.         if move[1] < 0 then ybound[2] = -1
  218.         elseif move[1] > 0 then ybound[1] = 1 end
  219.         if move[2] < 0 then xbound[2] = -1
  220.         elseif move[2] > 0 then xbound[1] = 1 end
  221.         for _,v in pairs(all_fields_in(vector_field(ybound,xbound),{["0"]=true,["p"]=true})) do
  222.             mon = monster_at_vector(v)
  223.             --travel.set_exclude(x,y,0)
  224.             if mon and not mon:is_safe() then
  225.                 return true
  226.             end
  227.         end
  228.         return false
  229.     end
  230.  
  231.     function calculate_next_pillar_step()
  232.         if dance_direction_num ~= nil then
  233.             possible_moves = {walk_path[dance_direction_num][1],walk_path[dance_direction_num*-1][1]}
  234.         else
  235.             possible_moves = {walk_path[-1][1],walk_path[1][1]}
  236.         end
  237.         goodmove = nil
  238.         for _,move in pairs(possible_moves) do
  239.             goodmove = move
  240.             if monsters_at(move) then
  241.                 if dance_direction_num ~= nil and move[3] == dance_direction_num then dance_direction_num = dance_direction_num*-1 end
  242.                 goodmove = nil
  243.             else
  244.                 break
  245.             end
  246.         end
  247.         if goodmove ~= nil then
  248.             travel.del_exclude(goodmove[2], goodmove[1])
  249.             return goodmove
  250.         else
  251.             crawl.mpr("No suitable move found!")
  252.             StopPillardancing()
  253.             return nil
  254.         end
  255.     end
  256.    
  257.     function next_pillar_step()
  258.         for i,c in pairs(order_diag) do if vector_equal(c,next_move) then
  259.                 crawl.sendkeys(moves_diag[i])
  260.                 break
  261.         end end
  262.         pillar_center = vector_sub(pillar_center,next_move)
  263.         shift_fov(next_move)
  264.         rotate_forward(walk_path[next_move[3]])
  265.         rotate_backward(walk_path[next_move[3]*-1])
  266.         next_move = nil
  267.     end
  268.  
  269.     function Pillardance()
  270.         a=crawl.call_dlua("return crawl.millis()")
  271.         if not pillardancing then
  272.             pillardancing = true
  273.             init_fov()
  274.             p(crawl.call_dlua("return crawl.millis()"))
  275.             b=crawl.call_dlua("return crawl.millis()")
  276.             pillar_pos = next_to_pillar()
  277.             if pillar_pos == nil then
  278.                 crawl.mpr("No pillar found!")
  279.                 pillardancing = false
  280.                 return false
  281.             end
  282.             draw_path()
  283.             p(crawl.call_dlua("return crawl.millis()"))
  284.             c=crawl.call_dlua("return crawl.millis()")
  285.             fill_pillar()
  286.             p(crawl.call_dlua("return crawl.millis()"))
  287.             d=crawl.call_dlua("return crawl.millis()")
  288.             --for _,v in pairs(all_fields_in(los_vectorfield,{["p"]=true,["x"]=true})) do for _,dv in pairs(order_diag) do tendril(v,dv) end end
  289.             --fill_pillar()
  290.             p(crawl.call_dlua("return crawl.millis()"))
  291.             e=crawl.call_dlua("return crawl.millis()")
  292.             for _,v in pairs(all_fields_in(los_vectorfield,{["p"]=true,["x"]=true})) do exclude_at_vector(v) end
  293.             p(crawl.call_dlua("return crawl.millis()"))
  294.             f=crawl.call_dlua("return crawl.millis()")
  295.             pillar_center = {0, 0}
  296.             vectorcount = 0
  297.             --for y=-losrange,losrange do for x=-losrange,losrange do if pillar_fov[y][x] == "P" then
  298.             --      pillar_center = {pillar_center[1] + y, pillar_center[2] + x}
  299.             --      vectorcount = vectorcount + 1
  300.             --end end end
  301.             for _,v in pairs(all_fields_in(los_vectorfield,{["P"]=true})) do
  302.                     pillar_center = {pillar_center[1] + v[1], pillar_center[2] + v[2]}
  303.                     vectorcount = vectorcount + 1
  304.             end
  305.             pillar_center = {pillar_center[1] / vectorcount, pillar_center[2] / vectorcount}
  306.             p(crawl.call_dlua("return crawl.millis()"))
  307.             g=crawl.call_dlua("return crawl.millis()")
  308.             calculate_path()
  309.             p(crawl.call_dlua("return crawl.millis()"))
  310.             h=crawl.call_dlua("return crawl.millis()")
  311.             next_move = calculate_next_pillar_step()
  312.             p(crawl.call_dlua("return crawl.millis()"))
  313.             i=crawl.call_dlua("return crawl.millis()")
  314.             if next_move == nil then return false end
  315.             dance_direction_num = get_dance_direction(goodmove)
  316.             dance_direction = dance_direction_num > 0 and "clockwise" or "counterclockwise"
  317.             crawl.mpr("Dancing "..dance_direction.."!")
  318.             p(crawl.call_dlua("return crawl.millis()"))
  319.             j=crawl.call_dlua("return crawl.millis()")
  320.             p("init:"..b-a..",draw:"..c-b..",fill:"..d-c..",tendril:"..e-d..",exclude:"..f-e..",center:"..g-f..",calc:"..h-g..",next:"..i-h..",done:"..j-i..",total:"..j-a)
  321.         else
  322.             if next_move ~= nil then
  323.                 next_pillar_step()
  324.             else
  325.                 next_move = calculate_next_pillar_step()
  326.                 exclude_at_vector({0,0})
  327.                 crawl.redraw_screen()
  328.             end
  329.         end
  330.         --for y=-fielddim,fielddim do
  331.         --  ls = ""
  332.         --  for x=-fielddim,fielddim do
  333.         --      ls = ls .. pillar_fov[y][x]
  334.         --  end
  335.         --  dmsg(pad(y,3), ls)
  336.         --end
  337.     end
  338.    
  339.     function StopPillardancing()
  340.         if pillardancing then
  341.             for _,v in pairs(all_fields_in(field_vectorfield,{["p"]=true,["x"]=true})) do unexclude_at_vector(v) end
  342.             pillardancing = false
  343.             dance_direction = nil
  344.             dance_direction_num = nil
  345.             next_move = nil
  346.             pillar_center = {nil,nil}
  347.             walk_path = {[-1]={},[1]={}}
  348.         end
  349.     end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement