Exemplo n.º 1
0
        public void WarpPointAngularDistance()
        {
            Assert.IsTrue(GalaxyTemplate.AngleIsInRangeExclusive(15, 0, 60));
            Assert.IsTrue(GalaxyTemplate.AngleIsInRangeExclusive(-15, 0, 60));
            Assert.IsTrue(GalaxyTemplate.AngleIsInRangeExclusive(345, 0, 60));

            Assert.IsFalse(GalaxyTemplate.AngleIsInRangeExclusive(90, 0, 60));
            Assert.IsFalse(GalaxyTemplate.AngleIsInRangeExclusive(-90, 0, 60));
            Assert.IsFalse(GalaxyTemplate.AngleIsInRangeExclusive(270, 0, 60));

            Assert.IsTrue(GalaxyTemplate.AngleIsInRangeExclusive(165, 180, 60));
            Assert.IsTrue(GalaxyTemplate.AngleIsInRangeExclusive(-195, 180, 60));

            Assert.IsFalse(GalaxyTemplate.AngleIsInRangeExclusive(90, 180, 60));
            Assert.IsFalse(GalaxyTemplate.AngleIsInRangeExclusive(-90, 180, 60));
            Assert.IsFalse(GalaxyTemplate.AngleIsInRangeExclusive(270, 180, 60));

            Assert.IsTrue(GalaxyTemplate.AngleIsInRangeExclusive(0, 30, 60));
            Assert.IsTrue(GalaxyTemplate.AngleIsInRangeExclusive(15, 30, 60));
            Assert.IsTrue(GalaxyTemplate.AngleIsInRangeExclusive(-15, 30, 60));
            Assert.IsTrue(GalaxyTemplate.AngleIsInRangeExclusive(345, 30, 60));

            Assert.IsFalse(GalaxyTemplate.AngleIsInRangeExclusive(90, 30, 60));
            Assert.IsFalse(GalaxyTemplate.AngleIsInRangeExclusive(-30, 30, 60));
            Assert.IsFalse(GalaxyTemplate.AngleIsInRangeExclusive(330, 30, 60));

            Assert.IsTrue(GalaxyTemplate.AngleIsInRangeExclusive(0, -30, 60));
            Assert.IsTrue(GalaxyTemplate.AngleIsInRangeExclusive(15, -30, 60));
            Assert.IsTrue(GalaxyTemplate.AngleIsInRangeExclusive(-15, -30, 60));
            Assert.IsTrue(GalaxyTemplate.AngleIsInRangeExclusive(345, -30, 60));

            Assert.IsFalse(GalaxyTemplate.AngleIsInRangeExclusive(90, -30, 60));
            Assert.IsFalse(GalaxyTemplate.AngleIsInRangeExclusive(-90, -30, 60));
            Assert.IsFalse(GalaxyTemplate.AngleIsInRangeExclusive(270, -30, 60));
        }
Exemplo n.º 2
0
        public void VerticalAndHorizontalIntersectionsCount()
        {
            var p1 = new Point(-1, 0);
            var p2 = new Point(1, 0);
            var q1 = new Point(0, -1);
            var q2 = new Point(0, 1);

            Assert.IsTrue(GalaxyTemplate.IntersectsExceptAtEnds(p1, p2, q1, q2));
        }
Exemplo n.º 3
0
        public void CollinearIntersectionsCount()
        {
            var p1 = new Point(0, 0);
            var p2 = new Point(0, 10);
            var q1 = new Point(0, 2);
            var q2 = new Point(0, 11);

            Assert.IsTrue(GalaxyTemplate.IntersectsExceptAtEnds(p1, p2, q1, q2));
        }
Exemplo n.º 4
0
        public void CrossoverIntersectionsCount()
        {
            var p1 = new Point(-1, -1);
            var p2 = new Point(1, 1);
            var q1 = new Point(1, -1);
            var q2 = new Point(-1, 1);

            Assert.IsTrue(GalaxyTemplate.IntersectsExceptAtEnds(p1, p2, q1, q2));
        }
Exemplo n.º 5
0
        public void IntersectionsAtEndpointAndMiddleDoCount()
        {
            var p1 = new Point(0, 0);
            var p2 = new Point(10, 0);
            var q1 = new Point(9, -1);
            var q2 = new Point(11, 1);

            Assert.IsTrue(GalaxyTemplate.IntersectsExceptAtEnds(p1, p2, q1, q2));
        }
