예제 #1
0
        private void ListHitableTiles(List <Tile> resultList, List <Position> includedPositions)
        {
            List <TileWithDistance> openList = new List <TileWithDistance>();
            Dictionary <Position, TileWithDistance> reachedTiles = new Dictionary <Position, TileWithDistance>();

            TileWithDistance startTile = new TileWithDistance(Unit.Game.Map.GetTile(Unit.Pos), 0);

            openList.Add(startTile);
            reachedTiles.Add(startTile.Pos, startTile);

            while (openList.Count > 0)
            {
                TileWithDistance tile = openList[0];
                openList.RemoveAt(0);

                if (tile.Distance > Range)
                {
                    continue;
                }

                foreach (Tile n in tile.Neighbors)
                {
                    if (n.Pos == Unit.Pos)
                    {
                        continue;
                    }

                    if (!Unit.Owner.VisiblePositions.Contains(n.Pos))
                    {
                        continue;
                    }

                    if (includedPositions != null)
                    {
                        if (!includedPositions.Contains(n.Pos))
                        {
                            continue;
                        }
                    }
                    if (!reachedTiles.ContainsKey(n.Pos))
                    {
                        TileWithDistance neighborsTile = new TileWithDistance(Unit.Game.Map.GetTile(n.Pos), tile.Distance + 1);
                        reachedTiles.Add(neighborsTile.Pos, neighborsTile);

                        if (neighborsTile.Distance <= Range)
                        {
                            openList.Add(neighborsTile);
                            resultList.Add(n);
                        }
                    }
                }
            }
        }
