/**
  * Why would this mission be invalid with the given unit?
  *
  * @param aiUnit The <code>AIUnit</code> to test.
  * @return A reason why the mission would be invalid with the unit, or null if none found.
  */
 private static String invalidMissionReason(AIUnit aiUnit) {
   String reason = invalidAIUnitReason(aiUnit);
   IndianSettlement home;
   return (reason != null)
       ? reason
       : ((home = getHome(aiUnit)) == null || home.isDisposed()) ? "home-destroyed" : null;
 }
  /**
   * When searching for threats to a settlement, the indian player should ignore naval threats, as
   * he does not have naval power
   */
  public void testSecureIndianSettlementMissionIgnoreNavalThreat() {
    Game game = ServerTestHelper.startServerGame(getCoastTestMap(plainsType));
    Map map = game.getMap();
    AIMain aiMain = ServerTestHelper.getServer().getAIMain();
    InGameController igc = ServerTestHelper.getInGameController();

    // Create player and unit
    ServerPlayer inca = (ServerPlayer) game.getPlayerByNationId("model.nation.inca");
    NativeAIPlayer aiInca = (NativeAIPlayer) aiMain.getAIPlayer(inca);
    ServerPlayer dutch = (ServerPlayer) game.getPlayerByNationId("model.nation.dutch");

    Tile settlementTile = map.getTile(9, 9);
    Tile seaTile = map.getTile(10, 9);
    assertTrue("Settlement tile should be land", settlementTile.isLand());
    assertFalse("Galleon tile should be ocean", seaTile.isLand());
    FreeColTestCase.IndianSettlementBuilder builder =
        new FreeColTestCase.IndianSettlementBuilder(game);
    IndianSettlement camp =
        builder.player(inca).settlementTile(settlementTile).initialBravesInCamp(10).build();
    ServerUnit galleon = new ServerUnit(game, seaTile, dutch, galleonType);
    int unitsInGalleon = 6;
    for (int i = 0; i < unitsInGalleon; i++) {
      ServerUnit artillery = new ServerUnit(game, settlementTile, dutch, artilleryType);
      igc.embarkUnit(dutch, artillery, galleon);
    }
    assertEquals("Wrong number of units onboard galleon", unitsInGalleon, galleon.getUnitCount());
    assertEquals("Galleon should be full", 0, galleon.getSpaceLeft());

    for (Unit brave : camp.getUnitList()) {
      AIUnit aiUnit = aiMain.getAIUnit(brave);
      assertNotNull(aiUnit);
      new UnitWanderHostileMission(aiMain, aiUnit);

      assertTrue("No enemy units present", aiUnit.hasMission(UnitWanderHostileMission.class));
    }

    inca.setStance(dutch, Stance.WAR);
    inca.setTension(dutch, new Tension(Tension.Level.HATEFUL.getLimit()));
    assertTrue("Indian player should be at war with dutch", inca.getStance(dutch) == Stance.WAR);
    assertEquals(
        "Wrong Indian player tension towards dutch",
        Tension.Level.HATEFUL.getLimit(),
        inca.getTension(dutch).getValue());

    aiInca.abortInvalidMissions();
    aiInca.secureIndianSettlement(camp, lb);
    boolean seeking = false;
    for (Unit brave : inca.getUnits()) {
      AIUnit aiUnit = aiMain.getAIUnit(brave);
      assertNotNull(aiUnit);
      if (aiUnit.hasMission(UnitSeekAndDestroyMission.class)) {
        seeking = true;
        break;
      }
    }
    assertFalse("Braves should not pursue naval units", seeking);
  }
