コード例 #1
0
        private bool HasEnoughCities(uint x, uint y, int level)
        {
            int radius = RadiusBase + (level - 1) * RadiusPerLevel;
            // basic radius 200, then every each level is 50 radius
            int count = level * CitiesPerLevel;

            return(mapFactory.Locations.Count(loc => tileLocator.TileDistance(new Position(x, y), 1, loc, 1) < radius) > count);
        }
コード例 #2
0
        public Error NextLocation(out Position position)
        {
            var city = player.GetCityList().FirstOrDefault();

            if (city == null)
            {
                position = new Position();
                return(Error.CityNotFound);
            }

            var positions = mapFactory.Locations.Where(loc =>
            {
                if (tileLocator.TileDistance(city.PrimaryPosition, 1, loc, 1) > distance)
                {
                    return(false);
                }

                // Check if objects already on that point
                var objects = world.Regions.GetObjectsInTile(loc.X, loc.Y);

                return(!objects.Any() && !forestManager.HasForestNear(loc.X, loc.Y, formula.GetInitialCityRadius()));
            }).ToList();

            if (positions.Count == 0)
            {
                position = new Position();
                return(Error.FriendMapFull);
            }

            position = positions[random.Next(positions.Count)];
            return(Error.Ok);
        }
コード例 #3
0
 public bool HasForestNear(uint x, uint y, int radius)
 {
     return(world.Regions.GetRegion(x, y)
            .GetPrimaryObjects()
            .OfType <IForest>()
            .Any(forest => tileLocator.TileDistance(forest.PrimaryPosition, 1, new Position(x, y), 1) <= radius));
 }
コード例 #4
0
        public void Callback(object custom)
        {
            foreach (IStronghold stronghold in strongholdManager.Where(s => s.StrongholdState == StrongholdState.Inactive && strongholdActivationCondition.ShouldActivate(s)))
            {
                locker.Lock(stronghold).Do(() => strongholdManager.Activate(stronghold));
            }

            // Activate stronghold with highest score if there are no neutral strongholds
            var lastNeutralActivationTimeVar = systemVariableManager["Stronghold.neutral_check"];
            var lastNeutralActivationTime    = (DateTime)lastNeutralActivationTimeVar.Value;

            if (SystemClock.Now.Subtract(lastNeutralActivationTime).TotalHours >= 8)
            {
                if (strongholdManager.All(s => s.StrongholdState != StrongholdState.Neutral))
                {
                    var mapCenter = new Position(Config.map_width / 2, Config.map_height / 2);

                    var stronghold = strongholdManager.Where(s => s.StrongholdState == StrongholdState.Inactive && s.NearbyCitiesCount > 0)
                                     .OrderByDescending(s => strongholdActivationCondition.Score(s))
                                     .ThenBy(s => tileLocator.TileDistance(s.PrimaryPosition, 1, mapCenter, 1))
                                     .FirstOrDefault();

                    // Do the same check for a SH but w/o nearby cities restriction
                    if (stronghold == null)
                    {
                        stronghold = strongholdManager.Where(s => s.StrongholdState == StrongholdState.Inactive)
                                     .OrderByDescending(s => strongholdActivationCondition.Score(s))
                                     .ThenBy(s => tileLocator.TileDistance(s.PrimaryPosition, 1, mapCenter, 1))
                                     .FirstOrDefault();
                    }

                    if (stronghold != null)
                    {
                        locker.Lock(stronghold).Do(() => strongholdManager.Activate(stronghold));
                    }
                }

                using (dbManager.GetThreadTransaction())
                {
                    lastNeutralActivationTimeVar.Value = SystemClock.Now;
                    dbManager.Save(lastNeutralActivationTimeVar);
                }
            }

            Time = DateTime.UtcNow.Add(TimeSpan);
            scheduler.Put(this);
        }
