Beispiel #1
0
        public bool CanMoveTo(int relX, int relY)
        {
            // TODO only referenced by land units, move to BaseUnitLand?

            // Issue #93: fix problems with zone-of-control.

            // refactored out for unit testability
            ITile moveTarget = Map[X, Y][relX, relY];

            if (moveTarget == null)
            {
                return(false);
            }

            // Issue #116: allow ship-borne units to move to any unoccupied tile
            if (Map[X, Y].IsOcean)
            {
                return(!moveTarget.Units.Any(u => u.Owner != Owner));
            }

            var thisUnits = Map[X, Y].GetBorderTiles().SelectMany(t => t.Units);
            var destUnits = moveTarget.GetBorderTiles().SelectMany(t => t.Units);

            // Any enemy units around my position OR the target position?
            bool thisBlocked = thisUnits.Any(u => u.Owner != Owner);
            bool destBlocked = destUnits.Any(u => u.Owner != Owner);
            bool destOK      = moveTarget.Units.Any(u => u.Owner == Owner) || moveTarget.HasCity;

            // Cannot move from a square adjacent to enemy unit to a square adjacent to enemy unit
            // but _can_ move to square occupied by own units or to any undefended city square
            return(destOK || !thisBlocked || !destBlocked);
        }
Beispiel #2
0
        public bool BuildIrrigation()
        {
            ITile tile = Map[X, Y];

            if (tile.Irrigation)
            {
                // Tile already irrigated, ignore
                return(false);
            }

            if ((tile is Forest) || (tile is Jungle) || (tile is Swamp))
            {
                BuildingIrrigation = 4;
                MovesLeft          = 0;
                PartMoves          = 0;
                return(true);
            }
            else if ((tile.GetBorderTiles().Any(t => (t.X == X || t.Y == Y) && (t.City == null) && (t.IsOcean || t.Irrigation || (t is River)))) || (tile is River))
            {
                if (!tile.IsOcean && !(tile.Irrigation) && ((tile is Desert) || (tile is Grassland) || (tile is Hills) || (tile is Plains) || (tile is River)))
                {
                    BuildingIrrigation = 3;
                    MovesLeft          = 0;
                    PartMoves          = 0;
                    return(true);
                }
                if (Human == Owner)
                {
                    GameTask.Enqueue(Message.Error("-- Civilization Note --", TextFile.Instance.GetGameText("ERROR/NOIRR")));
                }
                return(false);
            }
            else
            {
                if (((tile is Desert) || (tile is Grassland) || (tile is Hills) || (tile is Plains) || (tile is River)) && tile.City == null)
                {
                    if (Human == Owner)
                    {
                        GameTask.Enqueue(Message.Error("-- Civilization Note --", TextFile.Instance.GetGameText("ERROR/NOWATER")));
                    }
                    return(true);
                }
                if (Human == Owner)
                {
                    GameTask.Enqueue(Message.Error("-- Civilization Note --", TextFile.Instance.GetGameText("ERROR/NOIRR")));
                }
            }
            return(false);
        }
Beispiel #3
0
        public virtual bool MoveTo(int relX, int relY)
        {
            if (Movement != null)
            {
                return(false);
            }

            ITile moveTarget = Map[X, Y][relX, relY];

            if (moveTarget == null)
            {
                return(false);
            }
            if (moveTarget.Units.Any(u => u.Owner != Owner))
            {
                if (Class == UnitClass.Land && Tile.IsOcean)
                {
                    GameTask.Enqueue(Message.Error("-- Civilization Note --", TextFile.Instance.GetGameText($"ERROR/AMPHIB")));
                    return(false);
                }
                return(Confront(relX, relY));
            }
            if (Class == UnitClass.Land && !(this is Diplomat || this is Caravan) && !new ITile[] { Map[X, Y], moveTarget }.Any(t => t.IsOcean || t.City != null) && moveTarget.GetBorderTiles().SelectMany(t => t.Units).Any(u => u.Owner != Owner))
            {
                if (!moveTarget.Units.Any(x => x.Owner == Owner))
                {
                    IUnit[] targetUnits = moveTarget.GetBorderTiles().SelectMany(t => t.Units).Where(u => u.Owner != Owner).ToArray();
                    IUnit[] borderUnits = Map[X, Y].GetBorderTiles().SelectMany(t => t.Units).Where(u => u.Owner != Owner).ToArray();

                    if (borderUnits.Any(u => targetUnits.Any(t => t.X == u.X && t.Y == u.Y)))
                    {
                        if (Human == Owner)
                        {
                            GameTask.Enqueue(Message.Error("-- Civilization Note --", TextFile.Instance.GetGameText($"ERROR/ZOC")));
                        }
                        return(false);
                    }
                }
            }
            if (moveTarget.City != null && Map[X, Y][relX, relY].City.Owner != Owner)
            {
                return(Confront(relX, relY));
            }

            if (!MoveTargets.Any(t => t.X == moveTarget.X && t.Y == moveTarget.Y))
            {
                // Target tile is invalid
                // TODO: For some tiles, display a message detailing why the move is illegal
                return(false);
            }

            // TODO: This implementation was done by observation, may need a revision
            if (MovesLeft == 0 && !moveTarget.Road && moveTarget.Movement > 1)
            {
                bool success;
                if (PartMoves >= 2)
                {
                    // 2/3 moves left? 50% chance of success
                    success = (Common.Random.Next(0, 2) == 0);
                }
                else
                {
                    // 2/3 moves left? 33% chance of success
                    success = (Common.Random.Next(0, 3) == 0);
                }

                if (!success)
                {
                    PartMoves = 0;
                    return(false);
                }
            }

            Movement       = new MoveUnit(relX, relY);
            Movement.Done += MoveEnd;
            GameTask.Insert(Movement);

            return(true);
        }