Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- abstract class TestAI extends AI {
- static function getNextMove($gameInfo, $playerId) {
- $vectorMapName = 'Map_' . $gameInfo['map_name'];
- if (!class_exists($vectorMapName)) {
- $vectorMapName = 'Map';
- }
- $vectors = $vectorMapName::getWaypointVectors();
- $gameInfo = static::populateInfoArrays($gameInfo, $playerId);
- $move = static::chooseMove($gameInfo, $playerId, $vectors);
- $purchase = false;
- if (empty($move)) {
- $purchase = static::purchaseUnit($gameInfo, $playerId, $vectors);
- }
- $endTurn = false;
- if (empty($move) && empty($purchase)) {
- $endTurn = true;
- }
- return ['move' => $move, 'purchase' => $purchase, 'end_turn' => $endTurn];
- }
- static function chooseMove($gameInfo, $playerId, $vectors) {
- $moveData = false;
- $moveOptions = [
- 'movementPaths' => [],
- 'attackPaths' => [],
- 'rangedAttackPaths' => [],
- 'capturePaths' => []
- ];
- // WRITE SOME LOGIC HERE TO DECIDE *WHICH* UNIT MOVES FIRST, NOT JUST ITERATING THROUGH
- // First, get all available options for moves
- foreach ($gameInfo['owned_units'] as $unit) {
- $movementPaths = [];
- $attackPaths = [];
- $rangedAttackPaths = [];
- $capturePaths = [];
- if ($unit['moved'] == 1) {
- continue;
- }
- // Get an array structure of all tiles and recursively all tiles that could be moved to
- // from that tile. Repeated until unit would be out of movement
- $paths = static::getPaths($gameInfo, $playerId, $vectors, $unit);
- // Take the previous array and create a new array indexed by each tile id and containing
- // the path of tiles that got this unit there.
- $mappedPaths = [];
- foreach ($paths as $path) {
- static::mapTilePaths($gameInfo, $path, [], $mappedPaths);
- }
- // Add the tile that the unit starts on
- $mappedPaths[$unit['tile_id']] = [
- 'path' => [],
- 'x' => $unit['x_coordinate'],
- 'y' => $unit['y_coordinate'],
- 'movesLeft' => intval($unit['unit_name']::MOVEMENT)
- ];
- if ($unit['unit_name']::MOVE_THEN_ATTACK) {
- $attackPaths = static::getAttackPaths($gameInfo, $mappedPaths, $unit);
- } else {
- $rangedAttackPaths = static::getRangedAttackPaths($gameInfo, $mappedPaths, $unit);
- }
- if ($unit['unit_name']::CAN_CAPTURE) {
- $capturePaths = static::getCapturePaths($gameInfo, $mappedPaths, $unit);
- }
- if (!empty($attackPaths)) {
- $moveOptions['attackPaths'][$unit['tile_id']] = $attackPaths;
- $moveOptions['attackPaths'][$unit['tile_id']]['unit_name'] = $unit['unit_name'];
- $moveOptions['attackPaths'][$unit['tile_id']]['x'] = $unit['x_coordinate'];
- $moveOptions['attackPaths'][$unit['tile_id']]['y'] = $unit['y_coordinate'];
- $moveOptions['attackPaths'][$unit['tile_id']]['tile_id'] = $unit['tile_id'];
- }
- if (!empty($rangedAttackPaths)) {
- $moveOptions['rangedAttackPaths'][$unit['tile_id']] = $rangedAttackPaths;
- $moveOptions['rangedAttackPaths'][$unit['tile_id']]['unit_name'] = $unit['unit_name'];
- $moveOptions['rangedAttackPaths'][$unit['tile_id']]['x'] = $unit['x_coordinate'];
- $moveOptions['rangedAttackPaths'][$unit['tile_id']]['y'] = $unit['y_coordinate'];
- $moveOptions['rangedAttackPaths'][$unit['tile_id']]['tile_id'] = $unit['tile_id'];
- }
- if (!empty($capturePaths)) {
- $moveOptions['capturePaths'][$unit['tile_id']] = $capturePaths;
- $moveOptions['capturePaths'][$unit['tile_id']]['unit_name'] = $unit['unit_name'];
- $moveOptions['capturePaths'][$unit['tile_id']]['x'] = $unit['x_coordinate'];
- $moveOptions['capturePaths'][$unit['tile_id']]['y'] = $unit['y_coordinate'];
- $moveOptions['capturePaths'][$unit['tile_id']]['tile_id'] = $unit['tile_id'];
- }
- if (!empty($mappedPaths)) {
- $moveOptions['movementPaths'][$unit['tile_id']] = $mappedPaths;
- $moveOptions['movementPaths'][$unit['tile_id']]['unit_name'] = $unit['unit_name'];
- $moveOptions['movementPaths'][$unit['tile_id']]['x'] = $unit['x_coordinate'];
- $moveOptions['movementPaths'][$unit['tile_id']]['y'] = $unit['y_coordinate'];
- $moveOptions['movementPaths'][$unit['tile_id']]['tile_id'] = $unit['tile_id'];
- }
- }
- // Then go through options and attempt to accomplish them in this order:
- // 1) Start/finish capturing any available building
- // 2) Attack with all ranged units
- // 3) Attack with all melee units
- // 4) Move all remaining units along the waypoint path toward enemy
- // When all of these steps have been exhausted for every unit, end turn
- if (!empty($moveOptions['capturePaths'])) {
- $moveData = self::getCaptureMoveData($moveOptions);
- }
- if (empty($moveData) && !empty($moveOptions['rangedAttackPaths'])) {
- $moveData = self::getRangedAttackMoveData($moveOptions);
- }
- if (empty($moveData) && !empty($moveOptions['attackPaths'])) {
- $moveData = self::getAttackPathsMoveData($moveOptions);
- }
- if (empty($moveData) && !empty($moveOptions['movementPaths'])) {
- $moveData = self::getNormalMoveData($moveOptions, $vectors, $gameInfo, $playerId);
- }
- // If, after all our options, a unit still doesn't have anywhere to be, try stumbling around
- if (empty($moveData) && !empty($moveOptions['movementPaths'])) {
- $moveData = self::getStumbleMoveData($moveOptions, $gameInfo);
- }
- return $moveData;
- }
- static function getCaptureMoveData($moveOptions) {
- $keys = array_keys($moveOptions['capturePaths']);
- $unitToMove = $moveOptions['capturePaths'][$keys[0]];
- $movements = [];
- $unitChoices = array_keys($unitToMove);
- $unitChoice = $unitToMove[$unitChoices[0]];
- foreach ($unitChoice['path'] as $tile) {
- $movements[] = [
- 'xCoordinate' => intval($tile['x']),
- 'yCoordinate' => intval($tile['y'])
- ];
- }
- $moveData = [
- 'x_coordinate' => $unitToMove['x'],
- 'y_coordinate' => $unitToMove['y'],
- 'movements' => $movements,
- 'unit_action' => 'capture'
- ];
- return $moveData;
- }
- static function getRangedAttackMoveData($moveOptions) {
- $keys = array_keys($moveOptions['rangedAttackPaths']);
- $unitToAttackWith = $moveOptions['rangedAttackPaths'][$keys[0]];
- $targets = array_keys($unitToAttackWith);
- $target = $unitToAttackWith[$targets[0]];
- $moveData = [
- 'x_coordinate' => $unitToAttackWith['x'],
- 'y_coordinate' => $unitToAttackWith['y'],
- 'movements' => [],
- 'x_coord_attack' => $target['x'],
- 'y_coord_attack' => $target['y']
- ];
- return $moveData;
- }
- static function getAttackPathsMoveData($moveOptions) {
- $keys = array_keys($moveOptions['attackPaths']);
- $highestDmg = -999;
- $highestDamageUnit = false;
- $highestDamageUnitTarget = false;
- foreach ($keys as $unit) {
- $unitToAttackWith = $moveOptions['attackPaths'][$unit];
- $unitTargetOptions = array_keys($unitToAttackWith);
- foreach ($unitTargetOptions as $targetOption) {
- if (is_numeric($targetOption)) {
- $outputDmg = $unitToAttackWith[$targetOption]['outputDmg'];
- $returnDmg = $unitToAttackWith[$targetOption]['returnDmg'];
- if (($outputDmg * 2) > $returnDmg) {
- $damageDelta = $outputDmg - $returnDmg;
- if ($damageDelta > $highestDmg) {
- $highestDmg = $damageDelta;
- $highestDamageUnit = $unitToAttackWith;
- $highestDamageUnitTarget = $targetOption;
- }
- }
- }
- }
- }
- if (empty($highestDamageUnit)) {
- return false;
- }
- $movements = [];
- foreach ($highestDamageUnit[$highestDamageUnitTarget]['path'] as $tile) {
- $movements[] = [
- 'xCoordinate' => intval($tile['x']),
- 'yCoordinate' => intval($tile['y'])
- ];
- }
- $moveData = [
- 'x_coordinate' => $highestDamageUnit['x'],
- 'y_coordinate' => $highestDamageUnit['y'],
- 'movements' => $movements,
- 'x_coord_attack' => $highestDamageUnit[$highestDamageUnitTarget]['x'],
- 'y_coord_attack' => $highestDamageUnit[$highestDamageUnitTarget]['y']
- ];
- return $moveData;
- }
- static function getNormalMoveData($moveOptions, $vectors, $gameInfo, $playerId) {
- $keys = array_keys($moveOptions['movementPaths']);
- $unitToMove = $moveOptions['movementPaths'][$keys[0]];
- $waypointMovements = [];
- $tileOptions = array_keys($unitToMove);
- foreach ($tileOptions as $tileOption) {
- foreach ($vectors as $i => $vector) {
- if ((isset($unitToMove[$tileOption]['x'])) &&
- (isset($unitToMove[$tileOption]['y'])) &&
- ($unitToMove[$tileOption]['x'] == $vector['destination_x_coordinate']) &&
- ($unitToMove[$tileOption]['y'] == $vector['destination_y_coordinate']) &&
- ($gameInfo['players'][$playerId]['turn_order'] == $vector['offensive_turn_order'])) {
- $tileInfo = $unitToMove[$tileOption];
- $tileInfo['vectorIndex'] = $i;
- $waypointMovements[] = $tileInfo;
- }
- }
- }
- // Remove the tiles that aren't the ones farthest along the path
- $waypointsToRemove = [];
- foreach ($waypointMovements as $i => $waypoint) {
- foreach ($waypointMovements as $j => $comparePoint) {
- if ($i == $j) continue;
- if (($vectors[$comparePoint['vectorIndex']]['origin_x_coordinate'] == $vectors[$waypoint['vectorIndex']]['destination_x_coordinate']) &&
- ($vectors[$comparePoint['vectorIndex']]['origin_y_coordinate'] == $vectors[$waypoint['vectorIndex']]['destination_y_coordinate'])) {
- $waypointsToRemove[] = $i;
- }
- }
- }
- foreach ($waypointsToRemove as $i) {
- unset($waypointMovements[$i]);
- }
- $waypointMovements = array_filter($waypointMovements);
- $alignedOptions = [];
- if (!empty($waypointMovements)) {
- shuffle($waypointMovements);
- $chosenProximityWaypoint = $waypointMovements[0];
- $possibleNextPoints = [];
- foreach ($vectors as $vector) {
- if (($vector['origin_x_coordinate'] == $chosenProximityWaypoint['x']) &&
- ($vector['origin_y_coordinate'] == $chosenProximityWaypoint['y']) &&
- ($vector['offensive_turn_order'] == $gameInfo['players'][$playerId]['turn_order'])) {
- $possibleNextPoints[] = $vector;
- }
- }
- $chosenDestination = false;
- foreach ($possibleNextPoints as $possibleNextPoint) {
- if (($possibleNextPoint['destination_x_coordinate'] == $unitToMove['x']) ||
- ($possibleNextPoint['destination_y_coordinate'] == $unitToMove['y'])) {
- $chosenDestination = $possibleNextPoint;
- }
- }
- if (!empty($possibleNextPoints)) {
- if (empty($chosenDestination)) {
- shuffle($possibleNextPoints);
- $chosenDestination = $possibleNextPoints[0];
- }
- if ($chosenProximityWaypoint['x'] == $chosenDestination['destination_x_coordinate']) {
- $movementX = $chosenProximityWaypoint['x'];
- } else {
- $movementY = $chosenProximityWaypoint['y'];
- }
- if (isset($movementX)) {
- foreach ($unitToMove as $option) {
- if (isset($option['x']) && ($option['x'] == $movementX)) {
- $alignedOptions[] = $option;
- }
- }
- } else {
- foreach ($unitToMove as $option) {
- if (isset($option['y']) && ($option['y'] == $movementY)) {
- $alignedOptions[] = $option;
- }
- }
- }
- $filteredOptions = [];
- foreach ($alignedOptions as $alignedOption) {
- if (empty($gameInfo['tiles'][$alignedOption['x']][$alignedOption['y']]['unit_name'])) {
- $filteredOptions[] = $alignedOption;
- } else {
- if (($unitToMove['x'] == $alignedOption['x']) && ($unitToMove['y'] == $alignedOption['y'])) {
- $filteredOptions[] = $alignedOption;
- }
- }
- }
- $alignedOptions = $filteredOptions;
- $closestOption = false;
- $closestDistance = 999999;
- foreach ($alignedOptions as $alignedOption) {
- if (isset($movementX)) {
- $distance = abs($alignedOption['y'] - $chosenDestination['destination_y_coordinate']);
- } else {
- $distance = abs($alignedOption['x'] - $chosenDestination['destination_x_coordinate']);
- }
- if ($distance < $closestDistance) {
- $closestOption = $alignedOption;
- $closestDistance = $distance;
- }
- }
- $movements = [];
- if (!empty($closestOption)) {
- foreach ($closestOption['path'] as $tile) {
- $movements[] = [
- 'xCoordinate' => intval($tile['x']),
- 'yCoordinate' => intval($tile['y'])
- ];
- }
- $moveData = [
- 'x_coordinate' => $unitToMove['x'],
- 'y_coordinate' => $unitToMove['y'],
- 'movements' => $movements
- ];
- return $moveData;
- }
- }
- }
- return false;
- }
- static function getStumbleMoveData($moveOptions, $gameInfo) {
- $keys = array_keys($moveOptions['movementPaths']);
- $unitToMove = $moveOptions['movementPaths'][$keys[0]];
- $moveData = [
- 'x_coordinate' => $unitToMove['x'],
- 'y_coordinate' => $unitToMove['y']
- ];
- unset($unitToMove['unit_name']);
- unset($unitToMove['x']);
- unset($unitToMove['y']);
- unset($unitToMove['tile_id']);
- $unitToMove = array_filter($unitToMove);
- if (!empty($unitToMove)) {
- $filteredOptions = [];
- foreach ($unitToMove as $moveOption) {
- if (empty($gameInfo['tiles'][$moveOption['x']][$moveOption['y']]['unit_name'])) {
- $filteredOptions[] = $moveOption;
- }
- }
- $unitToMove = $filteredOptions;
- if (empty($unitToMove)) {
- $moveData['movements'] = [];
- } else {
- shuffle($unitToMove);
- $pathChoice = $unitToMove[0];
- $movements = [];
- foreach ($pathChoice['path'] as $tile) {
- $movements[] = [
- 'xCoordinate' => intval($tile['x']),
- 'yCoordinate' => intval($tile['y'])
- ];
- }
- $moveData['movements'] = $movements;
- return $moveData;
- }
- }
- return false;
- }
- static function getPaths($gameInfo, $playerId, $vectors, $unit) {
- $movesLeft = intval($unit['unit_name']::MOVEMENT);
- $moves = self::getPathsRecursive($gameInfo, $playerId, $unit, $unit, $movesLeft);
- return $moves;
- }
- static function getPathsRecursive($gameInfo, $playerId, $unit, $tile, $movesLeft) {
- if ($movesLeft <= 0) {
- return [];
- }
- $validTiles = [];
- // Check north tile
- $northX = intval($tile['x_coordinate']);
- $northY = intval($tile['y_coordinate']) - 1;
- if (isset($gameInfo['tiles'][$northX]) && isset($gameInfo['tiles'][$northX][$northY])) {
- $northTile = $gameInfo['tiles'][$northX][$northY];
- if (self::isValidMoveTile($northTile, $movesLeft, $unit)) {
- $tileToAdd = [
- 'tileId' => $northTile['tile_id'],
- 'x' => $northTile['x_coordinate'],
- 'y' => $northTile['y_coordinate'],
- 'movesLeft' => $movesLeft - $unit['unit_name']::getMovementCost($northTile['terrain_name'])
- ];
- $childTiles = static::getPathsRecursive($gameInfo, $playerId, $unit, $northTile,
- $movesLeft - $unit['unit_name']::getMovementCost($northTile['terrain_name']));
- $tileToAdd['childTiles'] = $childTiles;
- $validTiles[] = $tileToAdd;
- }
- }
- // Check east tile
- $eastX = intval($tile['x_coordinate']) + 1;
- $eastY = intval($tile['y_coordinate']);
- if (isset($gameInfo['tiles'][$eastX]) && isset($gameInfo['tiles'][$eastX][$eastY])) {
- $eastTile = $gameInfo['tiles'][$eastX][$eastY];
- if (self::isValidMoveTile($eastTile, $movesLeft, $unit)) {
- $tileToAdd = [
- 'tileId' => $eastTile['tile_id'],
- 'x' => $eastTile['x_coordinate'],
- 'y' => $eastTile['y_coordinate'],
- 'movesLeft' => $movesLeft - $unit['unit_name']::getMovementCost($eastTile['terrain_name'])
- ];
- $childTiles = static::getPathsRecursive($gameInfo, $playerId, $unit, $eastTile,
- $movesLeft - $unit['unit_name']::getMovementCost($eastTile['terrain_name']));
- $tileToAdd['childTiles'] = $childTiles;
- $validTiles[] = $tileToAdd;
- }
- }
- // Check south tile
- $southX = intval($tile['x_coordinate']);
- $southY = intval($tile['y_coordinate']) + 1;
- if (isset($gameInfo['tiles'][$southX]) && isset($gameInfo['tiles'][$southX][$southY])) {
- $southTile = $gameInfo['tiles'][$southX][$southY];
- if (self::isValidMoveTile($southTile, $movesLeft, $unit)) {
- $tileToAdd = [
- 'tileId' => $southTile['tile_id'],
- 'x' => $southTile['x_coordinate'],
- 'y' => $southTile['y_coordinate'],
- 'movesLeft' => $movesLeft - $unit['unit_name']::getMovementCost($southTile['terrain_name'])
- ];
- $childTiles = static::getPathsRecursive($gameInfo, $playerId, $unit, $southTile,
- $movesLeft - $unit['unit_name']::getMovementCost($southTile['terrain_name']));
- $tileToAdd['childTiles'] = $childTiles;
- $validTiles[] = $tileToAdd;
- }
- }
- // Check west tile
- $westX = intval($tile['x_coordinate']) - 1;
- $westY = intval($tile['y_coordinate']);
- if (isset($gameInfo['tiles'][$westX]) && isset($gameInfo['tiles'][$westX][$westY])) {
- $westTile = $gameInfo['tiles'][$westX][$westY];
- if (self::isValidMoveTile($westTile, $movesLeft, $unit)) {
- $tileToAdd = [
- 'tileId' => $westTile['tile_id'],
- 'x' => $westTile['x_coordinate'],
- 'y' => $westTile['y_coordinate'],
- 'movesLeft' => $movesLeft - $unit['unit_name']::getMovementCost($westTile['terrain_name'])
- ];
- $childTiles = static::getPathsRecursive($gameInfo, $playerId, $unit, $westTile,
- $movesLeft - $unit['unit_name']::getMovementCost($westTile['terrain_name']));
- $tileToAdd['childTiles'] = $childTiles;
- $validTiles[] = $tileToAdd;
- }
- }
- return $validTiles;
- }
- static function isValidMoveTile($tile, $movesLeft, $unit) {
- if ($tile['tile_id'] == $unit['tile_id']) {
- return false;
- }
- if (!empty($tile['unit_team_name']) && $tile['unit_team_name'] != $unit['unit_team_name']) {
- return false;
- }
- $movementCost = $unit['unit_name']::getMovementCost($tile['terrain_name']);
- if (($movementCost < 0) || ($movesLeft < $movementCost)) {
- return false;
- }
- return true;
- }
- static function mapTilePaths($gameInfo, $tile, $pathArr, &$mappedPaths) {
- $newPathArr = $pathArr;
- $newPathArr[] = $tile;
- if (isset($mappedPaths[$tile['tileId']])) {
- if ($mappedPaths[$tile['tileId']]['movesLeft'] < $tile['movesLeft']) {
- $mappedPaths[$tile['tileId']] = [
- 'path' => $newPathArr,
- 'x' => $tile['x'],
- 'y' => $tile['y'],
- 'movesLeft' => $tile['movesLeft']
- ];
- }
- } else {
- $mappedPaths[$tile['tileId']] = [
- 'path' => $newPathArr,
- 'x' => $tile['x'],
- 'y' => $tile['y'],
- 'movesLeft' => $tile['movesLeft']
- ];
- }
- foreach ($tile['childTiles'] as $childTile) {
- static::mapTilePaths($gameInfo, $childTile, $newPathArr, $mappedPaths);
- }
- }
- static function getAttackPaths($gameInfo, $mappedPaths, $attackingUnit) {
- $attackPaths = [];
- if (!$attackingUnit['unit_name']::CAN_ATTACK) {
- return [];
- }
- $attackerHP = $attackingUnit['health'];
- $attackerBaseHP = $attackingUnit['unit_name']::HEALTH;
- foreach ($mappedPaths as $tileId => $path) {
- // Skip checking path
- if (!empty($gameInfo['tiles'][$path['x']][$path['y']]['deployed_unit_id']) &&
- ($gameInfo['tiles'][$path['x']][$path['y']]['deployed_unit_id'] != $attackingUnit['deployed_unit_id'])) {
- continue;
- }
- $attackTile = $gameInfo['tiles'][$path['x']][$path['y']];
- // Check north tile
- $northX = intval($path['x']);
- $northY = intval($path['y']) - 1;
- if (isset($gameInfo['tiles'][$northX]) && isset($gameInfo['tiles'][$northX][$northY])) {
- $northTile = $gameInfo['tiles'][$northX][$northY];
- if (!empty($northTile['unit_team_name']) && ($northTile['unit_team_name'] != $attackingUnit['unit_team_name'])) {
- $baseOutputDmg = $attackingUnit['unit_name']::getBaseOutputDamage($northTile['unit_name']);
- $outputDmg = intval(($baseOutputDmg * ($attackerHP / $attackerBaseHP)) * (1 - ($northTile['defense'] / 10)));
- $newDefenderHP = $northTile['health'] - $outputDmg;
- $defenderBaseHP = $northTile['unit_name']::HEALTH;
- $baseReturnDmg = $northTile['unit_name']::getBaseOutputDamage($attackingUnit['unit_name']);
- $returnDmg = intval(($baseReturnDmg * ($newDefenderHP / $defenderBaseHP)) * (1 - ($attackTile['defense'] / 10)));
- if (empty($attackPaths[$northTile['tile_id']])) {
- $attackPaths[$northTile['tile_id']] = [
- 'path' => $path['path'],
- 'x' => $northTile['x_coordinate'],
- 'y' => $northTile['y_coordinate'],
- 'movesLeft' => $path['movesLeft'],
- 'outputDmg' => $outputDmg,
- 'returnDmg' => $returnDmg
- ];
- } else if ($path['movesLeft'] > $attackPaths[$northTile['tile_id']]['movesLeft']) {
- $attackPaths[$northTile['tile_id']] = [
- 'path' => $path['path'],
- 'x' => $northTile['x_coordinate'],
- 'y' => $northTile['y_coordinate'],
- 'movesLeft' => $path['movesLeft'],
- 'outputDmg' => $outputDmg,
- 'returnDmg' => $returnDmg
- ];
- }
- }
- }
- // Check east tile
- $eastX = intval($path['x']) + 1;
- $eastY = intval($path['y']);
- if (isset($gameInfo['tiles'][$eastX]) && isset($gameInfo['tiles'][$eastX][$eastY])) {
- $eastTile = $gameInfo['tiles'][$eastX][$eastY];
- if (!empty($eastTile['unit_team_name']) && ($eastTile['unit_team_name'] != $attackingUnit['unit_team_name'])) {
- $baseOutputDmg = $attackingUnit['unit_name']::getBaseOutputDamage($eastTile['unit_name']);
- $outputDmg = intval(($baseOutputDmg * ($attackerHP / $attackerBaseHP)) * (1 - ($eastTile['defense'] / 10)));
- $newDefenderHP = $eastTile['health'] - $outputDmg;
- $defenderBaseHP = $eastTile['unit_name']::HEALTH;
- $baseReturnDmg = $eastTile['unit_name']::getBaseOutputDamage($attackingUnit['unit_name']);
- $returnDmg = intval(($baseReturnDmg * ($newDefenderHP / $defenderBaseHP)) * (1 - ($attackTile['defense'] / 10)));
- if (empty($attackPaths[$eastTile['tile_id']])) {
- $attackPaths[$eastTile['tile_id']] = [
- 'path' => $path['path'],
- 'x' => $eastTile['x_coordinate'],
- 'y' => $eastTile['y_coordinate'],
- 'movesLeft' => $path['movesLeft'],
- 'outputDmg' => $outputDmg,
- 'returnDmg' => $returnDmg
- ];
- } else if ($path['movesLeft'] > $attackPaths[$eastTile['tile_id']]['movesLeft']) {
- $attackPaths[$eastTile['tile_id']] = [
- 'path' => $path['path'],
- 'x' => $eastTile['x_coordinate'],
- 'y' => $eastTile['y_coordinate'],
- 'movesLeft' => $path['movesLeft'],
- 'outputDmg' => $outputDmg,
- 'returnDmg' => $returnDmg
- ];
- }
- }
- }
- // Check south tile
- $southX = intval($path['x']);
- $southY = intval($path['y']) + 1;
- if (isset($gameInfo['tiles'][$southX]) && isset($gameInfo['tiles'][$southX][$southY])) {
- $southTile = $gameInfo['tiles'][$southX][$southY];
- if (!empty($southTile['unit_team_name']) && ($southTile['unit_team_name'] != $attackingUnit['unit_team_name'])) {
- $baseOutputDmg = $attackingUnit['unit_name']::getBaseOutputDamage($southTile['unit_name']);
- $outputDmg = intval(($baseOutputDmg * ($attackerHP / $attackerBaseHP)) * (1 - ($southTile['defense'] / 10)));
- $newDefenderHP = $southTile['health'] - $outputDmg;
- $defenderBaseHP = $southTile['unit_name']::HEALTH;
- $baseReturnDmg = $southTile['unit_name']::getBaseOutputDamage($attackingUnit['unit_name']);
- $returnDmg = intval(($baseReturnDmg * ($newDefenderHP / $defenderBaseHP)) * (1 - ($attackTile['defense'] / 10)));
- if (empty($attackPaths[$southTile['tile_id']])) {
- $attackPaths[$southTile['tile_id']] = [
- 'path' => $path['path'],
- 'x' => $southTile['x_coordinate'],
- 'y' => $southTile['y_coordinate'],
- 'movesLeft' => $path['movesLeft'],
- 'outputDmg' => $outputDmg,
- 'returnDmg' => $returnDmg
- ];
- } else if ($path['movesLeft'] > $attackPaths[$southTile['tile_id']]['movesLeft']) {
- $attackPaths[$southTile['tile_id']] = [
- 'path' => $path['path'],
- 'x' => $southTile['x_coordinate'],
- 'y' => $southTile['y_coordinate'],
- 'movesLeft' => $path['movesLeft'],
- 'outputDmg' => $outputDmg,
- 'returnDmg' => $returnDmg
- ];
- }
- }
- }
- // Check west tile
- $westX = intval($path['x']) - 1;
- $westY = intval($path['y']);
- if (isset($gameInfo['tiles'][$westX]) && isset($gameInfo['tiles'][$westX][$westY])) {
- $westTile = $gameInfo['tiles'][$westX][$westY];
- if (!empty($westTile['unit_team_name']) && ($westTile['unit_team_name'] != $attackingUnit['unit_team_name'])) {
- $baseOutputDmg = $attackingUnit['unit_name']::getBaseOutputDamage($westTile['unit_name']);
- $outputDmg = intval(($baseOutputDmg * ($attackerHP / $attackerBaseHP)) * (1 - ($westTile['defense'] / 10)));
- $newDefenderHP = $westTile['health'] - $outputDmg;
- $defenderBaseHP = $westTile['unit_name']::HEALTH;
- $baseReturnDmg = $westTile['unit_name']::getBaseOutputDamage($attackingUnit['unit_name']);
- $returnDmg = intval(($baseReturnDmg * ($newDefenderHP / $defenderBaseHP)) * (1 - ($attackTile['defense'] / 10)));
- if (empty($attackPaths[$westTile['tile_id']])) {
- $attackPaths[$westTile['tile_id']] = [
- 'path' => $path['path'],
- 'x' => $westTile['x_coordinate'],
- 'y' => $westTile['y_coordinate'],
- 'movesLeft' => $path['movesLeft'],
- 'outputDmg' => $outputDmg,
- 'returnDmg' => $returnDmg
- ];
- } else if ($path['movesLeft'] > $attackPaths[$westTile['tile_id']]['movesLeft']) {
- $attackPaths[$westTile['tile_id']] = [
- 'path' => $path['path'],
- 'x' => $westTile['x_coordinate'],
- 'y' => $westTile['y_coordinate'],
- 'movesLeft' => $path['movesLeft'],
- 'outputDmg' => $outputDmg,
- 'returnDmg' => $returnDmg
- ];
- }
- }
- }
- }
- return $attackPaths;
- }
- static function getRangedAttackPaths($gameInfo, $mappedPaths, $attackingUnit) {
- $attackPaths = [];
- if (!$attackingUnit['unit_name']::CAN_ATTACK) {
- return [];
- }
- foreach ($gameInfo['tiles'] as $x => $tileColumn) {
- foreach ($tileColumn as $y => $tile) {
- $distance = abs((intval($x) - intval($attackingUnit['x_coordinate']))) +
- abs(intval($y) - intval($attackingUnit['y_coordinate']));
- if ($distance >= $attackingUnit['unit_name']::RANGE_DISTANCE_START &&
- $distance <= $attackingUnit['unit_name']::RANGE_DISTANCE_END) {
- if (!empty($tile['unit_team_name']) && ($tile['unit_team_name'] != $attackingUnit['unit_team_name'])) {
- $attackPaths[$tile['tile_id']] = [
- 'path' => [],
- 'x' => $x,
- 'y' => $y
- ];
- }
- }
- }
- }
- return $attackPaths;
- }
- static function getCapturePaths($gameInfo, $mappedPaths, $capturingUnit) {
- $capturePaths = [];
- $capturingTile = $gameInfo['tiles'][$capturingUnit['x_coordinate']][$capturingUnit['y_coordinate']];
- if (!empty($capturingUnit['capture_remaining']) && ($capturingTile['building_team_name'] != $capturingUnit['unit_team_name'])) {
- $capturePaths[$capturingUnit['tile_id']] = [
- 'path' => [],
- 'x' => $capturingUnit['x_coordinate'],
- 'y' => $capturingUnit['y_coordinate']
- ];
- return $capturePaths;
- }
- foreach ($mappedPaths as $path) {
- $tile = $gameInfo['tiles'][$path['x']][$path['y']];
- if (class_exists($tile['terrain_name'])) {
- if ($tile['building_team_name'] != $capturingUnit['unit_team_name']) {
- if (empty($tile['unit_name'])) {
- $capturePaths[$tile['tile_id']] = [
- 'path' => $path['path'],
- 'x' => $tile['x_coordinate'],
- 'y' => $tile['y_coordinate']
- ];
- }
- }
- }
- }
- return $capturePaths;
- }
- static function purchaseUnit($gameInfo, $playerId, $vectors) {
- $buildingTiles = [];
- foreach ($gameInfo['tiles'] as $x => $tileColumn) {
- foreach ($tileColumn as $y => $tile) {
- $terrainName = $tile['terrain_name'];
- if (!empty($tile['building_army_name']) &&
- empty($tile['unit_name']) &&
- ($tile['building_army_name'] == $gameInfo['players'][$playerId]['army_name']) &&
- class_exists($terrainName) &&
- !empty($terrainName::getProducableUnits())) {
- $buildingTiles[] = $tile;
- }
- }
- }
- $unitToBuy = false;
- if (!empty($buildingTiles)) {
- shuffle($buildingTiles);
- $unitToBuy = self::getWeightedUnitDecision($gameInfo, $playerId);
- if (!empty($unitToBuy)) {
- $unitToBuy = [
- 'x_coordinate' => $buildingTiles[0]['x_coordinate'],
- 'y_coordinate' => $buildingTiles[0]['y_coordinate'],
- 'unit_name' => $unitToBuy
- ];
- }
- }
- return $unitToBuy;
- }
- static function getWeightedUnitDecision($gameInfo, $playerId) {
- $purchaseableUnits = ['Boulder','Brimstone','Centaur','Giant','Knight','Mage','Mount','Ninja','Troll'];
- $unitWeights = [];
- $affordableUnits = [];
- foreach ($purchaseableUnits as $unit) {
- if ($unit::PRICE <= $gameInfo['players'][$playerId]['funds']) {
- $unitWeights[$unit] = 1;
- $affordableUnits[] = $unit;
- }
- }
- // Check to see if bot has any units at all
- $unitCount = count($gameInfo['owned_units']);
- if ($unitCount < 1) {
- return 'Knight';
- }
- // Check if bot needs more units that can capture
- $numUnitsCanCapture = 0;
- foreach ($gameInfo['owned_units'] as $unit) {
- if ($unit['unit_name']::CAN_CAPTURE) {
- $numUnitsCanCapture++;
- }
- }
- $percentForceCanCapture = ($numUnitsCanCapture / $unitCount) * 100;
- if (($percentForceCanCapture < 9) || ($numUnitsCanCapture < 3)) {
- if (in_array('Knight', $affordableUnits)) $unitWeights['Knight']+= 10;
- if (in_array('Ninja', $affordableUnits)) $unitWeights['Ninja']+= 10;
- }
- // Assign weights to purchaseable units based on enemy units
- foreach ($gameInfo['enemy_units'] as $enemyUnit) {
- switch ($enemyUnit['unit_name']) {
- case 'Knight':
- case 'Ninja':
- case 'Archer':
- if (in_array('Knight', $affordableUnits)) $unitWeights['Knight'] += 1;
- if (in_array('Ninja', $affordableUnits)) $unitWeights['Ninja'] += 1;
- if (in_array('Mount', $affordableUnits)) $unitWeights['Mount'] += 1.3;
- if (in_array('Mage', $affordableUnits)) $unitWeights['Mage'] += 1.3;
- if (in_array('Centaur', $affordableUnits)) $unitWeights['Centaur'] += 1;
- if (in_array('Troll', $affordableUnits)) $unitWeights['Troll'] += 1;
- if (in_array('Giant', $affordableUnits)) $unitWeights['Giant'] += 1;
- break;
- case 'Mount':
- if (in_array('Ninja', $affordableUnits)) $unitWeights['Ninja'] += 1;
- if (in_array('Mount', $affordableUnits)) $unitWeights['Ninja'] += 1;
- if (in_array('Mage', $affordableUnits)) $unitWeights['Mage'] += 2;
- if (in_array('Centaur', $affordableUnits)) $unitWeights['Centaur'] += 2;
- if (in_array('Troll', $affordableUnits)) $unitWeights['Troll'] += 2;
- if (in_array('Giant', $affordableUnits)) $unitWeights['Giant'] += 2;
- break;
- case 'Boulder':
- if (in_array('Knight', $affordableUnits)) $unitWeights['Knight'] += 1;
- if (in_array('Ninja', $affordableUnits)) $unitWeights['Ninja'] += 1;
- if (in_array('Mount', $affordableUnits)) $unitWeights['Ninja'] += 1;
- if (in_array('Mage', $affordableUnits)) $unitWeights['Mage'] += 2;
- if (in_array('Centaur', $affordableUnits)) $unitWeights['Centaur'] += 2;
- if (in_array('Brimstone', $affordableUnits)) $unitWeights['Brimstone'] += 2;
- if (in_array('Troll', $affordableUnits)) $unitWeights['Troll'] += 2;
- if (in_array('Giant', $affordableUnits)) $unitWeights['Giant'] += 2;
- break;
- case 'Unicorn':
- if (in_array('Knight', $affordableUnits)) $unitWeights['Knight'] += 1;
- if (in_array('Ninja', $affordableUnits)) $unitWeights['Ninja'] += 1;
- if (in_array('Mount', $affordableUnits)) $unitWeights['Ninja'] += 1;
- if (in_array('Boulder', $affordableUnits)) $unitWeights['Boulder'] += 1;
- if (in_array('Mage', $affordableUnits)) $unitWeights['Mage'] += 2;
- if (in_array('Centaur', $affordableUnits)) $unitWeights['Centaur'] += 2;
- if (in_array('Brimstone', $affordableUnits)) $unitWeights['Brimstone'] += 1;
- if (in_array('Troll', $affordableUnits)) $unitWeights['Troll'] += 2;
- if (in_array('Giant', $affordableUnits)) $unitWeights['Giant'] += 2;
- break;
- case 'Mage':
- if (in_array('Ninja', $affordableUnits)) $unitWeights['Ninja'] += 1;
- if (in_array('Boulder', $affordableUnits)) $unitWeights['Boulder'] += 1;
- if (in_array('Mage', $affordableUnits)) $unitWeights['Mage'] += 1;
- if (in_array('Centaur', $affordableUnits)) $unitWeights['Centaur'] += 2;
- if (in_array('Brimstone', $affordableUnits)) $unitWeights['Brimstone'] += 1;
- if (in_array('Troll', $affordableUnits)) $unitWeights['Troll'] += 2;
- if (in_array('Giant', $affordableUnits)) $unitWeights['Giant'] += 2;
- break;
- case 'Centaur':
- if (in_array('Ninja', $affordableUnits)) $unitWeights['Ninja'] += 1;
- if (in_array('Boulder', $affordableUnits)) $unitWeights['Boulder'] += 1;
- if (in_array('Centaur', $affordableUnits)) $unitWeights['Centaur'] += 3;
- if (in_array('Brimstone', $affordableUnits)) $unitWeights['Brimstone'] += 1;
- if (in_array('Troll', $affordableUnits)) $unitWeights['Troll'] += 4;
- if (in_array('Giant', $affordableUnits)) $unitWeights['Giant'] += 4;
- break;
- case 'Net':
- if (in_array('Knight', $affordableUnits)) $unitWeights['Knight'] += 1;
- if (in_array('Ninja', $affordableUnits)) $unitWeights['Ninja'] += 2;
- if (in_array('Mount', $affordableUnits)) $unitWeights['Ninja'] += 2;
- if (in_array('Boulder', $affordableUnits)) $unitWeights['Boulder'] += 1;
- if (in_array('Mage', $affordableUnits)) $unitWeights['Mage'] += 3;
- if (in_array('Centaur', $affordableUnits)) $unitWeights['Centaur'] += 3;
- if (in_array('Brimstone', $affordableUnits)) $unitWeights['Brimstone'] += 1;
- if (in_array('Troll', $affordableUnits)) $unitWeights['Troll'] += 3;
- if (in_array('Giant', $affordableUnits)) $unitWeights['Giant'] += 3;
- break;
- case 'Brimstone':
- if (in_array('Knight', $affordableUnits)) $unitWeights['Knight'] += 1;
- if (in_array('Ninja', $affordableUnits)) $unitWeights['Ninja'] += 2;
- if (in_array('Mount', $affordableUnits)) $unitWeights['Ninja'] += 2;
- if (in_array('Mage', $affordableUnits)) $unitWeights['Mage'] += 3;
- if (in_array('Centaur', $affordableUnits)) $unitWeights['Centaur'] += 3;
- if (in_array('Brimstone', $affordableUnits)) $unitWeights['Brimstone'] += 1;
- if (in_array('Troll', $affordableUnits)) $unitWeights['Troll'] += 3;
- if (in_array('Giant', $affordableUnits)) $unitWeights['Giant'] += 3;
- break;
- case 'Troll':
- if (in_array('Ninja', $affordableUnits)) $unitWeights['Ninja'] += 2;
- if (in_array('Boulder', $affordableUnits)) $unitWeights['Boulder'] += 1;
- if (in_array('Brimstone', $affordableUnits)) $unitWeights['Brimstone'] += 1;
- if (in_array('Troll', $affordableUnits)) $unitWeights['Troll'] += 4;
- if (in_array('Giant', $affordableUnits)) $unitWeights['Giant'] += 5;
- break;
- case 'Giant':
- if (in_array('Ninja', $affordableUnits)) $unitWeights['Ninja'] += 2;
- if (in_array('Boulder', $affordableUnits)) $unitWeights['Boulder'] += 1;
- if (in_array('Brimstone', $affordableUnits)) $unitWeights['Brimstone'] += 1;
- if (in_array('Troll', $affordableUnits)) $unitWeights['Troll'] += 5;
- if (in_array('Giant', $affordableUnits)) $unitWeights['Giant'] += 5;
- break;
- }
- }
- // Adjust weights to purchaseable units based on owned units
- $ownedUnitCountArr = [];
- foreach ($gameInfo['owned_units'] as $unit) {
- if (!empty($unitWeights[$unit['unit_name']])) {
- $unitWeights[$unit['unit_name']] = $unitWeights[$unit['unit_name']] * 0.75;
- }
- if (empty($ownedUnitCountArr[$unit['unit_name']])) {
- $ownedUnitCountArr[$unit['unit_name']] = 1;
- } else {
- $ownedUnitCountArr[$unit['unit_name']] += 1;
- }
- }
- // Adjust weights to purchaseable units based on missing unit variety
- foreach ($affordableUnits as $unitName) {
- if (empty($ownedUnitCountArr[$unitName])) {
- $unitWeights[$unitName] += 1;
- }
- }
- // Pick the winner
- if (empty($unitWeights)) {
- return false;
- }
- $candidateUnitNames = array_keys($unitWeights);
- $chosenUnitName = $candidateUnitNames[0];
- $chosenUnitScore = $unitWeights[$chosenUnitName];
- foreach ($unitWeights as $unitName => $unitScore) {
- if ($unitScore == $chosenUnitScore) {
- if ($unitName::PRICE < $chosenUnitName::PRICE) {
- $chosenUnitName = $unitName;
- $chosenUnitScore = $unitScore;
- }
- } else if ($unitScore > $chosenUnitScore) {
- $chosenUnitName = $unitName;
- $chosenUnitScore = $unitScore;
- }
- }
- // Save money if we have enough knights and ninjas
- if ($chosenUnitName == 'Knight' || $chosenUnitName == 'Ninja') {
- if ((count($gameInfo['owned_units']) > 7) && ($percentForceCanCapture > 40)) {
- return false;
- }
- }
- return $chosenUnitName;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment