/**
* Copyright (C) 2002-2012 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FreeCol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.common.model;
import net.sf.freecol.common.model.Map;
import net.sf.freecol.common.model.Player.Stance;
import net.sf.freecol.common.model.pathfinding.CostDecider;
import net.sf.freecol.common.model.pathfinding.CostDeciders;
import net.sf.freecol.server.model.ServerUnit;
import net.sf.freecol.util.test.FreeColTestCase;
/**
* Tests for the {@link BaseCostDecider} class.
*/
public class BaseCostDeciderTest extends FreeColTestCase {
private UnitType pioneerType = spec().getUnitType("model.unit.hardyPioneer");
private UnitType colonistType = spec().getUnitType("model.unit.freeColonist");
private UnitType galleonType = spec().getUnitType("model.unit.galleon");
private GoodsType tradeGoodsType = spec().getGoodsType("model.goods.tradeGoods");
private Game game;
@Override
public void setUp() {
game = getStandardGame();
}
@Override
public void tearDown() {
game = null;
}
/**
* Checks that the decider returns the right cost for a plain to plain move.
*/
public void testGetCostLandLand() {
TileType plainsType = spec().getTileType("model.tile.plains");
Map map = getTestMap(plainsType);
game.setMap(map);
final CostDecider decider = CostDeciders.avoidSettlements();
Tile start = game.getMap().getTile(5, 5);
Unit unit = new ServerUnit(game, start, game.getCurrentPlayer(),
pioneerType);
for (Map.Direction dir : Map.Direction.values()) {
Tile end = start.getNeighbourOrNull(dir);
assertNotNull(end);
int cost = decider.getCost(unit, start, game.getMap().getTile(5, 6),
100);
assertEquals(plainsType.getBasicMoveCost(), cost);
}
}
/**
* Checks that {@link BaseCostDecider#getMovesLeft() } and {@link
* BaseCostDecider#isNewTurn() } return the expected values after
* a move.
*/
public void testGetRemainingMovesAndNewTurn() {
TileType plainsType = spec().getTileType("model.tile.plains");
Map map = getTestMap(plainsType);
game.setMap(map);
final CostDecider decider = CostDeciders.avoidSettlements();
Unit unit = new ServerUnit(game, game.getMap().getTile(1, 1),
game.getCurrentPlayer(), pioneerType);
int cost = decider.getCost(unit, game.getMap().getTile(1, 1),
game.getMap().getTile(2, 2), 4);
assertEquals(plainsType.getBasicMoveCost(), cost);
assertEquals(4 - plainsType.getBasicMoveCost(), decider.getMovesLeft());
assertEquals(0, decider.getNewTurns());
}
/**
* Checks possible move of a land unit to an ocean tile
* Verifies that is invalid
*/
public void testInvalidMoveOfLandUnitToAnOceanTile() {
// For this test we need a different map
TileType plainsType = spec().getTileType("model.tile.plains");
Map map = getCoastTestMap(plainsType);
game.setMap(map);
Tile unitTile = map.getTile(9, 9);
assertTrue("Unit tile should be land",unitTile.isLand());
Unit unit = new ServerUnit(game, unitTile, game.getCurrentPlayer(), pioneerType);
Tile seaTile = map.getTile(10, 9);
assertFalse("Tile should be ocean",seaTile.isLand());
// Execute
CostDecider decider = CostDeciders.avoidSettlements();
int cost = decider.getCost(unit, unitTile, seaTile, 4);
assertTrue("Move should be invalid", cost == CostDecider.ILLEGAL_MOVE);
}
/**
* Checks possible move of a naval unit to a land tile without settlement
* Verifies that is invalid
*/
public void testInvalidMoveOfNavalUnitToALandTile() {
// For this test we need a different map
TileType plainsType = spec().getTileType("model.tile.plains");
Map map = getCoastTestMap(plainsType);
game.setMap(map);
Tile unitTile = map.getTile(10, 9);
assertFalse("Unit tile should be ocean",unitTile.isLand());
Unit unit = new ServerUnit(game, unitTile, game.getCurrentPlayer(), galleonType);
Tile landTile = map.getTile(9, 9);
assertTrue("Tile should be land",landTile.isLand());
// Execute
final CostDecider decider = CostDeciders.avoidSettlements();
int cost = decider.getCost(unit, unitTile, landTile, 4);
assertTrue("Move should be invalid",cost == CostDecider.ILLEGAL_MOVE);
}
/**
* Checks possible move of a unit through a tile with a settlement
* Verifies that is invalid
*/
public void testInvalidMoveThroughTileWithSettlement() {
TileType plainsType = spec().getTileType("model.tile.plains");
Map map = getTestMap(plainsType);
game.setMap(map);
//Setup
Tile settlementTile = map.getTile(2,1);
FreeColTestCase.IndianSettlementBuilder builder = new FreeColTestCase.IndianSettlementBuilder(game);
settlementTile.setSettlement(builder.settlementTile(settlementTile).build());
Tile unitTile = map.getTile(1, 1);
Unit unit = new ServerUnit(game, unitTile, game.getCurrentPlayer(), pioneerType);
// unit is going somewhere else
Tile unitDestination = map.getTile(3, 1);
unit.setDestination(unitDestination);
// Execute
final CostDecider decider = CostDeciders.avoidSettlements();
int cost = decider.getCost(unit, unitTile, settlementTile, 4);
assertEquals("Move should be invalid", CostDecider.ILLEGAL_MOVE, cost);
}
/**
* Checks possible move of a naval unit to a tile with a settlement
*/
public void testNavalUnitMoveToTileWithSettlement() {
// For this test we need a different map
TileType plainsType = spec().getTileType("model.tile.plains");
Map map = getCoastTestMap(plainsType);
game.setMap(map);
Tile unitTile = map.getTile(10, 9);
assertFalse("Unit tile should be ocean",unitTile.isLand());
Unit galleon = new ServerUnit(game, unitTile, game.getCurrentPlayer(), galleonType);
Tile settlementTile = map.getTile(9, 9);
assertTrue("Tile should be land", settlementTile.isLand());
FreeColTestCase.IndianSettlementBuilder builder = new FreeColTestCase.IndianSettlementBuilder(game);
Settlement settlement = builder.settlementTile(settlementTile).build();
// galleon is trying go to settlement
galleon.setDestination(settlementTile);
CostDecider base = CostDeciders.avoidIllegal();
int cost;
// Try to find a path
cost = base.getCost(galleon, unitTile, settlementTile, 4);
assertTrue("Move should be invalid, no contact or goods to trade",
cost == CostDecider.ILLEGAL_MOVE);
// Add contact
Player.makeContact(galleon.getOwner(), settlement.getOwner());
cost = base.getCost(galleon, unitTile, settlementTile, 4);
assertTrue("Move should be invalid, no goods to trade",
cost == CostDecider.ILLEGAL_MOVE);
// Add goods to trade
Goods goods = new Goods(game, null, tradeGoodsType, 50);
galleon.add(goods);
cost = base.getCost(galleon, unitTile, settlementTile, 4);
assertTrue("Move should be valid, has contact and goods to trade",
cost != CostDecider.ILLEGAL_MOVE);
assertTrue("Move should consume whole turn",
base.getMovesLeft() == 0 && base.getNewTurns() == 0);
// Try with colonist on galleon
Unit colonist = new ServerUnit(game, galleon, game.getCurrentPlayer(),
colonistType);
cost = base.getCost(colonist, unitTile, settlementTile, 4);
if (spec().getBooleanOption("model.option.amphibiousMoves")
.getValue()) {
assertFalse("Move valid, direct from carrier to settlement",
cost == CostDecider.ILLEGAL_MOVE);
} else {
assertTrue("Move invalid, direct from carrier to settlement",
cost == CostDecider.ILLEGAL_MOVE);
}
assertNotNull("Path should be valid from carrier to settlement",
map.findPath(colonist, unitTile, settlementTile,
galleon, base));
// Set players at war
Player indianPlayer = settlement.getOwner();
indianPlayer.setStance(galleon.getOwner(), Stance.WAR);
galleon.getOwner().setStance(indianPlayer, Stance.WAR);
cost = base.getCost(galleon, unitTile, settlementTile, 4);
assertTrue("Move should be valid, war should not block gifts",
cost != CostDecider.ILLEGAL_MOVE);
}
}