Beispiel #1
0
  /**
   * Returns change in battle strength if unit at region switches places with neighbor.
   *
   * @param region
   * @param neighbor
   * @param includeNeighborStrengthChange true if change in neighbor strength should be included
   * @return
   */
  private static float getBattleStrengthChange(
      Region region, Neighbor neighbor, boolean includeNeighborStrengthChange) {
    // get current strengths of region, neighbor
    float regionStrength = RegionUtils.getRegionBattleStrength(region);
    float neighborStrength = RegionUtils.getRegionBattleStrength(neighbor.region);

    // swap units, see change in strengths
    Unit tempUnit = region.unit;
    region.unit = neighbor.region.unit;
    neighbor.region.unit = tempUnit;

    Player tempPlayer = region.player;
    region.player = neighbor.region.player;
    neighbor.region.player = tempPlayer;

    float regionMoveStrength = RegionUtils.getRegionBattleStrength(region);
    float neighborMoveStrength = RegionUtils.getRegionBattleStrength(neighbor.region);

    // put units back
    tempUnit = region.unit;
    region.unit = neighbor.region.unit;
    neighbor.region.unit = tempUnit;

    tempPlayer = region.player;
    region.player = neighbor.region.player;
    neighbor.region.player = tempPlayer;

    if (includeNeighborStrengthChange) {
      return (regionMoveStrength + neighborMoveStrength - regionStrength - neighborStrength + 2)
          / 4;
    } else {
      return (regionMoveStrength - regionStrength + 1) / 2;
    }
  }
Beispiel #2
0
  /**
   * Returns change in island strength for given reinforcement
   *
   * @param region
   * @param reinforcementType
   * @param player
   * @return
   */
  private static float getIslandStrengthChange(
      Region region, ReinforcementType reinforcementType, Player player) {

    float regionUnitHealth = -1f;
    float regionIslandStrength = RegionUtils.getIslandStrength(region.island, player);

    // add reinforcement, see change in island strength
    if (reinforcementType.unitType != null) {
      region.unit = new Unit(reinforcementType.unitType, Unit.MAX_HEALTH);
    } else {
      regionUnitHealth = region.unit.health;
      region.unit.health = Unit.MAX_HEALTH;
    }

    float regionIslandReinforcementStrength = RegionUtils.getIslandStrength(region.island, player);

    // remove reinforcement
    if (reinforcementType.unitType != null) {
      region.unit = null;
    } else {
      region.unit.health = regionUnitHealth;
    }

    return (regionIslandReinforcementStrength - regionIslandStrength)
        / regionIslandReinforcementStrength;
  }
Beispiel #3
0
  /**
   * Returns likelihood that region could defeat neighboring regions.
   *
   * @param region
   * @return
   */
  protected static Map<Region, Float> checkAttacks(Region region) {
    Map<Region, Float> result = new HashMap<Region, Float>();

    for (Neighbor neighbor : region.neighbors) {
      // check if region can be attacked
      if (RegionUtils.canAttack(region, neighbor)) {
        float[] battleDamage = BattleUtils.calculateBattleDamage(region, neighbor.region, 0);
        result.put(neighbor.region, battleDamage[0] - battleDamage[1]);
      }
    }

    return result;
  }
Beispiel #4
0
  /**
   * Returns changes in region strengths for each possible move.
   *
   * @param region
   * @return
   */
  protected static Map<Neighbor, Float> checkMoves(Region region) {
    Map<Neighbor, Float> result = new HashMap<Neighbor, Float>();

    for (Neighbor neighbor : region.neighbors) {
      // check if neighbor can be moved to
      if (RegionUtils.canMove(region, neighbor)) {
        // get current strengths of region, neighbor
        float regionStrength = RegionUtils.getRegionBattleStrength(region);
        float neighborStrength = RegionUtils.getRegionBattleStrength(neighbor.region);

        // swap units, see change in strengths
        Unit tempUnit = region.unit;
        region.unit = neighbor.region.unit;
        neighbor.region.unit = tempUnit;

        Player tempPlayer = region.player;
        region.player = neighbor.region.player;
        neighbor.region.player = tempPlayer;

        float regionMoveStrength = RegionUtils.getRegionBattleStrength(region);
        float neighborMoveStrength = RegionUtils.getRegionBattleStrength(neighbor.region);

        // put units back
        tempUnit = region.unit;
        region.unit = neighbor.region.unit;
        neighbor.region.unit = tempUnit;

        tempPlayer = region.player;
        region.player = neighbor.region.player;
        neighbor.region.player = tempPlayer;

        result.put(
            neighbor,
            regionMoveStrength + neighborMoveStrength - regionStrength - neighborStrength);
      }
    }

    return result;
  }