コード例 #5
0
        public bool HasPath(Position start, byte startSize, ICity city, IEnumerable <Position> excludedPoints)
        {
            var fromStructure         = world.Regions.GetObjectsInTile(start.X, start.Y).OfType <IStructure>().Any();
            var startPositions        = tileLocator.ForeachMultitile(start.X, start.Y, startSize).ToList();
            var mainBuilding          = city.MainBuilding;
            var mainBuildingPositions = tileLocator.ForeachMultitile(mainBuilding).ToList();

            if (startPositions.Intersect(mainBuildingPositions).Any())
            {
                return(true);
            }

            return(BreadthFirst(end: mainBuildingPositions,
                                visited: new List <Position> {
                new Position(start.X, start.Y)
            },
                                excludedPoints: excludedPoints,
                                getNeighbors: node =>
            {
                var possibleNeighbors = new[]
                {
                    node.TopLeft(),
                    node.TopRight(),
                    node.BottomLeft(),
                    node.BottomRight()
                };

                return possibleNeighbors.Where(location =>
                {
                    // If the neighbor we are checking is where the mainbuilding is then we've found the goal
                    if (mainBuildingPositions.Contains(location))
                    {
                        // We have only found the target if the structure we're checking is not directly next to the main building
                        return !fromStructure || !startPositions.Contains(node);
                    }

                    if (startPositions.Contains(location))
                    {
                        return true;
                    }

                    if (tileLocator.TileDistance(location, 1, city.PrimaryPosition, 1) > city.Radius)
                    {
                        return false;
                    }

                    var structureOnTile = world.Regions.GetObjectsInTile(location.X, location.Y).OfType <IStructure>().FirstOrDefault();
                    if (structureOnTile != null)
                    {
                        return false;
                    }

                    return world.Roads.IsRoad(location.X, location.Y);
                }).ToList();
            }));
        }
コード例 #6
0
        public void Callback_WhenInactiveStrongholdsHaveSameScore_ShouldActivateClosestToCenter(
            [Frozen] ISystemVariableManager systemVariableManager,
            [Frozen] IStrongholdActivationCondition activationCondition,
            [Frozen] IStrongholdManager strongholdManager,
            [Frozen] ITileLocator tileLocator,
            IStronghold sh1,
            IStronghold sh2,
            IFixture fixture)
        {
            sh1.StrongholdState.Returns(StrongholdState.Inactive);
            sh1.PrimaryPosition.Returns(new Position(10, 20));

            sh2.StrongholdState.Returns(StrongholdState.Inactive);
            sh2.PrimaryPosition.Returns(new Position(30, 40));

            activationCondition.Score(null).ReturnsForAnyArgs(0);

            tileLocator.TileDistance(sh1.PrimaryPosition, 1, Arg.Any <Position>(), 1)
            .Returns(10);

            tileLocator.TileDistance(sh2.PrimaryPosition, 1, Arg.Any <Position>(), 1)
            .Returns(5);

            var lastCheckTime = Substitute.For <SystemVariable>();

            lastCheckTime.Value.Returns(SystemClock.Now.AddHours(-8));
            systemVariableManager["Stronghold.neutral_check"].Returns(lastCheckTime);

            var locker = new LockerStub();

            fixture.Register <ILocker>(() => locker);

            strongholdManager.GetEnumerator().Returns(_ => new List <IStronghold> {
                sh1, sh2
            }.GetEnumerator());

            var checker = fixture.Create <StrongholdActivationChecker>();

            checker.Callback(null);

            strongholdManager.Received().Activate(sh2);
            strongholdManager.DidNotReceive().Activate(sh1);
        }
コード例 #7
0
        public void Execute_WhenAStructureTileIsOutOfCityRadius_ReturnsError(
            [Frozen] IWorld world,
            [Frozen] ITileLocator tileLocator,
            [Frozen] ICity city,
            [Frozen] IStructureBaseStats structureBaseStats,
            Fixture fixture)
        {
            var action = new StructureBuildActiveActionExecuteBuilder(fixture).Build();

            structureBaseStats.Size.Returns <byte>(11);

            tileLocator.ForeachMultitile(action.X, action.Y, 11).Returns(new[] { new Position(1, 1), new Position(1, 2) });
            tileLocator.TileDistance(city.PrimaryPosition, 1, Arg.Is <Position>(p => p.X == 1 && p.Y == 1), 1).Returns(5);
            tileLocator.TileDistance(city.PrimaryPosition, 1, Arg.Is <Position>(p => p.X == 1 && p.Y == 2), 1).Returns(6);

            city.Radius.Returns <byte>(6);

            action.Execute().Should().Be(Error.NotWithinWalls);
        }
