/******************************************************************************* * Copyright (c) 2001, 2010 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/epl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Luis Crespo * - Added getCurrentScore() * Flemming N. Larsen * - Bugfix: scoreDeath() incremented totalFirsts even if the robot was * already a winner, where scoreWinner() has already been called previously * - Added constructor that takes an additonal RobotResults that must be * copied into this object and added the getResults() in order to support * the replay feature * - Changed the survivalScore and totalSurvivalScore fields to be integers * - Renamed method names and removed unused methods * - Ordered all methods more naturally * - Added methods for getting current scores * - Optimizations * - Removed damage parameter from the scoreRammingDamage() method, as the * damage is constant and defined by Rules.ROBOT_HIT_DAMAGE and the score * of hitting a robot is defined by Rules.ROBOT_HIT_BONUS * Titus Chen * - Bugfix: Initial getResults() method only factored in the most recent * round * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap * Nathaniel Troutman * - Added cleanup() method for cleaning up references to internal classes * to prevent circular references causing memory leaks *******************************************************************************/ package net.sf.robocode.battle.peer; import robocode.BattleResults; import java.util.Map; import java.util.HashMap; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Luis Crespo (contributor) * @author Titus Chen (contributor) * @author Robert D. Maupin (contributor) * @author Nathaniel Troutman (contributor) */ public class RobotStatistics implements ContestantStatistics { private final RobotPeer robotPeer; private int rank; private final int robots; private boolean isActive; private boolean isInRound; private double survivalScore; private double lastSurvivorBonus; private double bulletDamageScore; private double bulletKillBonus; private double rammingDamageScore; private double rammingKillBonus; private Map<String, Double> robotDamageMap; private double totalScore; private double totalSurvivalScore; private double totalLastSurvivorBonus; private double totalBulletDamageScore; private double totalBulletKillBonus; private double totalRammingDamageScore; private double totalRammingKillBonus; private int totalFirsts; private int totalSeconds; private int totalThirds; public RobotStatistics(RobotPeer robotPeer, int robots) { super(); this.robotPeer = robotPeer; this.robots = robots; } public RobotStatistics(RobotPeer robotPeer, int robots, BattleResults results) { this(robotPeer, robots); totalScore = results.getScore(); totalSurvivalScore = results.getSurvival(); totalLastSurvivorBonus = results.getLastSurvivorBonus(); totalBulletDamageScore = results.getBulletDamage(); totalBulletKillBonus = results.getBulletDamageBonus(); totalRammingDamageScore = results.getRamDamage(); totalRammingKillBonus = results.getRamDamageBonus(); totalFirsts = results.getFirsts(); totalSeconds = results.getSeconds(); totalThirds = results.getThirds(); } public void setRank(int rank) { this.rank = rank; } public void initialize() { resetScores(); isActive = true; isInRound = true; } public void resetScores() { robotDamageMap = null; survivalScore = 0; lastSurvivorBonus = 0; bulletDamageScore = 0; bulletKillBonus = 0; rammingDamageScore = 0; rammingKillBonus = 0; } public void generateTotals() { totalSurvivalScore += survivalScore; totalLastSurvivorBonus += lastSurvivorBonus; totalBulletDamageScore += bulletDamageScore; totalBulletKillBonus += bulletKillBonus; totalRammingDamageScore += rammingDamageScore; totalRammingKillBonus += rammingKillBonus; totalScore = totalBulletDamageScore + totalRammingDamageScore + totalSurvivalScore + totalRammingKillBonus + totalBulletKillBonus + totalLastSurvivorBonus; isInRound = false; } public double getTotalScore() { return totalScore; } public double getTotalSurvivalScore() { return totalSurvivalScore; } public double getTotalLastSurvivorBonus() { return totalLastSurvivorBonus; } public double getTotalBulletDamageScore() { return totalBulletDamageScore; } public double getTotalBulletKillBonus() { return totalBulletKillBonus; } public double getTotalRammingDamageScore() { return totalRammingDamageScore; } public double getTotalRammingKillBonus() { return totalRammingKillBonus; } public int getTotalFirsts() { return totalFirsts; } public int getTotalSeconds() { return totalSeconds; } public int getTotalThirds() { return totalThirds; } public double getCurrentScore() { return bulletDamageScore + rammingDamageScore + survivalScore + rammingKillBonus + bulletKillBonus + lastSurvivorBonus; } public double getCurrentSurvivalScore() { return survivalScore; } public double getCurrentSurvivalBonus() { return lastSurvivorBonus; } public double getCurrentBulletDamageScore() { return bulletDamageScore; } public double getCurrentBulletKillBonus() { return bulletKillBonus; } public double getCurrentRammingDamageScore() { return rammingDamageScore; } public double getCurrentRammingKillBonus() { return rammingKillBonus; } public void scoreSurvival() { if (isActive) { survivalScore += 50; } } public void scoreLastSurvivor() { if (isActive) { int enemyCount = robots - 1; if (robotPeer.getTeamPeer() != null) { enemyCount -= (robotPeer.getTeamPeer().size() - 1); } lastSurvivorBonus += 10 * enemyCount; if (robotPeer.getTeamPeer() == null || robotPeer.isTeamLeader()) { totalFirsts++; } } } public void scoreBulletDamage(String robot, double damage) { if (isActive) { incrementRobotDamage(robot, damage); bulletDamageScore += damage; } } public double scoreBulletKill(String robot) { if (isActive) { double bonus; if (robotPeer.getTeamPeer() == null) { bonus = getRobotDamage(robot) * 0.20; } else { bonus = 0; for (RobotPeer teammate : robotPeer.getTeamPeer()) { bonus += teammate.getRobotStatistics().getRobotDamage(robot) * 0.20; } } bulletKillBonus += bonus; return bonus; } return 0; } public void scoreRammingDamage(String robot) { if (isActive) { incrementRobotDamage(robot, robocode.Rules.ROBOT_HIT_DAMAGE); rammingDamageScore += robocode.Rules.ROBOT_HIT_BONUS; } } public double scoreRammingKill(String robot) { if (isActive) { double bonus; if (robotPeer.getTeamPeer() == null) { bonus = getRobotDamage(robot) * 0.30; } else { bonus = 0; for (RobotPeer teammate : robotPeer.getTeamPeer()) { bonus += teammate.getRobotStatistics().getRobotDamage(robot) * 0.30; } } rammingKillBonus += bonus; return bonus; } return 0; } public void scoreRobotDeath(int enemiesRemaining) { switch (enemiesRemaining) { case 0: if (!robotPeer.isWinner()) { totalFirsts++; } break; case 1: totalSeconds++; break; case 2: totalThirds++; break; } } public void scoreFirsts() { if (isActive) { totalFirsts++; } } public void setInactive() { resetScores(); isActive = false; } public BattleResults getFinalResults() { return new BattleResults(robotPeer.getTeamName(), rank, totalScore, totalSurvivalScore, totalLastSurvivorBonus, totalBulletDamageScore, totalBulletKillBonus, totalRammingDamageScore, totalRammingKillBonus, totalFirsts, totalSeconds, totalThirds); } private double getRobotDamage(String robot) { if (robotDamageMap == null) { robotDamageMap = new HashMap<String, Double>(); } Double damage = robotDamageMap.get(robot); return (damage != null) ? damage : 0; } private void incrementRobotDamage(String robot, double damage) { double newDamage = getRobotDamage(robot) + damage; robotDamageMap.put(robot, newDamage); } public void cleanup() {// Do nothing, for now } public boolean isInRound() { return isInRound; } }