Beispiel #5
0
  /**
   * Returns best reinforcement for given region.
   *
   * @param region
   * @return
   */
  protected static ReinforcementType getBestReinforcement(Region region) {

    ReinforcementType result = new ReinforcementType();

    // existing unit
    if (region.unit != null) {
      float originalRegionHealth = region.unit.health;
      float originalBattleStrength = RegionUtils.getRegionBattleStrength(region);

      // simulate max health
      region.unit.health = Unit.MAX_HEALTH;
      result.strengthChange = RegionUtils.getRegionBattleStrength(region) - originalBattleStrength;
      region.unit.health = originalRegionHealth;
    }
    // new unit
    else {

      // get optimal unit type
      // check each possible unit type
      for (Unit.Type unitType : Unit.Type.values()) {
        region.unit = new Unit(unitType, Unit.MAX_HEALTH);

        float regionBattleStrength = RegionUtils.getRegionBattleStrength(region);

        if (result.unitType == null || regionBattleStrength > result.strengthChange) {
          result.strengthChange = regionBattleStrength;
          result.unitType = unitType;
        }
      }

      // reset region to have no unit
      region.unit = null;
    }

    return result;
  }
Beispiel #6
0
  /**
   * Returns random move (attack or move).
   *
   * @param overworld overworld
   * @param player player
   * @param forceAttack true if we want to force an attack if possible
   * @param forceMove true if we want to force a move if possible
   * @param types types of moves allowed (attack or move)
   * @return random move
   */
  protected static Move getRandomMove(
      Overworld overworld,
      Player player,
      boolean forceAttack,
      boolean forceMove,
      Move.Type... types) {

    List<Region> regions = PlayerUtils.getPlayerRegions(overworld, player, false);

    // check possible moves
    boolean allowAttack = false;
    boolean allowMove = false;
    for (Move.Type type : types) {
      switch (type) {
        case ATTACK:
          allowAttack = true;
          break;
        case MOVE:
          allowMove = true;
          break;
      }
    }

    // choose random region to take action with
    int regionIndex = Utils.random().nextInt(regions.size());
    int regionStartIndex = regionIndex;

    // check if region can take action

    // get regions to attack
    List<Region> attackRegions = RegionUtils.getAttacks(regions.get(regionIndex));
    List<Region> moveRegions = RegionUtils.getMoves(regions.get(regionIndex));

    // if region can't attack or move, check other regions if we force an attack or move
    while ((allowAttack && forceAttack && attackRegions.size() == 0)
        || (allowMove && forceMove && moveRegions.size() == 0)) {

      regionIndex++;

      if (regionIndex >= regions.size()) {
        regionIndex = 0;
      }

      // exit loop if we've checked all regions
      if (regionIndex == regionStartIndex) {
        break;
      }

      attackRegions = RegionUtils.getAttacks(regions.get(regionIndex));
      moveRegions = RegionUtils.getMoves(regions.get(regionIndex));
    }

    // region to attack
    if (allowAttack && attackRegions.size() > 0) {
      // choose random region to attack
      Region attackRegion = attackRegions.get(Utils.random().nextInt(attackRegions.size()));

      return new Move(Move.Type.ATTACK, regions.get(regionIndex), attackRegion);
    } else if (allowMove && moveRegions.size() > 0) {
      // choose random region to move to
      Region moveRegion = moveRegions.get(Utils.random().nextInt(moveRegions.size()));

      return new Move(Move.Type.MOVE, regions.get(regionIndex), moveRegion);
    }

    return new Move(Move.Type.END_PHASE);
  }
