schemes = {} --   
stypes = {} --  

--          .
-- :
-- 	filename -  ,    ,  
-- 	scheme -  
function load_scheme(filename, scheme, stype)
	module(filename)
	schemes[scheme] = filename
	stypes[scheme] = stype
end

----------------------------------------------------------------------
--  :
----------------------------------------------------------------------

module("modules")

----------------------------------------------------------------------

function printf(fmt,...)
    log(string.format(fmt,unpack(arg)))
end

function wait_game(time_to_wait)
    verify_if_thread_is_running()
    if (time_to_wait == nil) then
        coroutine.yield()
    else
        local time_to_stop = game.time() + time_to_wait
        while game.time() <= time_to_stop do
            coroutine.yield()
        end
    end
end

function wait(time_to_wait)
    verify_if_thread_is_running()
    if (time_to_wait == nil) then
        coroutine.yield()
    else
        local time_to_stop = device():time_global() + time_to_wait
        while device():time_global() <= time_to_stop do
            coroutine.yield()
        end
    end
end

function random(low,up)
    rnd     = math.random(10000)
    rnd     = rnd/10000
    rnd     = rnd * (up - low)
    rnd     = rnd + low
    return  rnd
end

function action(obj,...)
    local act = entity_action()
    local i = 1
    while true do
        if (arg[i] ~= nil) then
            act:set_action(arg[i])
        else
            break
        end
        i = i + 1
    end
    if (obj ~= nil) then
        obj:command(act,false)
    end
    return  entity_action(act)
end

function action_first(obj,...)
    local act = entity_action()
    local i = 1
    while true do
        if (arg[i] ~= nil) then
            act:set_action(arg[i])
        else
            break
        end
        i = i + 1
    end
    if (obj ~= nil) then
        obj:command(act,true)
    end
    return  entity_action(act)
end

function round (value)
    local min = math.floor (value)
    local max = min + 1
    if value - min > max - value then return max end
    return min
end

class "pp_effector" (effector)

function pp_effector:__init(effector_type,start_time,dest_power,life_time) super(effector_type,start_time)
    self.start_time = start_time
    self.stop_time  = start_time + life_time
    self.max_power  = dest_power
end

function pp_effector:process(pp)
    effector.process(self,pp)

    local curr_time = device():time_global()
    local d         = 0.0

    if curr_time < self.start_time then
        d           = 0.0
    else
        if curr_time < self.stop_time then
            d           = (curr_time - self.start_time) / (self.stop_time - self.start_time)
        else
            self.info   = self.max_power
            return      true
        end
    end

    local dual      = duality()
    local noise     = noise()
    local base      = color()
    local gray      = color()
    local add       = color()

    dual.h          = self.max_power.dual.h         * d
    dual.v          = self.max_power.dual.v         * d

    noise.grain     = self.max_power.noise.grain        * d
    noise.intensity     = self.max_power.noise.intensity    * d
    noise.fps       = self.max_power.noise.fps      * d

    base.r          = self.max_power.color_base.r       * d
    base.g          = self.max_power.color_base.g       * d
    base.b          = self.max_power.color_base.b       * d

    gray.r          = self.max_power.color_gray.r       * d
    gray.g          = self.max_power.color_gray.g       * d
    gray.b          = self.max_power.color_gray.b       * d

    add.r           = self.max_power.color_add.r        * d
    add.g           = self.max_power.color_add.g        * d
    add.b           = self.max_power.color_add.b        * d

    pp.gray         = self.max_power.gray           * d
    pp.blur         = self.max_power.blur           * d

    pp.dual         = dual
    pp.noise        = noise
    pp.color_base       = base
    pp.color_gray       = gray
    pp.color_add        = add

    self.info       = pp

    return              true
end

function pp_effector:finished()
    return          self.stop_time < device():time_global()
end

--
-- postprocess for rainbow
--
class "pp_linear_lerp" (effector)

function pp_linear_lerp:__init(effector_type,start_time,life_time,start_power,dest_power) super(effector_type,start_time)
    self.start_time = start_time
    self.stop_time  = start_time + life_time
    self.min_power  = start_power
    self.max_power  = dest_power
