/**
* 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 java.io.StringWriter;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import net.sf.freecol.common.model.Modifier;
import net.sf.freecol.server.model.ServerBuilding;
import net.sf.freecol.util.test.FreeColTestCase;
public class BuildingTest extends FreeColTestCase {
private static final BuildingType armoryType
= spec().getBuildingType("model.building.armory");
private static final BuildingType blacksmithType
= spec().getBuildingType("model.building.blacksmithHouse");
private static final BuildingType chapelType
= spec().getBuildingType("model.building.chapel");
private static final BuildingType countryType
= spec().getBuildingType("model.building.country");
private static final BuildingType depotType
= spec().getBuildingType("model.building.depot");
private static final BuildingType fortType
= spec().getBuildingType("model.building.fort");
private static final BuildingType fortressType
= spec().getBuildingType("model.building.fortress");
private static final BuildingType newspaperType
= spec().getBuildingType("model.building.newspaper");
private static final BuildingType printingPressType
= spec().getBuildingType("model.building.printingPress");
private static final BuildingType schoolType
= spec().getBuildingType("model.building.schoolhouse");
private static final BuildingType stockadeType
= spec().getBuildingType("model.building.stockade");
private static final BuildingType townHallType
= spec().getBuildingType("model.building.townHall");
private static final BuildingType universityType
= spec().getBuildingType("model.building.university");
private static final BuildingType warehouseType
= spec().getBuildingType("model.building.warehouse");
private static final BuildingType weaverHouseType
= spec().getBuildingType("model.building.weaverHouse");
private static final GoodsType bellsType
= spec().getGoodsType("model.goods.bells");
private static final GoodsType clothType
= spec().getGoodsType("model.goods.cloth");
private static final GoodsType cottonType
= spec().getGoodsType("model.goods.cotton");
private static final GoodsType foodType
= spec().getPrimaryFoodType();
private static final GoodsType grainType
= spec().getGoodsType("model.goods.grain");
private static final GoodsType horsesType
= spec().getGoodsType("model.goods.horses");
private static final GoodsType musketsType
= spec().getGoodsType("model.goods.muskets");
private static final GoodsType toolsType
= spec().getGoodsType("model.goods.tools");
private static final TileType plainsType
= spec().getTileType("model.tile.plains");
private static final UnitType elderStatesmanType
= spec().getUnitType("model.unit.elderStatesman");
private static final UnitType expertFarmerType
= spec().getUnitType("model.unit.expertFarmer");
private static final UnitType freeColonistType
= spec().getUnitType("model.unit.freeColonist");
private static final UnitType indenturedServantType
= spec().getUnitType("model.unit.indenturedServant");
private static final UnitType indianConvertType
= spec().getUnitType("model.unit.indianConvert");
private static final UnitType masterCarpenterType
= spec().getUnitType("model.unit.masterCarpenter");
private static final UnitType masterDistillerType
= spec().getUnitType("model.unit.masterDistiller");
private static final UnitType pettyCriminalType
= spec().getUnitType("model.unit.pettyCriminal");
public void testCanBuildNext() {
Game game = getGame();
game.setMap(getTestMap(true));
Colony colony = getStandardColony();
// First check with a building that can be fully built with a
// normal colony
Building warehouse = new ServerBuilding(getGame(), colony, depotType);
colony.addBuilding(warehouse);
assertTrue(warehouse.canBuildNext());
warehouse.upgrade();
assertTrue(warehouse.canBuildNext());
warehouse.upgrade();
assertFalse(warehouse.canBuildNext());
assertFalse(warehouse.upgrade());
assertFalse(warehouse.canBuildNext());
// Check whether population restrictions work
// Colony smallColony = getStandardColony(1);
//
// Colony largeColony = getStandardColony(6);
// ...
// Check whether founding fathers work
}
public void testInitialColony() {
Game game = getGame();
game.setMap(getTestMap(true));
Colony colony = getStandardColony();
Building warehouse = colony.getBuilding(warehouseType);
// Is build as depot...
assertTrue(warehouse != null);
assertTrue(warehouse.canBuildNext());
// Check other building...
// Check dock -> only possible if not landlocked...
}
public void testChurch() {
Game game = getGame();
game.setMap(getTestMap(true));
Colony colony = getStandardColony(6);
Unit unit = colony.getUnitList().get(0);
EquipmentType missionary = spec().getEquipmentType("model.equipment.missionary");
assertFalse(chapelType.hasAbility("model.ability.dressMissionary"));
assertFalse(unit.hasAbility("model.ability.dressMissionary"));
assertFalse(unit.canBeEquippedWith(missionary));
Building church = colony.getBuilding(chapelType);
assertTrue(church != null);
assertFalse(colony.hasAbility("model.ability.dressMissionary"));
assertFalse(unit.hasAbility("model.ability.dressMissionary"));
assertFalse(unit.canBeEquippedWith(missionary));
church.upgrade();
assertTrue(church.getType().hasAbility("model.ability.dressMissionary"));
assertTrue(colony.hasAbility("model.ability.dressMissionary"));
assertTrue(unit.hasAbility("model.ability.dressMissionary"));
assertTrue(unit.canBeEquippedWith(missionary));
}
public void testCanAddToBuilding() {
Game game = getGame();
game.setMap(getTestMap(true));
Colony colony = getStandardColony(6);
List<Unit> units = colony.getUnitList();
for (Building building : colony.getBuildings()) {
// schoolhouse is special, see testCanAddToSchool
if (building.canTeach()) continue;
int maxUnits = building.getUnitCapacity();
assertEquals(0, building.getUnitCount());
for (int index = 0; index < maxUnits; index++) {
assertTrue("unable to add unit " + index
+ " to building type " + building.getType(),
building.canAdd(units.get(index)));
building.add(units.get(index));
}
assertFalse("able to add unit " + maxUnits
+ " to building type " + building.getType(),
building.canAdd(units.get(maxUnits)));
for (int index = 0; index < maxUnits; index++) {
building.remove(building.getUnitList().get(0));
}
}
}
/**
* WARNING! This test makes implicit assumptions about the
* schoolhouse that could be invalidated by the
* specification.
*
* TODO: make this more generic.
*/
public void testCanAddToSchool(){
Game game = getGame();
game.setMap(getTestMap(true));
Colony colony = getStandardColony(10);
Iterator<Unit> units = colony.getUnitIterator();
Unit farmer = units.next();
farmer.setType(expertFarmerType);
Unit colonist = units.next();
colonist.setType(freeColonistType);
Unit criminal = units.next();
criminal.setType(pettyCriminalType);
Unit servant = units.next();
servant.setType(indenturedServantType);
Unit indian = units.next();
indian.setType(indianConvertType);
Unit distiller = units.next();
distiller.setType(masterDistillerType);
Unit elder = units.next();
elder.setType(elderStatesmanType);
Unit carpenter = units.next();
carpenter.setType(masterCarpenterType);
// Check school
Building school = colony.getBuilding(schoolType);
assertTrue(school == null);
// build school
colony.addBuilding(new ServerBuilding(getGame(), colony, schoolType));
school = colony.getBuilding(schoolType);
assertTrue(school != null);
// these can never teach
assertFalse("able to add free colonist to Schoolhouse",
school.canAdd(colonist));
assertFalse("able to add petty criminal to Schoolhouse",
school.canAdd(criminal));
assertFalse("able to add indentured servant to Schoolhouse",
school.canAdd(servant));
assertFalse("able to add indian convert to Schoolhouse",
school.canAdd(indian));
assertFalse("able to add elder statesman to Schoolhouse",
school.canAdd(elder));
assertFalse("able to add master distiller to Schoolhouse",
school.canAdd(distiller));
assertTrue("unable to add master farmer to Schoolhouse",
school.canAdd(farmer));
school.add(farmer);
assertFalse("able to add master carpenter to Schoolhouse",
school.canAdd(carpenter));
school.remove(farmer);
school.upgrade();
// these can never teach
assertFalse("able to add free colonist to College",
school.canAdd(colonist));
assertFalse("able to add petty criminal to College",
school.canAdd(criminal));
assertFalse("able to add indentured servant to College",
school.canAdd(servant));
assertFalse("able to add indian convert to College",
school.canAdd(indian));
assertFalse("able to add elder statesman to College",
school.canAdd(elder));
assertTrue("unable to add master distiller to College",
school.canAdd(distiller));
school.add(distiller);
assertTrue("unable to add master farmer to College",
school.canAdd(farmer));
school.add(farmer);
assertFalse("able to add master carpenter to College",
school.canAdd(carpenter));
school.remove(distiller);
school.remove(farmer);
school.upgrade();
assertEquals(school.getType().toString(), school.getType(),
universityType);
// these can never teach
assertFalse("able to add free colonist to University",
school.canAdd(colonist));
assertFalse("able to add petty criminal to University",
school.canAdd(criminal));
assertFalse("able to add indentured servant to University",
school.canAdd(servant));
assertFalse("able to add indian convert to University",
school.canAdd(indian));
assertTrue("unable to add elder statesman to University",
school.canAdd(elder));
school.add(elder);
assertTrue("unable to add master distiller to University",
school.canAdd(distiller));
school.add(distiller);
assertTrue("unable to add master farmer to University",
school.canAdd(farmer));
school.add(farmer);
assertFalse("able to add master carpenter to University",
school.canAdd(carpenter));
school.remove(elder);
school.remove(distiller);
school.remove(farmer);
}
public void testSerialize() {
Game game = getGame();
game.setMap(getTestMap(true));
Colony colony = getStandardColony(6);
for (Building building : colony.getBuildings()) {
try {
StringWriter sw = new StringWriter();
XMLOutputFactory xif = XMLOutputFactory.newInstance();
XMLStreamWriter xsw = xif.createXMLStreamWriter(sw);
building.toXML(xsw, building.getColony().getOwner(), true, true);
xsw.close();
} catch (XMLStreamException e) {
fail();
}
}
}
public void testStockade() {
Game game = getGame();
game.setMap(getTestMap(true));
Set<Modifier> modifierSet;
Colony colony = getStandardColony(2);
modifierSet = colony.getModifierSet("model.modifier.defence");
assertEquals(1, modifierSet.size());
Modifier modifier = modifierSet.iterator().next();
assertEquals(50f, modifier.getValue());
assertEquals(Modifier.Type.PERCENTAGE, modifier.getType());
modifierSet = stockadeType.getModifierSet("model.modifier.defence");
assertEquals(1, modifierSet.size());
modifier = modifierSet.iterator().next();
assertEquals(100f, modifier.getValue());
assertEquals(Modifier.Type.PERCENTAGE, modifier.getType());
assertEquals(0f, stockadeType.applyModifier(0,
"model.modifier.minimumColonySize"));
modifierSet = fortType.getModifierSet("model.modifier.defence");
assertEquals(1, modifierSet.size());
modifier = modifierSet.iterator().next();
assertEquals(150f, modifier.getValue());
assertEquals(Modifier.Type.PERCENTAGE, modifier.getType());
assertEquals(0f, stockadeType.applyModifier(0,
"model.modifier.minimumColonySize"));
modifierSet = fortressType.getModifierSet("model.modifier.defence");
assertEquals(1, modifierSet.size());
modifier = modifierSet.iterator().next();
assertEquals(200f, modifier.getValue());
assertEquals(Modifier.Type.PERCENTAGE, modifier.getType());
assertEquals(0f, stockadeType.applyModifier(0,
"model.modifier.minimumColonySize"));
}
public void testCottonClothProduction() {
Game game = getGame();
game.setMap(getTestMap(true));
Colony colony = getStandardColony(2);
List<Unit> units = colony.getUnitList();
Unit colonist = units.get(0);
Unit worker = units.get(1);
Building weaver = colony.getBuilding(weaverHouseType);
assertEquals(cottonType, weaver.getGoodsInputType());
assertEquals(clothType, weaver.getGoodsOutputType());
assertTrue(colonist.getLocation() instanceof ColonyTile);
assertEquals(plainsType, ((ColonyTile)colonist.getLocation()).getWorkTile().getType());
assertTrue(worker.getLocation() instanceof ColonyTile);
assertEquals(plainsType, ((ColonyTile)worker.getLocation()).getWorkTile().getType());
weaver.add(worker);
assertEquals(worker, weaver.getUnitList().get(0));
colony.addGoods(cottonType, 2);
assertEquals(2, colony.getTotalProductionOf(cottonType));
assertEquals(3, weaver.getTotalProductionOf(clothType));
assertEquals(3, colony.getTotalProductionOf(clothType));
assertEquals(-1, colony.getNetProductionOf(cottonType));
assertEquals(3, colony.getNetProductionOf(clothType));
colonist.setWorkType(cottonType);
colony.invalidateCache();
assertEquals(4, colony.getTotalProductionOf(cottonType));
colony.addGoods(cottonType, 4);
assertEquals(3, colony.getTotalProductionOf(clothType));
assertEquals(1, colony.getNetProductionOf(cottonType));
assertEquals(3, colony.getNetProductionOf(clothType));
}
public void testAutoProduction() {
Game game = getGame();
game.setMap(getTestMap(true));
Colony colony = getStandardColony(1);
Building pasture = colony.getBuilding(countryType);
assertEquals(grainType, pasture.getGoodsInputType());
assertEquals(horsesType, pasture.getGoodsOutputType());
// no horses yet
assertEquals(8, colony.getNetProductionOf(foodType));
assertEquals(0, pasture.getTotalProductionOf(horsesType));
assertEquals(0, colony.getNetProductionOf(horsesType));
assertEquals(0, pasture.getMaximumProductionOf(horsesType));
colony.addGoods(horsesType, 50);
assertEquals(2, pasture.getTotalProductionOf(horsesType));
assertEquals(2, pasture.getMaximumProductionOf(horsesType));
assertEquals(2, colony.getNetProductionOf(horsesType));
colony.addGoods(horsesType, 1);
assertEquals(4, pasture.getTotalProductionOf(horsesType));
assertEquals(4, pasture.getMaximumProductionOf(horsesType));
assertEquals(4, colony.getNetProductionOf(horsesType));
pasture.upgrade();
colony.removeGoods(horsesType);
colony.addGoods(horsesType, 25);
assertEquals(25, colony.getGoodsCount(horsesType));
assertEquals(2, pasture.getTotalProductionOf(horsesType));
assertEquals(2, pasture.getMaximumProductionOf(horsesType));
assertEquals(2, colony.getNetProductionOf(horsesType));
colony.addGoods(horsesType, 1);
assertEquals(26, colony.getGoodsCount(horsesType));
assertEquals(4, pasture.getTotalProductionOf(horsesType));
assertEquals(4, pasture.getMaximumProductionOf(horsesType));
assertEquals(4, colony.getNetProductionOf(horsesType));
colony.addGoods(horsesType, 24);
assertEquals(50, colony.getGoodsCount(horsesType));
assertEquals(4, pasture.getTotalProductionOf(horsesType));
assertEquals(4, pasture.getMaximumProductionOf(horsesType));
assertEquals(4, colony.getNetProductionOf(horsesType));
colony.addGoods(horsesType, 1);
assertEquals(51, colony.getGoodsCount(horsesType));
// no more than half the surplus production!
assertEquals(4, pasture.getTotalProductionOf(horsesType));
assertEquals(6, pasture.getMaximumProductionOf(horsesType));
assertEquals("Horse production should equal food surplus.",
colony.getNetProductionOf(foodType),
colony.getNetProductionOf(horsesType));
}
public void testTownhallProduction() {
Game game = getGame();
game.setMap(getTestMap(true));
Colony colony = getStandardColony(6);
Player owner = colony.getOwner();
Unit colonist = colony.getUnitList().get(0);
Unit statesman = colony.getUnitList().get(1);
statesman.setType(elderStatesmanType);
Building building = colony.getBuilding(townHallType);
GoodsType bellsType = spec().getGoodsType("model.goods.bells");
Set<Modifier> modifiers = colony.getModifierSet("model.goods.bells");
assertEquals(1, modifiers.size());
Modifier bellsModifier = modifiers.iterator().next();
assertEquals(Modifier.Type.ADDITIVE, bellsModifier.getType());
assertEquals(1.0f, bellsModifier.getValue());
assertEquals("Wrong initial bell production",
(int) bellsModifier.getValue(),
building.getTotalProductionOf(bellsType));
building.add(colonist);
// 3 from the colonist
assertEquals(3, building.getUnitConsumption(colonist));
// 3 from the colonist + 1
assertEquals("Wrong bell production", 4,
building.getTotalProductionOf(bellsType));
FoundingFather jefferson = spec().getFoundingFather("model.foundingFather.thomasJefferson");
modifiers = jefferson.getModifierSet("model.goods.bells");
assertEquals(1, modifiers.size());
bellsModifier = modifiers.iterator().next();
owner.addFather(jefferson);
assertTrue(colony.getOwner().getModifierSet("model.goods.bells")
.contains(bellsModifier));
// The colony does not contain the bellsModifier, only the player...
assertFalse(colony.getModifierSet("model.goods.bells")
.contains(bellsModifier));
// ...but the Building.getModifierSet() routine does pull in the
// player modifiers.
assertTrue(building.getProductionModifiers(bellsType, freeColonistType)
.contains(bellsModifier));
assertEquals(3, building.getUnitConsumption(colonist));
// 3 from the colonist + 50% + 1 = 5.5
assertEquals("Wrong bell production with Jefferson", 5,
building.getTotalProductionOf(bellsType));
building.add(statesman);
assertEquals(3, building.getUnitConsumption(colonist));
assertEquals(6, building.getUnitConsumption(statesman));
// 3 + 6 + 50% + 1 = 14
assertEquals("Wrong bell production with Jefferson", 14,
building.getTotalProductionOf(bellsType));
setProductionBonus(colony, 2);
assertEquals(5, building.getUnitConsumption(colonist));
assertEquals(10, building.getUnitConsumption(statesman));
// 5 + 10 + 50% + 1 = 23
assertEquals("Wrong bell production with Jefferson and +2 production bonus",
23, building.getTotalProductionOf(bellsType));
Building newspaper = new ServerBuilding(getGame(), colony, newspaperType);
colony.addBuilding(newspaper);
assertEquals(5, building.getUnitConsumption(colonist));
assertEquals(10, building.getUnitConsumption(statesman));
// 5 + 10 + 50% + 1 + 100% = 47
assertEquals("Wrong bell production with Jefferson, newspaper and +2 production bonus",
47, building.getTotalProductionOf(bellsType));
}
public void testPrintingPressBonus() {
Game game = getGame();
game.setMap(getTestMap(true));
Colony colony = getStandardColony(6);
Unit unit = colony.getUnitList().get(0);
Building building = colony.getBuilding(townHallType);
int bellProduction = building.getTotalProductionOf(bellsType);
int expectBellProd = 1;
assertEquals("Wrong initial bell production",expectBellProd,bellProduction);
Building printingPress = new ServerBuilding(getGame(), colony, printingPressType);
colony.addBuilding(printingPress);
bellProduction = building.getTotalProductionOf(bellsType);
expectBellProd = 1;
assertEquals("Wrong bell production with printing press",expectBellProd,bellProduction);
building.add(unit);
bellProduction = building.getTotalProductionOf(bellsType);
expectBellProd = 6; // 1 initial plus 3 from the colonist + 2 from printing press
assertEquals("Wrong final bell production",expectBellProd,bellProduction);
}
public void testNewspaperBonus() {
Game game = getGame();
game.setMap(getTestMap(true));
Colony colony = getStandardColony(6);
Unit unit = colony.getUnitList().get(0);
Building building = colony.getBuilding(townHallType);
int bellProduction = building.getTotalProductionOf(bellsType);
int expectBellProd = 1;
assertEquals("Wrong initial bell production",expectBellProd,bellProduction);
Building newspaper = new ServerBuilding(getGame(), colony, newspaperType);
colony.addBuilding(newspaper);
bellProduction = building.getTotalProductionOf(bellsType);
expectBellProd = 2;
assertEquals("Wrong bell production with newspaper",expectBellProd,bellProduction);
building.add(unit);
bellProduction = building.getTotalProductionOf(bellsType);
expectBellProd = 8; // 1 initial plus 3 from the colonist + 4 from newspaper
assertEquals("Wrong final bell production",expectBellProd,bellProduction);
}
public void testUnitConsumption() {
Game game = getGame();
game.setMap(getTestMap(true));
Colony colony = getStandardColony(4);
Unit unit = colony.getUnitList().get(0);
for (Building building : colony.getBuildings()) {
GoodsType outputType = building.getGoodsOutputType();
if (outputType == null) continue;
for (UnitType type : spec().getUnitTypeList()) {
if (!building.getType().canAdd(type)
|| !type.isAvailableTo(colony.getOwner())) continue;
unit.setType(type);
int productivity = building.getUnitConsumption(unit);
int expected = building.getType().getBasicProduction();
if (type == building.getExpertUnitType()) {
expected = 6;
} else if (type == indenturedServantType) {
expected = 2;
} else if (type == indianConvertType) {
expected = 1;
} else if (type == pettyCriminalType) {
expected = 1;
}
if (expected != building.getType().getBasicProduction()) {
assertFalse("ModifierSet should not be empty!",
type.getModifierSet(outputType.getId()).isEmpty());
}
assertEquals("Wrong productivity for " + type, expected,
productivity);
}
}
}
public void testToolsMusketProduction() {
Game game = getGame();
game.setMap(getTestMap(true));
Colony colony = getStandardColony(8);
List<Unit> units = colony.getUnitList();
// make sure there are enough goods to get started
//colony.addGoods(spec().getGoodsType("model.goods.food"), 100);
colony.addGoods(spec().getGoodsType("model.goods.ore"), 100);
// make sure no penalties apply
colony.addGoods(spec().getGoodsType("model.goods.bells"),
Colony.LIBERTY_PER_REBEL * 3);
colony.updatePopulation(0);
Building smithy = colony.getBuilding(blacksmithType);
smithy.add(units.get(0));
smithy.add(units.get(1));
Building armory = new ServerBuilding(game, colony, armoryType);
colony.addBuilding(armory);
armory.add(units.get(2));
armory.add(units.get(3));
assertEquals(3, smithy.getType().getBasicProduction());
assertEquals(6, smithy.getTotalProductionOf(toolsType));
assertEquals(3, armory.getType().getBasicProduction());
assertEquals(6, armory.getTotalProductionOf(musketsType));
smithy.upgrade();
armory.upgrade();
assertEquals(6, smithy.getType().getBasicProduction());
assertEquals(12, smithy.getTotalProductionOf(toolsType));
assertEquals(6, armory.getType().getBasicProduction());
assertEquals(12, armory.getTotalProductionOf(musketsType));
// make sure we can build factory level buildings
colony.getOwner().addFather(spec().getFoundingFather("model.foundingFather.adamSmith"));
smithy.upgrade();
armory.upgrade();
assertEquals(6, smithy.getType().getBasicProduction());
assertEquals(18, smithy.getTotalProductionOf(toolsType));
assertEquals(6, armory.getType().getBasicProduction());
assertEquals("According to bug report #3430371, the arsenal does not enjoy "
+ "the usual factory level production bonus of 50%",
12, armory.getTotalProductionOf(musketsType));
}
}