Пример #1
0
        private bool Update()
        {
            if (!GameTask.Update() && (!GameTask.Fast && (_gameTick % 4) > 0))
            {
                return(false);
            }
            if (Common.Screens.Any(x => Common.HasAttribute <Modal>(x)))
            {
                return(Common.Screens.Last(x => Common.HasAttribute <Modal>(x)).Update(_gameTick / 4));
            }

            bool update = false;

            foreach (IScreen screen in Common.Screens.Reverse())
            {
                if (screen.Update(_gameTick / 4))
                {
                    update = true;
                }
                if (Common.HasAttribute <Break>(screen))
                {
                    return(update);
                }
            }
            return(update);
        }
Пример #2
0
 public static void Insert(GameTask task)
 {
     if (task == null)
     {
         return;
     }
     task.Done += Finish;
     _tasks.Insert(0, task);
 }
Пример #3
0
 public static void Enqueue(GameTask task)
 {
     if (task == null)
     {
         return;
     }
     task.Done += Finish;
     _tasks.Add(task);
 }
Пример #4
0
 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."));
 }
Пример #5
0
        private static void Finish(object sender, EventArgs args)
        {
            _tasks.Remove((sender as GameTask));
            if (!_tasks.Any())
            {
                _currentTask = null;
                return;
            }

            NextTask();
        }
Пример #6
0
 private static void Finish(object sender, EventArgs args)
 {
     _tasks.Remove((sender as GameTask));
     if (!_tasks.Any())
     {
         _currentTask = null;
     }
     else
     {
         (_currentTask = _tasks[0]).Run();
     }
 }
Пример #7
0
 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);
 }
Пример #8
0
        public static bool Update()
        {
            if (_currentTask != null)
            {
                return(_currentTask.Step());
            }
            else if (_tasks.Count == 0)
            {
                return(false);
            }

            (_currentTask = _tasks[0]).Run();
            return(true);
        }
Пример #9
0
        private static void NextTask()
        {
            _currentTask = _tasks[0];
            TaskEventArgs eventArgs = new TaskEventArgs();

            Started?.Invoke(_currentTask, eventArgs);
            if (eventArgs.Aborted)
            {
                _currentTask.EndTask();
            }
            else
            {
                _currentTask.Run();
            }
        }
Пример #10
0
        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--;
            }
        }
Пример #11
0
        public void CheckDestroyed()
        {
            if (DestroyTurn != -1 || !IsDestroyed)
            {
                return;
            }
            if (IsHuman)
            {
                // TODO: Move Game Over code here
                return;
            }

            ICivilization destroyCivilization = Game.CurrentPlayer.Civilization;

            if (destroyCivilization == Civilization)
            {
                destroyCivilization = Game.GetPlayer(0).Civilization;
            }

            GameTask.Insert(Message.Advisor(Advisor.Defense, false, Civilization.Name, "civilization", "destroyed", $"by {destroyCivilization.NamePlural}!"));
        }
Пример #12
0
        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;
            }
        }
Пример #13
0
        private void PlayerDestroyed(object sender, EventArgs args)
        {
            Player player = (sender as Player);

            ICivilization destroyed   = player.Civilization;
            ICivilization destroyedBy = Game.CurrentPlayer.Civilization;

            if (destroyedBy == destroyed)
            {
                destroyedBy = Game.GetPlayer(0).Civilization;
            }

            _replayData.Add(new ReplayData.CivilizationDestroyed(_gameTurn, destroyed.Id, destroyedBy.Id));

            if (player.IsHuman)
            {
                // TODO: Move Game Over code here
                return;
            }

            GameTask.Insert(Message.Advisor(Advisor.Defense, false, destroyed.Name, "civilization", "destroyed", $"by {destroyedBy.NamePlural}!"));
        }
Пример #14
0
        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());
        }
Пример #15
0
        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--;
            }
        }
