// The Worker first goes away from the queen (mindset AMS0), leaving the PHER0 (for exploration) pheromone behind // The Queen can be found because it leaves four PHER0 pheromones on her tile // When an obstacle is hit, its mindset changes and the ant comes back to the queen, changing the pheromone to a pheromone describing the obstacle: // - AMS1 and PHER1 mean FOOD public override Decision OnWorkerTurn(TurnInformation info) { ChoiceDescriptor choice = ChoiceDescriptor.ChooseNone(); AntMindset mindset = AntMindset.AMS0; List <PheromoneDigest> pheromones = info.pheromones; // If this is the first turn if (info.pastTurn == null) { // The Worker tries to find the Queen HexDirection queenDirection = HexDirection.CENTER; foreach (KeyValuePair <HexDirection, List <PheromoneDigest> > entry in info.adjacentPheromoneGroups) { if (IsQueenSignal(entry.Value)) { queenDirection = entry.Key; break; } } if (queenDirection == HexDirection.CENTER) { // Logger.Info("The Queen is missing!"); } else { choice = ChoiceDescriptor.ChooseMove(DirectionManip.InvertDirection(queenDirection)); mindset = AntMindset.AMS0; pheromones = MarkExploration(DirectionManip.InvertDirection(queenDirection)); } } else { switch (info.mindset) { case AntMindset.AMS0: // FLEES THE QUEEN if (info.pastTurn.error == TurnError.NONE) { choice = ChoiceDescriptor.ChooseMove(info.pastTurn.pastDecision.choice.direction); mindset = AntMindset.AMS0; pheromones = MarkExploration(info.pastTurn.pastDecision.choice.direction); } else if (info.pastTurn.error == TurnError.COLLISION_FOOD) { //choice = ChoiceDescriptor.ChooseMove(DirectionManip.InvertDirection(info.pastTurn.pastDecision.choice.direction)); choice = ChoiceDescriptor.ChooseStock(info.pastTurn.pastDecision.choice.direction, 100); mindset = AntMindset.AMS1; pheromones = info.pheromones; // Because theoretically the tile has been marked during the previous turn } else { choice = ChoiceDescriptor.ChooseMove(DirectionManip.RotateDirectionCW(info.pastTurn.pastDecision.choice.direction)); mindset = AntMindset.AMS0; pheromones = MarkExploration(DirectionManip.RotateDirectionCW(info.pastTurn.pastDecision.choice.direction)); } break; case AntMindset.AMS1: // COMES BACK WITH FOOD if (info.pastTurn.pastDecision.choice.type == ActionType.STOCK) // Stock => go back { choice = ChoiceDescriptor.ChooseMove(GoBackExploration(info.adjacentPheromoneGroups)); mindset = AntMindset.AMS1; pheromones = MarkFood(info.pastTurn.pastDecision.choice.direction); } else if (info.pastTurn.error == TurnError.NONE) // No error => go back (if cannot, give food) { HexDirection direction = GoBackExploration(info.adjacentPheromoneGroups); choice = ChoiceDescriptor.ChooseMove(direction != HexDirection.CENTER ? direction : info.pastTurn.pastDecision.choice.direction); mindset = AntMindset.AMS1; pheromones = MarkFood(info.pastTurn.pastDecision.choice.direction); } else if (info.pastTurn.error == TurnError.COLLISION_ANT) // No error => go back { choice = ChoiceDescriptor.ChooseGive(info.pastTurn.pastDecision.choice.direction, 100); mindset = AntMindset.AMS1; pheromones = MarkFood(info.pastTurn.pastDecision.choice.direction); } else // Error => still try to go back { choice = ChoiceDescriptor.ChooseMove(GoBackExploration(info.adjacentPheromoneGroups)); mindset = AntMindset.AMS1; pheromones = MarkFood(info.pastTurn.pastDecision.choice.direction); } break; default: choice = ChoiceDescriptor.ChooseNone(); mindset = AntMindset.AMS0; pheromones = info.pheromones; break; } } return(new Decision(mindset, choice, pheromones)); }
// Priority #0: If the ant is attacked and is not capital, it fights back (an ant is capital if it has more than or equal to MEDIUM food, or knows where the enemy Queen is (AMS7 or recent analyse)) // Priority #1: If the ant detects that it is on the spawn tile, it moves away to the right or to the left of the Queen, and leaves three PHER3 in the same direction as the ones under the Queen // AMS0 (exploration): If there is 0 pheromone under the ant, it moves straight and turns randomly when there is an obstacle (without going back), and leaves a PHER0 // AMS0 (exploration): If there is 1 to 3 pheromones under the ant, it follows them without leaving anything, and has a chance to leave the path, leaving a trace // AMS0 (exploration): If there is 4 pheromones under the ant, it follows them without leaving anything // AMS0 (exploration): If there is 2 to 4 pheromones, if the ant tried to leave the path but found an obstacle, in has to remove its mark // AMS0 (exploration): If the ant bumps into an enemy, it analyses it public override Decision OnWorkerTurn(TurnInformation info) { AntMindset mindset = info.mindset; ChoiceDescriptor choice = ChoiceDescriptor.ChooseNone(); List <PheromoneDigest> pheromones = info.pheromones; // Analyses the situation bool isImportant = IsImportant(info); KeyValuePair <HexDirection, List <PheromoneDigest> > queenPheromones = FindAdjacentQueen(info.adjacentPheromoneGroups); HexDirection attackOrigin = HasBeenAttacked(info.eventInputs); // Priority #0: Fights back if attacked and not important if (attackOrigin != HexDirection.CENTER == !isImportant) { choice = ChoiceDescriptor.ChooseAttack(attackOrigin); } // Priority #1: Checks if the Worker is in the spawn tile if (queenPheromones.Key != HexDirection.CENTER && queenPheromones.Value != null && queenPheromones.Value[0].direction == DirectionManip.InvertDirection(queenPheromones.Key)) { mindset = AntMindset.AMS0; int rand = Random.Range(0, 2); if (rand == 0) { choice = ChoiceDescriptor.ChooseMove(DirectionManip.RotateDirectionCCW(queenPheromones.Key)); } else { choice = ChoiceDescriptor.ChooseMove(DirectionManip.RotateDirectionCW(queenPheromones.Key)); } pheromones = new List <PheromoneDigest>(); } else { switch (mindset) { case AntMindset.AMS0: break; } } return(new Decision(mindset, choice, pheromones)); }
private HexDirection GoBackExploration(Dictionary <HexDirection, List <PheromoneDigest> > pheromoneGroups) { foreach (KeyValuePair <HexDirection, List <PheromoneDigest> > entry in pheromoneGroups) { // If there is exactly one pheromone, that it is an exploration one pointing towards the current tile, go there if (entry.Value.Count == 1 && entry.Value[0].type == PheromoneType.PHER0 && entry.Value[0].direction == DirectionManip.InvertDirection(entry.Key)) { return(entry.Key); } } return(HexDirection.CENTER); }