-- function imp:_moure( foo, name )
    -- -- name = name or "anonymous"
    -- -- if not foo then 
    -- --     print_dbg(name.." not found") 
    -- -- else
    -- --     print_dbg(name)
    -- -- end
    -- self.moure = foo
-- end

function noop ()
end

-------------------------------
--
-------------------------------
function imp:reduce_timers()
    if self.mood=="stop" then return end
if DEBUG_FN_NAME then print_dbg("reduce_timers") end
    
    for key, val in pairs(self.timers) do
        local is_locked = string.sub(key, -7) == "_locked"
        if not is_locked then
            self.timers[key] = val - 1
            if (val-1)<0 then self.timers[key] = 0 end
        end
    end
    
    if self.invencible and self.invencible_time >0 then
        self.invencible_time = self.invencible_time - 1
    else
        self.invencible = false
    end
end

-------------------------------
--
-------------------------------
function imp:reset_timer( timer )
    if self.mood == "stop" then return end
if DEBUG_FN_NAME then print_dbg("reduce_timers") end
    local time = 0
    if     timer=="mood"        then time = 150
    elseif timer=="target"      then time = 350
    elseif timer=="shot"        then time = 100
    elseif timer=="super"       then time = 600
    elseif timer=="super_wait"  then time = 200
    elseif timer=="flip_wait" then time = 50
    end
    
    if time > 0 then self.timers[timer] = time end
end

-------------------------------
--
-------------------------------
function imp:analyze_env() --OK
    if self.mood=="stop" then return end
if DEBUG_FN_NAME then print_dbg("analyze_env") end
    -- Distancia fins a l'abad
    local r = distancia(self,abad)

    self.analisis.can_chase_abad = false
    if r<=100 then 
        self.analisis.can_chase_abad=true 
    end
    
    -- Els dos punts de cintura per a saber si es pot escalar
    local x1_check = self.x+self.bb.x
    local x2_check = self.x+self.bb.x+self.bb.w
    local y_check  = self.y+self.bb.h-4
    local tile_type1, tile_code1= arc_check_tile(x1_check,y_check)
    local tile_type2, tile_code2= arc_check_tile(x2_check,y_check)
    self.analisis.can_climb = false
    if tile_type1~=tiletype.void or tile_type2~=tiletype.void then
        self.analisis.can_climb = true
    end
    
    -- Abad a tir
    self.analisis.can_shot = false
    if h_collision(self,abad) then self.analisis.can_shot=true end
    
    -- Super preparat
    self.analisis.can_super = false
    if self.timers.super<=0 then self.analisis.can_super=true end
    
    -- Acces a la zona central (només si el super està preparat)
    x1_check = self.x+self.bb.x
    x2_check = self.x+self.bb.x+self.bb.w
    y_check  = self.y+self.bb.h+8
    self.analisis.can_go_altar = false
    hab1, tx1, ty1 = coords.world_to_tile(x1_check, y_check)
    hab2, tx2, ty2 = coords.world_to_tile(x2_check, y_check)
    if (hab1==44 and tx1==6 and ty1==4) or (hab2==44 and tx2==7 and ty2==4)
       or (hab1==45 and tx1==7 and ty1==3) or (hab2==45 and tx2==8 and ty2==3)then
        if self.analisis.can_super then self.analisis.can_go_altar = true end
    end

    -- Caiguent
    self.analisis.falling = false
    local tile_type1, tile_code1= arc_check_tile(x1_check,y_check)
    local tile_type2, tile_code2= arc_check_tile(x2_check,y_check)
    if tile_type1==tiletype.void and tile_type2==tiletype.void then
        self.analisis.falling = true
    end
    
    -- Cau al següent moviment?
    self.analisis.going_to_fall = false
    if not self.analisis.falling then
        local step_length = self.step_length
        
        -- default movent-se cap a la dreta
        x1_check = self.x+self.bb.x+(self.bb.w/2)
        x2_check = self.x+self.bb.x+self.bb.w
        if self.x_old>self.x then
            -- movent-se cap a l'esquerra
            step_length = -step_length 
            x1_check = self.x+self.bb.x
            x2_check = x1_check+(self.bb.w/2)
        elseif self.x_old==self.x then
            -- quet
            step_length = 0
            x1_check = self.x+self.bb.x
            x2_check = self.x+self.bb.x+self.bb.w
        end
        local tile_type1, tile_code1= arc_check_tile(x1_check+step_length,y_check)
        local tile_type2, tile_code2= arc_check_tile(x2_check+step_length,y_check)
        if tile_type1==tiletype.void and tile_type2==tiletype.void then
            self.analisis.going_to_fall = true
        end
    end
    
    -- Ha arribat a destí
    self.analisis.target_reached = false
    if not empty_table(self.pattern:target_node()) then
        -- Target reached
        if self.pattern:in_target(self) then self.analisis.target_reached=true end
    end