コード例 #8
0
        public StructureBuildActiveActionExecuteBuilder(IFixture fixture)
        {
            this.fixture = fixture;

            requirementCsvFactory = fixture.Freeze <IRequirementCsvFactory>();
            requirementCsvFactory
            .GetLayoutRequirement(Arg.Any <ushort>(), Arg.Any <byte>())
            .Validate(Arg.Any <IStructure>(), Arg.Any <ushort>(), Arg.Any <uint>(), Arg.Any <uint>(), Arg.Any <byte>())
            .Returns(true);

            structureBaseStats = fixture.Freeze <IStructureBaseStats>();
            structureBaseStats.Size.Returns <byte>(0);
            var structureCost = new Resource(1234, 8446, 1343, 1234, 1246);

            structureBaseStats.Cost.Returns(structureCost);

            var structure = fixture.Freeze <IStructure>();

            structure.Stats.Base.Returns(structureBaseStats);

            objectTypeFactory = fixture.Freeze <IObjectTypeFactory>();
            objectTypeFactory.IsObjectType("NoRoadRequired", Arg.Any <ushort>()).Returns(true);

            city = fixture.Create <ICity>();
            city.PrimaryPosition.Returns(new Position(99, 98));
            city.Radius.Returns <byte>(5);
            city.Resource.HasEnough(structureBaseStats.Cost).Returns(true);
            city.CreateStructure(Arg.Any <ushort>(), Arg.Any <byte>(), Arg.Any <uint>(), Arg.Any <uint>()).Returns(structure);

            roadPathFinder = fixture.Freeze <IRoadPathFinder>();
            roadPathFinder.CanBuild(Arg.Any <Position>(), Arg.Any <byte>(), city, Arg.Any <bool>()).Returns(Error.Ok);

            tileLocator = fixture.Freeze <ITileLocator>();
            tileLocator.TileDistance(new Position(99, 98), 1, Arg.Any <Position>(), 1).Returns(1);

            world = fixture.Freeze <IWorld>();
            ICity outCity;

            world.TryGetObjects(Arg.Any <uint>(), out outCity).Returns(x =>
            {
                x[1] = city;
                return(true);
            });
            world.Regions.GetObjectsInTile(Arg.Any <uint>(), Arg.Any <uint>()).Returns(new List <ISimpleGameObject>());
            world.Regions.IsValidXandY(0, 0).ReturnsForAnyArgs(true);
            world.Regions.Add(structure).Returns(true);

            structureCsvFactory = fixture.Freeze <IStructureCsvFactory>();
            structureCsvFactory.GetBaseStats(0, 0).ReturnsForAnyArgs(structureBaseStats);

            formula = Substitute.For <Formula>();
            formula.CityMaxConcurrentBuildActions(0, 0, null, null).ReturnsForAnyArgs(Error.Ok);
            formula.StructureCost(null, null).ReturnsForAnyArgs(structureCost);
            fixture.Register(() => formula);
        }
コード例 #9
0
        void CityManagerCityAdded(object sender, NewCityEventArgs e)
        {
            if (!e.IsNew)
            {
                return;
            }

            var city = (ICity)sender;

            foreach (var stronghold in strongholds.Values.Where(s => s.StrongholdState == StrongholdState.Inactive &&
                                                                tileLocator.TileDistance(s.PrimaryPosition, s.Size, city.PrimaryPosition, 1) < Config.stronghold_radius_base + Config.stronghold_radius_per_level * s.Lvl))
            {
                stronghold.BeginUpdate();
                ++stronghold.NearbyCitiesCount;
                stronghold.EndUpdate();
            }
        }
