/*
* Datei: FitDrehRichtung.java
* Autor(en): Lukas K�nig
* Java-Version: 6.0
* Erstellt: 05.10.2009
*
* (c) Lukas K�nig, die Datei unterliegt der LGPL
* -> http://www.gnu.de/lgpl-ger.html
*/
package fmg.fmg8.endlAutomat.fitness;
import java.util.HashMap;
import fmg.fmg8.umgebung2D.Roboter;
import fmg.fmg8.umgebung2D.Vektor2D;
import fmg.fmg8.umgebung2D.dynWaende.GrZahnr;
/**
* Implementiert eine Fitness abh�ngig von der Drehrichtung zweier Zahnr�der.
* Ben�tigt die Umgebung "grosseZahnraeder.bmp" und die dynamischen W�nde
* "GrosseZahnraeder.class".
*
* @author Lukas K�nig
*/
public class FitnessDrehRicht implements FitnessVerfahren {
/**
* Speichert zu jedem Roboter den Standort, an dem er zum Zeitpunkt der
* letzten Fitnessberechnung war.
*/
private HashMap<Roboter, String> alteAkteurOrte;
/**
* Konstruktor.
*/
public FitnessDrehRicht() {
super();
this.alteAkteurOrte = new HashMap<Roboter, String>();
}
/**
* Gibt zur�ck, in welchem Quadranten sich ein Roboter befindet
* ("NW", "NO", "SW" oder "SO").
*
* @param rob Der Roboter, dessen Positionierung bestimmt werden soll.
*
* @return Der Quadrant des Roboters.
*/
private String quadrant(final Roboter rob) {
Vektor2D mitte = rob.getUmg().getDynWaende()[221].mittelpunkt();
Vektor2D robPos = rob.getPosition();
String quadrant = "";
if (robPos.x > mitte.x && robPos.y > mitte.y) {
quadrant = "SO";
}
if (robPos.x > mitte.x && robPos.y <= mitte.y) {
quadrant = "NO";
}
if (robPos.x <= mitte.x && robPos.y > mitte.y) {
quadrant = "SW";
}
if (robPos.x <= mitte.x && robPos.y <= mitte.y) {
quadrant = "NW";
}
return quadrant;
}
/**
* Gibt zur�ck, ob der �bergang von Quadrant quad1 nach Quadrant quad2
* im Uhrzeigersinn erfolgte.
*
* @param quad1 Der erste Quadrant.
* @param quad2 Der zweite Quadrant.
*
* @return Ob der �bergang im Uhrzeigersinn erfolgte. Falls der Sprung
* von quad1 nach quad2 nicht m�glich ist (z.B. "SO => NW"), wird
* ein RuntimeError geworfen. Falls quad1.equals(quad2) gilt,
* wird ebenfalls ein RuntimeError geworfen.
*/
private boolean isUhrzSinn(
final String quad1,
final String quad2) {
if (quad1.equals("NW")) {
if (quad2.equals("SW")) {
return false;
}
if (quad2.equals("NO")) {
return true;
}
}
if (quad1.equals("NO")) {
if (quad2.equals("NW")) {
return false;
}
if (quad2.equals("SO")) {
return true;
}
}
if (quad1.equals("SO")) {
if (quad2.equals("NO")) {
return false;
}
if (quad2.equals("SW")) {
return true;
}
}
if (quad1.equals("SW")) {
if (quad2.equals("SO")) {
return false;
}
if (quad2.equals("NW")) {
return true;
}
}
throw new RuntimeException("Quadrantensprung nicht moeglich.");
}
/**
* Methode zum Berechnen der tempor�ren Fitness eines Roboters.
*
* @param rob Der Roboter.
*
* @return Den tempor�ren Fitnesswert f�r den aktuellen Zustand des
* Roboters.
*/
@Override
public int fitness(final Roboter rob) {
String altQuad = this.alteAkteurOrte.get(rob);
String neuQuad = this.quadrant(rob);
this.alteAkteurOrte.put(rob, this.quadrant(rob));
int fitDreh = 0;
// Kollisionen
int fitKoll = (int) ((double) rob.getAnzUnfaelle()
* rob.getPars().getAbzugUnfall().doubleValue());
rob.resetAnzUnf();
// Aus Collision avoidance (nur MOVE-Teil):
int bef0 = ((Integer) rob.getBefehle().get(0)).intValue();
String befehl0 = fmg.fmg8.umgebung2D.Konstanten.BEF[bef0].toUpperCase();
int fitCollAvoid = 1;
if (!befehl0.equals("MOV")) {
fitCollAvoid -= 1;
}
// Falls kein Quadrantenwechsel stattgefunden hat, keine weitere Rechn.
if (altQuad == neuQuad || altQuad == null) {
return fitDreh + fitCollAvoid - fitKoll;
}
if (((GrZahnr) rob.getUmg().getWandDynamik()).isUhrzgrSinn()
== this.isUhrzSinn(altQuad, neuQuad)) {
fitDreh += 5;
} else {
fitDreh -= 0;
}
return fitDreh + fitCollAvoid - fitKoll;
}
}