#textdomain wesnoth-utbs

# event for the teaching ability
#define ABILITY_TEACHING_EVENT
    [event]
        name=turn refresh,victory
        id=garak_teaching
        first_time_only=no

        [lua]
            # wmllint: markcheck off
            code=<<
                local _ = wesnoth.textdomain "wesnoth-utbs"

                local teachers = wesnoth.get_units { ability = "teaching", side = wesnoth.current.side }

                for i, teacher in ipairs(teachers) do
                    local students = wesnoth.get_units { side = wesnoth.current.side, { "filter_adjacent", { id = teacher.id } } }

                    if #students > 0 then -- don't divide by zero
                        wesnoth.scroll_to_tile(teacher.x, teacher.y)

                        local function cf(u1, u2)
                            -- criteria: the unit with lower level comes first
                            -- if level is equal, the unit with less experience comes first
                            if u1.level < u2.level then return true end
                            if u1.level > u2.level then return false end
                            if u1.experience < u2.experience then return true end
                            return false
                        end

                        table.sort(students, cf)

                        -- now we need to divide Garak's xp between all the units
                        -- we can't just round the result of the division, because this will mean
                        -- either not redistributing all the XP points, or generating them out of thin air
                        -- so we perform both a division and a modulo
                        -- # (length) has a higher precedence than *, / and %
                        local div = math.floor(teacher.experience / #students)
                        local mod = teacher.experience % #students

                        for j, student in ipairs(students) do
                            -- the modulo operation is used to redistribute every remaining XP
                            -- so at the start of each turn Garak goes back to 0 XP
                            -- concrete example: we have 9 XP and 4 units
                            -- the first unit will receive 3 XP, while the other units 2
                            local xp_to_add = div
                            if j <= mod then
                                xp_to_add = xp_to_add + 1
                            end

                            -- having a message that tells you that the unit gained 0 XP is simply obnoxious
                            if xp_to_add > 0 then
                                student.experience = student.experience + xp_to_add
                                -- performance-wise, string concatenation is slower than string interpolation
                                -- but it's way more readable than two nested interpolations...
                                wesnoth.float_label(student.x, student.y, "<span color='cyan'>" .. tostring(_ "+%d XP"):format(xp_to_add) .. "</span>")
                                if student.experience >= student.max_experience then
                                    -- advance unit, animate and fire events
                                    wesnoth.advance_unit(student, true, true)
                                end
                            end
                        end
                    end

                    -- in case that Garak has no "students", his experience goes wasted instead of being redistributed...
                    teacher.experience = 0
                end
            >>
            # wmllint: markcheck off
        [/lua]
    [/event]
#enddef
