public void recomputeInformationAvailability(SocialGroup sg)
        {
            int CUTOFF = 128;
            HashSet <Location> closed    = new HashSet <Location>();
            List <Location>    working   = new List <Location>();
            List <double>      distances = new List <double>();

            foreach (Location a in locations)
            {
                if (a.soc == sg)
                {
                    closed.Add(a);
                    working.Add(a);
                    double dist = 1;
                    distances.Add(dist);
                    a.information.set(sg, dist);
                }
            }

            int steps = 0;

            while (working.Count > 0)
            {
                steps += 1;
                if (steps >= CUTOFF)
                {
                    break;
                }
                List <Location> next          = new List <Location>();
                List <double>   nextDistances = new List <double>();
                for (int i = 0; i < working.Count; i++)
                {
                    Location l    = working[i];
                    double   dist = distances[i];
                    dist *= l.getInformationAvailability();

                    dist = Math.Max(param.minInformationAvailability, dist);

                    l.information.set(sg, dist);

                    foreach (Location n in l.getNeighbours())
                    {
                        if (closed.Contains(n))
                        {
                            continue;
                        }

                        closed.Add(n);
                        nextDistances.Add(dist);
                        next.Add(n);
                    }
                }

                working   = next;
                distances = nextDistances;
            }
        }
        public List <SocialGroup> getExtendedNeighbours(SocialGroup sg)
        {
            int CUTOFF = 128;
            List <SocialGroup> reply   = new List <SocialGroup>();
            HashSet <Location> closed  = new HashSet <Location>();
            List <Location>    working = new List <Location>();

            foreach (Location a in locations)
            {
                if (a.soc == sg)
                {
                    closed.Add(a);
                    working.Add(a);
                }
            }

            int steps = 0;

            while (working.Count > 0)
            {
                steps += 1;
                if (steps >= CUTOFF)
                {
                    break;
                }
                List <Location> next          = new List <Location>();
                List <double>   nextDistances = new List <double>();
                for (int i = 0; i < working.Count; i++)
                {
                    Location l = working[i];

                    if (l.soc != null && l.soc != sg)
                    {
                        if (reply.Contains(l.soc) == false)
                        {
                            reply.Add(l.soc);
                        }
                    }
                    else
                    {
                        foreach (Location n in l.getNeighbours())
                        {
                            if (closed.Contains(n))
                            {
                                continue;
                            }

                            closed.Add(n);
                            next.Add(n);
                        }
                    }
                }
                working = next;
            }
            return(reply);
        }
        public void recomputeInformationAvailability(SocialGroup sg)
        {
            int CUTOFF = 128;
            HashSet <Location> closed    = new HashSet <Location>();
            List <Location>    working   = new List <Location>();
            List <int>         distances = new List <int>();

            foreach (Location a in locations)
            {
                if (a.soc == sg)
                {
                    closed.Add(a);
                    working.Add(a);
                    int dist = 0;
                    distances.Add(dist);
                    a.distanceToTarget[sg] = 0;
                }
            }

            int steps = 0;

            while (working.Count > 0)
            {
                steps += 1;
                if (steps >= CUTOFF)
                {
                    break;
                }
                List <Location> next          = new List <Location>();
                List <int>      nextDistances = new List <int>();
                for (int i = 0; i < working.Count; i++)
                {
                    Location l    = working[i];
                    int      dist = distances[i];

                    l.distanceToTarget[sg] = dist;

                    dist += 1;

                    foreach (Location n in l.getNeighbours())
                    {
                        if (closed.Contains(n))
                        {
                            continue;
                        }

                        closed.Add(n);
                        nextDistances.Add(dist);
                        next.Add(n);
                    }
                }

                working   = next;
                distances = nextDistances;
            }
        }
 public List <Location> getNeighbours(Location loc)
 {
     //List<Location> reply = new List<Location>();
     //foreach (Link l in loc.links)
     //{
     //    reply.Add(l.other(loc));
     //}
     //return reply;
     return(loc.getNeighbours());
 }
        public override void turnTick(Property p, Location location)
        {
            base.turnTick(p, location);

            bool underQuarantine = false;

            foreach (Property p2 in location.properties)
            {
                if (p2.proto is Pr_Quarantine)
                {
                    underQuarantine = true; break;
                }
            }

            if (location.settlement != null && location.settlement is SettlementHuman)
            {
                SettlementHuman set = (SettlementHuman)location.settlement;
                set.population -= 1;
                if (set.population <= 0)
                {
                    location.map.addMessage(set.location.getName() + " has been eradicated by the Red Death", MsgEvent.LEVEL_RED, true, location.hex);
                    if (set.title != null && set.title.heldBy != null)
                    {
                        set.title.heldBy.die("Died of the Red Death", true);
                    }
                    set.fallIntoRuin();
                }
            }

            foreach (Location l2 in location.getNeighbours())
            {
                if (l2.settlement != null && l2.settlement.isHuman && l2.soc != null && l2.soc is Society)
                {
                    bool canApply = true;
                    foreach (Property p2 in l2.properties)
                    {
                        if (p2.proto is Pr_RedDeath || p2.proto is Pr_RedDeathImmunity)
                        {
                            canApply = false;
                            break;
                        }
                    }
                    double pSpread = World.staticMap.param.unit_rd_redDeathPlaguePSpread;
                    if (underQuarantine)
                    {
                        pSpread /= 2;
                    }
                    if (canApply && Eleven.random.NextDouble() < pSpread)
                    {
                        Property.addProperty(World.staticMap, l2, "Red Death");
                        Society soc = (Society)l2.soc;
                        if (location.map.turn - soc.lastPlagueCrisis > location.map.param.society_crisis_plagueCrisisCooldown)
                        {
                            soc.crisisPlague     = "The Red Death Plague";
                            soc.crisisPlagueLong = "The Red Death plague is spreading in our lands, we must deal with this new crisis. " +
                                                   "We can either quarantine the disased settlements, treat infected patients, or we could deploy our agents as disease curing specialists.";
                            soc.lastPlagueCrisis = location.map.turn;
                        }
                    }
                }
            }
        }
        public override void turnTick(Unit unit)
        {
            if (unit.location.settlement != null)
            {
                unit.task = null;
                return;
            }

            dur += 1;
            if (dur >= unit.location.map.param.unit_establishNewSettlementTime || (!unit.location.map.burnInComplete))
            {
                unit.task = null;

                Location loc      = unit.location;
                int      c        = 0;
                Society  receiver = null;
                foreach (Location l2 in loc.getNeighbours())
                {
                    if (l2.soc != null && l2.soc is Society)
                    {
                        c += 1;
                        if (Eleven.random.Next(c) == 0)
                        {
                            receiver = (Society)l2.soc;
                        }
                    }
                }
                if (receiver == null)
                {
                    //foreach (SocialGroup sg in loc.map.socialGroups)
                    //{
                    //    if (sg is Society)
                    //    {
                    //        c += 1;
                    //        if (Eleven.random.Next(c) == 0)
                    //        {
                    //            receiver = (Society)sg;
                    //        }
                    //    }
                    //}
                    //Start a fully new colony.
                    //Maybe in time this could have a cool name, like "Merchant republic" and be a free port city or something
                    receiver = new Society(unit.location.map, loc);
                    receiver.setName(loc.shortName);
                    loc.soc = receiver;
                    unit.location.map.socialGroups.Add(receiver);
                }

                if (receiver != null)
                {
                    if (loc.isMajor)
                    {
                        loc.settlement = new Set_City(loc);
                    }
                    else
                    {
                        int      q       = 0;
                        double[] weights = new double[] { 2, 1, 2 };
                        double   roll    = 0;
                        for (int i = 0; i < weights.Length; i++)
                        {
                            roll += weights[i];
                        }
                        roll *= Eleven.random.NextDouble();
                        for (int i = 0; i < weights.Length; i++)
                        {
                            roll -= weights[i]; if (roll <= 0)
                            {
                                q = i; break;
                            }
                        }

                        if (q == 0)
                        {
                            loc.settlement = new Set_Abbey(loc);
                        }
                        else if (q == 1)
                        {
                            loc.settlement = new Set_University(loc);
                        }
                        else
                        {
                            loc.settlement = new Set_Fort(loc);
                        }
                    }

                    loc.soc = receiver;
                    SettlementHuman set = (SettlementHuman)loc.settlement;
                    set.population = 1;//Start at the start
                    loc.map.addMessage(loc.soc.getName() + " expands, add new settlement: " + loc.getName(), MsgEvent.LEVEL_RED, false, loc.hex);
                }
            }
        }
Exemple #7
0
        public void AI_WeakReleased(Map map)
        {
            if (this.movesTaken != 0)
            {
                return;
            }
            if (this.task is Task_GoToLocation)
            {
                return;
            }                                              //Already moving or fleeing

            if (this is Unit_Vampire vamp)
            {
                if (vamp.blood < vamp.maxBlood * 0.3 && location.person() != null)
                {
                    //Drink
                    vamp.blood = vamp.maxBlood;

                    double   amount = map.param.unit_minorEvidence;
                    Evidence e2     = new Evidence(map.turn);
                    e2.pointsTo = vamp;
                    e2.weight   = amount;
                    vamp.location.evidence.Add(e2);
                    return;
                }
            }


            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_Weak();
                        return;
                    }
                }
                else if (this.location.person().shadow < 1)
                {
                    this.task = new Task_SpreadShadow_Weak();
                    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");;
                }
            }
        }