Beispiel #7
0
  /**
   * Returns collection of moves for given score factor, ordered by descending score.
   *
   * @param overworld
   * @param player
   * @param scoreThreshold
   * @param scoreFactor
   * @return
   */
  protected static Collection<Move> getMoves(
      Overworld overworld,
      Player player,
      ScoreFactor scoreThreshold,
      ScoreFactor captureScoreThreshold,
      ScoreFactor scoreFactor) {

    Map<Float, Move> moves = new TreeMap<Float, Move>();

    // go through each region
    for (Region region : overworld.regions) {
      if (region.player.equals(player) && region.unit != null && region.unit.hasMove) {

        // go through each neighbor
        for (Neighbor neighbor : region.neighbors) {
          if (RegionUtils.canMove(region, neighbor)) {

            ScoreFactor score = new ScoreFactor();
            float scoreValue = 0;
            boolean aboveThreshold = true;

            // get each score type
            for (ScoreFactor.Type type : ScoreFactor.Type.values()) {
              if (scoreThreshold.usesType(type) || scoreFactor.usesType(type)) {
                switch (type) {
                  case BATTLE_STRENGTH_CHANGE:
                    score.addFactor(type, getBattleStrengthChange(region, neighbor, true));
                    break;
                  case ISLAND_PERCENTAGE:
                    score.addFactor(type, RegionUtils.getIslandPercentage(region.island, player));
                    break;
                  case ISLAND_STRENGTH:
                    score.addFactor(type, RegionUtils.getIslandStrength(region.island, player));
                    break;
                  case RANDOM:
                    score.addFactor(type, Utils.random().nextFloat());
                    break;
                  case BATTLE_LIKELIHOOD:
                  case ISLAND_STRENGTH_CHANGE:
                    // ignore
                    break;
                }

                // check if score meets threshold
                // capture threshold
                if (!neighbor.region.player.equals(region.player) && neighbor.region.unit == null) {
                  if (captureScoreThreshold.usesType(type)) {
                    aboveThreshold &= score.getScore(type) >= captureScoreThreshold.getScore(type);
                  }
                }
                // regular move threshold
                else {
                  if (scoreThreshold.usesType(type)) {
                    aboveThreshold &= score.getScore(type) >= scoreThreshold.getScore(type);
                  }
                }

                // update score value
                if (scoreFactor.usesType(type)) {
                  scoreValue += score.getScore(type) * scoreFactor.getScore(type);
                }
              }
            }

            // score above threshold
            if (aboveThreshold) {
              moves.put(scoreValue, new Move(Move.Type.MOVE, region, neighbor.region));
              System.out.println(
                  String.format("\tpossible move %f: %s", scoreValue, moves.get(scoreValue)));
              System.out.println("\t\t" + score);
            }
          }
        }
      }
    }

    return moves.values();
  }