コード例 #10
0
        private string CmdStrongholdFindNearbyCities(Session session, string[] parms)
        {
            var list = new List <Position>(mapFactory.Locations.Take(mapFactory.Index));

            foreach (var stronghold in strongholdManager.Where(s => s.StrongholdState == StrongholdState.Inactive))
            {
                locker.Lock(stronghold).Do(() =>
                {
                    stronghold.BeginUpdate();
                    int count = list.Count(pt =>
                                           tileLocator.TileDistance(stronghold.PrimaryPosition, 3, pt, 1) <= Config.stronghold_radius_base + Config.stronghold_radius_per_level * stronghold.Lvl);
                    stronghold.NearbyCitiesCount = (ushort)count;
                    stronghold.EndUpdate();
                });
            }

            return("OK");
        }
コード例 #11
0
        public virtual double GetLumbermillCampBuildTime(int campBuildTime, IStructure lumbermill, IForest forest, ITileLocator tileLocator)
        {
            var distance = tileLocator.TileDistance(lumbermill, forest);

            return(BuildTime(campBuildTime, lumbermill.City, lumbermill.City.Technologies) + distance * 5);
        }
コード例 #12
0
        public override Error Execute()
        {
            ICity city;

            if (!world.TryGetObjects(cityId, out city))
            {
                return(Error.ObjectNotFound);
            }

            var maxConcurrentUpgradesResult = formula.CityMaxConcurrentBuildActions(type, ActionId, city, objectTypeFactory);

            if (maxConcurrentUpgradesResult != Error.Ok)
            {
                return(maxConcurrentUpgradesResult);
            }

            var structureBaseStats = structureCsvFactory.GetBaseStats(type, level);

            var lockedRegions = world.Regions.LockMultitileRegions(X, Y, structureBaseStats.Size);

            foreach (var position in tileLocator.ForeachMultitile(X, Y, structureBaseStats.Size))
            {
                var tileType = world.Regions.GetTileType(position.X, position.Y);
                // tile requirement
                if (!string.IsNullOrEmpty(tileRequirement) && !objectTypeFactory.IsTileType(tileRequirement, tileType))
                {
                    world.Regions.UnlockRegions(lockedRegions);
                    return(Error.TileMismatch);
                }

                // Only allow buildings that require resource tile to built on them
                if (tileRequirement != "TileResource" && objectTypeFactory.IsTileType("TileResource", tileType))
                {
                    world.Regions.UnlockRegions(lockedRegions);
                    return(Error.TileMismatch);
                }

                // dont allow building on edge of world
                if (!world.Regions.IsValidXandY(position.X, position.Y))
                {
                    world.Regions.UnlockRegions(lockedRegions);
                    return(Error.ActionInvalid);
                }

                // radius requirements
                if (tileLocator.TileDistance(city.PrimaryPosition, 1, position, 1) >= city.Radius)
                {
                    world.Regions.UnlockRegions(lockedRegions);
                    return(Error.NotWithinWalls);
                }

                // check if tile is occupied
                if (world.Regions.GetObjectsInTile(position.X, position.Y).Any(obj => obj is IStructure))
                {
                    world.Regions.UnlockRegions(lockedRegions);
                    return(Error.StructureExists);
                }
            }

            // cost requirement
            cost = formula.StructureCost(city, structureBaseStats);
            if (!city.Resource.HasEnough(cost))
            {
                world.Regions.UnlockRegions(lockedRegions);
                return(Error.ResourceNotEnough);
            }

            // layout requirement
            if (!requirementCsvFactory.GetLayoutRequirement(type, level).Validate(WorkerObject as IStructure, type, X, Y, structureBaseStats.Size))
            {
                world.Regions.UnlockRegions(lockedRegions);
                return(Error.LayoutNotFullfilled);
            }

            // check for road requirements
            var requiresRoad = !objectTypeFactory.IsObjectType("NoRoadRequired", type);
            var canBuild     = roadPathFinder.CanBuild(new Position(X, Y), structureBaseStats.Size, city, requiresRoad);

            if (canBuild != Error.Ok)
            {
                world.Regions.UnlockRegions(lockedRegions);
                return(canBuild);
            }

            // add structure to the map
            IStructure structure = city.CreateStructure(type, 0, X, Y);

            city.BeginUpdate();
            city.Resource.Subtract(cost);
            city.EndUpdate();

            structure.BeginUpdate();

            if (!world.Regions.Add(structure))
            {
                city.ScheduleRemove(structure, false);
                city.BeginUpdate();
                city.Resource.Add(cost);
                city.EndUpdate();
                structure.EndUpdate();

                world.Regions.UnlockRegions(lockedRegions);
                return(Error.MapFull);
            }

            structure.EndUpdate();

            callbackProcedure.OnStructureUpgrade(structure);

            structureId = structure.ObjectId;

            // add to queue for completion
            var buildTime = formula.BuildTime(structureBaseStats.BuildTime, city, city.Technologies);

            endTime   = SystemClock.Now.AddSeconds(CalculateTime(buildTime));
            BeginTime = SystemClock.Now;

            city.References.Add(structure, this);

            world.Regions.UnlockRegions(lockedRegions);
            return(Error.Ok);
        }
