// method for scoring attacks private int scoreAttack(MGPumAttackCommand attack) { int score = 0; // prio list //enemy unit dies if (attack.attacker.currentPower > attack.defender.currentHealth) { // enemy king dies if (attack.defender.unitID == "PUM008") { score += 100000; } //if we can kill a unit with a higher range its good if (attack.attacker.currentRange <= attack.defender.currentRange) { score += 3; } score += 5; // "strong" enemy unit dies // "weak" enemy unit dies score += (scoreUnit(attack.defender) * 2); } else { score += scoreUnit(attack.defender); } // attack from max range if (attack.attacker.currentRange == attack.chain.getLength() - 1) { score += 5; } // enemy range < our range if (attack.attacker.currentRange > attack.defender.currentRange) { score += 3; } //Debug.Log(attack); //Debug.Log("Defender Unit id: " + attack.defender.unitID); //Debug.Log("Score: " + score); return(score); }
internal override MGPumCommand calculateCommand() { int enemyID = 1 - playerID; //List<MGPumUnit> possibleMovers = new List<MGPumUnit>; foreach (MGPumUnit unit in state.getAllUnitsInZone(MGPumZoneType.Battlegrounds, this.playerID)) { if (stateOracle.canAttack(unit) && unit.currentRange > 0) { MGPumField goal = state.getField(unit.field.coords + Vector2Int.up); if (goal != null && goal.unit != null && goal.unit.ownerID == enemyID) { MGPumAttackChainMatcher matcher = unit.getAttackMatcher(); MGPumFieldChain chain = new MGPumFieldChain(this.playerID, matcher); chain.add(unit.field); chain.add(goal); MGPumAttackCommand command = new MGPumAttackCommand(playerID, chain, unit); return(command); } } if (stateOracle.canMove(unit) && unit.currentSpeed > 0) { //possibleMovers.Add(unit); MGPumField goal = state.getField(unit.field.coords + Vector2Int.up); if (goal != null) { if (goal.unit == null) { MGPumMoveChainMatcher matcher = unit.getMoveMatcher(); MGPumFieldChain chain = new MGPumFieldChain(this.playerID, matcher); chain.add(unit.field); chain.add(goal); MGPumMoveCommand command = new MGPumMoveCommand(this.playerID, chain, unit); return(command); } } } } return(new MGPumEndTurnCommand(this.playerID)); }
// method to score a move command private int scoreMove(MGPumMoveCommand move) { int score = 0; MGPumGameState copiedState = state.deepCopy(); MGPumAIPlayerDummyController dummy1 = new MGPumAIPlayerDummyController(playerID); MGPumAIPlayerDummyController dummy2 = new MGPumAIPlayerDummyController(1 - playerID); MGPumGameController copiedController = new MGPumGameController(dummy1, dummy2, copiedState); copiedController.acceptCommand(move); MGPumUnit copiedUnit = null; if (copiedController.state.getUnitForField(move.chain.getLast()) != null) { copiedUnit = copiedController.state.getUnitForField(move.chain.getLast()); } else { // this should never happen, but just in case we give it a really bad score return(-1000); } // get fields for different vision ranges List <MGPumField> possibleEnemyFields = getPossibleEnemyFields(copiedUnit, copiedState, 0); List <MGPumField> possibleEnemyFieldsExtraRange = getPossibleEnemyFields(copiedUnit, copiedState, 2); List <MGPumField> possibleEnemyFieldsExtraRangeKing = getPossibleEnemyFields(copiedUnit, copiedState, 1); List <MGPumField> allyFields = getAllyFields(copiedUnit, copiedState); foreach (MGPumField allyField in allyFields) { // if Bummz is nearby, reduce score if (state.getUnitForField(allyField).unitID == "PUM007") { score -= 5; } } //Debug.Log("Move: " + move); //Debug.Log("Possible Enemy Fields Count: " + possibleEnemyFields.Count); // if buffy or haley find a move to reach a lot of allies, score will be increased if (state.getUnitForField(move.chain.getFirst()).unitID == "PUM013" || state.getUnitForField(move.chain.getFirst()).unitID == "PUM014") { score += (allyFields.Count * 3); } // if unit is bummz, get away from teammates and go towards enemies if (state.getUnitForField(move.chain.getFirst()).unitID == "PUM007") { score += (possibleEnemyFieldsExtraRange.Count * 5); score -= (allyFields.Count * 2); } else if (state.getUnitForField(move.chain.getFirst()).unitID == "PUM004") { // Wolli should tank, sending him towards enemies rewards points score += (possibleEnemyFieldsExtraRange.Count * 3); } else if (state.getUnitForField(move.chain.getFirst()).unitID == "PUM008") { // the more wounded our king is, the higher the penalty for stepping near enemies score -= (possibleEnemyFieldsExtraRangeKing.Count * (state.getUnitForField(move.chain.getFirst()).damage + 1)); } else { // the more enemies in attack range of the unit, the higher the penalty score -= (possibleEnemyFields.Count * 3); } // method in case no prior weighting has been given if (score == 0) { Debug.Log("Score ist 0"); List <MGPumField> allEnemyFields = getPossibleEnemyFields(copiedUnit, copiedState, 7); foreach (MGPumField enemyField in allEnemyFields) { // move towards enemies if (Vector2Int.Distance(move.chain.getFirst().coords, enemyField.coords) > Vector2Int.Distance(move.chain.getLast().coords, enemyField.coords)) { score += 1; break; } } } //Debug.Log("Score sollte hier negativ sein: " + score); List <MGPumAttackCommand> attackCommands = new List <MGPumAttackCommand>(); int bestAttackScore = 0; MGPumAttackCommand bestAttackCommand = null; foreach (MGPumField enemyField in possibleEnemyFields) { MGPumAttackCommand attackCommand = findAttack(enemyField, copiedUnit, copiedState); //Debug.Log(attackCommand); if (attackCommand != null) { attackCommands.Add(attackCommand); } } if (attackCommands.Count > 0) { foreach (MGPumAttackCommand ac in attackCommands) { int attackScore = scoreAttack(ac); if (attackScore >= bestAttackScore) { bestAttackScore = attackScore; bestAttackCommand = ac; } } } // final score is based on movement score and attack score score += bestAttackScore; //Debug.Log("Best Move Score: " + bestAttackScore); //Debug.Log("Best Move: "+ bestAttackCommand); return(score); }
internal override MGPumCommand calculateCommand() { foreach (MGPumUnit unit in state.getAllUnitsInZone(MGPumZoneType.Battlegrounds, this.playerID)) { if (stateOracle.canMove(unit)) { List <MGPumField> possibleFields = getPossibleFields(unit); //Debug.Log("Unit:" + unit); //Debug.Log("Count:" + possibleFields.Count); List <MGPumMoveCommand> moveCommands = new List <MGPumMoveCommand>(); int bestMoveScore = 0; MGPumMoveCommand bestMoveCommand = null; foreach (MGPumField field in possibleFields) { // find path to field MGPumMoveCommand moveCommand = findPath(field, unit); // only add path if one was found if (moveCommand != null) { moveCommands.Add(moveCommand); } } // check if there were any possible move commands if (moveCommands.Count > 0) { foreach (MGPumMoveCommand mc in moveCommands) { // score move int score = scoreMove(mc); if (score >= bestMoveScore) { bestMoveScore = score; bestMoveCommand = mc; } } if (bestMoveCommand != null) { //Debug.Log("Best move score: " + bestMoveScore); //Debug.Log("Best move: " + bestMoveCommand); //Debug.Log("---------------------"); return(bestMoveCommand); } } } if (stateOracle.canAttack(unit)) { List <MGPumField> possibleEnemyFields = getPossibleEnemyFields(unit, state, 0); //Debug.Log(unit); //Debug.Log(possibleEnemyFields.Count); List <MGPumAttackCommand> attackCommands = new List <MGPumAttackCommand>(); int bestAttackScore = 0; MGPumAttackCommand bestAttackCommand = null; foreach (MGPumField enemyField in possibleEnemyFields) { MGPumAttackCommand attackCommand = findAttack(enemyField, unit, state); //Debug.Log(attackCommand); if (attackCommand != null) { attackCommands.Add(attackCommand); } } if (attackCommands.Count > 0) { foreach (MGPumAttackCommand ac in attackCommands) { int score = scoreAttack(ac); if (score >= bestAttackScore) { bestAttackScore = score; bestAttackCommand = ac; } } if (bestAttackCommand != null) { //Debug.Log("Best Command Score: " + bestAttackScore); return(bestAttackCommand); } } } } return(new MGPumEndTurnCommand(this.playerID)); }
// find possible attack and return it MGPumAttackCommand findAttack(MGPumField field, MGPumUnit unit, MGPumGameState state) { // can we find this out in a better way? queued = new bool[8, 8]; tilesToVisit = new SortedSet <Vector2Int>(new AStarComparer(field.coords)); predecessors = new Dictionary <Vector2Int, Vector2Int>(); //distance = new Dictionary<Vector2Int, int>(); tilesToVisit.Add(unit.field.coords); queued[unit.field.coords.x, unit.field.coords.y] = true; int recursion = 0; int maxRecursion = 500; while (tilesToVisit.Count > 0) { recursion++; if (recursion > maxRecursion) { break; } Vector2Int position = tilesToVisit.Min; tilesToVisit.Remove(position); if (!state.fields.inBounds(position)) { continue; } //touchedTiles.Add(position); if (position == field.coords) { List <Vector2Int> path = new List <Vector2Int>(); path.Add(position); //reconstruct path in reverse while (predecessors.ContainsKey(path[0])) { path.Insert(0, predecessors[path[0]]); } MGPumAttackChainMatcher matcher = unit.getAttackMatcher(); MGPumFieldChain chain = new MGPumFieldChain(unit.ownerID, matcher); for (int i = 0; i < path.Count; i++) { chain.add(state.getField(path[i])); } if (chain.isValidChain()) { MGPumAttackCommand ac = new MGPumAttackCommand(this.playerID, chain, unit); return(ac); } continue; } foreach (Vector2Int direction in getDirections()) { Vector2Int neighbor = position + direction; if (!state.fields.inBounds(neighbor)) { continue; } if (!queued[neighbor.x, neighbor.y]) { queued[neighbor.x, neighbor.y] = true; tilesToVisit.Add(neighbor); predecessors.Add(neighbor, position); //distance.Add(neighbor, ) } } } return(null); }
internal override MGPumCommand calculateCommand() { foreach (MGPumUnit unit in state.getAllUnitsInZone(MGPumZoneType.Battlegrounds, this.playerID)) { if (stateOracle.canAttack(unit)) { List <MGPumField> possibleEnemyFields = getPossibleEnemyFields(unit); //Debug.Log(unit); //Debug.Log(possibleEnemyFields.Count); List <MGPumAttackCommand> attackCommands = new List <MGPumAttackCommand>(); foreach (MGPumField enemyField in possibleEnemyFields) { MGPumAttackCommand attackCommand = findAttack(enemyField, unit); //Debug.Log(attackCommand); if (attackCommand != null) { attackCommands.Add(attackCommand); } } if (attackCommands.Count > 0) { int index = rng.Next(attackCommands.Count); //Debug.Log(attackCommands[index]); return(attackCommands[index]); } } if (stateOracle.canMove(unit)) { List <MGPumField> possibleFields = getPossibleFields(unit); //Debug.Log("Unit:" + unit); //Debug.Log("Count:" + possibleFields.Count); List <MGPumMoveCommand> moveCommands = new List <MGPumMoveCommand>(); foreach (MGPumField field in possibleFields) { // find path to field MGPumMoveCommand moveCommand = findPath(field, unit); // only add path if one was found if (moveCommand != null) { moveCommands.Add(moveCommand); } } // check if there were any possible move commands if (moveCommands.Count > 0) { int index = rng.Next(moveCommands.Count); //Debug.Log(moveCommands[index]); return(moveCommands[index]); } } } return(new MGPumEndTurnCommand(this.playerID)); }