public void flee(Map map)
        {
            double bestDist = 0;
            Location target = null;
            foreach (Location l2 in map.locations)
            {
                bool safe = true;
                if (l2.soc == null  || l2.soc.hostileTo(this)) {continue; }
                foreach (Unit u in l2.units)
                {
                    if (u.hostileTo(this)) { safe = false;break; }
                }
                if (!safe) { continue; }
                foreach (Location l3 in l2.getNeighbours())
                {
                    if (!safe) { break; }
                    foreach (Unit u in l3.units)
                    {
                        if (u.hostileTo(this)) { safe = false;break; }
                    }
                }
                if (!safe) { continue; }

                //Evaluated as safe. Flee option
                double dist = map.getDist(this.location, l2);
                if (dist < bestDist || target == null)
                {
                    target = l2;
                    bestDist = dist;
                }
            }
            task = new Task_GoToLocation(target);
        }
        public override void turnTickInner(Map map)
        {
            if (this.movesTaken != 0)
            {
                return;
            }
            if (this.task is Task_GoToLocation)
            {
                return;
            }                                              //Already moving or fleeing


            bool shouldFlee = false;

            if (this.location.soc != null && this.location.soc.hostileTo(this))
            {
                shouldFlee = true;
            }
            if (!shouldFlee)
            {
                foreach (Unit u in location.units)
                {
                    if (u.hostileTo(this))
                    {
                        shouldFlee = true; break;
                    }
                }
            }
            if (!shouldFlee)
            {
                foreach (Location l2 in location.getNeighbours())
                {
                    if (shouldFlee)
                    {
                        break;
                    }
                    foreach (Unit u in l2.units)
                    {
                        if (u.hostileTo(this))
                        {
                            shouldFlee = true; break;
                        }
                    }
                }
            }
            if (shouldFlee)
            {
                flee(map);
            }
            if (this.task != null)
            {
                return;
            }


            this.movesTaken += 1;
            if (this.location.person() != null)
            {
                if (this.location.settlement.infiltration < World.staticMap.param.ability_unit_spreadShadowInfiltrationReq)
                {
                    bool lockedDown = false;
                    foreach (Property p in location.properties)
                    {
                        if (p.proto is Pr_Lockdown)
                        {
                            lockedDown = true;
                            break;
                        }
                    }
                    if (location.settlement.security >= 5)
                    {
                        lockedDown = true;
                    }
                    if (!lockedDown)
                    {
                        this.task = new Task_Infiltrate();
                        return;
                    }
                }
                else if (this.location.person().shadow < 1)
                {
                    this.task = new Task_SpreadShadow();
                    return;
                }
            }

            //We're not starting a new task, so this location is bad. Onwards to greener pastures
            Location target     = null;
            double   bestDist   = -1;
            int      c          = 0;
            Location safeHarbor = null;

            foreach (Location loc in map.locations)
            {
                if (loc == this.location)
                {
                    continue;
                }
                if (loc.soc == null)
                {
                    continue;
                }
                if (loc.soc.hostileTo(this))
                {
                    continue;
                }
                if (loc.person() != null && loc.soc is Society && loc.person().shadow < 1)
                {
                    bool good = true;
                    foreach (Unit u in loc.units)
                    {
                        if (u.hostileTo(this))
                        {
                            good = false; break;
                        }
                    }
                    if (loc.settlement.security >= 5)
                    {
                        good = false;
                    }
                    if (good)
                    {
                        foreach (Property pr in loc.properties)
                        {
                            if (pr.proto is Pr_Lockdown)
                            {
                                good = false; break;
                            }
                            if (pr.proto is Pr_MajorSecurityBoost)
                            {
                                good = false; break;
                            }
                        }
                    }

                    if (good)
                    {
                        double dist = Math.Abs(loc.hex.x - this.location.hex.x) + Math.Abs(loc.hex.y - this.location.hex.y);
                        //dist *= Eleven.random.NextDouble();
                        double score = (loc.person().prestige + 5) / (dist + 1);

                        if (loc.map.overmind.lightbringerLocations.Contains(loc))
                        {
                            score *= 25;
                        }
                        //score *= Eleven.random.NextDouble() * Eleven.random.NextDouble();
                        //if (dist < bestDist || bestDist == -1)
                        //{
                        //    bestDist = dist;
                        //    target = loc;
                        //}
                        if (score > bestDist || bestDist == -1)
                        {
                            bestDist = score;
                            target   = loc;
                        }
                    }
                }

                if (loc.soc is Society)
                {
                    c += 1;
                    if (Eleven.random.Next(c) == 0)
                    {
                        safeHarbor = loc;
                    }
                }
            }
            if (target != null)
            {
                task = new Task_GoToLocation(target);
            }
            else
            {
                //We're unable to find anywhere to infiltrate. Probably banned from everywhere else. Do we have safe harbor? Can we change our name?
                if (location.soc is Society && location.soc.hostileTo(this) == false)
                {
                    //In a safe harbor, swap out now
                    task = new Task_ChangeIdentity();
                }
                else if (safeHarbor != null)
                {
                    task = new Task_GoToLocation(safeHarbor);
                }
                else
                {
                    die(map, "Was no further use");;
                }
            }
        }
        public override void turnTickAI(Map map)
        {
            if (task != null)
            {
                task.turnTick(this);
                return;
            }

            if (location.settlement == null && location.isForSocieties && location.soc == null && location.hex.getHabilitability() > map.param.mapGen_minHabitabilityForHumans)
            {
                task = new Task_EstablishNewSettlement();
                task.turnTick(this);
                return;
            }
            if (Eleven.random.NextDouble() < map.param.unit_merchantChanceToExpandIntoNeighbouring)
            {
                int      c      = 0;
                Location target = null;
                //foreach (Location loc in society.lastTurnLocs)
                //{
                foreach (Location l2 in map.locations)
                {
                    if (l2.settlement == null && l2.isForSocieties && l2.soc == null && l2.hex.getHabilitability() > map.param.mapGen_minHabitabilityForHumans)
                    {
                        c += 1;
                        if (Eleven.random.Next(c) == 0)
                        {
                            target = l2;
                        }
                    }
                }
                //}
                task = new Task_GoToLocation(target);
                task.turnTick(this);
                return;
            }

            if (this.cash >= 50)
            {
                if (location.soc == society)
                {
                    task = new Task_SpendWealth();
                    return;
                }
                else
                {
                    task = new Task_GoToSocialGroup(society);
                    return;
                }
            }
            if (this.cargo >= 50)
            {
                if (location.soc != null && location.soc != society)
                {
                    task = new Task_SellCargo();
                    return;
                }
                double   bestV   = 0;
                Location bestLoc = null;
                foreach (Location l2 in map.locations)
                {
                    if (l2.soc is Society && l2.soc != society && (l2.soc.hostileTo(this) == false))
                    {
                        double v = Eleven.random.NextDouble() * location.map.getDist(location.hex, l2.hex);
                        if (v > bestV)
                        {
                            bestV   = v;
                            bestLoc = l2;
                        }
                    }
                }
                if (bestLoc != null)
                {
                    task = new Task_GoToLocation(bestLoc);
                    return;
                }

                //Otherwise
                if (location.soc is Society && (location.soc.hostileTo(this) == false) && location.settlement != null)
                {
                    //Couldn't find anywhere better
                    task = new Task_SellCargo();
                    return;
                }
            }
            else
            {
                if (location.soc == society)
                {
                    task = new Task_LoadCargo();
                    return;
                }
                else
                {
                    task = new Task_GoToSocialGroup(society);
                }
            }
        }
        public void turnTickAI_Medic(Map map)
        {
            if (task == null)
            {
                bool onDisease = false;
                foreach (Property pr in location.properties)
                {
                    if (pr.proto.isDisease)
                    {
                        onDisease = true;
                        break;
                    }
                }
                if (onDisease)
                {
                    task = new Task_TreatDisease();
                    return;
                }

                double   dist      = 0;
                Location plagueLoc = null;
                foreach (Location loc in map.locations)
                {
                    if (loc.soc == null || loc.soc.hostileTo(this))
                    {
                        continue;
                    }

                    bool hasDisease = false;
                    foreach (Property pr in loc.properties)
                    {
                        if (pr.proto.isDisease)
                        {
                            hasDisease = true;
                            break;
                        }
                    }
                    if (!hasDisease)
                    {
                        continue;
                    }
                    double d = map.getDist(loc.hex, location.hex);
                    if (plagueLoc == null)
                    {
                        plagueLoc = loc;
                        dist      = d;
                    }
                    else if (plagueLoc.soc != this.society && loc.soc == this.society)
                    {
                        plagueLoc = loc;
                        dist      = d;
                    }
                    else if (plagueLoc.soc == this.society && loc.soc != this.society)
                    {
                        //Don't switch to prefer a foreign location
                    }
                    else if (d < dist)
                    {
                        dist      = d;
                        plagueLoc = loc;
                    }
                }
                if (plagueLoc != null)
                {
                    task = new Task_GoToLocation(plagueLoc);
                }
            }
            if (task != null)
            {
                task.turnTick(this);
            }
        }