/**
* Copyright (c) 2001-2014 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
*/
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 numberOfRobots;
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;
RobotStatistics(RobotPeer robotPeer, int numberOfRobots) {
super();
this.robotPeer = robotPeer;
this.numberOfRobots = numberOfRobots;
}
public void setRank(int rank) {
this.rank = rank;
}
void reset() {
resetScores();
isActive = true;
isInRound = true;
}
private 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 = robotPeer.isSentryRobot()
? 0
: 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 robotPeer.isSentryRobot()
? 0
: (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 && !robotPeer.isSentryRobot()) {
survivalScore += 50;
}
}
public void scoreLastSurvivor() {
if (isActive && !robotPeer.isSentryRobot()) {
int enemyCount = numberOfRobots - 1;
if (robotPeer.getTeamPeer() != null) {
enemyCount -= (robotPeer.getTeamPeer().size() - 1);
}
lastSurvivorBonus += 10 * enemyCount;
if ((robotPeer.getTeamPeer() == null || robotPeer.isTeamLeader())) {
totalFirsts++;
}
}
}
void scoreBulletDamage(String robot, double damage) {
if (isActive) {
incrementRobotDamage(robot, damage);
bulletDamageScore += damage;
}
}
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;
}
void scoreRammingDamage(String robot) {
if (isActive) {
incrementRobotDamage(robot, robocode.Rules.ROBOT_HIT_DAMAGE);
rammingDamageScore += robocode.Rules.ROBOT_HIT_BONUS;
}
}
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) {
if (!robotPeer.isSentryRobot()) {
switch (enemiesRemaining) {
case 0:
if (!robotPeer.isWinner()) {
totalFirsts++;
}
break;
case 1:
totalSeconds++;
break;
case 2:
totalThirds++;
break;
}
}
}
public void scoreFirsts() {
if (isActive && !robotPeer.isSentryRobot()) {
totalFirsts++;
}
}
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);
}
void cleanup() {// Do nothing, for now
}
public boolean isInRound() {
return isInRound;
}
}