public void Revolt() { _anarchy = (short)((HasWonder <Pyramids>() && !Game.WonderObsolete <Pyramids>()) ? 0 : 4 - (Game.GameTurn % 4) - 1); Government = new Anarchy(); if (!IsHuman) { return; } GameTask.Enqueue(Message.Newspaper(null, $"The {Game.Instance.HumanPlayer.TribeNamePlural} are", "revolting! Citizens", "demand new govt.")); }
public void AddAdvance(IAdvance advance, bool setOrigin = true) { if (Game.Started && Game.CurrentPlayer.CurrentResearch?.Id == advance.Id) { GameTask.Enqueue(new TechSelect(Game.CurrentPlayer)); } _advances.Add(advance.Id); if (!setOrigin) { return; } Game.Instance.SetAdvanceOrigin(advance, this); }
public void NewTurn() { if (!Game.GetCities().Any(x => this == x.Owner) && !Game.Instance.GetUnits().Any(x => this == x.Owner)) { GameTask.Enqueue(Turn.GameOver(this)); } if (_anarchy == 0 && Government is Anarchy) { GameTask.Enqueue(Show.ChooseGovernment); } if (_anarchy > 0) { _anarchy--; } }
public void EndTurn() { foreach (Player player in _players.Where(x => !(x.Civilization is Barbarian))) { player.IsDestroyed(); } if (++_currentPlayer >= _players.Length) { _currentPlayer = 0; GameTurn++; if (GameTurn % 50 == 0 && Settings.AutoSave) { GameTask.Enqueue(Show.AutoSave); } } if (!_players.Any(x => Game.PlayerNumber(x) != 0 && x != Human && !x.IsDestroyed())) { GameTask conquest; GameTask.Enqueue(Message.Newspaper(null, "Your civilization", "has conquered", "the entire planet!")); GameTask.Enqueue(conquest = Show.Screen <Conquest>()); conquest.Done += (s, a) => Runtime.Quit(); } foreach (IUnit unit in _units.Where(u => u.Owner == _currentPlayer)) { GameTask.Enqueue(Turn.New(unit)); } foreach (City city in _cities.Where(c => c.Owner == _currentPlayer).ToArray()) { GameTask.Enqueue(Turn.New(city)); } GameTask.Enqueue(Turn.New(CurrentPlayer)); if (CurrentPlayer == HumanPlayer) { return; } }
public void Update() { IUnit unit = ActiveUnit; if (CurrentPlayer == HumanPlayer) { if (unit != null && !unit.Goto.IsEmpty) { int distance = unit.Tile.DistanceTo(unit.Goto); ITile[] tiles = (unit as BaseUnit).MoveTargets.OrderBy(x => x.DistanceTo(unit.Goto)).ThenBy(x => x.Movement).ToArray(); if (tiles.Length == 0 || tiles[0].DistanceTo(unit.Goto) > distance) { // No valid tile to move to, cancel goto unit.Goto = Point.Empty; return; } else if (tiles[0].DistanceTo(unit.Goto) == distance) { // Distance is unchanged, 50% chance to cancel goto if (Common.Random.Next(0, 100) < 50) { unit.Goto = Point.Empty; return; } } unit.MoveTo(tiles[0].X - unit.X, tiles[0].Y - unit.Y); return; } return; } if (unit != null && (unit.MovesLeft > 0 || unit.PartMoves > 0)) { GameTask.Enqueue(Turn.Move(unit)); return; } GameTask.Enqueue(Turn.End()); }
public void NewTurn() { if (!Game.GetCities().Any(x => this == x.Owner) && !Game.Instance.GetUnits().Any(x => this == x.Owner)) { GameTask.Enqueue(Turn.GameOver(this)); } if (_anarchy == 0 && Government is Anarchy) { if (Human == Game.CurrentPlayer) { GameTask.Enqueue(Show.ChooseGovernment); } else { Government = new Despotism(); } } if (_anarchy > 0) { _anarchy--; } }
internal static void Move(IUnit unit) { Player player = Game.GetPlayer(unit.Owner); if (unit.Owner == 0) { BarbarianMove(unit); return; } if (unit is Settlers) { ITile tile = unit.Tile; bool hasCity = (tile.City != null); bool validCity = (tile is Grassland || tile is River || tile is Plains) && (tile.City == null); bool validIrrigaton = (tile is Grassland || tile is River || tile is Plains || tile is Desert) && (tile.City == null) && (!tile.Mine) && (!tile.Irrigation) && tile.CrossTiles().Any(x => x.IsOcean || x is River || x.Irrigation); bool validMine = (tile is Mountains || tile is Hills) && (tile.City == null) && (!tile.Mine) && (!tile.Irrigation); bool validRoad = (tile.City == null) && tile.Road; int nearestCity = 255; int nearestOwnCity = 255; if (Game.GetCities().Any()) { nearestCity = Game.GetCities().Min(x => Common.DistanceToTile(x.X, x.Y, tile.X, tile.Y)); } if (Game.GetCities().Any(x => x.Owner == unit.Owner)) { nearestOwnCity = Game.GetCities().Where(x => x.Owner == unit.Owner).Min(x => Common.DistanceToTile(x.X, x.Y, tile.X, tile.Y)); } if (validCity && nearestCity > 3) { GameTask.Enqueue(Orders.FoundCity(unit as Settlers)); return; } else if (nearestOwnCity < 3) { switch (Common.Random.Next(5 * nearestOwnCity)) { case 0: if (validRoad) { GameTask.Enqueue(Orders.BuildRoad(unit)); return; } break; case 1: if (validIrrigaton) { GameTask.Enqueue(Orders.BuildIrrigation(unit)); return; } break; case 2: if (validMine) { GameTask.Enqueue(Orders.BuildMines(unit)); return; } break; } } for (int i = 0; i < 1000; i++) { int relX = Common.Random.Next(-1, 2); int relY = Common.Random.Next(-1, 2); if (relX == 0 && relY == 0) { continue; } if (unit.Tile[relX, relY] is Ocean) { continue; } if (unit.Tile[relX, relY].Units.Any(x => x.Owner != unit.Owner)) { continue; } if (!unit.MoveTo(relX, relY)) { continue; } return; } unit.SkipTurn(); return; } else if (unit is Militia || unit is Phalanx || unit is Musketeers || unit is Riflemen || unit is MechInf) { unit.Fortify = true; while (unit.Tile.City != null && unit.Tile.Units.Count(x => x is Militia || x is Phalanx || x is Musketeers || x is Riflemen || x is MechInf) > 2) { IUnit disband = null; IUnit[] units = unit.Tile.Units.Where(x => x != unit).ToArray(); if ((disband = unit.Tile.Units.FirstOrDefault(x => x is Militia)) != null) { Game.DisbandUnit(disband); continue; } if ((disband = unit.Tile.Units.FirstOrDefault(x => x is Phalanx)) != null) { Game.DisbandUnit(disband); continue; } if ((disband = unit.Tile.Units.FirstOrDefault(x => x is Musketeers)) != null) { Game.DisbandUnit(disband); continue; } if ((disband = unit.Tile.Units.FirstOrDefault(x => x is Riflemen)) != null) { Game.DisbandUnit(disband); continue; } if ((disband = unit.Tile.Units.FirstOrDefault(x => x is MechInf)) != null) { Game.DisbandUnit(disband); continue; } } } else { if (unit.Class != UnitClass.Land) { Game.DisbandUnit(unit); } for (int i = 0; i < 1000; i++) { if (unit.Goto.IsEmpty) { int gotoX = Common.Random.Next(-5, 6); int gotoY = Common.Random.Next(-5, 6); if (gotoX == 0 && gotoY == 0) { continue; } if (!player.Visible(unit.X + gotoX, unit.Y + gotoY)) { continue; } unit.Goto = new Point(unit.X + gotoX, unit.Y + gotoY); continue; } if (!unit.Goto.IsEmpty) { int distance = unit.Tile.DistanceTo(unit.Goto); ITile[] tiles = unit.MoveTargets.OrderBy(x => x.DistanceTo(unit.Goto)).ThenBy(x => x.Movement).ToArray(); if (tiles.Length == 0 || tiles[0].DistanceTo(unit.Goto) > distance) { // No valid tile to move to, cancel goto unit.Goto = Point.Empty; continue; } else if (tiles[0].DistanceTo(unit.Goto) == distance) { // Distance is unchanged, 50% chance to cancel goto if (Common.Random.Next(0, 100) < 50) { unit.Goto = Point.Empty; continue; } } if (tiles[0].Units.Any(x => x.Owner != unit.Owner)) { if (unit.Role == UnitRole.Civilian || unit.Role == UnitRole.Settler) { // do not attack with civilian or settler units unit.Goto = Point.Empty; continue; } if (unit.Role == UnitRole.Transport && Common.Random.Next(0, 100) < 67) { // 67% chance of cancelling attack with transport unit unit.Goto = Point.Empty; continue; } if (unit.Attack < tiles[0].Units.Select(x => x.Defense).Max() && Common.Random.Next(0, 100) < 50) { // 50% of attacking cancelling attack of stronger unit unit.Goto = Point.Empty; continue; } } if (!unit.MoveTo(tiles[0].X - unit.X, tiles[0].Y - unit.Y)) { // The code below is to prevent the game from becoming stuck... if (Common.Random.Next(0, 100) < 67) { unit.Goto = Point.Empty; continue; } else if (Common.Random.Next(0, 100) < 67) { unit.SkipTurn(); return; } else { Game.DisbandUnit(unit); return; } } return; } } unit.SkipTurn(); return; } }
public void Disaster() { List <string> message = new List <string>(); bool humanGetsCity = false; if (Player.Cities.Length == 1) { return; } if (Size < 5) { return; } switch (Common.Random.Next(0, 9)) { case 0: { // Earthquake bool hillsNearby = CityTiles.Any(t => t.Type == Terrain.Hills); IList <IBuilding> buildingsOtherThanPalace = Buildings.Where(b => !(b is Palace)).ToList(); if (!hillsNearby || !buildingsOtherThanPalace.Any()) { return; } IBuilding buildingToDestroy = buildingsOtherThanPalace[Common.Random.Next(0, buildingsOtherThanPalace.Count - 1)]; RemoveBuilding(buildingToDestroy); message.Add($"Earthquake in {Name}!"); message.Add($"{buildingToDestroy} destroyed!"); break; } case 1: { // Plague bool hasMedicine = Player.HasAdvance <Medicine>(); bool hasAqueduct = HasBuilding <Aqueduct>(); bool hasConstruction = Player.Advances.Any(a => a is Construction); if (!hasMedicine && !hasAqueduct && hasConstruction) { Size = (byte)(Size - Size / 4); message.Add($"Plague in {Name}!"); message.Add($"Citizens killed!"); message.Add($"Citizens demand AQUEDUCT."); } break; } case 2: { // Flooding bool riverNearby = CityTiles.Any(t => t.Type == Terrain.River); bool hasCityWalls = HasBuilding <CityWalls>(); bool hasMasonry = Player.HasAdvance <Masonry>(); if (riverNearby && !hasCityWalls && hasMasonry) { Size = (byte)(Size - Size / 4); message.Add($"Flooding in {Name}!"); message.Add($"Citizens killed!"); message.Add($"Citizens demand CITY WALLS."); } break; } case 3: { // Volcano bool mountainNearby = CityTiles.Any(t => t.Type == Terrain.Mountains); bool hasTemple = HasBuilding <Temple>(); bool hasCeremonialBurial = Player.HasAdvance <CeremonialBurial>(); if (mountainNearby && !hasTemple && hasCeremonialBurial) { Size = (byte)(Size - Size / 3); message.Add($"Volcano erupts near {Name}!"); message.Add($"Citizens killed!"); message.Add($"Citizens demand TEMPLE."); } break; } case 4: { // Famine bool hasGranary = HasBuilding <Granary>(); bool hasPottery = Player.HasAdvance <Pottery>(); if (!hasGranary && hasPottery) { Size = (byte)(Size - Size / 3); message.Add($"Famine in {Name}!"); message.Add($"Citizens killed!"); message.Add($"Citizens demand POTTERY."); } break; } case 5: { // Fire IList <IBuilding> buildingsOtherThanPalace = Buildings.Where(b => !(b is Palace)).ToList(); bool hasAqueduct = HasBuilding <Aqueduct>(); bool hasConstruction = Player.HasAdvance <Construction>(); if (buildingsOtherThanPalace.Any() && !hasAqueduct && hasConstruction) { IBuilding buildingToDestroy = buildingsOtherThanPalace[Common.Random.Next(0, buildingsOtherThanPalace.Count - 1)]; RemoveBuilding(buildingToDestroy); message.Add($"Fire in {Name}!"); message.Add($"{buildingToDestroy.Name} destroyed!"); message.Add($"Citizens demand AQUEDUCT."); } break; } case 6: { // Pirates bool oceanNearby = CityTiles.Any(t => t.Type == Terrain.Ocean); bool hasBarracks = HasBuilding <Barracks>(); if (oceanNearby && !hasBarracks) { Food = 0; Shields = 0; message.Add($"Pirates plunder {Name}!"); message.Add($"Production halted, Food Stolen.!"); message.Add($"Citizens demand BARRACKS."); } break; } case 7: case 8: case 9: // Riot, scandal, corruption string[] disasterTypes = { "Scandal", "Riot", "Corruption" }; string disasterType = disasterTypes[Common.Random.Next(0, disasterTypes.Length - 1)]; string buildingDemanded = ""; if (HappyCitizens >= UnhappyCitizens) { return; } if (!HasBuilding <Temple>()) { buildingDemanded = nameof(Temple); } else if (!HasBuilding <Courthouse>()) { buildingDemanded = nameof(Courthouse); } else if (!HasBuilding <MarketPlace>()) { buildingDemanded = nameof(MarketPlace); } else if (!HasBuilding <Cathedral>()) { buildingDemanded = nameof(Cathedral); } else { buildingDemanded = "lower taxes"; } Food = 0; Shields = 0; message.Add($"{disasterType} in {Name}"); message.Add($"Citizens demand {buildingDemanded}"); if (HasBuilding <Palace>()) { return; } if (Player.Cities.Length < 4) { return; } City admired = null; int mostAppeal = 0; foreach (City city in Game.GetCities()) { if (city == this) { break; } int appeal = ((city.HappyCitizens - city.UnhappyCitizens) * 32) / city.Tile.DistanceTo(this); if (appeal > 4 && appeal > mostAppeal) { admired = city; mostAppeal = appeal; } } if (admired != null && admired.Owner != this.Owner) { message.Clear(); message.Add($"Residents of {Name} admire the prosperity of {admired.Name}"); message.Add($"{admired.Name} capture {Name}"); Player previousOwner = Game.GetPlayer(this.Owner); Show captureCity = Show.CaptureCity(this); captureCity.Done += (s1, a1) => { this.Owner = admired.Owner; previousOwner.IsDestroyed(); if (Human == admired.Owner) { GameTask.Insert(Tasks.Show.CityManager(this)); } }; if (Human == admired.Owner) { humanGetsCity = true; GameTask.Insert(captureCity); } } break; } if (message.Count > 0 && (Player == Owner || humanGetsCity)) { GameTask.Enqueue(Message.Advisor(Advisor.Domestic, false, message.ToArray())); } }
public void NewTurn() { UpdateResources(); Food += FoodIncome; if (Food < 0) { Food = 0; Size--; if (Human == Owner) { GameTask.Enqueue(Message.Newspaper(this, "Food storage exhausted", $"in {Name}!", "Famine feared.")); } if (Size == 0) { return; } } else if (Food > FoodRequired) { Food -= FoodRequired; if (Size == 10 && !_buildings.Any(b => b.Id == (int)Building.Aqueduct)) { GameTask.Enqueue(Message.Advisor(Advisor.Domestic, false, $"{Name} requires an AQUEDUCT", "for further growth.")); } else { Size++; } if (_buildings.Any(b => (b is Granary))) { if (Food < (FoodRequired / 2)) { Food = (FoodRequired / 2); } } } if (ShieldIncome < 0) { int maxDistance = Units.Max(u => Common.DistanceToTile(X, Y, u.X, u.Y)); IUnit unit = Units.Last(u => Common.DistanceToTile(X, Y, u.X, u.Y) == maxDistance); if (Human == Owner) { Message message = Message.DisbandUnit(this, unit); message.Done += (s, a) => { Game.DisbandUnit(unit); }; GameTask.Enqueue(message); } else { Game.DisbandUnit(unit); } } else if (ShieldIncome > 0) { Shields += ShieldIncome; } if (Shields >= (int)CurrentProduction.Price * 10) { if (CurrentProduction is Settlers && Size == 1 && Game.Difficulty == 0) { // On Chieftain level, it's not possible to create a Settlers in a city of size 1 } else if (CurrentProduction is IUnit) { Shields = 0; IUnit unit = Game.Instance.CreateUnit((CurrentProduction as IUnit).Type, X, Y, Owner); unit.SetHome(); unit.Veteran = (_buildings.Any(b => (b is Barracks))); if (CurrentProduction is Settlers) { if (Size == 1 && Player.Cities.Length == 1) { Size++; } if (Size == 1) { unit.SetHome(null); } Size--; } if (Human == Owner && (unit is Settlers || unit is Diplomat || unit is Caravan)) { GameTask advisorMessage = Message.Advisor(Advisor.Defense, true, $"{this.Name} builds {unit.Name}."); advisorMessage.Done += (s, a) => GameTask.Insert(Show.CityManager(this)); GameTask.Enqueue(advisorMessage); } } if (CurrentProduction is IBuilding && !_buildings.Any(b => b.Id == (CurrentProduction as IBuilding).Id)) { Shields = 0; if (CurrentProduction is ISpaceShip) { Message message = Message.Newspaper(this, $"{this.Name} builds", $"{(CurrentProduction as ICivilopedia).Name}."); message.Done += (s, a) => { // TODO: Add space ship component GameTask.Insert(Show.CityManager(this)); }; GameTask.Enqueue(message); } else if (CurrentProduction is Palace) { foreach (City city in Game.Instance.GetCities().Where(c => c.Owner == Owner)) { // Remove palace from all cites. city.RemoveBuilding <Palace>(); } if (HasBuilding <Courthouse>()) { _buildings.RemoveAll(x => x is Courthouse); } _buildings.Add(CurrentProduction as IBuilding); Message message = Message.Newspaper(this, $"{this.Name} builds", $"{(CurrentProduction as ICivilopedia).Name}."); message.Done += (s, a) => { GameTask advisorMessage = Message.Advisor(Advisor.Foreign, true, $"{Player.TribeName} capital", $"moved to {Name}."); advisorMessage.Done += (s1, a1) => GameTask.Insert(Show.CityManager(this)); GameTask.Enqueue(advisorMessage); }; GameTask.Enqueue(message); } else { _buildings.Add(CurrentProduction as IBuilding); GameTask.Enqueue(new ImprovementBuilt(this, (CurrentProduction as IBuilding))); } } if (CurrentProduction is IWonder && !Game.Instance.BuiltWonders.Any(w => w.Id == (CurrentProduction as IWonder).Id)) { Shields = 0; AddWonder(CurrentProduction as IWonder); GameTask.Enqueue(new ImprovementBuilt(this, (CurrentProduction as IWonder))); } } // TODO: Handle luxuries Player.Gold += Taxes; Player.Gold -= TotalMaintenance; Player.Science += Science; BuildingSold = false; GameTask.Enqueue(new ProcessScience(Player)); if (Player == Human) { return; } Player.AI.CityProduction(this); }
public void EndTurn() { foreach (Player player in _players.Where(x => !(x.Civilization is Barbarian))) { player.IsDestroyed(); } if (++_currentPlayer >= _players.Length) { _currentPlayer = 0; GameTurn++; if (GameTurn % 50 == 0 && AutoSave) { GameTask.Enqueue(Show.AutoSave); } IEnumerable <City> disasterCities = _cities.OrderBy(o => Common.Random.Next(0, 1000)).Take(2).AsEnumerable(); foreach (City city in disasterCities) { city.Disaster(); } if (Barbarian.IsSeaSpawnTurn) { ITile tile = Barbarian.SeaSpawnPosition; if (tile != null) { foreach (UnitType unitType in Barbarian.SeaSpawnUnits) { CreateUnit(unitType, tile.X, tile.Y, 0, false); } } } } if (!_players.Any(x => Game.PlayerNumber(x) != 0 && x != Human && !x.IsDestroyed())) { PlaySound("wintune"); GameTask conquest; GameTask.Enqueue(Message.Newspaper(null, "Your civilization", "has conquered", "the entire planet!")); GameTask.Enqueue(conquest = Show.Screen <Conquest>()); conquest.Done += (s, a) => Runtime.Quit(); } foreach (IUnit unit in _units.Where(u => u.Owner == _currentPlayer)) { GameTask.Enqueue(Turn.New(unit)); } foreach (City city in _cities.Where(c => c.Owner == _currentPlayer).ToArray()) { GameTask.Enqueue(Turn.New(city)); } GameTask.Enqueue(Turn.New(CurrentPlayer)); if (CurrentPlayer != HumanPlayer) { return; } if (Game.InstantAdvice && (Common.TurnToYear(Game.GameTurn) == -3600 || Common.TurnToYear(Game.GameTurn) == -2800)) { GameTask.Enqueue(Message.Help("--- Civilization Note ---", TextFile.Instance.GetGameText("HELP/HELP1"))); } else if (Game.InstantAdvice && (Common.TurnToYear(Game.GameTurn) == -3200 || Common.TurnToYear(Game.GameTurn) == -2400)) { GameTask.Enqueue(Message.Help("--- Civilization Note ---", TextFile.Instance.GetGameText("HELP/HELP2"))); } }
internal static void Move(IUnit unit) { if (unit.Owner == 0) { BarbarianMove(unit); return; } if (unit is Settlers) { ITile tile = unit.Tile; bool hasCity = (tile.City != null); bool validCity = (tile is Grassland || tile is River || tile is Plains) && (tile.City == null); bool validIrrigaton = (tile is Grassland || tile is River || tile is Plains || tile is Desert) && (tile.City == null) && (!tile.Mine) && (!tile.Irrigation) && tile.Cross().Any(x => x.IsOcean || x is River || x.Irrigation); bool validMine = (tile is Mountains || tile is Hills) && (tile.City == null) && (!tile.Mine) && (!tile.Irrigation); bool validRoad = (tile.City == null) && tile.Road; int nearestCity = 255; int nearestOwnCity = 255; if (Game.GetCities().Any()) { nearestCity = Game.GetCities().Min(x => Common.DistanceToTile(x.X, x.Y, tile.X, tile.Y)); } if (Game.GetCities().Any(x => x.Owner == unit.Owner)) { nearestOwnCity = Game.GetCities().Where(x => x.Owner == unit.Owner).Min(x => Common.DistanceToTile(x.X, x.Y, tile.X, tile.Y)); } if (validCity && nearestCity > 3) { GameTask.Enqueue(Orders.FoundCity(unit as Settlers)); return; } else if (nearestOwnCity < 3) { switch (Common.Random.Next(5 * nearestOwnCity)) { case 0: if (validRoad) { GameTask.Enqueue(Orders.BuildRoad(unit)); return; } break; case 1: if (validIrrigaton) { GameTask.Enqueue(Orders.BuildIrrigation(unit)); return; } break; case 2: if (validMine) { GameTask.Enqueue(Orders.BuildMines(unit)); return; } break; } } for (int i = 0; i < 1000; i++) { int relX = Common.Random.Next(-1, 2); int relY = Common.Random.Next(-1, 2); if (relX == 0 && relY == 0) { continue; } if (unit.Tile[relX, relY] is Ocean) { continue; } unit.MoveTo(relX, relY); return; } unit.SkipTurn(); return; } else if (unit is Militia || unit is Phalanx || unit is Musketeers || unit is Riflemen || unit is MechInf) { unit.Fortify = true; while (unit.Tile.City != null && unit.Tile.Units.Count(x => x is Militia || x is Phalanx || x is Musketeers || x is Riflemen || x is MechInf) > 2) { IUnit disband = null; IUnit[] units = unit.Tile.Units.Where(x => x != unit).ToArray(); if ((disband = unit.Tile.Units.FirstOrDefault(x => x is Militia)) != null) { Game.DisbandUnit(disband); continue; } if ((disband = unit.Tile.Units.FirstOrDefault(x => x is Phalanx)) != null) { Game.DisbandUnit(disband); continue; } if ((disband = unit.Tile.Units.FirstOrDefault(x => x is Musketeers)) != null) { Game.DisbandUnit(disband); continue; } if ((disband = unit.Tile.Units.FirstOrDefault(x => x is Riflemen)) != null) { Game.DisbandUnit(disband); continue; } if ((disband = unit.Tile.Units.FirstOrDefault(x => x is MechInf)) != null) { Game.DisbandUnit(disband); continue; } } } else { if (unit.Class != UnitClass.Land) { Game.DisbandUnit(unit); } for (int i = 0; i < 1000; i++) { int relX = Common.Random.Next(-1, 2); int relY = Common.Random.Next(-1, 2); if (relX == 0 && relY == 0) { continue; } if (unit.Tile[relX, relY] is Ocean) { continue; } unit.MoveTo(relX, relY); return; } unit.SkipTurn(); return; } }
private void OnInitialize(object sender, EventArgs args) { Runtime.WindowTitle = Settings.WindowTitle; GameTask.Enqueue(Show.Screens(StartupScreens)); }
public void Update() { IUnit unit = ActiveUnit; if (CurrentPlayer == HumanPlayer) { if (unit != null && !unit.Goto.IsEmpty) { ITile[] tiles = (unit as BaseUnit).MoveTargets.OrderBy(x => x.DistanceTo(unit.Goto)).ThenBy(x => x.Movement).ToArray(); if (Settings.Instance.PathFinding) { /* Use AStar */ AStar.sPosition Destination, Pos; Destination.iX = unit.Goto.X; Destination.iY = unit.Goto.Y; Pos.iX = unit.X; Pos.iY = unit.Y; if (Destination.iX == Pos.iX && Destination.iY == Pos.iY) { unit.Goto = Point.Empty; // eh... never mind return; } AStar AStar = new AStar(); AStar.sPosition NextPosition = AStar.FindPath(Destination, unit); if (NextPosition.iX < 0) { // if no path found unit.Goto = Point.Empty; return; } unit.MoveTo(NextPosition.iX - Pos.iX, NextPosition.iY - Pos.iY); return; } else { int distance = unit.Tile.DistanceTo(unit.Goto); if (tiles.Length == 0 || tiles[0].DistanceTo(unit.Goto) > distance) { // No valid tile to move to, cancel goto unit.Goto = Point.Empty; return; } else if (tiles[0].DistanceTo(unit.Goto) == distance) { // Distance is unchanged, 50% chance to cancel goto if (Common.Random.Next(0, 100) < 50) { unit.Goto = Point.Empty; return; } } } unit.MoveTo(tiles[0].X - unit.X, tiles[0].Y - unit.Y); return; } return; } if (unit != null && (unit.MovesLeft > 0 || unit.PartMoves > 0)) { GameTask.Enqueue(Turn.Move(unit)); return; } GameTask.Enqueue(Turn.End()); }
public void NewTurn() { UpdateResources(); if (IsInDisorder) { if (Common.Random.Next(20) == 1 && HasBuilding <Buildings.NuclearPlant>() && !Player.HasAdvance <Advances.FusionPower>()) { // todo: meltdown } if (WasInDisorder) { if (Player == Human) { GameTask.Insert(Message.Advisor(Advisor.Domestic, true, "Civil Disorder in", $"{Name}! Mayor", "flees in panic.")); } } else { if (Player == Human) { Show disorderCity = Show.DisorderCity(this); GameTask.Insert(disorderCity); } Log($"City {Name} belonging to {Player.TribeName} has gone into disorder"); } if (WasInDisorder && Player.Government is Advances.Democracy) { // todo: Force revolution } WasInDisorder = true; } else { if (WasInDisorder) { if (Player == Human) { GameTask.Insert(Message.Advisor(Advisor.Domestic, true, "Order restored", $" in{Name}.")); } Log($"City {Name} belonging to {Player.TribeName} is no longer in disorder"); } WasInDisorder = false; } if (UnhappyCitizens == 0 && HappyCitizens >= ContentCitizens && Size >= 3) { // we love the president day if (Player.Government is Governments.Democracy || Player.Government is Republic) { if (Food > 0) { Size++; } } else { // we love the king day } GameTask.Insert(Show.WeLovePresidentDayCity(this)); } Food += IsInDisorder ? 0 : FoodIncome; if (Food < 0) { Food = 0; Size--; if (Human == Owner) { GameTask.Enqueue(Message.Newspaper(this, "Food storage exhausted", $"in {Name}!", "Famine feared.")); } if (Size == 0) { return; } } else if (Food > FoodRequired) { Food -= FoodRequired; if (Size == 10 && !_buildings.Any(b => b.Id == (int)Building.Aqueduct)) { GameTask.Enqueue(Message.Advisor(Advisor.Domestic, false, $"{Name} requires an AQUEDUCT", "for further growth.")); } else { Size++; } if (_buildings.Any(b => (b is Granary))) { if (Food < (FoodRequired / 2)) { Food = (FoodRequired / 2); } } } if (ShieldIncome < 0) { int maxDistance = Units.Max(u => Common.DistanceToTile(X, Y, u.X, u.Y)); IUnit unit = Units.Last(u => Common.DistanceToTile(X, Y, u.X, u.Y) == maxDistance); if (Human == Owner) { Message message = Message.DisbandUnit(this, unit); message.Done += (s, a) => { Game.DisbandUnit(unit); }; GameTask.Enqueue(message); } else { Game.DisbandUnit(unit); } } else if (ShieldIncome > 0) { Shields += IsInDisorder ? 0 : ShieldIncome; } if (Shields >= (int)CurrentProduction.Price * 10) { if (CurrentProduction is Settlers && Size == 1 && Game.Difficulty == 0) { // On Chieftain level, it's not possible to create a Settlers in a city of size 1 } else if (CurrentProduction is IUnit) { Shields = 0; IUnit unit = Game.Instance.CreateUnit((CurrentProduction as IUnit).Type, X, Y, Owner); unit.SetHome(); unit.Veteran = (_buildings.Any(b => (b is Barracks))); if (CurrentProduction is Settlers) { if (Size == 1 && Player.Cities.Length == 1) { Size++; } if (Size == 1) { unit.SetHome(null); } Size--; } if (Human == Owner && (unit is Settlers || unit is Diplomat || unit is Caravan)) { GameTask advisorMessage = Message.Advisor(Advisor.Defense, true, $"{this.Name} builds {unit.Name}."); advisorMessage.Done += (s, a) => GameTask.Insert(Show.CityManager(this)); GameTask.Enqueue(advisorMessage); } } if (CurrentProduction is IBuilding && !_buildings.Any(b => b.Id == (CurrentProduction as IBuilding).Id)) { Shields = 0; if (CurrentProduction is ISpaceShip) { Message message = Message.Newspaper(this, $"{this.Name} builds", $"{(CurrentProduction as ICivilopedia).Name}."); message.Done += (s, a) => { // TODO: Add space ship component GameTask.Insert(Show.CityManager(this)); }; GameTask.Enqueue(message); } else if (CurrentProduction is Palace) { foreach (City city in Game.Instance.GetCities().Where(c => c.Owner == Owner)) { // Remove palace from all cites. city.RemoveBuilding <Palace>(); } if (HasBuilding <Courthouse>()) { _buildings.RemoveAll(x => x is Courthouse); } _buildings.Add(CurrentProduction as IBuilding); Message message = Message.Newspaper(this, $"{this.Name} builds", $"{(CurrentProduction as ICivilopedia).Name}."); message.Done += (s, a) => { GameTask advisorMessage = Message.Advisor(Advisor.Foreign, true, $"{Player.TribeName} capital", $"moved to {Name}."); advisorMessage.Done += (s1, a1) => GameTask.Insert(Show.CityManager(this)); GameTask.Enqueue(advisorMessage); }; GameTask.Enqueue(message); } else { _buildings.Add(CurrentProduction as IBuilding); GameTask.Enqueue(new ImprovementBuilt(this, (CurrentProduction as IBuilding))); } } if (CurrentProduction is IWonder && !Game.Instance.BuiltWonders.Any(w => w.Id == (CurrentProduction as IWonder).Id)) { Shields = 0; AddWonder(CurrentProduction as IWonder); GameTask.Enqueue(new ImprovementBuilt(this, (CurrentProduction as IWonder))); } } // TODO: Handle luxuries Player.Gold += IsInDisorder ? (short)0 : Taxes; Player.Gold -= TotalMaintenance; Player.Science += Science; BuildingSold = false; GameTask.Enqueue(new ProcessScience(Player)); if (Player == Human) { return; } Player.AI.CityProduction(this); }
public void EndTurn() { foreach (Player player in _players.Where(x => !(x.Civilization is Barbarian))) { player.IsDestroyed(); } if (++_currentPlayer >= _players.Length) { _currentPlayer = 0; GameTurn++; if (GameTurn % 50 == 0 && Settings.AutoSave) { GameTask.Enqueue(Show.AutoSave); } // TODO: Figure out how barbarians spawn if (Common.TurnToYear(_gameTurn) > -2000) { if (Common.Random.Next(0, 40) == 0) { City[] oceanCities = _cities.Where(x => x.Tile.GetBorderTiles().Any(t => t.IsOcean)).ToArray(); if (oceanCities.Any()) { City barbarianTarget = oceanCities.OrderBy(x => Common.Random.Next(0, 200)).First(); ITile[,] tiles = (barbarianTarget.Tile as BaseTile)[-6, -6, 13, 13]; for (int i = 0; i < 1000; i++) { int relX = Common.Random.Next(0, 13); int relY = Common.Random.Next(0, 13); ITile tile = tiles[relX, relY]; if (!tile.IsOcean) { continue; } if (_cities.Min(x => Common.DistanceToTile(x.X, x.Y, tile.X, tile.Y)) < 3) { continue; } foreach (UnitType unitType in new [] { UnitType.Sail, UnitType.Legion, UnitType.Legion, UnitType.Diplomat }) { CreateUnit(unitType, tile.X, tile.Y, 0, false); } break; } } } } } if (!_players.Any(x => Game.PlayerNumber(x) != 0 && x != Human && !x.IsDestroyed())) { GameTask conquest; GameTask.Enqueue(Message.Newspaper(null, "Your civilization", "has conquered", "the entire planet!")); GameTask.Enqueue(conquest = Show.Screen <Conquest>()); conquest.Done += (s, a) => Runtime.Quit(); } foreach (IUnit unit in _units.Where(u => u.Owner == _currentPlayer)) { GameTask.Enqueue(Turn.New(unit)); } foreach (City city in _cities.Where(c => c.Owner == _currentPlayer).ToArray()) { GameTask.Enqueue(Turn.New(city)); } GameTask.Enqueue(Turn.New(CurrentPlayer)); if (CurrentPlayer == HumanPlayer) { return; } }