end

function imp:update_action_events()
   if self.analisis.going_to_fall then
        self:add_action_event("prefall")
    end
    
    if self.analisis.falling  then 
        self:add_action_event("falling")
    end
    
    if self.analisis.target_reached then 
        self:add_action_event("target")
    end
    
    if self.analisis.can_go_altar   then
        self:add_action_event("super_ready")
    end

    if self.x_old>self.x then
        self:add_action_event("left")
    end
    
    if self.x_old<self.x then
        self:add_action_event("right")
    end
end

function imp:check_action_event ( event ) 
    for _, v in ipairs(self.action_event) do
        -- print_dbg(v)
        if v == event then return true end
    end
    return false 
end

function imp:add_action_event ( event )
    table.insert(self.action_event, event)
end

-------------------------------
--
-------------------------------
function imp:choose_action() -- antic imp:move
if DEBUG_FN_NAME then print_dbg("choose_action "..self.mood.." / ".."stop") end
    -- if self.mood=="stop" then return self.mood end
    -- Si no te ganes de fer res, no moure
    if self.mood=="stop" then return self.actions.no_action end

    local next_action = self:next_action()
    
    if self.analisis.target_reached and next_action=="super" then
        self.add_action_event("super ready")
        -- next_action = self:next_action()
        -- self:super()
    end
    
    if self.old_action~=next_action then 
        self.old_action=next_action
    end

    self.action = next_action

    return next_action
end

-------------------------------
-- imp.controller_input()
--
-- Traduir a una entrada de pad
-------------------------------
function imp:controller_input()
if DEBUG_FN_NAME then print_dbg("controller_input") end

    if (self.action == self.actions.right or 
        self.action == self.actions.left) then
        if self.moure == imp.state_normal or self.moure == imp.state_walking then
            self.moure=imp.state_walking
        end
    elseif (self.action == self.actions.jump) then
        if self.moure == imp.state_normal or self.moure == imp.state_walking then
            self:jump()
        end
    elseif (self.action == self.actions.jumpfwd) then
        if self.moure == imp.state_normal or self.moure == imp.state_walking then
            self:jump(true)
        end
    elseif (self.action == self.actions.shot) then
        self:shot()
    elseif (self.action == self.actions.super) then
        self:super()
    end
    
    self.old_action = self.action
    self.action = self.actions.no_action
end

-------------------------------
--
-------------------------------
function imp:fight() -- OK
if DEBUG_FN_NAME then print_dbg("fight") end
    self:create_hot_points()
    self:load_pattern_paths()
    
    local node = 6
    local path = {target=6, actions={{action="right",event="target"}}}
    self.pattern:add_manual_target ( node, path )
    -- self.pattern.recovery = imp.pattern_recovery

    self.shot_target = abad

    self.mood=self.moods.chase
    self:pattern_movement()
    self.moure = imp.state_normal
    self.stucked = {x=0, y=0, t=0 }
end

-------------------------------
--
-------------------------------
function imp:shot(actor)
if DEBUG_FN_NAME then print("shot") end
    self:do_flip(abad)
    -- print_dbg("FIREBALL!!")
    
    local flip = false
    local x_ini = self.x+self.bb.x+self.bb.w+4
    if self.x>abad.x then 
        flip=true 
        x_ini = self.x-4
    end
    local hab, tx, ty, off_x, off_y = coords.world_to_tile(x_ini,self.y+(self.h/4))
    fireball.init(hab, tx, ty, flip, off_x, off_y)
    sound.play(audio_hit)
    
    self:reset_timer("shot")