end

function pp_linear_lerp:process(pp)
    effector.process(self,pp)

    local curr_time = device():time_global()
    local d         = 0.0

    if curr_time < self.start_time then
        d           = 0.0
    else
        if curr_time < self.stop_time then
            d           = (curr_time - self.start_time) / (self.stop_time - self.start_time)
        else
            self.info   = self.max_power
            return      true
        end
    end

    local dual      = duality(100)
    local noise     = noise()
    local base      = color()
    local gray      = color()
    local add       = color()

    dual.h          = self.min_power.dual.h         + (self.max_power.dual.h        - self.min_power.dual.h     )   * d
    dual.v          = self.min_power.dual.v         + (self.max_power.dual.v        - self.min_power.dual.v     )   * d

    noise.grain     = self.min_power.noise.grain        + (self.max_power.noise.grain       - self.min_power.noise.grain    )   * d
    noise.intensity     = self.min_power.noise.intensity    + (self.max_power.noise.intensity   - self.min_power.noise.intensity)   * d
    noise.fps       = self.min_power.noise.fps      + (self.max_power.noise.fps         - self.min_power.noise.fps  )   * d

    base.r          = self.min_power.color_base.r       + (self.max_power.color_base.r      - self.min_power.color_base.r   )   * d
    base.g          = self.min_power.color_base.g       + (self.max_power.color_base.g      - self.min_power.color_base.g   )   * d
    base.b          = self.min_power.color_base.b       + (self.max_power.color_base.b      - self.min_power.color_base.b   )   * d

    gray.r          = self.min_power.color_gray.r       + (self.max_power.color_gray.r      - self.min_power.color_gray.r   )   * d
    gray.g          = self.min_power.color_gray.g       + (self.max_power.color_gray.g      - self.min_power.color_gray.g   )   * d
    gray.b          = self.min_power.color_gray.b       + (self.max_power.color_gray.b      - self.min_power.color_gray.b   )   * d

    add.r           = self.min_power.color_add.r        + (self.max_power.color_add.r       - self.min_power.color_add.r    )   * d
    add.g           = self.min_power.color_add.g        + (self.max_power.color_add.g       - self.min_power.color_add.g    )   * d
    add.b           = self.min_power.color_add.b        + (self.max_power.color_add.b       - self.min_power.color_add.b    )   * d

    pp.gray         = self.min_power.gray           + (self.max_power.gray          - self.min_power.gray       )   * d
    pp.blur         = self.min_power.blur           + (self.max_power.blur          - self.min_power.blur       )   * d

    pp.dual         = dual
    pp.noise        = noise
    pp.color_base       = base
    pp.color_gray       = gray
    pp.color_add        = add

    self.info       = pp

    return          true
end

function pp_linear_lerp:finished()
    return          self.stop_time < device():time_global()
end
--
-- end of postprocess for rainbow
--

function get_level_object(obj_name)
    local res = level.object(obj_name)
    while res == nil do

    	-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    	-- !!!!!  ,         !!!!!
	-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        printf("get_level_object() is waiting for object \"%s\"", obj_name)

        res         = level.object(obj_name)
        wait        ()
    end
    return          res
end

function get_actor()
    local res       = level.actor()
    while res == nil do
        res         = level.actor()
        wait        ()
    end
    return          res
end

function distance_between(obj1, obj2)
    return obj1:position():distance_to(obj2:position())
end

//    nil,   ,  ,   
function distance_between_safe(obj1, obj2)
    if(obj1 == nil or obj2 == nil) then return 100000 end
	return obj1:position():distance_to(obj2:position())
end

--------------------------------------------------
--  LUA     Finite State Machine
--   
--------------------------------------------------
class 'FSM'

--      Non-Player Character
function FSM:__init(script_name, npc_obj)
    --   v NPC
    self.npc = npc_obj
    --  -  , v  
    self.script_name = script_name
    -- ,       
    --    
    self.transition_matrix = {[0] = {}}
    --      
    self.current_state = 0

    --  ,   
    self.machine_running = true

    printf("inialization FSM for NPC %s", self.npc:name())
end