Beispiel #8
0
  /**
   * Returns collection of reinforcements for given score factor, ordered by descending score.
   *
   * @param overworld
   * @param player
   * @param minScore
   * @param scoreFactor
   * @return
   */
  protected static Collection<Move> getReinforcements(
      Overworld overworld, Player player, ScoreFactor scoreThreshold, ScoreFactor scoreFactor) {

    Map<Float, Move> reinforcements = new TreeMap<Float, Move>();

    // go through each region
    for (Region region : overworld.regions) {
      if (region.player.equals(player)
          && (region.unit == null || region.unit.health < Unit.MAX_HEALTH)) {

        // get optimal reinforcement type for region
        ReinforcementType reinforcementType = getBestReinforcement(region);

        ScoreFactor score = new ScoreFactor();
        float scoreValue = 0;
        boolean aboveThreshold = true;

        // get each score type
        for (ScoreFactor.Type type : ScoreFactor.Type.values()) {
          if (scoreThreshold.usesType(type) || scoreFactor.usesType(type)) {
            switch (type) {
              case BATTLE_STRENGTH_CHANGE:
                score.addFactor(type, reinforcementType.strengthChange);
                break;
              case ISLAND_PERCENTAGE:
                score.addFactor(type, RegionUtils.getIslandPercentage(region.island, player));
                break;
              case ISLAND_STRENGTH:
                score.addFactor(type, RegionUtils.getIslandStrength(region.island, player));
                break;
              case ISLAND_STRENGTH_CHANGE:
                score.addFactor(type, getIslandStrengthChange(region, reinforcementType, player));
                break;
              case RANDOM:
                score.addFactor(type, Utils.random().nextFloat());
                break;
              case BATTLE_LIKELIHOOD:
                // ignore
                break;
            }

            // check if score meets threshold
            if (scoreThreshold.usesType(type)) {
              aboveThreshold &= score.getScore(type) >= scoreThreshold.getScore(type);
            }

            // update score value
            if (scoreFactor.usesType(type)) {
              scoreValue += score.getScore(type) * scoreFactor.getScore(type);
            }
          }
        }

        // score above threshold
        if (aboveThreshold) {
          reinforcements.put(
              scoreValue, new Move(Move.Type.REINFORCE, region, null, reinforcementType.unitType));
          System.out.println(
              String.format(
                  "\tpossible reinforcement %f: %s", scoreValue, reinforcements.get(scoreValue)));
          System.out.println("\t\t" + score);
        }
      }
    }

    return reinforcements.values();
  }
Beispiel #9
0
  /**
   * Returns collection of attacks for given score factor, ordered by descending score.
   *
   * @param overworld
   * @param player
   * @param scoreThreshold
   * @param scoreFactor
   * @return
   */
  protected static Collection<Move> getAttacks(
      Overworld overworld, Player player, ScoreFactor scoreThreshold, ScoreFactor scoreFactor) {

    Map<Float, Move> attacks = new TreeMap<Float, Move>();

    // go through each region
    for (Region region : overworld.regions) {
      if (region.player.equals(player) && region.unit != null && region.unit.hasAttack) {

        // check each neighbor
        for (Neighbor neighbor : region.neighbors) {
          if (RegionUtils.canAttack(region, neighbor)) {

            ScoreFactor score = new ScoreFactor();
            float scoreValue = 0;
            boolean aboveThreshold = true;

            // get each score type
            for (ScoreFactor.Type type : ScoreFactor.Type.values()) {
              if (scoreThreshold.usesType(type) || scoreFactor.usesType(type)) {
                switch (type) {
                  case BATTLE_STRENGTH_CHANGE:
                    if (neighbor.type != Neighbor.Type.RANGED) {
                      score.addFactor(type, getBattleStrengthChange(region, neighbor, false));
                    } else {
                      score.addFactor(type, 0.5f);
                    }
                    break;
                  case BATTLE_LIKELIHOOD:
                    score.addFactor(
                        type, BattleUtils.calculateBattleLikelihood(region, neighbor.region));
                    break;
                  case ISLAND_PERCENTAGE:
                    score.addFactor(type, RegionUtils.getIslandPercentage(region.island, player));
                    break;
                  case ISLAND_STRENGTH:
                    score.addFactor(type, RegionUtils.getIslandStrength(region.island, player));
                    break;
                  case RANDOM:
                    score.addFactor(type, Utils.random().nextFloat());
                    break;
                  case ISLAND_STRENGTH_CHANGE:
                    // ignore
                    break;
                }

                // check if score meets threshold
                if (scoreThreshold.usesType(type)) {
                  aboveThreshold &= score.getScore(type) >= scoreThreshold.getScore(type);
                }

                // update score value
                if (scoreFactor.usesType(type)) {
                  scoreValue += score.getScore(type) * scoreFactor.getScore(type);
                }
              }
            }

            // score above threshold
            if (aboveThreshold) {
              attacks.put(scoreValue, new Move(Move.Type.ATTACK, region, neighbor.region));
              System.out.println(
                  String.format("\tpossible attack %f: %s", scoreValue, attacks.get(scoreValue)));
              System.out.println("\t\t" + score);
            }
          }
        }
      }
    }

    return attacks.values();
  }