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); } } } } }
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); } }
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); }