Exemplo n.º 6
0
        public void IntersectionsAtEndpointsDoNotCount()
        {
            var p1 = new Point(0, 0);
            var p2 = new Point(10, 0);
            var q1 = new Point(10, 0);
            var q2 = new Point(11, 1);

            Assert.IsFalse(GalaxyTemplate.IntersectsExceptAtEnds(p1, p2, q1, q2));
        }
Exemplo n.º 7
0
        // TODO - status messages for the GUI
        private void PlaceEmpire(Galaxy gal, Empire emp, PRNG dice)
        {
            if (AllSystemsExplored)
            {
                // set all systems explored
                foreach (var sys in gal.StarSystemLocations.Select(ssl => ssl.Item))
                {
                    sys.ExploredByEmpires.Add(emp);
                }
            }

            // give empire starting techs
            Galaxy.Current.CleanGameState();             // need to know what the techs in the game are!
            foreach (var tech in Mod.Current.Technologies.Where(t => !t.IsRacial || emp.Abilities().Any(a => a.Rule.Matches("Tech Area") && a.Value1 == t.RacialTechID)))
            {
                switch (StartingTechnologyLevel)
                {
                case StartingTechnologyLevel.Low:
                    emp.ResearchedTechnologies[tech] = tech.StartLevel;
                    break;

                case StartingTechnologyLevel.Medium:
                    emp.ResearchedTechnologies[tech] = Math.Max(tech.StartLevel, tech.RaiseLevel);
                    break;

                case StartingTechnologyLevel.High:
                    emp.ResearchedTechnologies[tech] = tech.MaximumLevel;
                    break;
                }
            }

            // give empire starting resources and storage capacity
            foreach (var r in Resource.All.Where(r => r.IsGlobal))
            {
                emp.StoredResources.Add(r, StartingResources);
                emp.IntrinsicResourceStorage.Add(r, ResourceStorage);
            }

            // give empire starting research
            emp.BonusResearch = StartingResearch + (int)(ResearchPointsPerUnspentEmpirePoint * (EmpirePoints - emp.PrimaryRace.Traits.Sum(q => q.Cost)));

            // TODO - moddable colony techs?
            string colonyTechName = null;

            if ((emp.PrimaryRace.NativeSurface) == "Rock")
            {
                colonyTechName = "Rock Planet Colonization";
            }
            else if ((emp.PrimaryRace.NativeSurface) == "Ice")
            {
                colonyTechName = "Ice Planet Colonization";
            }
            else if ((emp.PrimaryRace.NativeSurface) == "Gas Giant")
            {
                colonyTechName = "Gas Giant Colonization";
            }
            var colonyTech = Mod.Current.Technologies.SingleOrDefault(t => t.Name == colonyTechName);

            if (colonyTech != null && emp.ResearchedTechnologies[colonyTech] < 1)
            {
                emp.ResearchedTechnologies[colonyTech] = 1;
            }

            // find facilities to place on homeworlds
            var facils = emp.UnlockedItems.OfType <FacilityTemplate>();
            var sy     = facils.WithMax(facil => facil.GetAbilityValue("Space Yard", 2).ToInt()).LastOrDefault();
            var sp     = facils.LastOrDefault(facil => facil.HasAbility("Spaceport"));
            var rd     = facils.LastOrDefault(facil => facil.HasAbility("Supply Generation"));
            var min    = facils.WithMax(facil => facil.GetAbilityValue("Resource Generation - Minerals").ToInt()).LastOrDefault();
            var org    = facils.WithMax(facil => facil.GetAbilityValue("Resource Generation - Organics").ToInt()).LastOrDefault();
            var rad    = facils.WithMax(facil => facil.GetAbilityValue("Resource Generation - Radioactives").ToInt()).LastOrDefault();
            var res    = facils.WithMax(facil => facil.GetAbilityValue("Point Generation - Research").ToInt()).LastOrDefault();
            // TODO - game setup option for intel facilities on homeworlds? HomeworldStartingFacilities.txt ala se5?

            // SY rate, for colonies
            var rate = new ResourceQuantity();

            if (sy != null)
            {
                // TODO - define mappings between SY ability numbers and resource names in a mod file
                rate.Add(Resource.Minerals, sy.GetAbilityValue("Space Yard", 2, true, true, a => a.Value1 == "1").ToInt());
                rate.Add(Resource.Organics, sy.GetAbilityValue("Space Yard", 2, true, true, a => a.Value1 == "2").ToInt());
                rate.Add(Resource.Radioactives, sy.GetAbilityValue("Space Yard", 2, true, true, a => a.Value1 == "3").ToInt());
            }

            // build connectivity graph for computing warp distance
            var graph = new ConnectivityGraph <StarSystem>();

            foreach (var s in Galaxy.Current.StarSystemLocations.Select(ssl => ssl.Item))
            {
                graph.Add(s);
            }
            foreach (var s in Galaxy.Current.StarSystemLocations.Select(ssl => ssl.Item))
            {
                foreach (var wp in s.FindSpaceObjects <WarpPoint>())
                {
                    graph.Connect(s, wp.TargetStarSystemLocation.Item, true);
                }
            }

            for (int i = 0; i < HomeworldsPerEmpire; i++)
            {
                // TODO - respect Empire Placement and Max Homeworld Dispersion settings
                var planets   = gal.StarSystemLocations.SelectMany(ssl => ssl.Item.FindSpaceObjects <Planet>(p => p.Owner == null && p.MoonOf == null));
                var okSystems = gal.StarSystemLocations.Select(ssl => ssl.Item).Where(sys => sys.EmpiresCanStartIn);
                if (i > 0)
                {
                    // make sure subsequent homeworlds are placed within a limited number of warps from the first homeworld
                    okSystems = okSystems.Where(sys => graph.ComputeDistance(sys, emp.OwnedSpaceObjects.OfType <Planet>().First().FindStarSystem()) <= MaxHomeworldDispersion);
                }
                switch (EmpirePlacement)
                {
                case EmpirePlacement.CanStartInSameSystem:
                    // no further filtering
                    break;

                case EmpirePlacement.DifferentSystems:
                    // filter to systems containing no other empires' homeworlds
                    okSystems = okSystems.Where(sys => !sys.FindSpaceObjects <Planet>(p => p.Owner != null && p.Owner != emp).Any());
                    break;

                case EmpirePlacement.Equidistant:
                    // filter to systems containing no other empires' homeworlds
                    okSystems = okSystems.Where(sys => !sys.FindSpaceObjects <Planet>(p => p.Owner != null && p.Owner != emp).Any());
                    // filter to systems that are the maximum distance away from any other empire's homeworlds
                    var otherEmpireHomeSystems = gal.StarSystemLocations.SelectMany(ssl => ssl.Item.FindSpaceObjects <Planet>(p => p.Owner != null && p.Owner != emp).Select(p => p.FindStarSystem()).Distinct()).ToArray();
                    okSystems = okSystems.WithMax(sys => otherEmpireHomeSystems.Min(o => graph.ComputeDistance(sys, o)));
                    break;
                }
                okSystems = okSystems.ToArray();
                if (!okSystems.Any())
                {
                    // replace an inhospitable system with a hospitable one
                    var convertSys = gal.StarSystemLocations.Select(ssl => ssl.Item).Where(sys => !sys.EmpiresCanStartIn).PickRandom(dice);
                    if (convertSys == null)
                    {
                        throw new Exception("No suitable system found to place " + emp + "'s homeworld #" + (i + 1) + ". (Try increasing the number of star systems.)");
                    }
                    var newSys = Mod.Current.StarSystemTemplates.Where(q => q.EmpiresCanStartIn).PickRandom(dice).Instantiate();
                    var sid    = convertSys.ID;
                    newSys.CopyTo(convertSys);
                    convertSys.ID   = sid;
                    convertSys.Name = Mod.Current.StarSystemNames.Except(gal.StarSystemLocations.Select(q => q.Item.Name)).PickRandom(dice);
                    foreach (var l in Galaxy.Current.StarSystemLocations)
                    {
                        foreach (var wp in l.Item.FindSpaceObjects <WarpPoint>().Where(q => q.Target.StarSystem == convertSys).ToArray())
                        {
                            wp.Dispose();
                            WarpPointPlacementStrategy.PlaceWarpPoints(Galaxy.Current.StarSystemLocations.Single(q => q.Item == convertSys), l);
                        }
                    }
                    GalaxyTemplate.NameStellarObjects(convertSys);
                    okSystems = new[] { convertSys };
                }
                Planet hw;
                planets = planets.Where(p => okSystems.Contains(p.FindStarSystem()));
                if (!planets.Any())
                {
                    // make sure we're placing the homeworld in a system with at least one empty sector
                    okSystems = okSystems.Where(sys2 => sys2.Sectors.Any(sec => !sec.SpaceObjects.Any()));

                    if (!okSystems.Any())
                    {
                        throw new Exception("No suitable system found to place " + emp + "'s homeworld #" + (i + 1) + ". (Try regenerating the map or increasing the number of star systems.)");
                    }

                    // make brand new planet in an OK system
                    var sys     = okSystems.PickRandom(dice);
                    var nextNum = sys.FindSpaceObjects <Planet>(p => p.MoonOf == null).Count() + 1;
                    hw = MakeHomeworld(emp, sys.Name + " " + nextNum.ToRomanNumeral(), dice);
                    var okSectors = sys.Sectors.Where(sector => !sector.SpaceObjects.Any());
                    okSectors.PickRandom(dice).Place(hw);
                }
                else
                {
                    hw = planets.PickRandom(dice);
                }
                if (hw.Surface != emp.PrimaryRace.NativeSurface || hw.Atmosphere != emp.PrimaryRace.NativeAtmosphere || hw.Size != HomeworldSize)
                {
                    var replacementHomeworld = MakeHomeworld(emp, hw.Name, dice);
                    replacementHomeworld.CopyTo(hw);
                }
                hw.ResourceValue[Resource.Minerals] = hw.ResourceValue[Resource.Organics] = hw.ResourceValue[Resource.Radioactives] = HomeworldValue;
                hw.Colony = new Colony
                {
                    Owner             = emp,
                    ConstructionQueue = new ConstructionQueue(hw),
                    IsHomeworld       = true,
                };
                hw.AddPopulation(emp.PrimaryRace, hw.Size.MaxPopulation);
                if (sy != null && hw.Colony.Facilities.Count < hw.MaxFacilities)
                {
                    hw.Colony.Facilities.Add(sy.Instantiate());
                }
                if (sp != null && hw.Colony.Facilities.Count < hw.MaxFacilities && (!emp.HasAbility("No Spaceports") || sp.Abilities.Count > 1))
                {
                    // natural merchants get spaceports only if spaceports have more than one ability
                    // of course, if the other abilities are *penalties*... oh well, they can scrap them!
                    hw.Colony.Facilities.Add(sp.Instantiate());
                }
                if (rd != null && hw.Colony.Facilities.Count < hw.MaxFacilities)
                {
                    hw.Colony.Facilities.Add(rd.Instantiate());
                }
                var lastCount = 0;
                while (hw.Colony.Facilities.Count < hw.MaxFacilities && hw.Colony.Facilities.Count > lastCount)
                {
                    lastCount = hw.Colony.Facilities.Count;

                    if (min != null && hw.Colony.Facilities.Count < hw.MaxFacilities)
                    {
                        hw.Colony.Facilities.Add(min.Instantiate());
                    }
                    if (org != null && hw.Colony.Facilities.Count < hw.MaxFacilities)
                    {
                        hw.Colony.Facilities.Add(org.Instantiate());
                    }
                    if (rad != null && hw.Colony.Facilities.Count < hw.MaxFacilities)
                    {
                        hw.Colony.Facilities.Add(rad.Instantiate());
                    }

                    // no research facilities needed at max tech!
                    if (StartingTechnologyLevel != StartingTechnologyLevel.High)
                    {
                        if (res != null && hw.Colony.Facilities.Count < hw.MaxFacilities)
                        {
                            hw.Colony.Facilities.Add(res.Instantiate());
                        }
                    }
                }
                foreach (var f in hw.Colony.Facilities)
                {
                    f.ConstructionProgress = f.Cost;
                }
            }

            // mark home systems explored
            foreach (var sys in gal.StarSystemLocations.Select(ssl => ssl.Item))
            {
                if (!sys.ExploredByEmpires.Contains(emp) && sys.FindSpaceObjects <Planet>().Any(planet => planet.Owner == emp))
                {
                    sys.ExploredByEmpires.Add(emp);
                }
            }

            // in case two empires started in the same system
            foreach (var x in gal.FindSpaceObjects <ISpaceObject>().Owned().ToArray())
            {
                x.UpdateEmpireMemories();
            }
        }