Esempio n. 3
0
  /**
   * Allows spread of horses and arms between settlements
   *
   * <p>FIXME: the hardwired goods/equipment types are a wart.
   *
   * @param settlement The other <code>IndianSettlement</code> to trade with.
   */
  public void tradeGoodsWithSettlement(IndianSettlement settlement) {
    GoodsType armsType = getSpecification().getGoodsType("model.goods.muskets");
    GoodsType horsesType = getSpecification().getGoodsType("model.goods.horses");
    List<GoodsType> goodsToTrade = new ArrayList<>();
    goodsToTrade.add(armsType);
    goodsToTrade.add(horsesType);

    for (GoodsType goods : goodsToTrade) {
      int goodsInStock = getGoodsCount(goods);
      if (goodsInStock <= 50) {
        continue;
      }
      int goodsTraded = goodsInStock / 2;
      settlement.addGoods(goods, goodsTraded);
      removeGoods(goods, goodsTraded);
    }
  }
  /** {@inheritDoc} */
  @Override
  public Mission doMission(LogBuilder lb) {
    lb.add(tag);
    String reason = invalidReason();
    if (reason != null) return lbFail(lb, false, reason);

    final AIUnit aiUnit = getAIUnit();
    final Unit unit = getUnit();
    final IndianSettlement is = unit.getHomeIndianSettlement();
    Direction d;

    while (!this.demanded) {
      Unit.MoveType mt = travelToTarget(getTarget(), null, lb);
      switch (mt) {
        case MOVE_HIGH_SEAS:
        case MOVE_NO_MOVES:
        case MOVE_ILLEGAL:
          return lbWait(lb);

        case MOVE_NO_REPAIR:
          return lbFail(lb, false, AIUNITDIED);

        case MOVE_NO_TILE:
          return this;

        case ATTACK_SETTLEMENT: // Arrived?
          d = unit.getTile().getDirection(getTarget().getTile());
          if (d != null) break; // Yes, arrived at target
          // Fall through
        case ATTACK_UNIT: // Something is blocking our path
          Location blocker = resolveBlockage(aiUnit, getTarget());
          if (blocker == null) {
            moveRandomly(tag, null);
            continue;
          }
          d = unit.getTile().getDirection(blocker.getTile());
          if (AIMessage.askAttack(aiUnit, d)) {
            return lbAttack(lb, blocker);
          }
          continue;

        default:
          return lbMove(lb, mt);
      }

      // Load the goods.
      lbAt(lb);
      Colony colony = (Colony) getTarget();
      Player enemy = colony.getOwner();
      Goods goods = selectGoods(colony);
      GoodsType type = (goods == null) ? null : goods.getType();
      int amount = (goods == null) ? 0 : goods.getAmount();
      if (goods == null) {
        if (!enemy.checkGold(1)) {
          return lbDone(lb, false, "empty handed");
        }
        amount = enemy.getGold() / 20;
        if (amount == 0) amount = enemy.getGold();
      }
      this.demanded = AIMessage.askIndianDemand(aiUnit, colony, type, amount);
      if (this.demanded && (goods == null || hasTribute())) {
        if (goods == null) {
          return lbDone(lb, false, "accepted tribute ", amount, " gold");
        }
        lb.add(", accepted tribute ", goods);
        return lbRetarget(lb);
      }

      // Consider attacking if not content.
      int unitTension = (is == null) ? 0 : is.getAlarm(enemy).getValue();
      int tension = Math.max(unitTension, unit.getOwner().getTension(enemy).getValue());
      d = unit.getTile().getDirection(colony.getTile());
      if (tension >= Tension.Level.CONTENT.getLimit() && d != null) {
        if (AIMessage.askAttack(aiUnit, d)) lbAttack(lb, colony);
      }
      return lbDone(lb, false, "refused at ", colony);
    }

    // Take the goods home
    for (; ; ) {
      Unit.MoveType mt =
          travelToTarget(getTarget(), CostDeciders.avoidSettlementsAndBlockingUnits(), lb);
      switch (mt) {
        case MOVE: // Arrived
          break;

        case MOVE_HIGH_SEAS:
        case MOVE_NO_MOVES:
        case MOVE_ILLEGAL:
          return lbWait(lb);

        case MOVE_NO_REPAIR:
          return lbFail(lb, false, AIUNITDIED);

        case MOVE_NO_TILE:
          return this;

        default:
          return lbMove(lb, mt);
      }

      // Unload the goods
      lbAt(lb);
      GoodsContainer container = unit.getGoodsContainer();
      for (Goods goods : container.getCompactGoods()) {
        Goods tribute = container.removeGoods(goods.getType());
        is.addGoods(tribute);
      }
      return lbDone(lb, false, "unloaded tribute");
    }
  }
  public void testSecureIndianSettlementMission() {
    Game game = ServerTestHelper.startServerGame(getTestMap());
    Map map = game.getMap();
    AIMain aiMain = ServerTestHelper.getServer().getAIMain();

    // Create player and unit
    ServerPlayer inca = (ServerPlayer) game.getPlayerByNationId("model.nation.inca");
    NativeAIPlayer aiInca = (NativeAIPlayer) aiMain.getAIPlayer(inca);
    ServerPlayer dutch = (ServerPlayer) game.getPlayerByNationId("model.nation.dutch");

    Tile settlementTile = map.getTile(9, 9);
    Tile adjacentTile = settlementTile.getNeighbourOrNull(Direction.N);
    assertTrue("Settlement tile should be land", settlementTile.isLand());
    assertTrue("Adjacent tile should be land", adjacentTile != null && adjacentTile.isLand());
    FreeColTestCase.IndianSettlementBuilder builder =
        new FreeColTestCase.IndianSettlementBuilder(game);
    IndianSettlement camp =
        builder.player(inca).settlementTile(settlementTile).initialBravesInCamp(8).build();
    assertEquals("One camp", 1, inca.getNumberOfSettlements());

    // Put one brave outside the camp, but in the settlement tile,
    // so that he may defend the settlement
    Unit braveOutside = new ServerUnit(game, settlementTile, inca, braveType);
    braveOutside.setHomeIndianSettlement(camp);

    // Setup enemy units
    int enemyUnits = camp.getUnitCount() + 1;
    for (int i = 0; i < enemyUnits; i++) {
      new ServerUnit(game, adjacentTile, dutch, veteranType);
    }

    Iterator<Unit> campUnitIter = camp.getOwnedUnitsIterator();
    while (campUnitIter.hasNext()) {
      Unit brave = campUnitIter.next();
      assertNotNull("Got null while getting the camps units", brave);
      AIUnit aiUnit = aiMain.getAIUnit(brave);
      assertNotNull("Couldnt get the ai object for the brave", aiUnit);
      new UnitWanderHostileMission(aiMain, aiUnit);
      assertTrue(
          "Should be UnitWanderHostileMission", aiUnit.hasMission(UnitWanderHostileMission.class));
      assertEquals(
          "Unit should be candidate for seek+destroy",
          null,
          UnitSeekAndDestroyMission.invalidReason(aiUnit));
      assertEquals(
          "Unit should be candidate for defend",
          null,
          DefendSettlementMission.invalidReason(aiUnit));
    }

    inca.setStance(dutch, Stance.WAR);
    inca.setTension(dutch, new Tension(Tension.Level.HATEFUL.getLimit()));
    camp.setAlarm(dutch, inca.getTension(dutch));
    assertTrue("Indian player should be at war with dutch", inca.getStance(dutch) == Stance.WAR);
    assertEquals(
        "Wrong Indian player tension towards dutch",
        Tension.Level.HATEFUL.getLimit(),
        inca.getTension(dutch).getValue());
    aiInca.secureIndianSettlement(camp, lb);

    // Verify if a unit was assigned a UnitSeekAndDestroyMission
    boolean isSeekAndDestroyMission = false;
    for (Unit brave : inca.getUnits()) {
      AIUnit aiUnit = aiMain.getAIUnit(brave);
      assertNotNull("Couldnt get aiUnit for players brave", aiUnit);
      assertNotNull("Unit missing mission", aiUnit.getMission());
      isSeekAndDestroyMission = aiUnit.hasMission(UnitSeekAndDestroyMission.class);
      if (isSeekAndDestroyMission) break;
    }
    assertTrue("A brave should have a UnitSeekAndDestroyMission", isSeekAndDestroyMission);
  }