end

-------------------------------
--
-------------------------------
function imp:create_hot_points() --OK
    self.pattern.node[1]  = point.new(44, 6, 3,  0, 0,"P1")
    self.pattern.node[2]  = point.new(45, 7, 3,  0, 0,"P2")
    self.pattern.node[3]  = point.new(44,12, 5,  8, 0,"P3")
    self.pattern.node[4]  = point.new(54, 5, 4,  0, 0,"P4")
    self.pattern.node[5]  = point.new(54,12, 4,  8, 0,"P5")
    self.pattern.node[6]  = point.new(55, 8, 4,  0, 0,"P6")
    self.pattern.node[7]  = point.new(55, 8, 0,  0, 0,"P7")
    self.pattern.node[8]  = point.new(54, 5, 0,  0, 0,"P8")
    self.pattern.node[9]  = point.new(54, 9, 1,  0, 0,"P9")
    self.pattern.node[10] = point.new(55, 4, 1,  0, 0,"P10")
    -- self.hot_points[11] = abad
    -- self.hot_points[11] = point.new(45, 1, 5, 8, 0,"altar-R")
    -- self.hot_points[12] = point.new(44,11, 5, 0, 0,"altar-L")
end

-------------------------------
--
-------------------------------
function imp:load_pattern_paths() --OK
    self.pattern.path[1] = { 
        {target=3, actions= {{action="right"  , event="prefall"},
                             {action="jumpfwd", event="land"},
                             {action="right"  , event="target"}}},
        {target=4, actions= {{action=""       , event="land"},
                             {action="right"  , event="land"},
                             {action="left"   , event="target"}}},
        {target=4, actions= {{action="right"  , event="prefall"},
                             {action="jumpfwd", event="land"},
                             {action="left"   , event="target"}}},
        {target=10, actions= {{action="right" , event="prefall"},
                              {action="jumpfwd", event="land"},
                              {action="right"  , event="target"}}},
        {target=6, actions= {{action="right"  , event="prefall"},
                             {action="jumpfwd", event="land"},
                             {action="right"  , event="target"}}},
        {target=5, actions= {{action="right"  , event="prefall"},
                             {action="jumpfwd", event="land"},
                             {action="right"  , event="land"},
                             {action="left"   , event="target"}}},
        {target=5, actions= {{action="right"  , event="target"}}}
    }
    self.pattern.path[2] = {
        {target=3, actions= {{action="left"   , event="prefall"},
                           {action="jumpfwd", event="land"},
                           {action="left"   , event="target"}}},
        {target=6, actions= {{action=""       , event="land"},
                             {action="left"   , event="land"},
                             {action="right"  , event="target"}}},
        {target=6, actions= {{action="left"   , event="prefall"},
                           {action="jumpfwd", event="land"},
                           {action="right"  , event="target"}}},
        {target=6, actions= {{action="left"   , event="prefall"},
                           {action="jumpfwd", event="land"},
                           {action="left"   , event="land"},
                           {action="right"  , event="target"}}},
        {target=6, actions= {{action="left"   , event="prefall"},
                           {action="jumpfwd", event="land"},
                           {action="right"   , event="land"},
                           {action="left"   , event="land"},
                           {action="right"  , event="target"}}},
        {target=9, actions= {{action="left"   , event="prefall"},
                           {action="jumpfwd", event="land"},
                           {action="left"   , event="target"}}},
        {target=4, actions= {{action="left"   , event="prefall"},
                           {action="jumpfwd", event="land"},
                           {action="left"   , event="target"}}},
        {target=5, actions= {{action="left"   , event="prefall"},
                           {action="jumpfwd", event="land"},
                           {action="left"   , event="land"},
                           {action="right"  , event="target"}}},
        {target=5, actions= {{action="left"   , event="target"}}}
    }
    self.pattern.path[3] = {
        {target=1, actions={{action="left"   , event="prefall"},
                          {action="jumpfwd", event="land"},
                          {action="left"   , event="prefall"},
                          {action="jump"   , event="target"}}},
        {target=2, actions={{action="right"  , event="prefall"},
                          {action="jumpfwd", event="land"},
                          {action="right"  , event="prefall"},
                          {action="jump"   , event="target"}}},
        {target=4, actions={{action="left"   , event="prefall"},
                          {action="jumpfwd", event="land"},
                          {action="right"  , event="land"},
                          {action="left"   , event="target"}}},
        {target=5, actions={{action="left"   , event="land"},
                          {action="right"  , event="target"}}},
        {target=6, actions={{action="left"   , event="land"},
                          {action="right"  , event="target"}}}
    }
    self.pattern.path[4] = {
        {target=1, actions={{action="jump" , event="target"}}},
        {target=5, actions={{action="right", event="target"}}},
        {target=6, actions={{action="right", event="target"}}},
        {target=8, actions={{action="jump" , event="target"}}},
    }
    self.pattern.path[5] = {
        {target=4, actions={{action="left" , event="target"}}},
        {target=6, actions={{action="right", event="target"}}}
    }
    self.pattern.path[6] = {
        {target=2, actions={{action="jump", event="target"}}},
        {target=5, actions={{action="left", event="target"}}},
        {target=7, actions={{action="jump", event="target"}}},
        {target=4, actions={{action="left", event="target"}}}
    }
    self.pattern.path[7] = {
        {target=5, actions={{action="left"   , event="prefall"},
                          {action="jumpfwd", event="land"},
                          {action="left"   , event="target"}}},
        {target=10,actions={{action=""   , event="land"},
                            {action="left"   , event="land"},
                            {action="left"   , event="prefall"},
                            {action="jumpfwd", event="land"},
                            {action="left"   , event="target"}}},
        {target=2, actions={{action="jump"   , event="target"}}},
        {target=6, actions={{action="" , event="land"},
                            {action="left" , event="land"},
                            {action="left" , event="land"},
                            {action="right", event="target"}}},
        
    }
    self.pattern.path[8] = {
        {target=5, actions={{action="right"   , event="prefall"},
                         {action="jumpfwd" , event="land"},
                         {action="right"   , event="target"}}},
        {target=9, actions={{action=""   , event="land"},
                          {action="right"   , event="land"},
                          {action="jumpfwd" , event="land"},
                          {action="right"   , event="target"}}},
        {target=1, actions={{action="jump"    , event="target"}}}
    }
    self.pattern.path[9] = {
        {target=6, actions={{action="right"   , event="target"}}},
        {target=5, actions={{action="right"   , event="target"}}},
        {target=1, actions={{action="left"   , event="prefall"},
                          {action="jumpfwd" , event="land"},
                          {action="left"   , event="prefall"},
                          {action="jump"    , event="target"}}},
        {target=4, actions={{action="left"    , event="target"}}}
    }
    self.pattern.path[10] = {
        {target=5, actions={{action="left"    , event="target"}}},
        {target=2, actions={{action="right"    , event="prefall"},
                         {action="jumpfwd" , event="land"},
                         {action="right"    , event="prefall"},
                         {action="jump"    , event="target"}}},
        {target=6, actions={{action="right"   , event="target"}}},
        {target=6, actions={{action="left"   , event="land"},
                            {action="right" , event = "target"}}}
    }
    self.pattern.path[11] = {
        {target=4, actions={{action="left", event="target"}}}
    }
    self.pattern.path[12] = {
        {target=6, actions={{action="right", event="target"}}}
    }