예제 #2
0
        public override void AttachUnits(Dispatcher dispatcher, Player player, List <PlayerUnit> moveableUnits)
        {
            base.AttachUnits(dispatcher, player, moveableUnits);

            List <string> deadUnits = new List <string>();

            foreach (string unitId in AssignedUnits)
            {
                bool playerUnitFound = false;
                foreach (PlayerUnit playerUnit in player.Units.Values)
                {
                    if (playerUnit.Unit.UnitId == unitId)
                    {
                        if (playerUnit.PossibleMoves.Count > 0)
                        {
                            playerUnitFound = true;
                            break;
                        }

                        if (!moveableUnits.Contains(playerUnit))
                        {
                            // Attached unit found, but is busy doing something else
                            // Keep unit, no request
                            foreach (UnitType unitType in DemandedUnitTypes)
                            {
                                if (unitType.Matches(playerUnit))
                                {
                                    currentDemandedUnitTypes.Remove(unitType);
                                    break;
                                }
                            }
                        }
                        else
                        {
                            if (playerUnit.Unit.IsComplete())
                            {
                                if (playerUnit.Unit.Extractor.CanExtract)
                                {
                                    TileWithDistance nextTile = null;
                                    if (nextTile == null || nextTile.Metal == 0)
                                    {
                                        // Move that punk to metal
                                        Dictionary <Position, TileWithDistance> tiles = Map.EnumerateTiles(Center, Range, true, matcher: tile =>
                                        {
                                            if (!this.PosititionsInArea.ContainsKey(tile.Pos))
                                            {
                                                return(false);
                                            }

                                            if (tile.Pos != playerUnit.Unit.Pos)
                                            {
                                                // Extract from others, not the extractor
                                                if (tile.Unit != null)
                                                {
                                                    if (tile.Unit.Owner.PlayerModel.Id != playerUnit.Unit.Owner.PlayerModel.Id)
                                                    {
                                                        // Extract from eneny? Why not.
                                                        return(true);
                                                    }
                                                    else
                                                    {
                                                        if (tile.Unit.ExtractMe)
                                                        {
                                                            return(true);
                                                        }
                                                        else
                                                        {
                                                            return(false);
                                                        }
                                                    }
                                                }
                                            }
                                            return(tile.Metal > 0);
                                        });

                                        nextTile = null;
                                        if (tiles.Count > 0)
                                        {
                                            foreach (TileWithDistance possibleTile in tiles.Values)
                                            {
                                                if (possibleTile.Tile.CanMoveTo()) // && */possibleTile.Unit == null)
                                                {
                                                    nextTile = possibleTile;
                                                    break;
                                                }
                                                else
                                                {
                                                    // If cannot move on tile, move next to it
                                                    foreach (Tile tx in possibleTile.Neighbors)
                                                    {
                                                        if (tx.CanMoveTo())
                                                        {
                                                            nextTile = new TileWithDistance(tx, 0);
                                                            break;
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    if (nextTile != null)
                                    {
                                        playerUnit.Unit.ExtractMe         = false;
                                        UnitReachedCommandDoNotFollowPath = true;
                                        if (nextTile.Pos != playerUnit.Unit.Pos)
                                        {
                                            dispatcher.MoveUnit(this, playerUnit, nextTile.Pos);
                                        }

                                        playerUnitFound = true;
                                    }
                                    else
                                    {
                                        // Release container. No more metal to collect. The stray collector should catch this
                                        playerUnit.Unit.ExtractMe = true;
                                        nomoreMetalFound          = true;

                                        foreach (CommandSource commandSource in CommandSources)
                                        {
                                            // Assign it to the source. The source will take care of extraction
                                            commandSource.Parent.AssignUnit(playerUnit.Unit.UnitId);
                                        }
                                    }
                                }
                                else
                                {
                                    // Container full. Release it
                                    playerUnit.Unit.ExtractMe = true;

                                    foreach (CommandSource commandSource in CommandSources)
                                    {
                                        // Assign it to the source. The source will take care of extraction
                                        commandSource.Parent.AssignUnit(playerUnit.Unit.UnitId);
                                    }
                                }
                            }
                            else
                            {
                                if (!UnitReachedCommandDoNotFollowPath)
                                {
                                    // Not arrived yet. In production?
                                    playerUnitFound = true;
                                }
                                else
                                {
                                    // Otherwise: Has arrived, was collecting and is now damaged. Unassign and mark for extraction
                                    if (!playerUnit.Unit.UnderConstruction)
                                    {
                                        playerUnit.Unit.ExtractMe = true;

                                        foreach (CommandSource commandSource in CommandSources)
                                        {
                                            // Assign it to the source. The source will take care of extraction
                                            commandSource.Parent.AssignUnit(playerUnit.Unit.UnitId);
                                        }
                                    }
                                    else
                                    {
                                        playerUnitFound = true;
                                    }
                                }
                            }
                        }
                        break;
                    }
                }
                if (!playerUnitFound)
                {
                    // Unit no longer exists
                    deadUnits.Add(unitId);
                }
            }

            foreach (string deadUnitId in deadUnits)
            {
                AssignedUnits.Remove(deadUnitId);
            }
        }
예제 #3
0
        public Dictionary <Position, TileWithDistance> EnumerateTiles(Position startPos, int range, bool includeStartPos = true, Func <TileWithDistance, bool> stopper = null, Func <TileWithDistance, bool> matcher = null)
        {
            Dictionary <Position, TileWithDistance> resultList = new Dictionary <Position, TileWithDistance>();

            List <TileWithDistance> openList = new List <TileWithDistance>();
            Dictionary <Position, TileWithDistance> reachedTiles = new Dictionary <Position, TileWithDistance>();

            Tile startTilePos = GetTile(startPos);

            if (startTilePos == null)
            {
                return(null);
            }

            TileWithDistance startTile = new TileWithDistance(startTilePos, 0);

            openList.Add(startTile);
            reachedTiles.Add(startTile.Pos, startTile);

            if (includeStartPos)
            {
                if (matcher == null || matcher(startTile))
                {
                    resultList.Add(startTile.Pos, startTile);
                }
            }

            while (openList.Count > 0)
            {
                TileWithDistance tile = openList[0];
                openList.RemoveAt(0);

                // Distance at all
                if (tile.Distance > range)
                {
                    continue;
                }

                foreach (Tile n in tile.Neighbors)
                {
                    if (n.Pos == startPos)
                    {
                        continue;
                    }

                    if (!reachedTiles.ContainsKey(n.Pos))
                    {
                        TileWithDistance neighborsTile = new TileWithDistance(GetTile(n.Pos), tile.Distance + 1);

                        reachedTiles.Add(neighborsTile.Pos, neighborsTile);

                        // Distance at all
                        if (neighborsTile.Distance <= range)
                        {
                            openList.Add(neighborsTile);

                            if (matcher == null || matcher(neighborsTile))
                            {
                                if (includeStartPos)
                                {
                                    resultList.Add(neighborsTile.Pos, neighborsTile);
                                }
                                else if (neighborsTile.Pos != startPos)
                                {
                                    resultList.Add(neighborsTile.Pos, neighborsTile);
                                }
                            }
                            if (stopper != null && stopper(neighborsTile))
                            {
                                return(resultList);
                            }
                        }
                    }
                }
            }
            return(resultList);
        }