package Balrog;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import net.sf.colossus.common.Constants;
import net.sf.colossus.game.Player;
import net.sf.colossus.server.CustomRecruitBase;
import net.sf.colossus.server.VariantSupport;
import net.sf.colossus.variant.CreatureType;
import net.sf.colossus.variant.MasterBoardTerrain;
import net.sf.colossus.variant.MasterHex;
/**
* Custom class to allow recruitment of Balrog in 6-tower game.
*
* One becomes available in a Player home Tower for every 300 points earned
* by the Player.
*
* @author Romain Dolbeau
*/
public class BalrogRecruitment extends CustomRecruitBase
{
private static final Logger LOGGER = Logger
.getLogger(BalrogRecruitment.class.getName());
private final static int balrogValue = 300;
private final static String balrogPrefix = "Balrog";
@Override
public List<CreatureType> getAllPossibleSpecialRecruiters(
MasterBoardTerrain terrain)
{
// Balrog recruited in Tower, where everything recruit anyway.
return new ArrayList<CreatureType>();
}
/** This one is called from an inner loop in the TerrainRecruitLoader,
* BEFORE the current Variant becomes available through VariantSupport.
* This means we can't enumerate all CreatureType here!!!!
*/
@Override
public List<CreatureType> getAllPossibleSpecialRecruits(
MasterBoardTerrain terrain)
{
return CreatureBalrog.getAllBalrogs();
}
@Override
public List<CreatureType> getPossibleSpecialRecruiters(
MasterHex hex)
{
// Balrog recruited in Tower, where everything recruit anyway.
return new ArrayList<CreatureType>();
}
@Override
public List<CreatureType> getPossibleSpecialRecruits(
MasterHex hex)
{
List<CreatureType> temp = new ArrayList<CreatureType>();
if (hex == null)
{
return temp;
}
// need to update, as we might have earned points in the Engagement
// phase and recruit in the Recruit phase
updateBalrogCount3(hex);
String name = balrogPrefix + hex.getLabel();
List<CreatureType> allBalrogs = CreatureBalrog.getAllBalrogs();
CreatureType balrogType = null;
for (CreatureType bt : allBalrogs)
{
if (bt.getName().equals(name))
{
balrogType = bt;
}
}
if (getCount(balrogType) > 0)
{
temp.add(balrogType);
}
return temp;
}
@Override
public int numberOfRecruiterNeeded(CreatureType recruiter,
CreatureType recruit, MasterHex hex)
{
LOGGER.finest("Called with recruiter " + recruiter + " and recruit " + recruit);
if ((recruit == null) || (recruit instanceof CreatureBalrog))
return 1;
LOGGER.finest("Recruit " + recruit + " isn't a Balrog");
return Constants.BIGNUM;
}
@Override
protected synchronized void initCustomVariant()
{
changeOfTurn(0);
}
@Override
protected void changeOfTurn(int newActivePlayer)
{
Set<MasterHex> towerSet = VariantSupport.getCurrentVariant()
.getMasterBoard().getTowerSet();
// update all Balrogs, as a lost fight may have given points
// to a different Player
for (MasterHex tower : towerSet)
{
updateBalrogCount3(tower);
}
}
private void updateBalrogCount3(MasterHex tower)
{
for (int i = 0; i < 3; i++)
{
try
{
updateBalrogCount(tower);
return;
}
catch (ConcurrentModificationException e)
{
// TODO Fix this properly
LOGGER.info("ConcurrentModificationException while "
+ "doing updateBalrogCount() - ignoring it.");
/*
* This is just a workaround to prevent the game crashing/hanging.
* To fix this properly would involve lot of changes at various
* places for which I right now simply do not have the time.
* Or do not want to spend time.
*
* See the bug report 2855208: "Balrog exception in V0.9.2"
* for details.
*/
}
}
return;
}
/** The magic function that add more Balrogs to the Caretaker when
* players score points goes up.
*/
private void updateBalrogCount(MasterHex tower)
{
Player player = findPlayerWithStartingTower(tower);
if (player == null)
{
LOGGER.finest("CUSTOM: no player info for hex " + tower);
return;
}
if (player.isDead())
{
LOGGER.finest("INIT CUSTOM: player " + player.getName()
+ " is dead - doing nothing for hex " + tower);
return;
}
String creatureName = balrogPrefix + tower.getLabel();
if (!VariantSupport.getCurrentVariant().isCreature(creatureName))
{
LOGGER.severe("CUSTOM: Balrog by the name of " + creatureName
+ " doesn't exist !");
return;
}
CreatureType type = VariantSupport.getCurrentVariant()
.getCreatureByName(creatureName);
int score = player.getScore();
int maxCountShouldBe = (score / balrogValue);
type.setMaxCount(maxCountShouldBe);
adjustAvailableCount(type);
}
private Player findPlayerWithStartingTower(MasterHex tower)
{
//LOGGER.finest("Finding player for tower " + tower);
for (Player player : allPlayers)
{
//LOGGER.finest("Finding tower for player " + player);
MasterHex pst = player.getStartingTower();
//LOGGER.finest("Found tower " + pst + " for player " + player);
if ((pst != null) && (pst.equals(tower)))
{
return player;
}
}
return null;
}
@Override
protected void resetInstance()
{
LOGGER.finest("CUSTOM: resetting instance " + getClass().getName());
resetAllBalrogCounts();
}
protected void resetAllBalrogCounts()
{
LOGGER.finest("CUSTOM: Resetting all Balrog counts");
Set<MasterHex> towerSet = VariantSupport.getCurrentVariant()
.getMasterBoard().getTowerSet();
for (MasterHex tower : towerSet)
{
resetBalrogCount(tower);
}
}
private void resetBalrogCount(MasterHex tower)
{
String name = balrogPrefix + tower.getLabel();
CreatureBalrog cre = (CreatureBalrog)VariantSupport
.getCurrentVariant().getCreatureByName(name);
LOGGER.info("Setting count for " + name + " to 0.");
cre.setMaxCount(0);
setCount(cre, 0, true);
}
}