end

-------------------------------------------------------------------
-- // PATTERN MOVEMENT

function imp:pattern_movement() --OK
if DEBUG_FN_NAME then print_dbg("pattern_movement") end
    self.move_type = self.move_types.pattern
    -- print("Pattern")
end

function imp:pattern_recovery() -- OK
-- print("Pattern recovery")
    self:pattern_movement() -- Canviar a moviment per patró
    
    -- Situar-se en el mapa respecte als punts de recuperació (els tres punts del pis)
    local x_after_4 = false
    local x_after_5 = false
    local x_after_6 = false
    local y_upper_4 = false
    local y_upper_5 = false
    local y_upper_6 = false
    
    if self.pattern.node[4].x<self.x then x_after_4 = true end
    if self.pattern.node[5].x<self.x then x_after_5 = true end
    if self.pattern.node[6].x<self.x then x_after_6 = true end
    -- Comparar en el punt dels peus
    if self.pattern.node[4].y>self.y+self.h then y_upper_4 = true end
    if self.pattern.node[5].y>self.y+self.h then y_upper_5 = true end
    if self.pattern.node[6].y>self.y+self.h then y_upper_6 = true end

    local node = 0
    local path = {}
    -- Seleccionar les instruccions segons la posicio
    if not y_upper_5 then
        -- target 5
        node = 5
        if not x_after_5 then
            -- right target
            path = {target=5, actions={{action="right",event="target"}}}
        else
            -- left target
            path = {target=5, actions={{action="left",event="target"}}}
        end
    else
        if x_after_5 then
            --target 4
            node = 4
            -- left target
            path = {target=4, actions={{action="left",event="target"}}}
        else
            --target 6
            node = 6
            -- right target
            path = {target=6, actions={{action="right",event="target"}}}
        end
    end
    self.pattern:add_manual_target ( node, path )
    
    -- Tornar l'acció a fer
    -- return self.actions[self.path.actions[1].action]