function FSM:is_running()
    return self.machine_running
end

function FSM:start()
    printf("starting FSM for %s", self.npc:name())
    self.machine_running = true
end

function FSM:stop()
    printf("stoping FSM for %s", self.npc:name())
    self.machine_running = false
    self:reset_script_control()
end


--     
--    
function FSM:set_transition(from_state_num, to_state_num, cond_func)
    printf("in setting transition %d, %d ", from_state_num, to_state_num)

    if self.transition_matrix[from_state_num] == nil then
       self.transition_matrix[from_state_num] = {[to_state_num] = cond_func}
    else
       self.transition_matrix[from_state_num][to_state_num] = cond_func
    end
end

--   FSM
function FSM:run()
    local transition_vector = self.transition_matrix[self.current_state]
    table.foreach(transition_vector,
                  function(to_state_num, cond_func)
                        if cond_func(self.npc, self) == true then
                            printf("transition from %d to %d", self.current_state, to_state_num)

                            if to_state_num == 0 then
                                self:reset_script_control()
                            end

                            --if  self.current_state == 0 then
                            --  self:set_script_control()
                            --end

                            self.current_state = to_state_num
                            return true
                        end
                        return nil
                  end)
end


--    FSM
function FSM:run_loop()
    printf("running FSM loop for NPC %s", self.npc:name())

    while self:is_running() do
        local transition_vector = self.transition_matrix[self.current_state]
        table.foreach(transition_vector,
                      function(to_state_num, cond_func)
                            if cond_func(self.npc, self) == true then
                                printf("transition from %d to %d", self.current_state, to_state_num)

                                if to_state_num == 0 then
                                    self:reset_script_control()
                                end

                                --if  self.current_state == 0 then
                                --  self:set_script_control()
                                --end

                                self.current_state = to_state_num
                                return true
                            end
                            return nil
                      end)
        if self.npc:alive () == false then
           self.npc:script (false, self.script_name)
           return
           end
        wait()
    end
end

--     NPC (   )
function FSM:set_script_control()
    printf("set script control for FSM of NPC %s", self.npc:name())
    self.npc:script(true, self.script_name)
end

--      NPC (   )
function FSM:reset_script_control()
    printf("reset script control for FSM of NPC %s", self.npc:name())
    self.npc:script(false, self.script_name)
end

--------------------------------------------------
-- end of  class 'FSM'
--------------------------------------------------

function reset_action (npc, script_name)
    if npc:get_script () then
       npc:script (false, script_name)
    end
    npc:script (true, script_name)
end

class "script_object"

function script_object:__init(name,script,...)
    self.action         = action(nil,unpack(arg))
    self.object_name    = name
    self.script_name    = script
    self.object         = nil
end

function script_object:update()
    local                   obj = self.object
    self.object             = level.object(self.object_name)
    if ((obj == nil) and (self.object ~= nil)) then
        self.object:script  (true,self.script_name)
        self.object:command (self.action,false)
    end
end

--
--   
--
function GiveInfo(obj, info_number)

    local result = obj:give_info_portion(info_number)
    while not result do
        wait()
        result = obj:give_info_portion(info_number)
    end
end

function GiveInfoViaPda(obj_receiver, obj_sender, info_number)
    obj_receiver:give_info_portion_via_pda(info_number, obj_sender)
end


--------------------------------------------------
-- Functions and variables added by Zmey
--------------------------------------------------

-- ,    ,      
time_infinite = 100000000

-- = , v  v    
-- (    v vv  debug_log)
debug_script_name = ""

-- Tv   ,  script_name == debug_script_name
-- L   
function debug_log(script_name, fmt, ...)
  if debug_script_name == script_name then
    log(string.format(fmt, unpack(arg)))
--    flush()
  end
end

-- +  v  v - , v    v 
function interrupt_action(who, script_name)
  if who:get_script() then
    who:script(false, script_name)
  end
end

function random_choice(...)
  local r = math.random(1, arg.n)
  return arg[r]
end

function new_action(...)
  local act = entity_action()
  for i = 1, arg.n do
    act:set_action(arg[i])
  end
  return act;
end

