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); }
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); }
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)); }
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); }
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(); })); }
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); }
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); }
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); }
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(); } }
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"); }
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); }
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); }
/// <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)))); }
public int CalculateTradeTime(IStructure structure, ICity targetCity) { return((int)CalculateTime(formula.SendTime(structure, tileLocator.TileDistance(structure.PrimaryPosition, structure.Size, targetCity.PrimaryPosition, 1)))); }
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); }); }