end


-------------------------------------------------------------------
-- // ACTION
function imp:next_action()
    local next_action = self.actions.no_action
    
    -- Si el blanc està a tir disparar
    if self.timers.shot<=0 and 
       h_collision(self, self.shot_target) and 
       not self.invencible then
        next_action = "shot"
    end

    -- anar a fer el super
    if self.timers.super<=0 then
        self.pattern:set_target_mode(PATTERN_CHASE,self.pattern.node[1])
    else
        self.pattern:set_target_mode(self.mood,abad)
    end

    -- fer el super
    if self.timers.super<=0 and self:check_action_event("super_ready") then
        if self.x<self.pattern.node[3].x then
            local node = 3
            local path = {target=3, actions= {{action="jumpfwd", event="land"},
                                              {action="right"  , event="target"},
                                              {action="super"  , event="super"}}}
            self.pattern:add_manual_target(node, path)
        end
    end

    -- Resta d'accions
    if next_action==self.actions.no_action then
        if self.timers.target<=0 or self.stucked.t>=self.timers.stucked_locked then 
            self:pattern_recovery()
            self:reset_timer("target")
        end
        if self.move_type==self.move_types.free then
        -- FREE
            -- next_action = self:free_next_action()
        elseif self.move_type==self.move_types.pattern then
        -- PATTERN
            local action_event_done = self:check_action_event(self.pattern:event())
            -- local str_aev = ""
            -- for k,v in pairs(self.action_event) do str_aev=str_aev..", "..v end
            if action_event_done then
                next_action=self.pattern:next_action()
                -- print_dbg("NEXT ACTION "..next_action)
            else
                next_action=self.pattern:action()
                -- print_dbg("HOLD ACTION "..next_action)
            end
        elseif self.move_type==self.move_types.super then
        -- SUPER
            --
            next_action = "no_action"
        end
    end
    self.action_event = {}
    -- next_action es text, traduir
    return self.actions[next_action]
end

function imp:jump ( jumpfwd )
if DEBUG_FN_NAME then print_dbg("") end
    -- Inicialització de fer el salt
    jumpfwd = jumpfwd or false
    self.jump_height = 0
    -- self.step=0
    self:_step(0,"jump")
    self.jumpfwd=jumpfwd
    self.moure = imp.state_jumping
end

function imp:state_jumping()
    if self.mood=="stop" then return self.mood end
if DEBUG_FN_NAME then print_dbg("state_jumping") end
    -- ??
    self.wait=self.wait+1
    self.wait=0
    self.next_frame=imp.jumping_next_frame
    -- Pujar o caure
    if self.jump_height<self.max_jump_height then
        -- Comprovar que pasa en l'aire
        self:do_jump()
    else
        -- Canviar a mode caure
        self.moure = imp.state_falling
    end
    -- self.step=self.step+1
    self:_step(self.step+1,"state_jumping")

    -- cap endavant?
    if self.jumpfwd then self:advance() end
end

function imp:do_jump()
if DEBUG_FN_NAME then print_dbg("jump") end

    local vspace = self.vmove_space
    -- Els dos punts de dalt del personatge
    local x1_check = self.x+self.bb.x
    local x2_check = self.x+self.bb.x+self.bb.w
    local y_check = self.y-vspace; -- posicio de dalt

    -- Comprovar on està pegant
    local tile1_hit_type= arc_check_tile(x1_check, y_check )
    local tile2_hit_type= arc_check_tile(x2_check, y_check)
    local not_block_tile = tile1_hit_type ~= tiletype.block and tile2_hit_type ~= tiletype.block

    -- Fer l'acció que correspon
    if not_block_tile then
        -- Ascendir
        self.old_y = self.y
        self.y=self.y-vspace
    else
        -- Si es un bloc permetre gastar l'espai no pintat
        local tile1_hit = arc_get_tile(x1_check, y_check )
        local tile2_hit = arc_get_tile(x2_check, y_check)
        local half_block1 = mapa_is_half_block_tile(map_to_editor_tile(tile1_hit))
        local half_block2 = mapa_is_half_block_tile(map_to_editor_tile(tile2_hit))
        local full_block1 = tile1_hit_type == tiletype.block and not half_block1
        local full_block2 = tile2_hit_type == tiletype.block and not half_block2
        local full_block = full_block1 and full_block2
        local half_block = half_block1 or half_block2
        -- Si ninguno dels tiles tocats es un block complet
        -- i almenys un dels tiles tocats es mig tile
        -- permetre continuar en el salt
        if not full_block and half_block then
            if self.jump_in_half_block==0 and not self.jump_in_half_block_used then
                self.jump_in_half_block = arcade_config.tiles_height / 2
            end
            if self.jump_in_half_block>0 then
                self.old_y = self.y
                self.y=self.y-vspace
                self.jump_in_half_block = self.jump_in_half_block-1
                self.jump_in_half_block_used = true
            end
        end
    end

    -- Registrar el desplaçament
    self.jump_height = self.jump_height+vspace
end

function imp:advance()
if DEBUG_FN_NAME then print_dbg("advance") end

    local limit=tiletype.block

    if self.moure~=imp.state_walking then limit=tiletype.half end

    local step_length=self.step_length; --lo que avança el imp cada pas
    local x_check = 0
    local y_check = self.y+self.bb.h-1

    if (self.old_action == self.actions.right or 
        self.old_action == self.actions.left) then
        -- orientació des de control
        if self.old_action == self.actions.left then
            step_length = -step_length
            x_check = self.x+self.bb.x
        else
            x_check = self.x+self.bb.x+self.bb.w
        end
        x_check = x_check + step_length
    else
        -- detectar orientacio des del movimentl
        if self.x_old>self.x then
            step_length = -step_length
            x_check = self.x+self.bb.x
        else
            x_check = self.x+self.bb.x+self.bb.w
        end
    
        x_check = x_check + step_length
    end

    if arc_check_tile(x_check, y_check)<limit then
        self.x_old = self.x
        self.x=self.x+step_length
    end

    local hab,xx, yy = coords.world_to_tile(self.x, self.y)
    self.hab = hab
end

function imp:state_falling()
if DEBUG_FN_NAME then print_dbg("state_falling") end
    -- self.frame=30
    self.wait=self.wait+1
    self.next_frame=imp.falling_next_frame
    -- Si toca terra canviar el mode
    if self:land() then
        self.moure = imp.state_normal
        self.jumpfwd = false
        return
    end

    -- Seguir caiguent
    self.old_y = self.y
    self.y=self.y+1
    self.jump_height = self.jump_height-1
    self.falling=self.falling+1

    -- Caiguent cap endavant?
    if self.jumpfwd then self:advance() end
end

function imp:land ()
if DEBUG_FN_NAME then print_dbg("land") end
    -- Els dos punts de baix de l'abad
    local x1_check = self.x+self.bb.x
    local x2_check = self.x+self.bb.x+self.bb.w
    local y_check = self.y+self.bb.h

    -- Comprovar on està aterrant
    local tile1_hit= arc_check_tile(x1_check, y_check )
    local tile2_hit= arc_check_tile(x2_check, y_check)
    local floor_tile = tile1_hit>=tiletype.half or tile2_hit>=tiletype.half

    -- Encara que siga un tile de piso s'ha de comprovar que
    -- la y es un múltiple de l'alt dels tiles
    local over_tile = (y_check & 0xF) == 0

    local can_land = floor_tile and over_tile

    if can_land then
        self.jump_in_half_block_used = false
        self.jump_height = 0
        self:add_action_event("land")
    end