obj_last_actions = {};

function perform_action(obj, action_name, action)
  if (obj ~= nil) then
    obj_last_actions[obj] = action_name
    obj:command(act, false)
  end
end

function last_action(obj)
  return obj_last_actions[obj]
end

function if_then_else(cond, if_true, if_false)
    if cond then
        return if_true
    end
    return if_false
end

function update_action (npc, script, ...)
    if npc == nil then return end
    local act = npc:action ()
    if arg.n == 0 then return end

    if act == nil then act = entity_action () end

    for a = 1, arg.n, 1 do
        if arg[a] ~= nil then act:set_action (arg[a]) end
    end
    reset_action (npc, script)
    npc:command (act, false)

end


function set_current_time (hour, min, sec)
    local current_time_factor = level.get_time_factor ()

    printf ("Need time : %d:%d:%d", hour, min, sec)

    local current_time = game.time ()
    local c_day = math.floor (current_time / 86400000)
    local c_time = current_time - c_day * 86400000
    local n_time = (sec + min * 60 + hour * 3600) * 1000

    if c_time > n_time then c_day = c_day + 1 end
    n_time = n_time + c_day * 86400000

    level.set_time_factor (10000)
    while game.time () < n_time do wait () end

    level.set_time_factor (current_time_factor)
end




----------------------------------------------------------------------------------------------------------------------
-- Evaluators
----------------------------------------------------------------------------------------------------------------------
-- v id    0  256   v .

--Constant evaluator
class "const_evaluator" (property_evaluator)

function const_evaluator:__init (value) super ()
    self.value = value
end

function const_evaluator:evaluate()
    return          self.value
end

--Wait evaluator
class "wait_evaluator" (property_evaluator)

function wait_evaluator:__init (wait_time) super ()
    self.wait_time = wait_time
    self.first_call = true
    self.current_time = 0
end

function wait_evaluator:evaluate ()
    if self.first_call == true then
       self.first_call = false
       self.current_time = device ():time_global ()
       return false
    end

    local t = device():time_global () - self.current_time;
    if t > self.wait_time then return true end
    return false
end
--------------------------------------------------------------------------------
class "enabled_evaluator" (property_evaluator)

function enabled_evaluator:__init (name, storage) super ()
    self.a = storage
end

function enabled_evaluator:evaluate()
    return  self.a.enabled
end


function str_split (str)

    local strlen = string.len (str)

    local parts = {{}, {}, {}, {}}
    local cpart = 1

    for a = 1, strlen, 1 do
        local char = string.byte (str, a)
        if char ~= 95 then
           table.insert (parts[cpart], char)
        else
           cpart = cpart + 1
           if cpart > 4 then break end
        end
    end

    if cpart ~= 4 then return "unknown", "stalker", 0, 0 end

    local str1 = string.char ()
    local str2 = string.char ()
    local str3 = string.char ()
    local str4 = string.char ()

    local ref = parts[1]
    for a = 1, table.getn (ref), 1 do
        str1 = string.format ("%s%c", str1, ref[a])
    end

    ref = parts[2]
    for a = 1, table.getn (ref), 1 do
        str2 = string.format ("%s%c", str2, ref[a])
    end

    ref = parts[3]
    for a = 1, table.getn (ref), 1 do
        str3 = string.format ("%s%c", str3, ref[a])
    end

    ref = parts[4]
    for a = 1, table.getn (ref), 1 do
        str4 = string.format ("%s%c", str4, ref[a])
    end

    printf ("%s %s %d %d", str1, str2, str3, str4)
    return str1, str2, (str3 + 1) - 1, (str4 + 1) - 1
end

function random_number (min_value, max_value)
    math.randomseed (device ():time_global ())
    if min_value == nil and max_value == nil then
      return math.random ()
    else
      return math.random (min_value, max_value)
    end
end

-- ६ ⮪  
-- 㣠
local ms_per_day = 24 * 60 * 60 * 1000
function day_time()
    return math.mod( game.time(), ms_per_day )
end

--Time in hours
function local_hours()
    return math.floor( math.mod( game.time()/1000, 86400 )/ 3600 )
end