コード例 #13
0
        /// <summary>
        ///     Calculates the departure time for a given troop stub
        /// </summary>
        /// <param name="stub"></param>
        /// <returns></returns>
        private DateTime DepartureTime(ITroopStub stub)
        {
            int distance = tileLocator.TileDistance(stub.City.PrimaryPosition, 1, new Position(X, Y), 1);

            return(TargetTime.Subtract(TimeSpan.FromSeconds(formula.MoveTimeTotal(stub, distance, IsAttack))));
        }
コード例 #14
0
 public int CalculateTradeTime(IStructure structure, ICity targetCity)
 {
     return((int)CalculateTime(formula.SendTime(structure, tileLocator.TileDistance(structure.PrimaryPosition, structure.Size, targetCity.PrimaryPosition, 1))));
 }
コード例 #15
0
        private void RoadCreate(Session session, Packet packet)
        {
            var reply = new Packet(packet);

            uint x;
            uint y;
            uint cityId;

            try
            {
                cityId = packet.GetUInt32();
                x      = packet.GetUInt32();
                y      = packet.GetUInt32();
            }
            catch (Exception)
            {
                ReplyError(session, packet, Error.Unexpected);
                return;
            }

            if (!world.Regions.IsValidXandY(x, y))
            {
                ReplyError(session, packet, Error.Unexpected);
                return;
            }

            // Make sure there is no structure at this point that has no road requirement
            if (world.Regions.GetObjectsInTile(x, y).Any(
                    s =>
                    s is IStructure &&
                    objectTypeFactory.IsStructureType("NoRoadRequired", (IStructure)s)))
            {
                ReplyError(session, packet, Error.StructureExists);
                return;
            }

            ICity city;

            locker.Lock(cityId, out city).Do(() =>
            {
                if (city == null)
                {
                    ReplyError(session, packet, Error.CityNotFound);
                    return;
                }

                // Make sure user is building road within city walls
                if (tileLocator.TileDistance(city.PrimaryPosition, 1, new Position(x, y), 1) >= city.Radius)
                {
                    ReplyError(session, packet, Error.NotWithinWalls);
                    return;
                }

                world.Regions.LockRegion(x, y);

                // Make sure this tile is not already a road
                if (world.Roads.IsRoad(x, y))
                {
                    world.Regions.UnlockRegion(x, y);
                    ReplyError(session, packet, Error.RoadAlreadyExists);
                    return;
                }

                // Make sure there is a road next to this tile
                bool hasRoad = false;

                foreach (var position in tileLocator.ForeachRadius(x, y, 1, false))
                {
                    if ((world.Roads.IsRoad(position.X, position.Y) &&
                         !world.Regions.GetObjectsInTile(position.X, position.Y).Any(s => s is IStructure && s != city.MainBuilding)))
                    {
                        hasRoad = true;
                        break;
                    }
                }

                if (!hasRoad)
                {
                    world.Regions.UnlockRegion(x, y);
                    ReplyError(session, packet, Error.RoadNotAround);
                    return;
                }

                if (objectTypeFactory.IsTileType("TileResource", world.Regions.GetTileType(x, y)))
                {
                    world.Regions.UnlockRegion(x, y);
                    ReplyError(session, packet, Error.TileMismatch);
                    return;
                }

                world.Roads.CreateRoad(x, y, city.RoadTheme);

                world.Regions.UnlockRegion(x, y);

                session.Write(reply);
            });
        }