private int isTravellingToBase(Character unit, int prev_x, int prev_y, Tuple <int, int> basePos, Boolean isEnemyBase = true) { // if the base is not defined, the unit can't be traveling to it if (basePos.Item1 < 0) { return(0); } if (GameBoard.distance(unit.xPos, unit.yPos, basePos.Item1, basePos.Item2) < GameBoard.distance(prev_x, prev_y, basePos.Item1, basePos.Item2)) { if (isEnemyBase) { return(HEURISTIC_TRAVEL_TO_ENEMY_BASE); } else { int numGuarding = 0; foreach (EnemyCharacter friendly in cpuUnits) { if (GameBoard.distance(friendly.xPos, friendly.yPos, cpuBasePos.Item1, cpuBasePos.Item2) < 3) { numGuarding++; } } return(HEURISTIC_TRAVEL_TO_HOME_BASE - numGuarding); } } else { return(0); } }
private int canAttackBaseAttacker(Character unit, List <Character> enemy_units, Tuple <int, int> base_pos) { // if there is no base, obviously this will never be true if (base_pos.Item1 < 0) { return(0); } foreach (Character enemy_unit in enemy_units) { if (GameBoard.distance(enemy_unit.xPos, enemy_unit.yPos, base_pos.Item1, base_pos.Item2) < 2) { if (GameBoard.distance(enemy_unit.xPos, enemy_unit.yPos, unit.xPos, unit.yPos) < 2) { return(HEURISTIC_ATTACK_BASE_ATTACKER); } else { return(0); } } else { return(0); } } return(0); }
private int isGuardingBase(Character unit, Tuple <int, int> basePos) { if (GameBoard.distance(unit.xPos, unit.yPos, basePos.Item1, basePos.Item2) < 2) { return(HEURISTIC_GUARD_BASE); } else { return(0); } }
private int isMovingToInterceptOpponent(Character unit, List <Character> enemy_units, int prev_x, int prev_y) { // as long as the cpu unit is moving toward another player unit, return true foreach (Character e_unit in enemy_units) { if (GameBoard.distance(unit.xPos, unit.yPos, e_unit.xPos, e_unit.yPos) < GameBoard.distance(prev_x, prev_y, e_unit.xPos, e_unit.yPos)) { return(HEURISTIC_INTERCEPT_OPPONENT); } } return(0); }
private int canDamageOpponentBase(Character unit, Tuple <int, int> basePos) { if (basePos.Item1 < 0) { return(0); } if (GameBoard.distance(unit.xPos, unit.yPos, basePos.Item1, basePos.Item2) < 2) { return(HEURISTIC_DAMAGE_OPPONENT_BASE); } else { return(0); } }
private int isFleeingFromOverwhelmingForce(Character unit, List <Character> enemy_units, List <Character> friendly_units, int prev_x, int prev_y) { List <Character> unitsToConsider = new List <Character>(); int enemy_count = 0; int unit_count = 0; // get all units within 3 spaces of the current unit foreach (Character enemy in enemy_units) { if (GameBoard.distance(enemy.xPos, enemy.yPos, unit.xPos, unit.yPos) <= 3) { unitsToConsider.Add(enemy); enemy_count++; } } foreach (Character friendly_unit in friendly_units) { // don't include the given unit if (friendly_unit == unit) { continue; } if (GameBoard.distance(friendly_unit.xPos, friendly_unit.yPos, unit.xPos, unit.yPos) <= 3) { unit_count++; } } // if the player force is at least the overwhelming percentage, fleeing is an option if (enemy_count / (unit_count + 1) > OVERWHELMING_FORCE_PERCENT) { // now we need to get which direction they are all mainly coming from // get the average x and y vector they are coming from float avg_x = 0.0f; float avg_y = 0.0f; List <int> vectors = new List <int>(); foreach (Character enemy in unitsToConsider) { avg_x += (enemy.xPos - unit.xPos); avg_y += (enemy.yPos - unit.yPos); } // if the resultant additions so far are very small, we're surrounded, so there's nowhere to run to if ((avg_x < 1 && avg_x > -1) && (avg_y < 1 && avg_y > -1)) { return(0); } // get the unit vector of current motion float motion_x = unit.xPos - prev_x; float motion_y = unit.yPos - prev_y; motion_x = motion_x / ((float)Math.Sqrt(motion_x * motion_x + motion_y * motion_y)); motion_y = motion_x / ((float)Math.Sqrt(motion_x * motion_x + motion_y * motion_y)); // make the averages unit vectors avg_x = avg_x / ((float)Math.Sqrt(avg_x * avg_x + avg_y * avg_y)); avg_y = avg_y / ((float)Math.Sqrt(avg_x * avg_x + avg_y * avg_y)); // now just get the angle between the vectors float theta = (float)Math.Acos(motion_x * avg_x + motion_y * avg_y); // if current motion is greater than 90 degrees away from the enemy positions, unit is fleeing if (theta > Math.PI / 2) { return(HEURISTIC_FLEE_FROM_OVER_FORCE); } else { return(0); } } else { return(0); } }