Пример #16
0
        public void Generate(int landMass = 1, int temperature = 1, int climate = 1, int age = 1)
        {
            if (Ready || _tiles != null)
            {
                Log("ERROR: Map is already load{0}/generat{0}", (Ready ? "ed" : "ing"));
                return;
            }

            if (Settings.Instance.CustomMapSize)
            {
                CustomMapSize customMapSize = new CustomMapSize();
                customMapSize.Closed += (s, a) =>
                {
                    Size mapSize = (s as CustomMapSize).MapSize;
                    _width  = mapSize.Width;
                    _height = mapSize.Height;

                    _landMass    = landMass;
                    _temperature = temperature;
                    _climate     = climate;
                    _age         = age;

                    Task.Run(() => GenerateThread());
                };

                GameTask.Insert(Show.Screen(customMapSize));
                return;
            }

            _landMass    = landMass;
            _temperature = temperature;
            _climate     = climate;
            _age         = age;

            Task.Run(() => GenerateThread());
        }
Пример #17
0
        private static void BarbarianMoveWater(IUnit unit)
        {
            if (!unit.Tile.Units.Any(x => x.Class == UnitClass.Land))
            {
                Game.DisbandUnit(unit);
                return;
            }

            for (int i = 0; i < 1000; i++)
            {
                if (unit.Tile.GetBorderTiles().Any(x => !x.IsOcean))
                {
                    if (Game.GetCities().Any(x => x.Owner != 0) && unit.Tile.GetBorderTiles().Any(x => !x.IsOcean && !x.Units.Any(u => u.Owner != 0)))
                    {
                        City nearestCity = Game.GetCities().Where(x => x.Owner != 0).OrderBy(x => Common.DistanceToTile(x.X, x.Y, unit.X, unit.Y)).ThenBy(x => x.Player == Human ? 0 : 1).First();
                        if (nearestCity.Player == Human && Human.Visible(unit.Tile))
                        {
                            GameTask.Insert(Message.Advisor(Advisor.Defense, false, "Barbarian raiding party", $"lands near {nearestCity.Name}!", "Citizens are alarmed."));
                        }
                    }

                    foreach (IUnit landUnit in unit.Tile.Units.Where(x => x.Class == UnitClass.Land && x.Sentry))
                    {
                        landUnit.Sentry = false;
                    }
                    if (unit.Tile.Units.Any(x => x.Class == UnitClass.Land && x.MovesLeft > 0))
                    {
                        Game.UnitWait();
                    }
                    else
                    {
                        unit.SkipTurn();
                    }
                    return;
                }

                if (unit.Goto.IsEmpty)
                {
                    if (!Game.GetCities().Any(x => x.Owner != 0 && x.HasBuilding <Palace>()))
                    {
                        Game.DisbandUnit(unit);
                    }

                    City nearestCity = Game.GetCities().Where(x => x.Owner != 0 && x.HasBuilding <Palace>()).OrderBy(x => Common.DistanceToTile(x.X, x.Y, unit.X, unit.Y)).First();
                    if (Common.DistanceToTile(unit.X, unit.Y, nearestCity.X, nearestCity.Y) > 10)
                    {
                        Game.DisbandUnit(unit);
                    }
                    unit.Goto = new Point(nearestCity.X, nearestCity.Y);
                    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 (!unit.MoveTo(tiles[0].X - unit.X, tiles[0].Y - unit.Y))
                    {
                        unit.Goto = Point.Empty;
                        unit.SkipTurn();
                    }
                    return;
                }

                unit.SkipTurn();
                return;
            }
        }
Пример #18
0
        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")));
            }
        }
Пример #19
0
 public static void Enqueue(GameTask task)
 {
     task.Done += Finish;
     _tasks.Add(task);
 }
Пример #20
0
        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());
        }
Пример #21
0
        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;
            }
        }
Пример #22
0
 public static void Insert(GameTask task)
 {
     task.Done += Finish;
     _tasks.Insert(0, task);
 }
Пример #23
0
        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);
        }
Пример #24
0
        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;
            }
        }
Пример #25
0
        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);
        }
Пример #26
0
        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()));
            }
        }
Пример #27
0
 private void OnInitialize(object sender, EventArgs args)
 {
     Runtime.WindowTitle = Settings.WindowTitle;
     GameTask.Enqueue(Show.Screens(StartupScreens));
 }
Пример #28
0
        private static void BarbarianMove(IUnit unit)
        {
            switch (unit.Class)
            {
            case UnitClass.Water:
            {
                if (!unit.Tile.Units.Any(x => x.Class == UnitClass.Land))
                {
                    Game.DisbandUnit(unit);
                    return;
                }

                for (int i = 0; i < 1000; i++)
                {
                    if (unit.Tile.GetBorderTiles().Any(x => !x.IsOcean))
                    {
                        if (Game.GetCities().Any(x => x.Owner != 0))
                        {
                            City nearestCity = Game.GetCities().Where(x => x.Owner != 0).OrderBy(x => Common.DistanceToTile(x.X, x.Y, unit.X, unit.Y)).ThenBy(x => x.Player == Human ? 0 : 1).First();
                            if (nearestCity.Player == Human && Human.Visible(unit.Tile))
                            {
                                GameTask.Insert(Message.Advisor(Advisor.Defense, false, "Barbarian raiding party", $"lands near {nearestCity.Name}!", "Citizens are alarmed."));
                            }
                        }

                        foreach (IUnit landUnit in unit.Tile.Units.Where(x => x.Class == UnitClass.Land && x.Sentry))
                        {
                            landUnit.Sentry = false;
                        }
                        unit.SkipTurn();
                        continue;
                    }

                    if (unit.Goto.IsEmpty)
                    {
                        if (!Game.GetCities().Any(x => x.Owner != 0))
                        {
                            Game.DisbandUnit(unit);
                        }

                        City nearestCity = Game.GetCities().Where(x => x.Owner != 0).OrderBy(x => Common.DistanceToTile(x.X, x.Y, unit.X, unit.Y)).First();
                        if (Common.DistanceToTile(unit.X, unit.Y, nearestCity.X, nearestCity.Y) > 10)
                        {
                            Game.DisbandUnit(unit);
                        }
                        unit.Goto = new Point(nearestCity.X, nearestCity.Y);
                        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 (!unit.MoveTo(tiles[0].X - unit.X, tiles[0].Y - unit.Y))
                        {
                            unit.Goto = Point.Empty;
                            unit.SkipTurn();
                            return;
                        }
                    }

                    unit.SkipTurn();
                    return;
                }
            }
                return;

            case UnitClass.Land:
            {
                ITile[] tiles = unit.Tile.GetBorderTiles().Where(t => !((unit.Tile.IsOcean || unit is Diplomat) && t.City != null) && !t.IsOcean && t.Units.Any(u => u.Owner != 0)).ToArray();
                if (tiles.Length == 0)
                {
                    // No adjecent units found
                    if (Common.Random.Next(10) < 7)
                    {
                        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 is Diplomat && unit.Tile[relX, relY].City != null)
                            {
                                continue;
                            }
                            if (unit.Tile.IsOcean && unit.Tile[relX, relY].City != null)
                            {
                                continue;
                            }
                            unit.MoveTo(relX, relY);
                            return;
                        }
                    }
                    Game.DisbandUnit(unit);
                    return;
                }
                else
                {
                    ITile moveTo = tiles[Common.Random.Next(tiles.Length)];
                    int   relX   = moveTo.X - unit.X;
                    int   relY   = moveTo.Y - unit.Y;
                    while (relX < -1)
                    {
                        relX += 80;
                    }
                    while (relX > 1)
                    {
                        relX -= 80;
                    }
                    if (unit is Diplomat && unit.Tile.City != null)
                    {
                        return;
                    }

                    unit.MoveTo(relX, relY);
                }
            }
                return;

            default:
                Game.DisbandUnit(unit);
                return;
            }
        }
Пример #29
0
        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;
            }
        }