--  ப  ", , ..."  ⠡ { "", "", "", ... }
-- 㣠
function parse_names( s )
    local t = {}

    for name in string.gfind( s, "([%w_\\]+)%p*" ) do
        table.insert( t, name )
    end

    return t
end

--  ப  "n1, n2, n3..."  ⠡ { n1, n2, n3, ... }  n1, n2, n3... - 楫 ᫠
-- 㣠
function parse_nums( s )
    local t = {}

    for entry in string.gfind( s, "([%w_\\]+)%p*" ) do
        table.insert( t, tonumber( entry ) )
    end

    return t
end

-- 襭 砩 롮ઠ  ⠡  { obj1 = weight1, obj2 = weight2, ... }
-- 頥   obj.  >= 0
-- 㣠
function random_choice_weighted( a )
    local sum = 0

    for k, w in pairs( a ) do
        sum = sum + w
    end

    if sum <= 1 then
        printf( "!!!!!!!!!!!!!! SUM !!!!!!!!!!!!!!!!!!!!" )
    end

    local r = math.random( sum )
    sum = 0

    for k, w in pairs( a ) do
        sum = sum + w

        if r <= sum then
            return k
        end
    end
end

-- ஢,   ꥪ  
function is_object_online (object_id)
    local sim = alife ()
    if sim == nil then return true end
    local obj = sim:object (object_id)
    if obj == nil then return false end
    return obj.online
end
function get_clsid(npc)
    if npc == nil then return nil end

    if is_object_online(npc:id()) then
        return npc:clsid()
    else
        return nil
    end
end

-- ஢ 㦨   (। game_object)
function isWeapon(object)
    local id = get_clsid(object)
    if id == nil then return false end

    if id == clsid.wpn_vintorez then return true
    elseif id == clsid.wpn_fn2000 then return true
    elseif id == clsid.wpn_ak74 then return true
    elseif id == clsid.wpn_lr300 then return true
    elseif id == clsid.wpn_hpsa then return true
    elseif id == clsid.wpn_pm then return true
    elseif id == clsid.wpn_fort then return true
    elseif id == clsid.wpn_shotgun then return true
    elseif id == clsid.wpn_svd then return true
    elseif id == clsid.wpn_svu then return true
    elseif id == clsid.wpn_rpg7 then return true
    elseif id == clsid.wpn_val then return true
    elseif id == clsid.wpn_walther then return true
    elseif id == clsid.wpn_usp45 then return true
    elseif id == clsid.wpn_groza then return true
    elseif id == clsid.wpn_knife then return true
    elseif id == clsid.wpn_grenade_launcher then return true
    elseif id == clsid.wpn_grenade_f1 then return true
    elseif id == clsid.wpn_grenade_rpg7 then return true
    elseif id == clsid.wpn_grenade_rgd5 then return true
    elseif id == clsid.wpn_grenade_fake then return true
    else return false end
end

--Tv yaw  
function yaw( v1, v2 )
    return  math.acos( ( (v1.x*v2.x) + (v1.z*v2.z ) ) / ( math.sqrt(v1.x*v1.x + v1.z*v1.z ) * math.sqrt(v2.x*v2.x + v2.z*v2.z ) ) )
end

function yaw_degree( v1, v2 )
    return  (math.acos( ( (v1.x*v2.x) + (v1.z*v2.z ) ) / ( math.sqrt(v1.x*v1.x + v1.z*v1.z ) * math.sqrt(v2.x*v2.x + v2.z*v2.z ) ) ) * 57.2957)
end

//    y   

function vector_rotate_y (v, angle)
    angle = angle * 0.017453292519943295769236907684886
    local c = math.cos (angle)
    local s = math.sin (angle)
    return vector ():set (v.x * c - v.z * s, v.y, v.x * s + v.z * c)
end

--  
function clear_table (t)
    while table.getn (t) > 0 do
          table.remove (t, table.getn (t))
    end
end

