# script to fix loyalty cascade, when you order your militia to kill friendly units
=begin

fix/loyaltycascade
==================
Aborts loyalty cascades by fixing units whose own civ is the enemy.

=end
def fixunit(unit)
    return if unit.race != df.ui.race_id or unit.civ_id != df.ui.civ_id
    links = unit.hist_figure_tg.entity_links
    fixed = false

    # check if the unit is a civ renegade
    if i1 = links.index { |l|
        l.kind_of?(DFHack::HistfigEntityLinkFormerMemberst) and
        l.entity_id == df.ui.civ_id
    } and i2 = links.index { |l|
        l.kind_of?(DFHack::HistfigEntityLinkEnemyst) and
        l.entity_id == df.ui.civ_id
    }
        fixed = true
        i1, i2 = i2, i1 if i1 > i2
        links.delete_at i2
        links.delete_at i1
        links << DFHack::HistfigEntityLinkMemberst.cpp_new(:entity_id => df.ui.civ_id, :link_strength => 100)
        df.add_announcement "fixloyalty: #{unit.name} is now a member of #{df.ui.civ_tg.name} again"
    end

    # check if the unit is a group renegade
    if i1 = links.index { |l|
        l.kind_of?(DFHack::HistfigEntityLinkFormerMemberst) and
        l.entity_id == df.ui.group_id
    } and i2 = links.index { |l|
        l.kind_of?(DFHack::HistfigEntityLinkEnemyst) and
        l.entity_id == df.ui.group_id
    }
        fixed = true
        i1, i2 = i2, i1 if i1 > i2
        links.delete_at i2
        links.delete_at i1
        links << DFHack::HistfigEntityLinkMemberst.cpp_new(:entity_id => df.ui.group_id, :link_strength => 100)
        df.add_announcement "fixloyalty: #{unit.name} is now a member of #{df.ui.group_tg.name} again"
    end

    # fix the 'is an enemy' cache matrix (mark to be recalculated by the game when needed)
    if fixed and unit.enemy.enemy_status_slot != -1
        i = unit.enemy.enemy_status_slot
        unit.enemy.enemy_status_slot = -1
        cache = df.world.enemy_status_cache
        cache.slot_used[i] = false
        cache.rel_map[i].map! { -1 }
        cache.rel_map.each { |a| a[i] = -1 }
        cache.next_slot = i if cache.next_slot > i
    end

    # return true if we actually fixed the unit
    fixed
end

count = 0
df.unit_citizens.each { |u|
    count += 1 if fixunit(u)
}

if count > 0
    puts "loyalty cascade fixed (#{count} dwarves)"
else
    puts "no loyalty cascade found"
end