Exemplo n.º 8
0
        public override IEnumerable <IModObject> Load(Mod mod)
        {
            foreach (var rec in DataFile.Records)
            {
                var galtemp = new GalaxyTemplate();
                galtemp.TemplateParameters = rec.Parameters;
                string temp;
                int    index = -1;

                galtemp.ModID = rec.Get <string>("ID", galtemp);
                rec.TryFindFieldValue("Name", out temp, ref index, Mod.Errors, 0, true);
                galtemp.Name = temp;
                mod.GalaxyTemplates.Add(galtemp);

                rec.TryFindFieldValue("Description", out temp, ref index, Mod.Errors, 0, true);
                galtemp.Description = temp;

                rec.TryFindFieldValue("Min Dist Between Systems", out temp, ref index, Mod.Errors, 0, true);
                int mindist;
                if (!int.TryParse(temp, out mindist))
                {
                    Mod.Errors.Add(new DataParsingException("Cannot find field \"Min Dist Between Systems\"", Mod.CurrentFileName, rec));
                }
                galtemp.MinimumStarSystemDistance = mindist;

                rec.TryFindFieldValue("System Placement", out temp, ref index, Mod.Errors, 0, true);
                if (temp == "Random")
                {
                    galtemp.StarSystemPlacementStrategy = new RandomStarSystemPlacementStrategy();
                }
                else if (temp == "Clusters")
                {
                    galtemp.StarSystemPlacementStrategy = new ClusteredStarSystemPlacementStrategy();
                }
                else if (temp == "Spiral")
                {
                    galtemp.StarSystemPlacementStrategy = new SpiralStarSystemPlacementStrategy();
                }
                else if (temp == "Diffuse")
                {
                    galtemp.StarSystemPlacementStrategy = new DiffuseStarSystemPlacementStrategy();
                }
                else if (temp == "Grid")
                {
                    galtemp.StarSystemPlacementStrategy = new GridStarSystemPlacementStrategy();
                }
                else
                {
                    Mod.Errors.Add(new DataParsingException("Invalid value \"" + temp + "\" for field \"System Placement\". Must be Random, Clusters, Spiral, Diffuse, or Grid.", Mod.CurrentFileName, rec));
                    galtemp.StarSystemPlacementStrategy = new RandomStarSystemPlacementStrategy();                     // default
                }

                rec.TryFindFieldValue("Max Warp Points per Sys", out temp, ref index, Mod.Errors, 0, true);
                int maxwarp;
                if (!int.TryParse(temp, out maxwarp))
                {
                    Mod.Errors.Add(new DataParsingException("Cannot find field \"Max Warp Points per Sys\"", Mod.CurrentFileName, rec));
                }
                galtemp.MaxWarpPointsPerSystem = maxwarp;

                rec.TryFindFieldValue("Min Angle Between WP", out temp, ref index, Mod.Errors, 0, true);
                int minangle;
                if (!int.TryParse(temp, out minangle))
                {
                    Mod.Errors.Add(new DataParsingException("Cannot find field \"Min Angle Between WP\"", Mod.CurrentFileName, rec));
                }
                galtemp.MinWarpPointAngle = minangle;

                int count = 1;
                int start = 0;
                while (true)
                {
                    StarSystemTemplate sst;
                    int chance;

                    if (!rec.TryFindFieldValue(new string[] { "Type " + count + " Name", "Type Name" }, out temp, ref start, null, start, true))
                    {
                        break;                         // couldn't load next chance
                    }
                    else
                    {
                        sst = mod.StarSystemTemplates.FindByName(temp);
                        if (sst == null)
                        {
                            Mod.Errors.Add(new DataParsingException("Could not find star system template \"" + temp + "\".", Mod.CurrentFileName, rec, null));
                            continue;                             // skip this chance
                        }
                    }
                    start++;

                    if (!rec.TryFindFieldValue(new string[] { "Type " + count + " Chance", "Type Chance" }, out temp, ref start, null, start))
                    {
                        break;                         // couldn't load next chance
                    }
                    else
                    {
                        if (!int.TryParse(temp, out chance))
                        {
                            Mod.Errors.Add(new DataParsingException("Type Chance field value must be an integer.", Mod.CurrentFileName, rec, null));
                        }
                    }
                    start++;

                    // silly Adamant Mod refers to the same star system type twice...
                    if (galtemp.StarSystemTemplateChances.ContainsKey(sst))
                    {
                        galtemp.StarSystemTemplateChances[sst] += chance;
                    }
                    else
                    {
                        galtemp.StarSystemTemplateChances.Add(sst, chance);
                    }

                    count++;
                }

                yield return(galtemp);
            }
        }