-- if can_land then print_dbg ("LANDED") end
    return can_land
end

function imp:state_walking()
    if self.mood=="stop" then return end
if DEBUG_FN_NAME then print("state_walking") end

    -- Limitar la velocitat de moviment
    self.wait=self.wait+1

    -- Funció de selecció de frame
    self.next_frame = imp.walking_next_frame

    -- Comprovar dos punts de contacte del personatge en el piso a vore si cau
    local x1_check = self.x+self.bb.x
    local x2_check = x1_check+self.bb.w
    local y_check = self.y+self.bb.h; -- base del personatge
    local tile1 = arc_check_tile(x1_check,y_check)
    local tile2 = arc_check_tile(x2_check,y_check)
    if tile1==tiletype.void and tile2==tiletype.void then
        -- si no hi ha piso, caure
        self.moure = imp.state_falling
        return
    end

    self:advance()
end

function imp:state_normal()
if DEBUG_FN_NAME then print_dbg("state_normal") end
    self.frame=28
    self.wait=0
    -- self.step=0
    self:_step(0,"state_normal")
    self.jumpfwd=false
    self.jump_height = 0
    self.next_frame=imp.staying_next_frame
end

-- imp.next_frame()
function imp:walking_next_frame()
    -- Selecció de frame
    if self.wait>=6 then
        self.wait=0
        -- self.step=(self.step+1)%4
        self:_step((self.step+1)%4,"walking_next_frame")
        self.frame=self.anim[self.step+1]
    end
    
    -- Orientar
    self:do_flip()
    
    -- Aguantar el flip
    if self.timers.flip_wait<=0 then 
        if self.mood==self.moods.chase then
            self:do_flip(abad)
        else
            self:do_flip(self.pattern:target_node())
        end
    end
end

function imp:jumping_next_frame()
    self.frame=30
end

function imp:falling_next_frame()
    self.frame=30
end

function imp:staying_next_frame()
    self.frame=28
end

-- function imp:super_next_frame()
    -- self.frame=11
-- end

function imp:do_flip( actor )
    actor = actor or self.pattern:target_node()
    -- enllaçat a actor
    if actor.x<self.x then 
        self.flip=true
    else 
        self.flip=false 
    end
    self:reset_timer("flip_wait")
end

function imp:super()
if DEBUG_FN_NAME then print("super()") end
    self:super_movement()
    self.invencible = true
    self.moure = imp.state_super
    self:reset_timer("super_wait")
end

function imp:state_super()
if DEBUG_FN_NAME then print("state_super") end
    -- self.super_wait = self.super_wait -1
    local wait = self.timers.super_wait

    if self.zoom<1.75 and wait>100 then
        if wait%4==0 then self.zoom=self.zoom+0.1 end
    elseif not self.super_fired and self.zoom>=1.75 and wait>100 then
        local x_ini = self.x+self.bb.x+self.bb.w+4
        local hab, tx, ty, off_x, off_y = coords.world_to_tile(x_ini,self.y+(self.h/2))
        fireball.init(hab, tx, ty, false, off_x, off_y, 2)
        self.super_fired = true
    elseif self.zoom>1 and wait<=100 then
        if wait%4==0 then self.zoom=self.zoom-0.1 end
    end

    if wait == 0 then
        self.moure = imp.super_end
    end
end

function imp:super_end()
    self.zoom = 1
    self.invencible = false
    self.super_fired = false
    self.moure = imp.state_normal
    self:reset_timer("mood")
    self:reset_timer("super")
    self:reset_timer("super_wait")
    self:pattern_movement()
    self:pattern_recovery()
end

function imp:super_movement()
if DEBUG_FN_NAME then print("super_movement") end
    self.move_type = self.move_types.super
end


function imp:choose_mood()
    if self.mood=="stop" then return end
    if self.timers.mood<=0 then
        self.mood=self.moods[math.random(2+(math.random(2)-1))+1] -- chase o avoid o aleatoriament neutral
        self:reset_timer("mood")
        print(self.mood)
    end
end