--ᯮ  ஢. 롮 窨, 㤠   ஬ ࠤ  ⮡ 窠 뫠   ﭨ
-- min_radius  ⥪饩 樨(᫨  ). center_id - 業 樨,  ன ,
-- position_id -  , radius -   ࠤ 롨 , min_radius - 쭮 ﭨ,  ⥪饩 樨   窨.
function new_point(center_id, position_id,radius, min_radius)
    local dir = vector():set(math.random(-1000, 1000)/1000.0, 0.0001, math.random(-1000, 1000)/1000.0)
    local pos = level.vertex_in_direction(center_id, dir, radius)
    local i   = 1

    while(level.vertex_position(position_id):distance_to(level.vertex_position(pos) ) < min_radius and i < 20) do
        dir = vector():set(math.random(-1000, 1000)/1000.0, 0.0001, math.random(-1000, 1000)/1000.0)
        pos = level.vertex_in_direction(center_id, dir, radius)
        i   = i + 1
    end

    return (level.vertex_position(pos))
end

function stop_play_sound(obj)
	if obj:alive() == true then
		obj:set_sound_mask (-1)
		obj:set_sound_mask (0)
	end
end

function object_type(obj)
    local otype = get_clsid(obj)
    local type

    if  otype == clsid.actor or
        otype == clsid.soldier or
        otype == clsid.stalker or
        otype == clsid.trader
    then
        type = "stalker"
    elseif  otype == clsid.crow or
        otype == clsid.rat or
        otype == clsid.rat_group or
        otype == clsid.zombie or
        otype == clsid.flesh or
        otype == clsid.controller or
        otype == clsid.bloodsucker or
        otype == clsid.burer or
        otype == clsid.chimera or
        otype == clsid.boar or
        otype == clsid.flesh_group or
        otype == clsid.dog_red or
        otype == clsid.dog_black or
        otype == clsid.pseudo_gigant
    then
        type = "monstr"
    elseif  otype == clsid.wpn_fn2000 or
        otype == clsid.wpn_ak74 or
        otype == clsid.wpn_lr300 or
        otype == clsid.wpn_hpsa or
        otype == clsid.wpn_pm or
        otype == clsid.wpn_fort or
        otype == clsid.wpn_binocular or
        otype == clsid.wpn_shotgun or
        otype == clsid.wpn_svd or
        otype == clsid.wpn_svu or
        otype == clsid.wpn_rpg7 or
        otype == clsid.wpn_val or
        otype == clsid.wpn_vintorez or
        otype == clsid.wpn_walther or
        otype == clsid.wpn_usp45 or
        otype == clsid.wpn_groza or
        otype == clsid.wpn_knife or
        otype == clsid.wpn_scope or
        otype == clsid.wpn_silencer or
        otype == clsid.wpn_grenade_launcher or
        otype == clsid.obj_physic or
        otype == clsid.obj_breakable or
        otype == clsid.device_pda or
        otype == clsid.device_torch or
        otype == clsid.device_detector_simple or
        otype == clsid.obj_bolt or
        otype == clsid.obj_medkit or
        otype == clsid.obj_food or
        otype == clsid.obj_bottle or
        otype == clsid.obj_antirad or
        otype == clsid.obj_explosive or
        otype == clsid.obj_document or
        otype == clsid.obj_attachable or
        otype == clsid.wpn_grenade_f1 or
        otype == clsid.wpn_grenade_rpg7 or
        otype == clsid.wpn_grenade_rgd5 or
        otype == clsid.wpn_grenade_fake or
        otype == clsid.equ_scientific or
        otype == clsid.equ_stalker or
        otype == clsid.equ_military or
        otype == clsid.equ_exo or
        otype == clsid.wpn_ammo or
        otype == clsid.wpn_ammo_vog25 or
        otype == clsid.wpn_ammo_og7b or
        otype == clsid.wpn_ammo_m209
    then
        type = "item"
    else
        type = "none"
    end

    -- ஢塞    
    if type == "stalker" or
       type == "monstr" then
        if obj:alive() == false then
            type = "corpse"
        end
    end

    return type
end


