public override void AttachUnits(Dispatcher dispatcher, Player player, List <PlayerUnit> moveableUnits) { Dictionary <Position, TileWithDistance> positionsToScount = CollectIncludedPositions(); List <PlayerUnit> unitsAlreadyInArea = CollectUnitsAlreadyInArea(player, Range); List <UnitType> currentDemandedUnitTypes = new List <UnitType>(); currentDemandedUnitTypes.AddRange(DemandedUnitTypes); 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 (!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); playerUnitFound = true; break; } } } else { if (playerUnit.Unit.IsComplete()) { // Move that punk here or keep it foreach (UnitType unitType in DemandedUnitTypes) { if (unitType.Matches(playerUnit)) { currentDemandedUnitTypes.Remove(unitType); if (playerUnit.Unit.Pos != Center && playerUnit.Unit.Engine != null) { dispatcher.MoveUnit(this, playerUnit, Center); } playerUnitFound = true; break; } } } else { if (playerUnit.Unit.UnderConstruction) { // Wait for completion foreach (UnitType unitType in DemandedUnitTypes) { if (unitType.Fits(playerUnit)) { if (unitsAlreadyInArea.Contains(playerUnit)) { // Discard connection to demaged unit. deadUnits.Add(playerUnit.Unit.UnitId); } else { // Unit in production // Request the unit again, so the factorys will produce it, but add this unit as the favourite // so only this unit will be supplied and not a new unit dispatcher.RequestUnit(this, unitType, playerUnit); playerUnitFound = true; // It not attached, the extractor will eat this unit in the factory... //deadUnits.Add(playerUnit.Unit.UnitId); } currentDemandedUnitTypes.Remove(unitType); break; } } } } } break; } } if (!playerUnitFound) { // Unit no longer exists deadUnits.Add(unitId); } } foreach (string deadUnitId in deadUnits) { AssignedUnits.Remove(deadUnitId); } if (currentDemandedUnitTypes.Count > 0 && AssignedUnits.Count == 0) { List <UnitType> remainingUnitTypes = new List <UnitType>(); remainingUnitTypes.AddRange(currentDemandedUnitTypes); foreach (PlayerUnit playerUnit in unitsAlreadyInArea) { if (!moveableUnits.Contains(playerUnit)) { continue; } bool unitMatches = false; foreach (UnitType unitType in currentDemandedUnitTypes) { if (unitType.Matches(playerUnit)) { remainingUnitTypes.Remove(unitType); unitMatches = true; break; } } if (!unitMatches) { // Unmatching unit in area. Do not request another unit, wait for clear remainingUnitTypes.Clear(); } } foreach (UnitType unitType in remainingUnitTypes) { dispatcher.RequestUnit(this, unitType, null); } } }
public override void AttachUnits(Dispatcher dispatcher, Player player, List <PlayerUnit> moveableUnits) { base.AttachUnits(dispatcher, player, moveableUnits); if (WaitingForBuilder) { WaitForBuilder(dispatcher, moveableUnits); } else if (WaitingForDeconstrcut) { Deconstrcut(dispatcher, player, moveableUnits); } else { SanityCheck(dispatcher, player, moveableUnits); HandlyUnitsToExtract(dispatcher, player, moveableUnits); } #if old UnitsAlreadyInArea = CollectUnitsAlreadyInArea(player, Range); currentDemandedUnitTypes = new List <UnitType>(); currentDemandedUnitTypes.AddRange(DemandedUnitTypes); 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 (!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()) { // Move that punk here or keep it foreach (UnitType unitType in DemandedUnitTypes) { if (unitType.Matches(playerUnit)) { //dispatcher.ClaimUnit(this, playerUnit, RequestType.Attack); currentDemandedUnitTypes.Remove(unitType); if (playerUnit.Unit.Pos != Center && playerUnit.Unit.Engine != null) { dispatcher.MoveUnit(this, playerUnit, Center); } break; } } } else { // Wait for completion foreach (UnitType unitType in DemandedUnitTypes) { if (unitType.Fits(playerUnit)) { if (this is Assemble) { if (UnitsAlreadyInArea.Contains(playerUnit)) { // Units are produced int x = 0; } else { // called when new factory // Units are produced dispatcher.RequestUnit(this, unitType, playerUnit); currentDemandedUnitTypes.Remove(unitType); } } else { // Not called if (UnitsAlreadyInArea.Contains(playerUnit)) { // Discard connection to demaged unit deadUnits.Add(playerUnit.Unit.UnitId); } else { // Unit in production // Request the unit again, so the factorys will produce it, but add this unit as the favourite // so only this unit will be supplied and not a new unit dispatcher.RequestUnit(this, unitType, playerUnit); // It not attached, the extractor will eat this unit in the factory... //deadUnits.Add(playerUnit.Unit.UnitId); } currentDemandedUnitTypes.Remove(unitType); } break; } } } } playerUnitFound = true; break; } } if (!playerUnitFound) { // Unit no longer exists deadUnits.Add(unitId); } } foreach (string deadUnitId in deadUnits) { AssignedUnits.Remove(deadUnitId); } if (currentDemandedUnitTypes.Count > 0 && AssignedUnits.Count == 0) { // called when new factory List <UnitType> remainingUnitTypes = new List <UnitType>(); remainingUnitTypes.AddRange(currentDemandedUnitTypes); foreach (PlayerUnit playerUnit in UnitsAlreadyInArea) { if (!moveableUnits.Contains(playerUnit)) { continue; } bool unitMatches = false; foreach (UnitType unitType in currentDemandedUnitTypes) { if (unitType.Matches(playerUnit)) { remainingUnitTypes.Remove(unitType); unitMatches = true; break; } } if (!unitMatches) { // Unmatching unit in area. Do not request another unit, wait for clear remainingUnitTypes.Clear(); } } foreach (UnitType unitType in remainingUnitTypes) { currentDemandedUnitTypes.Remove(unitType); dispatcher.RequestUnit(this, unitType, null); } } string builderUnitId = null; if (WaitingForBuilder) { foreach (PlayerUnit playerUnit in UnitsAlreadyInArea) { if (playerUnit.PossibleMoves.Count > 0) { continue; } if (playerUnit.Unit.Pos == Center) { if (DemandedUnitTypes[0].Fits(playerUnit)) { // Builder arrived. Build factory builderUnitId = playerUnit.Unit.UnitId; WaitingForBuilder = false; DemandedUnitTypes.Clear(); DemandStartupUnits(); currentDemandedUnitTypes.Clear(); currentDemandedUnitTypes.AddRange(DemandedUnitTypes); break; } } } } if (currentDemandedUnitTypes.Count == DemandedUnitTypes.Count) { // Nothing fits Starting condition? foreach (PlayerUnit playerUnit in UnitsAlreadyInArea) { if (playerUnit.PossibleMoves.Count > 0) { continue; } if (builderUnitId == playerUnit.Unit.UnitId && playerUnit.Unit.Engine != null) { // Builder unit List <Move> possiblemoves = new List <Move>(); playerUnit.Unit.Assembler.ComputePossibleMoves(possiblemoves, null, MoveFilter.Assemble); if (possiblemoves.Count > 0) { // possiblemoves contains possible output places foreach (Move possibleMove in possiblemoves) { if (possibleMove.UnitId == "Engine") { PlayerMove playerMove = new PlayerMove(possibleMove); playerMove.NewUnitId = "RemoveEngine"; playerUnit.PossibleMoves.Add(playerMove); break; } } } break; } if (playerUnit.Unit.Assembler != null && playerUnit.Unit.Extractor != null && playerUnit.Unit.Reactor != null) { List <Move> possiblemoves = new List <Move>(); playerUnit.Unit.Assembler.ComputePossibleMoves(possiblemoves, null, MoveFilter.Assemble); if (possiblemoves.Count > 0) { // possiblemoves contains possible output places foreach (Move possibleMove in possiblemoves) { if (possibleMove.UnitId == "Reactor") { PlayerMove playerMove = new PlayerMove(possibleMove); playerMove.Command = this; playerMove.NewUnitId = "RemoveReactor"; playerUnit.PossibleMoves.Add(playerMove); break; } } } break; } if (playerUnit.PossibleMoves.Count == 0 && playerUnit.Unit.Assembler != null && playerUnit.Unit.Extractor != null && playerUnit.Unit.Container != null) { List <Move> possiblemoves = new List <Move>(); playerUnit.Unit.Assembler.ComputePossibleMoves(possiblemoves, null, MoveFilter.Assemble); if (possiblemoves.Count > 0) { // possiblemoves contains possible output places foreach (Move possibleMove in possiblemoves) { if (possibleMove.UnitId == "Container") { PlayerMove playerMove = new PlayerMove(possibleMove); playerMove.Command = this; playerMove.NewUnitId = "RemoveContainer"; playerUnit.PossibleMoves.Add(playerMove); break; } } } break; } if (playerUnit.PossibleMoves.Count > 0) { break; } } } PlayerUnit assemblerUnit = null; // units are missing or demaged, try to recover if (currentDemandedUnitTypes.Count > 0) { // Find a unit to produce foreach (PlayerUnit unit in UnitsAlreadyInArea) { if (unit.Unit.Assembler != null && unit.Unit.Assembler.CanProduce) { // produce missing part assemblerUnit = unit; break; } } } // Step 1: Doing Upgrades (used when building itself) if (assemblerUnit != null && assemblerUnit.PossibleMoves.Count == 0) { List <Move> possiblemoves = new List <Move>(); assemblerUnit.Unit.Assembler.ComputePossibleMoves(possiblemoves, null, MoveFilter.Upgrade); // check what is missing bool found = false; foreach (UnitType unitType in currentDemandedUnitTypes) { foreach (PlayerUnit playerUnit in UnitsAlreadyInArea) { if (unitType.Fits(playerUnit)) { foreach (Move move in possiblemoves) { if (move.Positions[1] != playerUnit.Unit.Pos) { continue; } // Will this move upgrade the unit so it fits into the unittype wanted if (Assembler.DoesMoveMinRequest(move, unitType, playerUnit.Unit)) { assemblerUnit.PossibleMoves.Add(new PlayerMove(move)); currentDemandedUnitTypes.Remove(unitType); found = true; break; } } } } if (found) { break; } } } // Step 2: Create new units if (assemblerUnit != null && assemblerUnit.PossibleMoves.Count == 0) { // not called List <Move> possibleAssemblemoves = new List <Move>(); assemblerUnit.Unit.Assembler.ComputePossibleMoves(possibleAssemblemoves, null, MoveFilter.Assemble); // check what is missing bool found = false; foreach (UnitType unitType in currentDemandedUnitTypes) { foreach (Move move in possibleAssemblemoves) { //if (IsOccupied(player, moves, move.Positions[move.Positions.Count - 1])) // continue; if (Assembler.DoesMoveMinRequest(move, unitType, null)) { PlayerMove playerMove = new PlayerMove(move); playerMove.Command = this; playerMove.NewUnitId = move.UnitId; assemblerUnit.PossibleMoves.Add(playerMove); currentDemandedUnitTypes.Remove(unitType); found = true; break; } } if (found) { break; } } } // Keep request if (assemblerUnit != null && assemblerUnit.PossibleMoves.Count == 0) { // not called // Still remaining demands? foreach (UnitType unitType in currentDemandedUnitTypes) { if (unitType.MinRadarLevel >= 1) { dispatcher.RequestUnit(this, unitType, null); } } } #endif }
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 override void AttachUnits(Dispatcher dispatcher, Player player, List <PlayerUnit> moveableUnits) { if (ScoutingPositions.Count == 0) { FindScoutingPositions(dispatcher, player); } List <Position> unseenTiles = new List <Position>(); Dictionary <Position, TileWithDistance> positionsToScount = Map.EnumerateTiles(Center, Range); // Search +2 to get units move behind the border List <PlayerUnit> unitsAlreadyInArea = CollectUnitsAlreadyInArea(player, Range + 2); if (EnemyUnits.Count > 0) { // Enemy detected dispatcher.RequestAttack(this, EnemyUnits[0]); IsPeaceFul = false; ScoutingPositions.Clear(); Center = EnemyUnits[0].Unit.Pos; return; } List <UnitType> remainingUnitTypes = new List <UnitType>(); remainingUnitTypes.AddRange(DemandedUnitTypes); List <PlayerUnit> unitsAlreadyInAreaMatchingDemand = new List <PlayerUnit>(); List <PlayerUnit> unitsAlreadyInAreaMatchingButDamaged = new List <PlayerUnit>(); 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) { playerUnitFound = true; if (moveableUnits.Contains(playerUnit)) { foreach (UnitType unitType in remainingUnitTypes) { if (unitType.Matches(playerUnit)) { unitsAlreadyInAreaMatchingDemand.Add(playerUnit); //dispatcher.ClaimUnit(this, playerUnit, RequestType.Scout); remainingUnitTypes.Remove(unitType); } break; } } } } if (!playerUnitFound) { // Unit no longer exists deadUnits.Add(unitId); } } foreach (string deadUnitId in deadUnits) { AssignedUnits.Remove(deadUnitId); } // Do not scout around. Attack! //if (!IsPeaceFul) return; // Collect all fit units /* * foreach (PlayerUnit playerUnit in unitsAlreadyInArea) * { * if (!moveableUnits.Contains(playerUnit)) * continue; * if (dispatcher.ClaimedUnits.Contains(playerUnit)) * continue; * //if (!playerUnit.Unit.IsComplete()) * // continue; * * foreach (UnitType unitType in remainingUnitTypes) * { * if (unitType.Matches(playerUnit)) * { * unitsAlreadyInAreaMatchingDemand.Add(playerUnit); * dispatcher.ClaimUnit(this, playerUnit, RequestType.Scout); * remainingUnitTypes.Remove(unitType); * } * break; * } * }*/ // Collect all demaged units that may fit /* * foreach (PlayerUnit playerUnit in unitsAlreadyInArea) * { * if (!moveableUnits.Contains(playerUnit)) * continue; * * foreach (UnitType unitType in remainingUnitTypes) * { * if (unitType.Matches(playerUnit)) * { * if (!playerUnit.Unit.IsComplete()) * { * // Do not collect damaged units. Request a new one. * //unitsAlreadyInAreaMatchingButDamaged.Add(playerUnit); * //remainingUnitTypes.Remove(unitType); * } * * } * break; * } * }*/ // Request new units if needed foreach (UnitType unitType in remainingUnitTypes) { dispatcher.RequestUnit(this, unitType, null); } foreach (PlayerUnit playerUnit in unitsAlreadyInAreaMatchingButDamaged) { //dispatcher.RequestUpgrade(this, playerUnit); } // Priorise scout position order SortedList <int, ScoutPosition> sortedScoutPositions = new SortedList <int, ScoutPosition>(new DegreeComparer()); foreach (ScoutPosition scoutPosition in ScoutingPositions) { scoutPosition.MovesNotVisited++; sortedScoutPositions.Add(scoutPosition.MovesNotVisited, scoutPosition); } if (unitsAlreadyInAreaMatchingDemand.Count > 0) { // Reverse for (int i = sortedScoutPositions.Values.Count - 1; i > 0; i--) { ScoutPosition scoutPosition = sortedScoutPositions.Values[i]; Map.EnumerateTiles(scoutPosition.Pos, Range, stopper: p => { foreach (PlayerUnit playerUnit in unitsAlreadyInAreaMatchingDemand) { if (!moveableUnits.Contains(playerUnit)) { continue; } if (playerUnit.Unit.Pos == p.Pos) { if (p.Distance <= 1) { // Close enough unit counts a visited scoutPosition.MovesNotVisited = 0; } // Closest unit to scout point. Move closer, remove unit from list if the unit isn't there already if (scoutPosition.Pos != playerUnit.Unit.Pos) { //unitsAlreadyInAreaMatchingDemand.Remove(playerUnit); dispatcher.MoveUnit(this, playerUnit, scoutPosition.Pos); /* Select a path that does not leave the area. Needed? * Move move = dispatcher.GameController.MoveTo(playerUnit.Unit.Pos, scoutPosition.Pos, playerUnit.Unit.Engine); * if (move != null) * { * bool pathOutsideOfArea = false; * foreach (Position path in move.Positions) * { * // Is each position in path in scout area? * if (!positionsToScount.ContainsKey(path)) * { * pathOutsideOfArea = true; * } * } * if (pathOutsideOfArea) * { * // unreachable, try another * } * else * { * dispatcher.MoveUnit(this, playerUnit, move); * unitsAlreadyInAreaMatchingDemand.Remove(playerUnit); * } * } * else * { * // unreachable, try another * }*/ } // Stop searching for this point return(true); } } return(false); }); } // Move any other attached units closer foreach (PlayerUnit playerUnit in unitsAlreadyInAreaMatchingDemand) { if (!moveableUnits.Contains(playerUnit)) { continue; } int ix; #pragma warning disable CS0162 // Unreachable code detected for (ix = sortedScoutPositions.Values.Count - 1; ix > 0; ix--) #pragma warning restore CS0162 // Unreachable code detected { ScoutPosition scoutPosition = sortedScoutPositions.Values[ix]; dispatcher.MoveUnit(this, playerUnit, scoutPosition.Pos); /* * Move move = dispatcher.GameController.MoveTo(playerUnit.Unit.Pos, scoutPosition.Pos, playerUnit.Unit.Engine); * if (move != null) * { * dispatcher.MoveUnit(this, playerUnit, move); * } * else * { * // Cannot reach, move unit to center, hope the best * //dispatcher.MoveUnit(this, playerUnit, Center); * } */ break; } } } }