/** * 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.server.ai; import net.sf.freecol.common.model.BuildableType; import net.sf.freecol.common.model.Building; import net.sf.freecol.common.model.BuildingType; import net.sf.freecol.common.model.Colony; import net.sf.freecol.common.model.ColonyTile; import net.sf.freecol.common.model.Game; import net.sf.freecol.common.model.GoodsContainer; import net.sf.freecol.common.model.GoodsType; import net.sf.freecol.common.model.Map; import net.sf.freecol.common.model.Tile; import net.sf.freecol.common.model.TileType; import net.sf.freecol.common.model.Unit; import net.sf.freecol.common.model.UnitType; import net.sf.freecol.server.ServerTestHelper; import net.sf.freecol.server.model.ServerBuilding; import net.sf.freecol.server.model.ServerPlayer; import net.sf.freecol.server.model.ServerUnit; import net.sf.freecol.util.test.FreeColTestCase; import net.sf.freecol.util.test.FreeColTestUtils; public class AIColonyTest extends FreeColTestCase { private static final BuildingType lumberMillType = spec().getBuildingType("model.building.lumberMill"); private static final BuildingType warehouseType = spec().getBuildingType("model.building.warehouse"); private static final GoodsType foodType = spec().getPrimaryFoodType(); private static final GoodsType grainType = spec().getGoodsType("model.goods.grain"); private static final GoodsType hammersType = spec().getGoodsType("model.goods.hammers"); private static final GoodsType lumberType = spec().getGoodsType("model.goods.lumber"); private static final GoodsType oreType = spec().getGoodsType("model.goods.ore"); private static final GoodsType rumType = spec().getGoodsType("model.goods.rum"); private static final GoodsType sugarType = spec().getGoodsType("model.goods.sugar"); private static final GoodsType toolsType = spec().getGoodsType("model.goods.tools"); private static final TileType forestType = spec().getTileType("model.tile.coniferForest"); private static final TileType savannahType = spec().getTileType("model.tile.savannah"); private static final TileType mountainType = spec().getTileType("model.tile.mountains"); private static final UnitType artilleryType = spec().getUnitType("model.unit.artillery"); private static final UnitType colonistType = spec().getUnitType("model.unit.freeColonist"); private static final UnitType lumberJackType = spec().getUnitType("model.unit.expertLumberJack"); @Override public void tearDown() throws Exception { ServerTestHelper.stopServerGame(); super.tearDown(); } // creates the special map for the tests // map will have: // - a colony in (5,8) (built after) // - a forest in (4,8) for lumber // - a mountain in (6,8) for ore private Map buildMap(boolean withBuildRawMat) { MapBuilder builder = new MapBuilder(getGame()); builder.setBaseTileType(savannahType); if (withBuildRawMat) { builder.setTile(4, 8, forestType); builder.setTile(6, 8, mountainType); } return builder.build(); } // Add buildings until the next buildable requires tools private BuildableType getToolsBuilder(AIColony aiColony) { Colony colony = aiColony.getColony(); for (BuildableType b : aiColony.getColonyPlan().getBuildableTypes()) { if (colony.canBuild(b) && b.getAmountRequiredOf(toolsType) > 0) return b; if (b instanceof BuildingType) { colony.addBuilding(new ServerBuilding(colony.getGame(), colony, (BuildingType)b)); } else if (b instanceof UnitType) { new ServerUnit(colony.getGame(), colony.getTile(), colony.getOwner(), (UnitType)b); } } return null; } /** * Tests worker allocation regarding building tasks */ public void testBuildersAllocation() { Game game = ServerTestHelper.startServerGame(buildMap(true)); AIMain aiMain = ServerTestHelper.getServer().getAIMain(); // Needs a decent sized colony. Colony colony = getStandardColony(6); game.setCurrentPlayer(colony.getOwner()); final Building carpenterHouse = colony.getBuildingForProducing(hammersType); final Building blacksmithHouse = colony.getBuildingForProducing(toolsType); AIColony aiColony = aiMain.getAIColony(colony); ServerPlayer player = (ServerPlayer) colony.getOwner(); // Add food so that the starvation avoidance is not triggered colony.addGoods(foodType, GoodsContainer.CARGO_SIZE); aiColony.propertyChange(null); // force rearranging workers aiColony.rearrangeWorkers(); assertEquals("Colony should be building lumber mill", lumberMillType, colony.getCurrentlyBuilding()); assertTrue("Colony should be producing lumber", colony.getNetProductionOf(lumberType) > 0); assertTrue("Colony should have been assigned a carpenter", carpenterHouse.getUnitCount() > 0); assertTrue("Colony should be producing sugar", colony.getNetProductionOf(sugarType) > 0); // Simulate that enough hammers have been gathered, re-arrange // and re-check. colony.addGoods(hammersType, lumberMillType.getAmountRequiredOf(hammersType)); aiColony.propertyChange(null); // force rearranging workers aiColony.rearrangeWorkers(); assertEquals("Colony should be building lumber mill", lumberMillType, colony.getCurrentlyBuilding()); assertEquals("Colony does not need a carpenter", 0, carpenterHouse.getUnitCount()); assertTrue("Colony should be producing sugar", colony.getNetProductionOf(sugarType) > 0); assertTrue("Colony should be producing rum", colony.getNetProductionOf(rumType) > 0); // Fill the warehouse with sugar, re-arrange and re-check. colony.addGoods(sugarType, GoodsContainer.CARGO_SIZE); aiColony.propertyChange(null); // force rearranging workers aiColony.rearrangeWorkers(); assertEquals("Colony does not need a carpenter", 0, carpenterHouse.getUnitCount()); assertEquals("Colony should not be producing sugar, except center", colony.getTile().getType().getProductionOf(sugarType,colonistType), colony.getTotalProductionOf(sugarType)); assertTrue("Colony should be producing rum", colony.getNetProductionOf(rumType) > 0); // Change to building something that needs tools. for (;;) { BuildableType toolsBuild = getToolsBuilder(aiColony); assertNotNull(toolsBuild); aiColony.propertyChange(null); // force rearranging workers aiColony.rearrangeWorkers(); if (colony.getCurrentlyBuilding() == toolsBuild) break; } assertEquals("Colony does not need a carpenter", 0, carpenterHouse.getUnitCount()); assertTrue("Colony should be producing ore", colony.getTotalProductionOf(oreType) > 0); assertTrue("Colony should be producing tools", colony.getTotalProductionOf(toolsType) > 0); } /** * Tests worker allocation regarding building tasks when the * colony does not have tiles that provide the raw materials for * the build. */ public void testBuildersAllocNoRawMatTiles() { Game game = ServerTestHelper.startServerGame(buildMap(false)); AIMain aiMain = ServerTestHelper.getServer().getAIMain(); // The number needs to be high to ensure allocation Colony colony = getStandardColony(6); game.setCurrentPlayer(colony.getOwner()); final Building carpenterHouse = colony.getBuildingForProducing(hammersType); final Building blacksmithHouse = colony.getBuildingForProducing(toolsType); AIColony aiColony = aiMain.getAIColony(colony); ServerPlayer player = (ServerPlayer) colony.getOwner(); // Add food so that the starvation avoidance is not triggered colony.addGoods(foodType, GoodsContainer.CARGO_SIZE); // We need to ensure that there are no tiles with production of // the raw materials. for (ColonyTile t : colony.getColonyTiles()) { Tile tile = t.getTile(); assertEquals("The colony can not have tiles that produce lumber", 0, tile.potential(lumberType, colonistType)); assertEquals("The colony can not have tiles that produce ore", 0, tile.potential(oreType, colonistType)); } assertEquals("Colony has no lumber", 0, colony.getGoodsCount(lumberType)); assertEquals("Colony has no ore", 0, colony.getGoodsCount(oreType)); aiColony.propertyChange(null); // force rearranging workers aiColony.rearrangeWorkers(); assertFalse("Colony can not have a lumberjack, no lumber", colony.getNetProductionOf(lumberType) > 0); assertEquals("Colony can not have a carpenter, no lumber", 0, carpenterHouse.getUnitCount()); assertFalse("Colony can not have an ore miner, no ore", colony.getNetProductionOf(oreType) > 0); assertEquals("Colony can not have a blacksmith, no ore", 0, blacksmithHouse.getUnitCount()); assertEquals("Colony should be building lumber mill", lumberMillType, colony.getCurrentlyBuilding()); // Add lumber to stock, re-arrange and re-check colony.addGoods(lumberType, GoodsContainer.CARGO_SIZE); aiColony.propertyChange(null); // force rearranging workers aiColony.rearrangeWorkers(); assertEquals("Colony should be building lumber mill", lumberMillType, colony.getCurrentlyBuilding()); assertFalse("Colony can not have a lumberjack, no lumber", colony.getNetProductionOf(lumberType) > 0); assertTrue("Colony should have a carpenter, has lumber in stock", carpenterHouse.getUnitCount() > 0); assertFalse("Colony can not have an ore miner, no ore", colony.getNetProductionOf(oreType) > 0); assertEquals("Colony can not have a blacksmith, no ore", 0, blacksmithHouse.getUnitCount()); // Simulate that enough hammers have been gathered, re-arrange // and re-check colony.addGoods(hammersType, lumberMillType.getAmountRequiredOf(hammersType)); aiColony.propertyChange(null); // force rearranging workers aiColony.rearrangeWorkers(); assertFalse("Colony can not have a lumberjack, no lumber", colony.getNetProductionOf(lumberType) > 0); assertEquals("Colony does not need a carpenter", 0, carpenterHouse.getUnitCount()); assertFalse("Colony can not have an ore miner, no ore", colony.getNetProductionOf(oreType) > 0); assertEquals("Colony can not have a blacksmith, no ore", 0, blacksmithHouse.getUnitCount()); // Change to building something that needs tools. BuildableType toolsBuild = getToolsBuilder(aiColony); aiColony.propertyChange(null); // force rearranging workers aiColony.rearrangeWorkers(); assertFalse("Colony can not have a lumberjack, no lumber", colony.getNetProductionOf(lumberType) > 0); assertEquals("Colony does not need a carpenter", 0, carpenterHouse.getUnitCount()); assertFalse("Colony can not have an ore miner, no ore", colony.getNetProductionOf(oreType) > 0); assertEquals("Colony can not have a blacksmith, no ore", 0, blacksmithHouse.getUnitCount()); assertEquals("Colony should be building tools-requirer", toolsBuild, colony.getCurrentlyBuilding()); // Add ore to stock, re-arrange and re-check colony.addGoods(oreType, GoodsContainer.CARGO_SIZE); aiColony.propertyChange(null); // force rearranging workers aiColony.rearrangeWorkers(); assertFalse("Colony can not have a lumberjack, no lumber", colony.getNetProductionOf(lumberType) > 0); assertEquals("Colony does not need a carpenter", 0, carpenterHouse.getUnitCount()); assertFalse("Colony can not have an ore miner, no ore", colony.getNetProductionOf(oreType) > 0); assertTrue("Colony should have a blacksmith, has ore in stock", blacksmithHouse.getUnitCount() > 0); } /** * Tests expert allocation regarding raw materials where there are * plenty already in stock. */ public void testExpertAllocColonyHasEnoughRawMat() { Game game = ServerTestHelper.startServerGame(getTestMap(forestType)); AIMain aiMain = ServerTestHelper.getServer().getAIMain(); FreeColTestUtils.ColonyBuilder builder = FreeColTestUtils.getColonyBuilder(); Colony colony = builder.addColonist(lumberJackType).build(); AIColony aiColony = aiMain.getAIColony(colony); game.setCurrentPlayer(colony.getOwner()); ServerPlayer player = (ServerPlayer) colony.getOwner(); assertEquals("Wrong number of units in colony", 1, colony.getUnitCount()); Unit lumberjack = colony.getUnitList().get(0); aiColony.propertyChange(null); // force rearranging workers aiColony.rearrangeWorkers(); assertEquals("Lumberjack should have been assigned to collect lumber", lumberType, lumberjack.getWorkType()); // Add lumber to stock, re-arrange and re-check colony.addGoods(lumberType, GoodsContainer.CARGO_SIZE); aiColony.propertyChange(null); // force rearranging workers aiColony.rearrangeWorkers(); assertTrue("Lumberjack should not collect lumber, in stock", lumberType != lumberjack.getWorkType()); } public void testBestDefender() { Game game = ServerTestHelper.startServerGame(getTestMap(savannahType)); AIMain aiMain = ServerTestHelper.getServer().getAIMain(); Colony colony = getStandardColony(); assertEquals(artilleryType, colony.getBestDefenderType()); } }