//   bj 
function is_object_monster(obj)
	local otype = get_clsid(obj)
	if(otype == clsid.crow			or
		otype == clsid.zombie		or
		otype == clsid.flesh		or
		otype == clsid.controller	or
		otype == clsid.bloodsucker	or
		otype == clsid.burer		or
		otype == clsid.chimera		or	
		otype == clsid.boar			or
		otype == clsid.dog_red		or		
		otype == clsid.dog_black	or
		otype == clsid.poltergeist	or
		otype == clsid.pseudo_gigant  )
	then
		return true
	end
	
	return false
end

--頥 ந    ன ⠭ 
function point_with_bit(patrol_path, bit, old_point)      -- old_point -  窨,    롨,
  local points = {}                                       -- ࠬ  易⥫( ਬ ⥪饩 窨 )

    for i = 0, patrol_path:count()-1 do
      --塞  ⠡ 窨  㦭 ⮬
      if( patrol_path:flag(i, bit)) then
            --塞  ᫨ old_point == nil   窠  ᮢ  old_point
            if(old_point == nil) then
                table.insert(points, patrol_path:point(i))
            elseif(old_point ~= i) then
                table.insert(points, patrol_path:point(i))
            end
        end
    end

    local number_point = table.getn(points)

    if(number_point == 0) then
        return nil
    elseif(number_point == 1) then
        return points[1]
    else
        return points[math.random(1, number_point)]
    end
end

--頥 ந    ன ⠭ 
function point_with_bit_id(patrol_path, bit, old_point)        -- old_point -  窨,    롨,
    local points = {}                                          -- ࠬ  易⥫( ਬ ⥪饩 窨 )

    for i = 0, patrol_path:count()-1 do
      --塞  ⠡ 窨  㦭 ⮬
      if( patrol_path:flag(i, bit)) then
            --塞  ᫨ old_point == nil   窠  ᮢ  old_point
            if(old_point == nil) then
                table.insert(points, i)
            elseif(old_point ~= i) then
                table.insert(points, i)
            end
        end
    end

    local number_point = table.getn(points)

    if(number_point == 0) then
        return nil
    elseif(number_point == 1) then
        return patrol_path:level_vertex_id(points[1])
    else
        return patrol_path:level_vertex_id(points[math.random(1, number_point)])
    end
end

--頥  ᠬ  窨    ⮬,  ⥪饩 窨
function near_point_with_bit(point, patrol_path, bit)
    local new_point = nil
    local index     = nil
    local dist      = 1000.0

    for i = 0, patrol_path:count()-1 do
        if( patrol_path:flag(i, bit) ) then
            if(new_point == nil or patrol_path:point(i):distance_to(point) < dist) then
                --᫨  窠 ࢠ  襤,     ,   
                new_point   = patrol_path:point(i)
                index       = i
                dist        = new_point:distance_to(point)
             end
        end
    end

    return index
end

-- ᨢ ᯥ⪠ ⠡
function print_table(table, subs)
  local sub
  if subs ~= nil then
    sub = subs
  else
    sub = ""
  end
  for k,v in table do
    if type(v) == "table" then
      printf(sub.."%s:", k)
      print_table(v, sub.."    ")
    elseif type(v) == "function" then
      printf(sub.."%s:function", k)
    elseif type(v) == "userdata" then
      printf(sub.."%s:userdata", k)
    elseif type(v) == "boolean" then
	if v == true then 
		printf(sub.."%s:true", k)
	else
		printf(sub.."%s:false", k)
	end
    else
      if v ~= nil then
        printf(sub.."%s:%s", k,v)
      else
        printf(sub.."%s:nil", k,v)
      end
    end
  end
end

-------------------------------------------------------------------------------------------
function switch_online (id)
    if id == -1 then return end
    local sim = alife ()
    if sim ~= nil then
       sim:set_switch_online  (id, true) 
       sim:set_switch_offline (id, false)
    end   
end
-------------------------------------------------------------------------------------------
function switch_offline (npc)
    if npc == nil or npc:alive () == false then return end
    local sim = alife ()
    if sim ~= nil then
       sim:set_switch_online  (npc:id (), false) 
       sim:set_switch_offline (npc:id (), true)
    end   
end
-------------------------------------------------------------------------------------------
function get_actor_id()
	if(level.actor() == nil) then return -1 end
	return level.actor():id()
end 
