Package fmg.fmg8.umgebung2D

Source Code of fmg.fmg8.umgebung2D.Umgebung

/*
* Datei:            Umgebung.java
* Autor(en):        Lukas K�nig
* Java-Version:     6.0
* Erstellt (vor): 05.05.2007
*
* (c) Lukas K�nig, die Datei unterliegt der LGPL
* -> http://www.gnu.de/lgpl-ger.html
*/

package fmg.fmg8.umgebung2D;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Random;
import java.util.Set;
import fmg.fmg8.endlAutomat.RobCode;
import fmg.fmg8.endlAutomat.conditions.Condition;
import fmg.fmg8.endlAutomat.translator.Translator;
import fmg.fmg8.graphVis.DargestellterGraph;
import fmg.fmg8.graphVis.darstellungsModi.DarstModEA;
import fmg.fmg8.graphVis.graph.Knoten;
import fmg.fmg8.graphVis.zeichenModi.Geometrie2D;
import fmg.fmg8.graphVis.zeichenModi.PfeilMaster;
import fmg.fmg8.graphVis.zeichenModi.Polygon2D;
import fmg.fmg8.sonstiges.SonstMeth;
import fmg.fmg8.statistik.Parametersatz;
import fmg.fmg8.umgebung2D.dynWaende.Dynamik;

/**
* Repr�sentiert ein Feld, auf dem Roboter fahren k�nnen.
*
* @author Lukas K�nig
*/
public class Umgebung extends Observable {

    /**
     * Das Feld. <code>false</code> bedeutet, dass kein Hindernis auf dem
     * Koordinatenpunkt ist, <code>true</code> ist ein normales Hindernis.
     */
    private byte[][] feld;

    /**
     * Die Roboter auf dem Feld.
     */
    private ArrayList<Roboter> akteure;

    /**
     * F�r jeden Akteur eine Liste von Pixeln, die seine letzte Position
     * bezeichnen.
     */
    private ArrayList<Vektor2D[]> akteurPunkte;
   
    /**
     * Die aktuell zu den Robotern dargestellten Informationstexte.
     */
    private ArrayList<String> akteurTexte;
   
    /**
     * Der Zufallsgenerator.
     */
    private Random rand;
   
    /**
     * Die Parameter.
     */
    private Parametersatz pars;

    /**
     * @return Returns the pars.
     */
    public Parametersatz getPars() {
        return this.pars;
    }

    /**
     * Der neu gesetzte Pixel.
     */
    private Pixel neuerPixel;
   
    /**
     * Flag, ob Simulation l�uft.
     */
    private boolean simLaeuft;
   
    /**
     * Liste von Gegenst�nden.
     */
    private ArrayList<HashMap<Vektor2D, Object>> gegenstaende;
   
    /**
     * Die Verschiebung der Gegenst�nde.
     */
    private ArrayList<Vektor2D> gegVerschieb;
   
    /**
     * Die Liste der dynamischen W�nde, sortiert nach Farben der W�nde.
     */
    private Polygon2D[] dynWaende;
   
    /**
     * Die Liste der zu den dynamischen W�nden geh�renden
     * Verschiebungsvektoren.
     */
    private Vektor2D[] dynVersch;
   
    /**
     * Die Liste der alten Verschiebungen.
     */
    private Vektor2D[] dynOldVersch;
   
    /**
     * Ob die dynamischen W�nde gesetzt sind.
     */
    private boolean[] dynGesetzt;

    /**
     * Drehwinkel der Objekte.
     */
    private double[] dynDrehWinkel;

    /**
     * Drehwinkel der Objekte.
     */
    private double[] dynDrehWinkelOld;

    /**
     * Drehmittelpunkt relativ zum Zentrum des Objekts.
     */
    private Vektor2D[] dynDrehMittPkt;
   
    /**
     * Horizontaler Verzerrungsfaktor.
     */
    private double[] dynHorFaktor;

    /**
     * Alter horizontaler Verzerrungsfaktor.
     */
    private double[] dynHorFaktorOld;

    /**
     * Vertikaler Verzerrungsfaktor.
     */
    private double[] dynVertFaktor;
   
    /**
     * Alter vertikaler Verzerrungsfaktor.
     */
    private double[] dynVertFaktorOld;
   
    /**
     * Die aktuellen Pixellisten f�r alle dynamischen W�nde.
     */
    private ArrayList<LinkedList<Point>> aktDynPixel;
   
    /**
     * Gibt die Koordinate einer Kollision mit einem Gegenstand an, falls eine
     * solche stattgefunden hat, <code>null</code> sonst.
     */
    private Vektor2D gegKoll;
   
    /**
     * Ob die dynamischen W�nde NICHT gezeichnet werden sollen.
     */
    private boolean dynWaendeIgnor;

    /**
     * Die alternativ als Pixelliste gegebenen dynamischen W�nde (wird im
     * TraceBetrachter-Modus verwendet).
     */
    private List<Point> altDynWaende;

    /**
     * Die Simulation, die zu dieser Umgebung geh�rt.
     */
    private Simulation simulation;
   
    /**
     * Das f�r die Dynamik der W�nde verwendete Objekt.
     */
    private Dynamik wandDynamik;
   
    /**
     * @return Returns the simulation.
     */
    public Simulation getSimulation() {
        return this.simulation;
    }

    /**
     * Initialisiert die Umgebung.
     *
     * @param zufall   Der Zufallsgenerator.
     * @param params   Die Parameter.
     * @param obs      Der Observer dieser Klasse.
     * @param sim      Die Simulation, die zu dieser Umgebung geh�rt.
     * @param wandDyn  Die Wanddynamik f�r diese Umgebung.
     */
    public Umgebung(final Random zufall,
                    final Parametersatz params,
                    final Observer obs,
                    final Simulation sim,
                    final Dynamik wandDyn) {
        int arrGroesse = Byte.MAX_VALUE - Byte.MIN_VALUE + 1;

        this.pars = params;
        if (this.pars.getGraphisch().booleanValue()) {
            this.addObserver(obs);
        }

        this.wandDynamik = wandDyn;
        this.simulation = sim;
       
        this.dynWaendeIgnor = false;
        this.simLaeuft = true;
        this.gegKoll = null;
       
        byte[][] feldPix = params.getFeld();
        this.aktDynPixel = new ArrayList<LinkedList<Point>>(arrGroesse);
        for (int i = 0; i < arrGroesse; i++) {
            this.aktDynPixel.add(null);
        }
       
        this.rand = zufall;
        this.feld = new byte[feldPix.length][feldPix[0].length];
        this.akteure = new ArrayList<Roboter>();
        this.akteurPunkte = new ArrayList<Vektor2D[]>();
        this.akteurTexte = new ArrayList<String>();
        this.gegenstaende = new ArrayList<HashMap<Vektor2D, Object>>();
        this.gegVerschieb = new ArrayList<Vektor2D>();
        this.erzeugeDynWaende(feldPix);
        this.setzeDynWaende();
        this.setzeFeld(Konstanten.FARBE_RAHMEN);
        this.holeGegenstaende();
        this.setzeGgste(Konstanten.FARBE_GGSTD);
       
        if (this.gegenstaende.size() > 0) {
            SonstMeth.log(
                    SonstMeth.LOG_INFO,
                    "Gegenstaende: " + this.gegenstaende.size(),
                    this.pars);
        }
    }
   
    /**
     * Setzt die dynamischen W�nde mit ihren aktuellen Verschiebungen in das
     * Feld, falls dabei keine Kollision auftritt. Gibt zur�ck, ob die Wand
     * verschoben werden konnte. Falls dynamische W�nde ignoriert werden
     * sollen, wird stattdessen die Pixelliste altDynWaende gesetzt.
     */
    private void setzeDynWaende() {
        if (!this.dynWaendeIgnor) {
            for (int i = 0; i < this.dynWaende.length; i++) {
                this.setzeDynWand(i);
            }
        } else {
            this.setzePixelliste(this.altDynWaende);
        }
    }
   
    /**
     * Setzt die wandNum-te dynamische Wand.
     *
     * @param wandNum  Die Nummer der zu setzenden Wand.
     *
     * @return  Ob die Wand gesetzt werden konnte (null = gesetzt,
     *          sonst das erste Pixel, das kollidiert).
     */
    private Point setzeDynWand(final int wandNum) {
        Point alleFrei = null;
       
        if (this.dynWaende[wandNum] != null) {
            // Falls Wand noch nicht gesetzt ist...
            if (!this.dynGesetzt[wandNum]) {
                alleFrei = this.setzeDynWand(
                        wandNum,
                        this.dynWaende[wandNum],
                        this.dynVersch[wandNum],
                        this.dynHorFaktor[wandNum],
                        this.dynVertFaktor[wandNum],
                        this.dynDrehMittPkt[wandNum],
                        this.dynDrehWinkel[wandNum],
                        Konstanten.FARBE_RAHMEN,
                        true,
                        true,
                        false);
                if (alleFrei == null) {
                    this.setzeDynWand(
                            wandNum,
                            this.dynWaende[wandNum],
                            this.dynVersch[wandNum],
                            this.dynHorFaktor[wandNum],
                            this.dynVertFaktor[wandNum],
                            this.dynDrehMittPkt[wandNum],
                            this.dynDrehWinkel[wandNum],
                            Konstanten.FARBE_RAHMEN,
                            true,
                            false,
                            true);
                    this.dynGesetzt[wandNum] = true;
                }
            } else { // Falls Wand schon gesetzt ist...
                // Alte Position tempor�r l�schen.
//                this.setzeDynWand(
//                        wandNum,
//                        this.dynWaende[wandNum],
//                        this.dynOldVersch[wandNum],
//                        this.dynHorFaktorOld[wandNum],
//                        this.dynVertFaktorOld[wandNum],
//                        this.dynDrehMittPkt[wandNum],
//                        this.dynDrehWinkelOld[wandNum],
//                        Konstanten.FARBE_HGND,
//                        true,
//                        false,
//                        false);
                this.setzePixelliste(
                        this.aktDynPixel.get(wandNum),
                        Konstanten.FARBE_HGND,
                        true,
                        false,
                        false,
                        false);
               
                // Wenn neue Position kollisionsfrei m�glich...
                alleFrei = this.setzeDynWand(
                        wandNum,
                        this.dynWaende[wandNum],
                        this.dynVersch[wandNum],
                        this.dynHorFaktor[wandNum],
                        this.dynVertFaktor[wandNum],
                        this.dynDrehMittPkt[wandNum],
                        this.dynDrehWinkel[wandNum],
                        Konstanten.FARBE_RAHMEN,
                        false,
                        true,
                        false);
                 if (alleFrei == null) {
                    // Setze neue Position fest und aktualisiere Versch.
                    this.setzeDynWand(
                            wandNum,
                            this.dynWaende[wandNum],
                            this.dynVersch[wandNum],
                            this.dynHorFaktor[wandNum],
                            this.dynVertFaktor[wandNum],
                            this.dynDrehMittPkt[wandNum],
                            this.dynDrehWinkel[wandNum],
                            Konstanten.FARBE_RAHMEN,
                            true,
                            false,
                            false);
                    this.dynOldVersch[wandNum]
                                      = new Vektor2D(this.dynVersch[wandNum]);
                    this.dynHorFaktorOld[wandNum] = dynHorFaktor[wandNum];
                    this.dynVertFaktorOld[wandNum] = dynVertFaktor[wandNum];
                    this.dynDrehWinkelOld[wandNum] = dynDrehWinkel[wandNum];
                } else {
                    // Setze alte Position fest.
                    this.setzeDynWand(
                            wandNum,
                            this.dynWaende[wandNum],
                            this.dynOldVersch[wandNum],
                            this.dynHorFaktorOld[wandNum],
                            this.dynVertFaktorOld[wandNum],
                            this.dynDrehMittPkt[wandNum],
                            this.dynDrehWinkelOld[wandNum],
                            Konstanten.FARBE_RAHMEN,
                            true,
                            false,
                            false);
                }
            }
        }
       
        return alleFrei;
    }
   
    /**
     * Setzt eine dynamische Wand mit der �bergebenen Verschiebung in das
     * Feld. Gibt zur�ck, ob die Wand kollisionsfrei gesetzt werden konnte.
     *
     * @param wandNum      Die Nummer der zu setzenden Wand.
     * @param wand         Das Wandobjekt, das gesetzt werden soll.
     * @param versch       Die Verschiebung des Objekts.
     * @param farbe        Die Farbe, auf die der Pixel gesetzt werden soll.
     * @param horzFakt     Horizontaler Faktor.
     * @param vertFakt     Vertikaler Faktor.
     * @param drehMittPkt  Drehmittelpunkt.
     * @param drehWinkel   Der Winkel, um den das Objekt gedreht ist.
     * @param setzen       Ob das Pixel in das Feld gesetzt werden soll und
     *                     die Observer informiert werden sollen.
     * @param temp         Ob das Pixel NICHT in die Liste der zu zeichnenden
     *                     Pixel �bernommen werden soll.
     * @param unbed        Wenn setzen true ist und dieser Parameter true ist,
     *                     dann wird das Pixel gesetzt, auch wenn es vorher
     *                     schon dieselbe Farbe hatte.
     *
     * @return  Ob die Wand kollisionsfrei gesetzt werden konnte
     *          (null = gesetzt, sonst das erste Pixel, das kollidiert).
     */
    private Point setzeDynWand(
            final int wandNum,
            final Polygon2D wand,
            final Vektor2D versch,
            final double horzFakt,
            final double vertFakt,
            final Vektor2D drehMittPkt,
            final double drehWinkel,
            final byte farbe,
            final boolean setzen,
            final boolean temp,
            final boolean unbed) {
        Point nichtFrei = null;
        Vektor2D aktPkt;
        Iterator<Vektor2D> it = wand.iterator();
        Vektor2D m = new Vektor2D(
                wand.mittelpunkt().x + versch.x + drehMittPkt.x,
                wand.mittelpunkt().y + versch.y + drehMittPkt.y);
        HashMap<Point, Object> gesetzte = new HashMap<Point, Object>();
        double xAnf, xEnd, yAnf, yEnd;
        double echtXdreh, echtYdreh;
        double cAlpha, sAlpha;
        double xLen, yLen;
        double zwischX, zwischY;
        int zwisch;
       
        while (it.hasNext()) {
            aktPkt = it.next();
            xAnf = m.x + versch.x
                    - horzFakt * (m.x - aktPkt.x)
                    - horzFakt / 2;
            xEnd = xAnf + horzFakt;
            for (double echtX = xAnf; echtX < xEnd; echtX++) {
                yAnf = m.y + versch.y
                        - vertFakt * (m.y - aktPkt.y)
                        - vertFakt / 2;
                yEnd = yAnf + vertFakt;
                for (double echtY = yAnf; echtY < yEnd; echtY++) {
                    cAlpha = Math.cos(drehWinkel);
                    sAlpha = Math.sin(drehWinkel);
                    xLen = echtX - m.x;
                    yLen = echtY - m.y;
                    echtXdreh = cAlpha * xLen - sAlpha * yLen + m.x;
                    echtYdreh = sAlpha * xLen + cAlpha * yLen + m.y;
                 
                    zwisch = 0;
                    while (zwisch < 4) {
                        zwischX = 0;
                        zwischY = 0;
                        if (zwisch == 0) {
                            zwischX = Math.ceil(echtXdreh);
                            zwischY = Math.ceil(echtYdreh);
                        } else if (zwisch == 1) {
                            zwischX = Math.floor(echtXdreh);
                            zwischY = Math.floor(echtYdreh);
                        } else if (zwisch == 2) {
                            zwischX = Math.ceil(echtXdreh);
                            zwischY = Math.floor(echtYdreh);
                        } else { // if (zwisch == 3) {
                            zwischX = Math.floor(echtXdreh);
                            zwischY = Math.ceil(echtYdreh);
                        }
                       
                        if (!gesetzte.containsKey(new Point(
                                (int) zwischX,
                                (int) zwischY))) {
                           
                            if (!this.setzePixel(
                                    (int) zwischX,
                                    (int) zwischY,
                                    farbe,
                                    setzen,
                                    temp,
                                    unbed,
                                    false)) {
                                nichtFrei = new Point(
                                        (int) zwischX,
                                        (int) zwischY);
                            }
                           
                            gesetzte.put(
                                    new Point((int) zwischX, (int) zwischY),
                                    null);
                        }
                       
                        zwisch++;
                    }
                }
            }
        }

        if (this.pars.getAufnSp()
                && nichtFrei == null
                && (farbe == Konstanten.FARBE_RAHMEN)) {
            this.aktDynPixel.set(
                    wandNum,
                    new LinkedList<Point>(gesetzte.keySet()));
        }
       
        return nichtFrei;
    }

    /**
     * Erzeugt alle dynamischen Wandelemente. Dabei wird f�r jede vorkommende
     * dynamische Farbe eine Liste mit Pixeln angelegt, die als gemeinsam
     * verschiebbare Wand interpretiert wird. Die W�nde m�ssen danach mit der
     * Methode <code>setzeDynWaende</code> gesetzt werden.
     *
     * @param feldPix  Das Feld, das als Bitmap eingelesen wurde.
     */
    private void erzeugeDynWaende(final byte[][] feldPix) {
        int arrGroesse = Byte.MAX_VALUE - Byte.MIN_VALUE + 1;
        this.dynWaende = new Polygon2D[arrGroesse];
        this.dynVersch = new Vektor2D[arrGroesse];
        this.dynGesetzt = new boolean[arrGroesse];
        this.dynOldVersch = new Vektor2D[arrGroesse];
        this.dynDrehMittPkt = new Vektor2D[arrGroesse];
        this.dynDrehWinkel = new double[arrGroesse];
        this.dynDrehWinkelOld = new double[arrGroesse];
        this.dynHorFaktor = new double[arrGroesse];
        this.dynVertFaktor = new double[arrGroesse];
        this.dynHorFaktorOld = new double[arrGroesse];
        this.dynVertFaktorOld = new double[arrGroesse];
        int dynFarbe;
       
        // F�r (fast) alle Farben ordne Pixel in Liste mit der Farbnummer an.
        for (int i = 0; i < feldPix.length; i++) {
            for (int j = 0; j < feldPix[0].length; j++) {
                if (feldPix[i][j] != Konstanten.FARBE_HGND
                        && feldPix[i][j] != Konstanten.FARBE_HGND_INP
                        && feldPix[i][j] != Konstanten.FARBE_RAHMEN
                        && feldPix[i][j] != Konstanten.FARBE_INP_GEG
                        && feldPix[i][j] != Konstanten.FARBE_INP_TABU) {
                    dynFarbe = feldPix[i][j] - Byte.MIN_VALUE;
                    if (this.dynWaende[dynFarbe] == null) {
                        this.dynWaende[dynFarbe] = new Polygon2D();
                        this.dynVersch[dynFarbe] = new Vektor2D(0, 0);
                        this.dynOldVersch[dynFarbe] = new Vektor2D(0, 0);
                        this.dynGesetzt[dynFarbe] = false;
                        this.dynDrehMittPkt[dynFarbe]
                                  = new Vektor2D(Vektor2D.NULL_VEKTOR);
                        this.dynDrehWinkel[dynFarbe] = 0;
                        this.dynHorFaktor[dynFarbe] = 1;
                        this.dynVertFaktor[dynFarbe] = 1;
                        this.dynHorFaktorOld[dynFarbe] = 1;
                        this.dynVertFaktorOld[dynFarbe] = 1;
                    }
                    this.dynWaende[dynFarbe].add(new Vektor2D(i, j));
                }
            }
        }
       
        // L�sche Farben, die schon eine andere explizite Verwendung haben.
        for (int i = 0; i < Konstanten.BENUTZTE_FARBEN.length; i++) {
            this.dynWaende[(int) Konstanten.BENUTZTE_FARBEN[i] - Byte.MIN_VALUE]
                           = null;
            this.dynVersch[(int) Konstanten.BENUTZTE_FARBEN[i] - Byte.MIN_VALUE]
                           = null;
        }
       
        int j = 0;
        // Gibt die Nummern der dynamischen W�nde aus.
        for (int i = 0; i < this.dynWaende.length; i++) {
            if (this.dynWaende[i] != null) {
                SonstMeth.log(
                        SonstMeth.LOG_INFO,
                        "Dynamische Wand " + j + " gefunden: " + i,
                        this.pars);
                j++;
            }
        }
    }
   
    /**
     * Verschiebt eine dynamische Wand auf die angegebene Position.
     *
     * @param wandNum  Die zu verschiebende Wand.
     * @param versch   Die Verschiebung.
     *
     * @return  Ob die Wand kollisionsfrei gesetzt werden konnte
     *          (null = gesetzt, sonst das erste Pixel, das kollidiert).
     */
    public Point verschWand(
            final int wandNum,
            final Vektor2D versch) {
        Point nichtFrei;
        this.dynVersch[wandNum].setzeKoord(versch.x, versch.y);
        nichtFrei = this.setzeDynWand(wandNum);
        return nichtFrei;
    }
   
    /**
     * Setzt Verzerrungsfaktoren f�r eine dynamische Wand.
     *
     * @param wandNum  Die Nummer der zu verzerrenden Wand.
     * @param x        Die Verzerrung in X-Richtung.
     * @param y        Die Verzerrung in Y-Richtung.
     *
     * @return  Ob die Wand kollisionsfrei gesetzt werden konnte
     *          (null = gesetzt, sonst das erste Pixel, das kollidiert).
     */        
    public Point verzerrWand(
            final int wandNum,
            final double x,
            final double y) {
        Point nichtFrei;
        if (x < 0 || y < 0) {
            throw new RuntimeException("Verzerrung darf nicht negativ sein: "
                    + new Vektor2D(x, y));
        }
        this.dynHorFaktor[wandNum] = x;
        this.dynVertFaktor[wandNum] = y;
        nichtFrei = this.setzeDynWand(wandNum);
        return nichtFrei;
    }
   
    /**
     * Setze Winkel.
     *
     * @param wandNum  Die Nummer der zu drehenden Wand.
     * @param winkel   Der Drehwinkel in Grad.
     *
     * @return  Ob die Wand kollisionsfrei gesetzt werden konnte
     *          (null = gesetzt, sonst das erste Pixel, das kollidiert).
     */
    public Point dreheWand(
            final int wandNum,
            final double winkel) {
        Point gesetzt;
        this.dynDrehWinkel[wandNum] = winkel * Math.PI / 180;
        gesetzt = this.setzeDynWand(wandNum);
        return gesetzt;
    }
   
    /**
     * Findet alle zusammenh�ngenden Pixel von einem bestimmten Pixel
     * ausgehend, die die Gegenstandfarbe haben, im �bergebenen Feld. Die
     * gefundenen Pixel werden zu der Hashtabelle <code>gegenstand</code>
     * hinzugef�gt.
     *
     * @param x           Startkoordinate x.
     * @param y           Startkoordinate y.
     * @param gegenstand  Die Hashtabelle, in die die Pixel eingef�gt werden.
     * @param feldPix     Das Feld.
     */
    private void findeGgstd(final int x,
                            final int y,
                            final HashMap<Vektor2D, Object> gegenstand,
                            final byte[][] feldPix) {
       
        if (x < 0 || y < 0 || x >= feldPix.length || y >= feldPix[0].length) {
            return;
        }
       
        if (feldPix[x][y] != Konstanten.FARBE_INP_GEG) {
            return;
        }
       
        if (gegenstand.containsKey(new Vektor2D(x, y))) {
            return;
        }
       
        gegenstand.put(new Vektor2D(x, y), null);
       
        for (int i = x - 1; i <= x + 1; i++) {
            for (int j = y - 1; j <= y + 1; j++) {
                if (i != x || j != y) {
                    findeGgstd(i, j, gegenstand, feldPix);
                }
            }
        }
    }
   
    /**
     * Sucht die Gegenst�nde im Feld und erzeugt entsprechende Objekte.
     */
    private void holeGegenstaende() {
        HashMap<Vektor2D, Object> gegenstand;
        Vektor2D neuVek;
        Iterator<HashMap<Vektor2D, Object>> it;
        byte[][] feldPix = this.pars.getFeld();
        boolean gefunden;
        Vektor2D verschiebung;

        for (int j = 0; j < feldPix[0].length; j++) {
            for (int i = 0; i < feldPix.length; i++) {
                if (feldPix[i][j] == Konstanten.FARBE_INP_GEG) {
                    neuVek = new Vektor2D(i, j);
                    gefunden = false;

                    it = this.gegenstaende.iterator();
                    while (it.hasNext()) {
                        gegenstand = it.next();
                        if (gegenstand.containsKey(neuVek)) {
                            gefunden = true;
                            break;
                        }
                    }
                   
                    if (!gefunden) {
                        gegenstand = new HashMap<Vektor2D, Object>();
                        this.findeGgstd(i, j, gegenstand, feldPix);
                        this.gegenstaende.add(gegenstand);
                        verschiebung = new Vektor2D(0, 0);
                        this.gegVerschieb.add(verschiebung);
                    }
                }
            }
        }
    }

    /**
     * Setzt die Gegenst�nde in das Feld.
     *
     * @param farbe  Die Farbe, in der die Gegenst�nde gesetzt werden sollen.
     */
    private void setzeGgste(final byte farbe) {
        Iterator<HashMap<Vektor2D, Object>> it = this.gegenstaende.iterator();
        HashMap<Vektor2D, Object> gegenstand;
       
        while (it.hasNext()) {
            gegenstand = it.next();
            this.setzeGgst(gegenstand, farbe, true, false, false);
        }
    }

    /**
     * Setzt einen einzelnen Gegenstand in das Feld.
     *
     * @param ggst    Der zu setzende Gegenstand.
     * @param farbe   Die Farbe des Gegenstands.
     * @param setzen  Ob der Gegenstand in das Feld gesetzt werden soll.
     * @param temp    Ob tempor�r gesetzt werden soll.
     * @param unbed   Ob unbedingt gesetzt werden soll.
     *
     * @return  Ob der Gegenstand ohne Kollision gesetzt werden kann.
     */
    private boolean setzeGgst(final HashMap<Vektor2D, Object> ggst,
                              final byte farbe,
                              final boolean setzen,
                              final boolean temp,
                              final boolean unbed) {
        boolean alleFrei = true;
        Vektor2D aktVek;
        Iterator<Vektor2D> it = ggst.keySet().iterator();
        while (it.hasNext()) {
            aktVek = (Vektor2D) it.next();
            alleFrei = alleFrei & this.setzePixel((int) aktVek.x,
                                                  (int) aktVek.y,
                                                  farbe,
                                                  setzen,
                                                  temp,
                                                  unbed,
                                                  false);
        }
       
        return alleFrei;
    }
   
    /**
     * Setzt die Pixel des Feldes.
     *
     * @param farbe  Die zu setzende Farbe f�r Rahmenpixel.
     */
    private void setzeFeld(final byte farbe) {
        byte[][] feldPix = this.pars.getFeld();
        for (int j = 0; j < feldPix[0].length; j++) {
            for (int i = 0; i < feldPix.length; i++) {
                if (feldPix[i][j] == 0) {
                    this.setzePixel(i, j, farbe, true, false, false, false);
                }
            }
        }
    }

    /**
     * F�gt einen Roboter zur Liste der Roboter hinzu, wenn er nicht
     * kollidiert.
     *
     * @param roboter  Der hinzuzuf�gende Roboter.
     *
     * @return Ob der Roboter hinzugef�gt wurde.
     */
    public boolean hinzuRobot(final Roboter roboter) {
        byte farbe;
        String text = "";
       
        if (this.pars.getFeld()[(int) roboter.getPosition().x]
                               [(int) roboter.getPosition().y]
                == Konstanten.FARBE_INP_TABU) {
            return false;
        }
       
        if (roboter.isSelektiert()) {
            farbe = Konstanten.FARBE_SEL;
        } else {
            farbe = Konstanten.FARBE_ROB;
        }

        Vektor2D[] eckpunkte = new Vektor2D[roboter.getEckPunkte().length];
        for (int i = 0; i < eckpunkte.length; i++) {
            eckpunkte[i] = new Vektor2D(50, 50);
        }

        this.akteure.add(roboter);
        this.akteurPunkte.add(eckpunkte);
        this.akteurTexte.add(text);
        if (this.setzeRobWennMoegl(roboter, true, farbe, text)) {
            return true;
        } else {
            this.akteure.remove(roboter);
            this.akteurPunkte.remove(eckpunkte);
            this.akteurTexte.remove(text);
            return false;
        }
    }

    /**
     * F�gt einen Roboter an eine zuf�llige Stelle in der Umgebung ein.
     *
     * @param rob  Der einzuf�gende Roboter.
     */
    public void hinzuRobotRand(final Roboter rob) {
        rob.setPosition(new Vektor2D(this.rand.nextDouble() * this.ausdX(),
                                   this.rand.nextDouble() * this.ausdY()));
        rob.setBlickRicht(this.rand.nextDouble() * 360);
       
        while (!this.hinzuRobot(rob)) {
            rob.setPosition(new Vektor2D(this.rand.nextDouble() * this.ausdX(),
                                       this.rand.nextDouble() * this.ausdY()));
            rob.setBlickRicht(this.rand.nextDouble() * 360);
        }
    }

    /**
     * Versetzt einen Roboter zuf�llig im Feld. Tabu-Felder werden nicht
     * besetzt.
     *
     * @param rob  Der zu versetzende Roboter.
     */
    public void setzeRobotRand(final Roboter rob) {
        boolean gesetzt = false;
        Vektor2D vek;
       
        while (!gesetzt) {
            vek = new Vektor2D(
                    this.rand.nextDouble() * this.ausdX(),
                    this.rand.nextDouble() * this.ausdY());
           
            if (this.pars.getFeld()[(int) vek.x][(int) vek.y]
                    != Konstanten.FARBE_INP_TABU) {
                gesetzt = rob.setPos(
                        vek.x,
                        vek.y,
                        false);
            } else {
                gesetzt = false;
            }
           
            gesetzt = gesetzt && rob.setBlck(this.rand.nextDouble() * 360);
        }
    }

    /**
     * Leert das aktuelle Feld.
     */
    public void leereFeld() {
        for (int i = 0; i < this.feld.length; i++) {
            for (int j = 0; j < this.feld[0].length; j++) {
                this.setzePixel(i,
                                j,
                                Konstanten.FARBE_HGND,
                                true,
                                false,
                                false,
                                false);
            }
        }
       
        this.setzeFeld(Konstanten.FARBE_RAHMEN);
    }

    /**
     * Entfernt den Roboter, falls er bereits gezeichnet war, NUR aus der
     * graphischen Darstellung.
     *
     * @param robot  Der zu entfernende Roboter.
     * @param temp   Ob das Pixel NICHT in die Liste der zu zeichnenden Pixel
     *               aufgenommen werden soll.
     */
    public void entferneRoboter(final Roboter robot,
                                final boolean temp) {
        if (this.akteure.contains(robot)) {
            this.setzeRobWennMoegl(robot, true, Konstanten.FARBE_HGND, "");
        }
    }

    /**
     * Entfernt den Roboter, falls er bereits gezeichnet war, aus der
     * graphischen Darstellung UND aus der Liste der darzustellenden Roboter.
     *
     * @param robot  Der zu entfernende Roboter.
     *
     * @return  Ob der Roboter gel�scht wurde oder nicht vorhanden war.
     */
    public boolean loescheRoboter(final Roboter robot) {
        if (this.akteure.contains(robot)) {
            this.entferneRoboter(robot, true);
            this.akteure.remove(robot);
            return true;
        } else {
            return false;
        }
    }
   
    /**
     * |=|   1 2 3
     *  =      4
     * |=|   5 6 7.
     *
     * @param nummer  Segnum.
     * @param lu      Koordinate des linken unteren Punkts.
     * @param ro      Koordinate des rechten oberen Punkts.
     * @param setzen  Ob gesetzt (oder gel�scht) werden soll.
     */
    private void setzeSegment(final int nummer,
            final Vektor2D lu,
            final Vektor2D ro,
            final boolean setzen) {
       
        Vektor2D lu2 = new Vektor2D(lu.x, ro.y);
        Vektor2D ro2 = new Vektor2D(ro.x, lu.y);
       
        byte farbe;
       
        if (setzen) {
            farbe = Konstanten.FARBE_DURCHLAESSIG;
        } else {
            farbe = Konstanten.FARBE_HGND;
        }
       
        if (nummer == 1) {
            this.setzeLinie(lu2.x, (ro2.y + lu2.y) / 2, lu2.x, ro2.y,
                            farbe, true, false, false, true);
        } else if (nummer == 2) {
            this.setzeLinie(lu2.x, ro2.y, ro2.x, ro2.y,
                            farbe, true, false, false, true);
        } else if (nummer == 3) {
            this.setzeLinie(ro2.x, (ro2.y + lu2.y) / 2, ro2.x, ro2.y,
                            farbe, true, false, false, true);
        } else if (nummer == 4) {
            this.setzeLinie(lu2.x, (lu2.y + ro2.y) / 2,
                            ro2.x, (lu2.y + ro2.y) / 2,
                            farbe, true, false, false, true);
        } else if (nummer == 5) {
            this.setzeLinie(lu2.x, (lu2.y + ro2.y) / 2, lu2.x, lu2.y,
                            farbe, true, false, false, true);
        } else if (nummer == 6) {
            this.setzeLinie(lu2.x, lu2.y, ro2.x, lu2.y,
                            farbe, true, false, false, true);
        } else if (nummer == 7) {
            this.setzeLinie(ro2.x, (lu2.y + ro2.y) / 2, ro2.x, lu2.y,
                            farbe, true, false, false, true);
        }
    }
   
    /**
     * Setzt oder l�scht einen Buchstaben im Feld.
     *
     * @param buchstabe   Der zu setzende Buchstabe.
     * @param lu  Koordinate des linken unteren Punkts.
     * @param ro  Koordinate des rechten oberen Punkts.
     * @param setzen      Ob der Buchstabe gesetzt (true) oder gel�scht
     *                    (false) werden soll.
     */
    private void setzeBuchstabe(final char buchstabe,
                                final Vektor2D lu,
                                final Vektor2D ro,
                                final boolean setzen) {
        if (buchstabe == '0') {
            this.setzeSegment(1, lu, ro, setzen);
            this.setzeSegment(2, lu, ro, setzen);
            this.setzeSegment(3, lu, ro, setzen);
            this.setzeSegment(7, lu, ro, setzen);
            this.setzeSegment(6, lu, ro, setzen);
            this.setzeSegment(5, lu, ro, setzen);
        } else if (buchstabe == '1') {
            this.setzeSegment(3, lu, ro, setzen);
            this.setzeSegment(7, lu, ro, setzen);
        } else if (buchstabe == '2') {
            this.setzeSegment(2, lu, ro, setzen);
            this.setzeSegment(4, lu, ro, setzen);
            this.setzeSegment(6, lu, ro, setzen);
            this.setzeSegment(3, lu, ro, setzen);
            this.setzeSegment(5, lu, ro, setzen);
        } else if (buchstabe == '3') {
            this.setzeSegment(2, lu, ro, setzen);
            this.setzeSegment(4, lu, ro, setzen);
            this.setzeSegment(6, lu, ro, setzen);
            this.setzeSegment(3, lu, ro, setzen);
            this.setzeSegment(7, lu, ro, setzen);
        } else if (buchstabe == '4') {
            this.setzeSegment(1, lu, ro, setzen);
            this.setzeSegment(3, lu, ro, setzen);
            this.setzeSegment(4, lu, ro, setzen);
            this.setzeSegment(7, lu, ro, setzen);
        } else if (buchstabe == '5') {
            this.setzeSegment(2, lu, ro, setzen);
            this.setzeSegment(4, lu, ro, setzen);
            this.setzeSegment(6, lu, ro, setzen);
            this.setzeSegment(1, lu, ro, setzen);
            this.setzeSegment(7, lu, ro, setzen);
        } else if (buchstabe == '6') {
            this.setzeSegment(2, lu, ro, setzen);
            this.setzeSegment(4, lu, ro, setzen);
            this.setzeSegment(6, lu, ro, setzen);
            this.setzeSegment(1, lu, ro, setzen);
            this.setzeSegment(5, lu, ro, setzen);
            this.setzeSegment(7, lu, ro, setzen);
        } else if (buchstabe == '7') {
            this.setzeSegment(2, lu, ro, setzen);
            this.setzeSegment(3, lu, ro, setzen);
            this.setzeSegment(7, lu, ro, setzen);
        } else if (buchstabe == '8') {
            this.setzeSegment(1, lu, ro, setzen);
            this.setzeSegment(2, lu, ro, setzen);
            this.setzeSegment(3, lu, ro, setzen);
            this.setzeSegment(4, lu, ro, setzen);
            this.setzeSegment(5, lu, ro, setzen);
            this.setzeSegment(6, lu, ro, setzen);
            this.setzeSegment(7, lu, ro, setzen);
        } else if (buchstabe == '9') {
            this.setzeSegment(1, lu, ro, setzen);
            this.setzeSegment(2, lu, ro, setzen);
            this.setzeSegment(3, lu, ro, setzen);
            this.setzeSegment(4, lu, ro, setzen);
            this.setzeSegment(6, lu, ro, setzen);
            this.setzeSegment(7, lu, ro, setzen);
        } else if (buchstabe == '-') {
            this.setzeSegment(4, lu, ro, setzen);
        } else if (buchstabe == ',') {
            this.setzeSegment(6, lu, ro, setzen);
        }
    }
   
    /**
     * Setzt einen Text in das Feld.
     *
     * @param text        Der zu setzende Text.
     * @param linksUnten  Die linke untere Koordinate.
     * @param setzen      Ob gesetzt (oder gel�scht) werden soll.
     */
    public void setzeText(final String text,
                          final Vektor2D linksUnten,
                          final boolean setzen) {
        Vektor2D lu = new Vektor2D(linksUnten);
        Vektor2D ro = new Vektor2D(linksUnten.x + Konstanten.TEXT_AUSDEHNUNG.x,
                               linksUnten.y + Konstanten.TEXT_AUSDEHNUNG.y);
        Vektor2D verschiebung = new Vektor2D(Konstanten.TEXT_AUSDEHNUNG.x
                                         + Konstanten.TEXT_AUSDEHNUNG.x / 3,
                                         0);
       
        for (int i = 0; i < text.length(); i++) {
            this.setzeBuchstabe(text.charAt(i), lu, ro, setzen);
           
            lu.x += verschiebung.x;
            lu.y += verschiebung.y;
            ro.x += verschiebung.x;
            ro.y += verschiebung.y;
        }
    }
   
    /**
     * Setzt einen Roboter und gibt zur�ck, ob eine Kollision aufgetreten ist.
     *
     * @param eckP    Die Eckpunkte des Roboters.
     * @param farbe   Die Farbe des Roboters.
     * @param setzen  Ob der Roboter ins normFeld gesetzt werden soll.
     * @param temp    Ob der Roboter nur tempor�r gesetzt, also nicht in die
     *                Liste der zu zeichnenden Pixel aufgenommen werden soll.
     * @param unbed   Ob auch die Pixel gesetzt werden sollen, die schon die
     *                gleiche Farbe haben.
     *               
     * @return        Ob der Roboter ohne Kollision gesetzt werden konnte.
     */
    public boolean setzeRob(final Vektor2D[] eckP,
                            final byte     farbe,
                            final boolean  setzen,
                            final boolean  temp,
                            final boolean  unbed) {
        final Vektor2D mitte = new Vektor2D((eckP[0].x + eckP[3].x) / 2,
                                        (eckP[0].y + eckP[3].y) / 2);
        boolean alleOk = true;

        alleOk = alleOk
        & this.setzeLinie(eckP[0].x, eckP[0].y, eckP[2].x, eckP[2].y,
                          farbe,
                          setzen,
                          temp,
                          unbed,
                          false);
        alleOk = alleOk
        & this.setzeLinie(eckP[2].x, eckP[2].y, eckP[3].x, eckP[3].y,
                          farbe,
                          setzen,
                          temp,
                          unbed,
                          false);
        alleOk = alleOk
        & this.setzeLinie(eckP[3].x, eckP[3].y, eckP[1].x, eckP[1].y,
                          farbe,
                          setzen,
                          temp,
                          unbed,
                          false);
        alleOk = alleOk
        & this.setzeLinie(eckP[1].x, eckP[1].y, eckP[0].x, eckP[0].y,
                          farbe,
                          setzen,
                          temp,
                          unbed,
                          false);
        alleOk = alleOk
        & this.setzeLinie(mitte.x, mitte.y, eckP[0].x, eckP[0].y,
                          farbe,
                          setzen,
                          temp,
                          unbed,
                          false);
        alleOk = alleOk
        & this.setzeLinie(mitte.x, mitte.y, eckP[1].x, eckP[1].y,
                          farbe,
                          setzen,
                          temp,
                          unbed,
                          false);
       
        return alleOk;
    }
   
    /**
     * Verschiebt einen Gegenstand in die angegebene Richtung, falls m�glich.
     *
     * @param xRicht  X-Richtung.
     * @param yRicht  Y-Richtung.
     * @param ggstID  Identifizierung des Gegenstands.
     *
     * @return  Ob der Gegenstand verschoben werden konnte.
     */
    public boolean verschGgstWennMoegl(final double xRicht,
                                        final double yRicht,
                                        final int ggstID) {
        boolean alleFrei = false;
        HashMap<Vektor2D, Object> altGgst = this.gegenstaende.get(ggstID);
        HashMap<Vektor2D, Object> neuGgst = new HashMap<Vektor2D, Object>();
        Set<Vektor2D> ggst = altGgst.keySet();
        Iterator<Vektor2D> it = ggst.iterator();
        Vektor2D aktVek;
        Vektor2D neuVek;
        Vektor2D altVersch = (Vektor2D) this.gegVerschieb.get(ggstID);
        Vektor2D neuVersch;
       
        while (it.hasNext()) {
            aktVek = (Vektor2D) it.next();
            neuVek = new Vektor2D(aktVek.x + xRicht,
                                aktVek.y + yRicht);
            neuGgst.put(neuVek, null);
        }
       
        this.setzeGgst(altGgst, Konstanten.FARBE_HGND, true, true, false);
       
        alleFrei = this.setzeGgst(neuGgst,
                                  Konstanten.FARBE_GGSTD,
                                  false,
                                  true,
                                  false);

        if (alleFrei) { // Alte Punkte endg. l�schen.
            this.setzeGgst(altGgst, Konstanten.FARBE_HGND, true, false, true);
        }
       
        if (alleFrei) { // Neue Punkte endg�ltig setzen.
            this.setzeGgst(neuGgst, Konstanten.FARBE_GGSTD, true, false, false);
           
            neuVersch
                = new Vektor2D(altVersch.x + xRicht, altVersch.y + yRicht);
           
            this.gegenstaende.remove(ggstID);
            this.gegVerschieb.remove(ggstID);
            this.gegenstaende.add(ggstID, neuGgst);
            this.gegVerschieb.add(ggstID, neuVersch);
           
            return true;
        } else { // Alte Punkte endg�ltig setzen.
            this.setzeGgst(altGgst, Konstanten.FARBE_GGSTD, true, true, false);
            return false;
        }
    }
   
    /**
     * Setzt einen Roboter ins Spielfeld.
     *
     * @param robot          Der zu setzende Roboter.
     * @param gegKollIgnore  Ob Kollisionen mit Gegenst�nden ignoriert werden
     *                       sollen.
     * @param farbe          Ob <code>true</code> oder <code>false</code>
     *                       gesetzt werden soll. Pixel �bernommen werden soll.
     * @param text           Ein Informationstext �ber den Roboter.
     *
     * @return  Ob der Roboter ohne Kollision gesetzt werden konnte (alle
     *          Felder m�ssen vorher != farbe gewesen sein; bei diesem
     *          Vergleich ist FarbeTRUE = FarbeSPEZIAL).
     */
    public boolean setzeRobWennMoegl(final Roboter robot,
                                     final boolean gegKollIgnore,
                                     final byte    farbe,
                                     final String  text) {

        boolean alleFrei = true;
        Vektor2D[] neueEcken = robot.getEckPunkte();
        Vektor2D[] zwischenEcken = new Vektor2D[4];
        int indexRob = this.akteure.indexOf(robot);
        Vektor2D[] alteEcken = (Vektor2D[]) this.akteurPunkte.get(indexRob);
        String alterText = (String) this.akteurTexte.get(indexRob);
        byte falseFarb = Konstanten.FARBE_HGND;
        Vektor2D ecke = null;
       
        if (alteEcken != null && alteEcken[0] != null) {
            ecke = new Vektor2D(alteEcken[0]);
        }
       
        if (alteEcken[0] != null) { // Alte Punkte tempor�r l�schen.
            this.setzeRob(alteEcken, falseFarb, true, true, false);
        }

        this.gegKoll = null;
       
        // Neue Punkte probehalber setzen.
        alleFrei = this.setzeRob(neueEcken, farbe, false, true, false);

        /*
         * Kollision mit einem Gegenstand hat stattgefunden und Roboter war
         * bereits gesetzt.
         */
        if (!gegKollIgnore && this.gegKoll != null && alteEcken[0] != null) {
            double verschX = (neueEcken[0].x - alteEcken[0].x);
            double verschY = (neueEcken[0].y - alteEcken[0].y);
            int gegID = 0;
            Iterator<HashMap<Vektor2D, Object>> it
                = this.gegenstaende.iterator();
            while (it.hasNext()) {
                if (it.next().containsKey(this.gegKoll)) {
                    break;
                }
                gegID++;
            }
           
            if (this.verschGgstWennMoegl(verschX, verschY, gegID)) {
                for (int i = 0; i < neueEcken.length; i++) {
                    zwischenEcken[i] = alteEcken[i];
                    alteEcken[i] = new Vektor2D(neueEcken[i]);
                }
                alleFrei = this.setzeRobWennMoegl(robot,
                                                  gegKollIgnore,
                                                  farbe,
                                                  text);
                for (int i = 0; i < neueEcken.length; i++) {
                    alteEcken[i] = zwischenEcken[i];
                }
            }
        }

        if (alleFrei && alteEcken[0] != null) { // Alte Punkte endg. l�schen.
            this.setzeRob(alteEcken, falseFarb, true, false, true);
        }
       
        if (alleFrei) { // Neue Punkte endg�ltig setzen.
            this.setzeRob(neueEcken, farbe, true, false, false);
           
            if (alteEcken != null && alteEcken[0] != null) {
                this.setzeText(alterText, ecke, false);
                this.setzeText(text, new Vektor2D(neueEcken[0]), true);
                this.akteurTexte.remove(indexRob);
                this.akteurTexte.add(indexRob, text);
            }
           
            for (int i = 0; i < neueEcken.length; i++) {
                alteEcken[i] = new Vektor2D(neueEcken[i]);
            }
           
            return true;
        } else if (alteEcken[0] != null) { // Alte Punkte endg�ltig setzen.
            this.setzeRob(alteEcken, farbe, true, true, false);
            this.setzeText(alterText, ecke, true);
           
            return false;
        } else { // Keine alten Punkte vorhanden - Roboter war nicht gesetzt.
            return false;
        }
    }

    /**
     * Setzt im Feld eine Linie von (x1, y1) nach (x2, y2).<BR>
     * <BR>
     * Seiteneffekte: Falls (mind.) eine Kollision mit einem Gegenstand
     *                stattfindet, werden die Koordinaten des ersten Pixels,
     *                bei dem eine Kollision stattgefunden hat in
     *                <code>this.gegKoll</code> geschrieben.
     *
     * @param x1      X-Koordinate1.
     * @param x2      Y-Koordinate1.
     * @param y1      X-Koordinate2.
     * @param y2      Y-Koordinate2.
     * @param setzen  Gibt an, ob die Linie tats�chlich gesetzt werden soll.
     * @param farbe   Welche Farbe gesetzt werden soll.
     * @param temp    Ob das Pixel NICHT in die Liste der zu zeichnenden
     *                Pixel �bernommen werden soll.
     * @param unbed   Wenn setzen true ist und dieser Parameter true ist,
     *                dann werden die Pixel gesetzt, auch wenn sie vorher
     *                schon dieselbe Farbe hatten.
     * @param passiv  Ob das Pixel nur gesetzt werden soll, wenn das Feld
     *                die Hintergrundfarbe oder die durchl�ssige Farbe hat.
     *
     * @return  Ob ALLE Pixel neu gesetzt wurden, dh. vorher != farbe waren
     *          (bei diesem Vergleich ist FarbeTRUE = FarbeSPEZIAL).
     */
    public boolean setzeLinie(final double  x1,
                              final double  y1,
                              final double  x2,
                              final double  y2,
                              final byte    farbe,
                              final boolean setzen,
                              final boolean temp,
                              final boolean unbed,
                              final boolean passiv) {
        boolean alleFrei = true;

        final int xx1;
        final int yy1;
        final int xx2;
        final int yy2;
        double aktX;
        double aktY;
        int aktXi;
        int aktYi;
        double schrittY;
        double schrittX;
       
        if (Math.abs(x2 - x1) > Math.abs(y2 - y1)) {
            if (x1 < x2) {
                xx1 = (int) Math.round(x1);
                yy1 = (int) Math.round(y1);
                xx2 = (int) Math.round(x2);
                yy2 = (int) Math.round(y2);
            } else {
                xx1 = (int) Math.round(x2);
                yy1 = (int) Math.round(y2);
                xx2 = (int) Math.round(x1);
                yy2 = (int) Math.round(y1);
            }

            schrittY = ((double) yy2 - (double) yy1)
                       / ((double) xx2 - (double) xx1);

            aktY = yy1;
            for (aktX = xx1; aktX <= xx2; aktX++) {
                aktXi = (int) Math.round(aktX);
                aktYi = (int) Math.round(aktY);
               
                alleFrei = alleFrei & this.setzePixel(aktXi,
                                                      aktYi,
                                                      farbe,
                                                      setzen,
                                                      temp,
                                                      unbed,
                                                      passiv);
               
                aktY = aktY + schrittY;
            }
        } else {
            if (y1 < y2) {
                xx1 = (int) Math.round(x1);
                yy1 = (int) Math.round(y1);
                xx2 = (int) Math.round(x2);
                yy2 = (int) Math.round(y2);
            } else {
                xx1 = (int) Math.round(x2);
                yy1 = (int) Math.round(y2);
                xx2 = (int) Math.round(x1);
                yy2 = (int) Math.round(y1);
            }

            schrittX = ((double) xx2 - (double) xx1)
                       / ((double) yy2 - (double) yy1);

            aktX = xx1;
            for (aktY = yy1; aktY <= yy2; aktY++) {
                aktXi = (int) Math.round(aktX);
                aktYi = (int) Math.round(aktY);

                alleFrei = alleFrei & this.setzePixel(aktXi,
                                                      aktYi,
                                                      farbe,
                                                      setzen,
                                                      temp,
                                                      unbed,
                                                      passiv);

                aktX = aktX + schrittX;
            }
        }
        return alleFrei;
    }
   
    /**
     * Setzt ein Pixel in das interne Feld.
     *
     * @param x       Die X-Koordinate des zu setzenden Pixel.
     * @param y       Die Y-Koordinate des zu setzenden Pixel.
     * @param farbe   Die Farbe, auf die der Pixel gesetzt werden soll.
     * @param setzen  Ob das Pixel in das Feld gesetzt werden soll und die
     *                Observer informiert werden sollen.
     * @param temp    Ob das Pixel NICHT in die Liste der zu zeichnenden
     *                Pixel �bernommen werden soll.
     * @param unbed   Wenn setzen true ist und dieser Parameter true ist,
     *                dann wird das Pixel gesetzt, auch wenn es vorher schon
     *                dieselbe Farbe hatte.
     * @param passiv  Ob das Pixel nur gesetzt werden soll, wenn das Feld
     *                die Hintergrundfarbe oder die durchl�ssige Farbe hat.
     *              
     * @return  Ob das Pixel ohne Kollision gesetzt werden kann.
     */
    private boolean setzePixel(
            final int     x,
            final int     y,
            final byte    farbe,
            final boolean setzen,
            final boolean temp,
            final boolean unbed,
            final boolean passiv) {
        boolean frei = true;
       
        if (x < 0 || x >= this.feld.length
            || y < 0 || y >= this.feld[0].length
            || (passiv && this.feld[x][y] != Konstanten.FARBE_HGND
                       && this.feld[x][y] != Konstanten.FARBE_DURCHLAESSIG)) {
            return false;
        } else {
            if (((farbe == Konstanten.FARBE_HGND
                || farbe == Konstanten.FARBE_DURCHLAESSIG)
                && this.feld[x][y] == farbe)
            || ((farbe != Konstanten.FARBE_HGND
                && farbe != Konstanten.FARBE_DURCHLAESSIG)
                && (this.feld[x][y] == Konstanten.FARBE_ROB
            || this.feld[x][y] == Konstanten.FARBE_SEL
            || this.feld[x][y] == Konstanten.FARBE_RAHMEN
            || this.feld[x][y] == Konstanten.FARBE_GGSTD))) {
                if (this.feld[x][y] == Konstanten.FARBE_GGSTD
                    && this.gegKoll == null) {
                    this.gegKoll = new Vektor2D(x, y);
                }
               
                frei = false;
            }
        }
       
        if (setzen) {
            if (this.feld[x][y] != farbe || unbed) {
                this.feld[x][y] = farbe;
   
                if (this.pars.getGraphisch().booleanValue() && !temp) {
                    this.neuerPixel = new Pixel(x, y, farbe);
                    this.setChanged();
                    this.notifyObservers();
                }
            }
        }
       
        return frei;
    }
   
    /**
     * Setzt eine Pixelliste als alternative dynamische W�nde. Die Pixel
     * werden gleich und beim Aufruf der Methode alleFelderNeu gezeichnet.
     *
     * @param liste  Die zu setzende Pixelliste.
     */
    public void setAltDynWaende(final List<Point> liste) {
        this.altDynWaende = liste;
        this.alleFelderNeu();
    }

    /**
     * Setzt das neue Pixel auf <code>null</code> als Zeichen f�r die GUI,
     * dass die aktuelle Zeichensession beendet ist.
     */
    public void beendeZeichenSession() {
        this.neuerPixel = null;
        this.setChanged();
        this.notifyObservers();
    }
   
    /**
     * Erzeugt eine Textausgabe des Feldes.
     *
     * @return  Testausgabe.
     */
    public String toString() {
        return SonstMeth.feldAusgabe(this.feld, 8, 17,
                SonstMeth.ZEICHEN_FELD, SonstMeth.PRIORITAET_FELD);
    }

    /**
     * Misst im aktuellen Feld den Wert f�r den durch seine Richtung
     * angegebenen Sensor des angegebenen Roboters.
     *
     * @param robot   Der Roboter, dessen Sensoren berechnet werden.
     * @param sensor  Die Nummer des Sensors, der berechnet werden soll.
     *
     * @return  Der Wert des Sensors.
     */
    public int berSensWerte(final Roboter robot, final int sensor) {
        final Vektor2D[][] sensRichtungen = robot.getAlleAbsSensRicht();
        double entfernung = 0;
        double minEntfernung;
        final int xAlti = (int) Math.round(robot.getPosition().x);
        final int yAlti = (int) Math.round(robot.getPosition().y);
        double x;
        double y;
        int xi;
        int yi;
        double verzerr = this.pars.getVerzerr().doubleValue();
        double konst1 = 1.0 / Math.pow(51.0, 1 / 150.0);
        double konst2 = 255.0 * Math.pow(konst1,
                                         -Konstanten.ROB_AUSDEHNUNG_X / 2.0);
        byte farbe;
        byte letztFarbe;

        if (robot.isSelektiert()) {
            farbe = Konstanten.FARBE_SEL;
        } else {
            farbe = Konstanten.FARBE_ROB;
        }

        this.entferneRoboter(robot, false);

        int i = sensor;
        minEntfernung = Double.MAX_VALUE;
        for (int j = 0; j < sensRichtungen.length; j++) {
            x = robot.getPosition().x;
            y = robot.getPosition().y;
            xi = (int) Math.round(x);
            yi = (int) Math.round(y);
            letztFarbe = Konstanten.FARBE_HGND;
            while (xi >= 0 && xi < this.feld.length
                   && yi >= 0 && yi < this.feld[0].length
                   && feld[xi][yi] != Konstanten.FARBE_ROB
                   && feld[xi][yi] != Konstanten.FARBE_SEL
                   && feld[xi][yi] != Konstanten.FARBE_RAHMEN) {
                x = x + sensRichtungen[j][i].x;
                y = y + sensRichtungen[j][i].y;
                xi = (int) Math.round(x);
                yi = (int) Math.round(y);
                if (xi >= 0 && xi < this.feld.length
                    && yi >= 0 && yi < this.feld[0].length) {
                    letztFarbe = feld[xi][yi];
                }
            }
            if (xi < 0 || xi >= this.feld.length
                || yi < 0 || yi >= this.feld[0].length) {
                entfernung = Double.MAX_VALUE;
            } else {
                entfernung = this.entfernung(xi, yi, xAlti, yAlti);
                if (letztFarbe == Konstanten.FARBE_SEL
                    || letztFarbe == Konstanten.FARBE_ROB) {

                    entfernung = entfernung * Konstanten.ROBOTER_KONST;
                }
                if (i == Konstanten.BEAMER - 1) {
                    entfernung = entfernung * Konstanten.BEAMER_KONST;
                }
            }
            if (entfernung < minEntfernung) {
                minEntfernung = entfernung;
            }
        }

        int indexRob = this.akteure.indexOf(robot);
        this.setzeRobWennMoegl(robot,
                               true,
                               farbe,
                               this.akteurTexte.get(indexRob));

        return (int) Math.round(konst2
                                    * Math.pow(konst1,
                                               minEntfernung
                                                   / verzerr));
    }

    /**
     * Berechnet die Entfernung zwischen zwei Punkten.
     *
     * @param x1  Punkt1, X.
     * @param y1  Punkt1, Y.
     * @param x2  Punkt2, X.
     * @param y2  Punkt2, Y.
     *
     * @return  Die Entfernung zwischen den Punkten.
     */
    private double entfernung(final double x1, final double y1,
                              final double x2, final double y2) {
        return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
    }

    /**
     * @return Returns the akteure.
     */
    public ArrayList<Roboter> getAkteure() {
        return this.akteure;
    }

    /**
     * Gibt die Ausdehnung des Feldes in X-Richtung zur�ck.
     *
     * @return  Die Ausdehnung des Feldes in X-Richtung.
     */
    public int ausdX() {
        return this.feld.length;
    }

    /**
     * Gibt die Ausdehnung des Feldes in Y-Richtung zur�ck.
     *
     * @return  Die Ausdehnung des Feldes in Y-Richtung.
     */
    public int ausdY() {
        return this.feld[0].length;
    }

    /**
     * Gibt eine Liste von Robotern zur�ck, die sich am n�chsten zum
     * angegebenen Punkt befinden. Insbesondere enth�lt die Liste einen
     * Roboter, wenn er sich genau auf dem Punkt befindet.
     * Die Koordinate bezieht sich dabei auf das NORMIERTE Feld.
     * Die Liste ist sortiert bez�glich der Entfernung zum Punkt. Der n�chste
     * Roboter hat Index 0 -- Im Fall, dass ein Roboter direkt auf dem Punkt
     * steht, hat er also den Index 0.
     *
     * @param x       X-Koordinate
     * @param y       Y-Koordinate
     * @param anzahl  Wie viele Roboter zur�ckgegeben werden sollen.
     *
     * @return  Die Roboter, die sich im Darstellungsfeld am n�chsten zu der
     *          Koordinate befinden.
     */
    public Roboter[] holeNahe(final double x, final double y,
            final int anzahl) {
        Roboter[] naechste = new Roboter[anzahl];
        Roboter[] alle = new Roboter[this.akteure.size()];
        double[] alleEntf = new double[this.akteure.size()];
        Iterator<Roboter> it = this.akteure.iterator();
        double min;
        int minInd;
        int i = 0;
       
        while (it.hasNext()) {
            alle[i] = it.next();
            alleEntf[i] = this.entfernung(x, y,
                                          alle[i].getPosition().x,
                                          alle[i].getPosition().y);
            i++;
        }

        for (int j = 0; j < anzahl; j++) {
            min = Double.MAX_VALUE;
            minInd = 0;
           
            for (int k = 0; k < alleEntf.length; k++) {
                if (alleEntf[k] < min) {
                    min = alleEntf[k];
                    minInd = k;
                }
            }
           
            naechste[j] = alle[minInd];
            alleEntf[minInd] = Double.MAX_VALUE;
        }
       
        return naechste;
    }
   
    /**
     * Gibt den Roboter zur�ck, der sich am n�chsten zum
     * angegebenen Punkt befindet. Die Koordinate bezieht sich dabei auf das
     * NORMIERTE Feld.
     *
     * @param x  X-Koordinate
     * @param y  Y-Koordinate
     * @param nicht  Welche Roboter nicht zur�ckgegeben werden sollen.
     *
     * @return  Der Roboter, der sich im normierten Feld am n�chsten zu der
     *          Koordinate befindet.
     */
    public Roboter holeNahenNorm(final int x, final int y,
            final HashSet<Roboter> nicht) {
        final double xx = (double) x;
        final double yy = (double) y;
        double minEntf = Double.MAX_VALUE;
        double aktEntf;
        Iterator<Roboter> it = this.akteure.iterator();
        Roboter naechster = null;
        Roboter aktRob;

        while (it.hasNext()) {
            aktRob = it.next();
            aktEntf = this.entfernung(xx, yy,
                    aktRob.getPosition().x, aktRob.getPosition().y);
            if (aktEntf < minEntf) {
                if (!nicht.contains(aktRob)) {
                    minEntf = aktEntf;
                    naechster = aktRob;
                }
           }
        }

        return naechster;
    }

    /**
     * Gibt die kleinste noch nicht von einem der aktuellen Graphen verwendete
     * ID zur�ck.
     *
     * @return  Die kleinste noch nicht verwendete ID.
     */
    public int kleinsteFreieID() {
        int kleinste = 0;
        Iterator<Roboter> it = this.getAkteure().iterator();
        Roboter aktEur;
       
        while (it.hasNext()) {
            aktEur = it.next();
            if (kleinste <= aktEur.getId()) {
                kleinste = aktEur.getId() + 1;
            }
        }
       
        return kleinste;
    }

    /**
     * �bernimmt die �bergebenen Roboter (als Robotercode) in die Population.
     * Dabei werden zuerst die bereits auf dem Feld vorhandenen Roboter mit
     * den neuen Automaten versehen (wobei versucht wird, die IDs zu matchen);
     * falls es weniger neue als alte Roboter gibt, werden die �brigen vom
     * Spielfeld gel�scht; falls es mehr neue als alte Roboter gibt, werden
     * entsprechend viele neu erzeugt.
     *
     * Die alten Roboter, deren Code durch neuen ersetzt werden soll, werden
     * als "H�llen" bezeichnet.
     *
     * @param semiPop  Die (m�glicherweise wegen doppelten IDs ung�ltige)
     *                 Population von neuen Robotern im Robotercode-Format.
     */
    protected void uebernimmPop(final ArrayList<RobCode> semiPop) {
        Iterator<Roboter> itAkt;
        Roboter rob;
        RobCode robC;
        Iterator<RobCode> itSemi;
        Translator[] stdTrans
            = new Translator[semiPop.get(0).getVCodes().length];
       
        for (int i = 0; i < stdTrans.length; i++) {
            stdTrans[i]
                = fmg.fmg8.endlAutomat.translator.Konstanten.STD_TRANSL_TR;
        }
       
        itAkt = this.akteure.iterator();
        itSemi = semiPop.iterator();
        while (itAkt.hasNext() && itSemi.hasNext()) {
            rob = itAkt.next();
            robC = itSemi.next();
                       
            rob.erzTransAusSeqs(robC.getTStdCodes(), stdTrans, false);
            rob.erzeugeAusSequenzen(robC.getVCodes(), rob.getConds(),
                    rob.getTranslatoren(), false);
           
            rob.setTransCodes(SonstMeth.listSeqAusStrings(robC.getTCodes()));
            rob.setVerhCodes(SonstMeth.listSeqAusStrings(robC.getVCodes()));
            rob.setFitness(robC.getFitness());
//          rob.setConds(rob2.getConds()); TODO
        }
    }

    /**
     * @return Returns the feld.
     */
    public byte[][] getFeld() {
        return this.feld;
    }

    /**
     * Setzt ein Flag, dass keine Simulation l�uft.
     */
    public void beendeSimulation() {
        this.simLaeuft = false;
    }
   
    /**
     * @return Returns the neuerPixel.
     */
    public Pixel getNeuerPixel() {
        return this.neuerPixel;
    }

    /**
     * @return Returns the simLaeuft.
     */
    public boolean isSimLaeuft() {
        return this.simLaeuft;
    }

    /**
     * Setzt eine Pixelliste in das Feld (Kollisionen werden nicht beachtet,
     * die Pixel werden unbedingt gesetzt.
     *
     * @param liste  Die zu setzenden Pixel.
     */
    private void setzePixelliste(final List<Point> liste) {
        if (liste != null) {
            for (Point p : liste) {
                this.setzePixel(p.x, p.y, umgebung2D.Konstanten.FARBE_RAHMEN,
                        true, false, true, false);
            }
        }
    }

    /**
     * Setzt eine Pixelliste in das Feld.
     *
     * @param liste  Die zu setzenden Pixel.
     * @param farbe   Die Farbe, auf die der Pixel gesetzt werden soll.
     * @param setzen  Ob das Pixel in das Feld gesetzt werden soll und die
     *                Observer informiert werden sollen.
     * @param temp    Ob das Pixel NICHT in die Liste der zu zeichnenden
     *                Pixel �bernommen werden soll.
     * @param unbed   Wenn setzen true ist und dieser Parameter true ist,
     *                dann wird das Pixel gesetzt, auch wenn es vorher schon
     *                dieselbe Farbe hatte.
     * @param passiv  Ob das Pixel nur gesetzt werden soll, wenn das Feld
     *                die Hintergrundfarbe oder die durchl�ssige Farbe hat.
     *              
     * @return  Ob das Pixel ohne Kollision gesetzt werden kann.
     */
    private boolean setzePixelliste(
            final List<Point> liste,
            final byte    farbe,
            final boolean setzen,
            final boolean temp,
            final boolean unbed,
            final boolean passiv) {
        boolean alleGesetzt = true;
       
        if (liste != null) {
            for (Point p : liste) {
                alleGesetzt = alleGesetzt & this.setzePixel(
                        p.x,
                        p.y,
                        farbe,
                        setzen,
                        temp,
                        unbed,
                        passiv);
            }
        }
       
        return alleGesetzt;
    }

    /**
     * Setzt alle Pixel-Felder der Umgebung neu.
     */
    public void alleFelderNeu() {
        Iterator<Roboter> it;
        byte farbe;
        Roboter aktRob;
       
        for (int i = 0; i < feld.length; i++) {
            for (int j = 0; j < feld[0].length; j++) {
                this.setzePixel(i, j, Konstanten.FARBE_HGND,
                        true, false, false, false);
            }
        }
       
        this.setzeFeld(Konstanten.FARBE_RAHMEN);
        this.setzeGgste(Konstanten.FARBE_GGSTD);
        this.setzeDynWaende();
       
        it = this.akteure.iterator();
        while (it.hasNext()) {
            aktRob = it.next();
            if (aktRob.isSelektiert()) {
                farbe = Konstanten.FARBE_SEL;
            } else {
                farbe = Konstanten.FARBE_ROB;
            }
            this.setzeRobWennMoegl(aktRob, true, farbe, "");
        }
    }
   
    /**
     * Setzt einige zentrale Eigenschaften eines Roboters, identifiziert durch
     * seine ID.
     *
     * @param id         Die ID des Roboters.
     * @param vAutStd    Die Verhaltensautomaten in Standardkodierung.
     * @param vAut       Die echten Verhaltensautomatencodes.
     * @param tAutStd    Die Translatoren in Standardkodierung.
     * @param tAut       Die echten Translatorencodes.
     * @param koord      Die Koordinaten des Roboters.
     * @param winkel     Der Winkel der Blickrichtung.
     * @param fitness    Die Fitnesswerte des Roboters.
     * @param conds      Die Bedingungen.
     *
     * @return  Ob alle Eigenschaften zugewiesen werden konnten.
     */
    public boolean setEigRobUnbed(
            final int         id,
            final String[]    vAutStd,
            final String[]    vAut,
            final String[]    tAutStd,
            final String[]    tAut,
            final Vektor2D    koord,
            final double      winkel,
            final int[]       fitness,
            final Condition[] conds) {
        Roboter aktRob;
        Iterator<Roboter> it = this.akteure.iterator();
        Translator[] stdTrans = new Translator[tAutStd.length];
       
        for (int i = 0; i < stdTrans.length; i++) {
            stdTrans[i]
                   = fmg.fmg8.endlAutomat.translator.Konstanten.STD_TRANSL_TR;
        }
       
        while (it.hasNext()) {
           aktRob = it.next();
           if (aktRob.getId() == id) {
               aktRob.erzTransAusSeqs(tAutStd, stdTrans, false);
               aktRob.erzeugeAusSequenzen(vAutStd, conds, null, false);
               aktRob.setRobUnbed(koord.x, koord.y, winkel);
               aktRob.setFitness(fitness);
               aktRob.setTransCodes(SonstMeth.listSeqAusStrings(tAut));
               aktRob.setVerhCodes(SonstMeth.listSeqAusStrings(vAut));
               break;
           }
        }
       
        return true;
    }

    /**
     * @return Returns the gegVerschieb.
     */
    public ArrayList<Vektor2D> getGegVerschieb() {
        return this.gegVerschieb;
    }
   
    /**
     * Gibt die Summe der Fitnesswerte aller Roboter der Population zur�ck.
     *
     * @return  Die Durchschnittswerte der Fitnesswerte der Population.
     */
    public String getDurchFit() {
        Roboter rob = this.akteure.get(0);
        int vAnzahl = 0;
        double[] fitness = new double[rob.vAuts().length];
        String s = "";
       
        Iterator<Roboter> it = this.akteure.iterator();
        while (it.hasNext()) {
            rob = it.next();
           
            for (int i = 0; i < rob.vAuts().length; i++) {
                fitness[i] += rob.getFitness()[i];
                vAnzahl++;
            }
        }

        for (int i = 0; i < rob.vAuts().length - 1; i++) {
            fitness[i] /= vAnzahl;
            s += Math.round(fitness[i] * 10) / 10 + ", ";
            vAnzahl++;
        }
       
        s += Math.round(fitness[rob.vAuts().length - 1] * 10) / 10 / vAnzahl;
       
        return s;
    }

    /**
     * Der konstante Modus "bester".
     */
    private final String modusBester = "best";

    /**
     * Der konstante Modus "einzelRoboter".
     */
    private final String modusEinzelRob = "rob";

    /**
     * @param modus  Der Modus.
     * @return  Das BufferedImage des Feldes.
     */
    private BufferedImage erzeugeFeldBild(
            final String[] str,
            final String modus) {
        BufferedImage buffImgFeld = new BufferedImage(
                this.feld.length,
                this.feld[0].length,
                BufferedImage.TYPE_INT_RGB);
        Graphics2D g = buffImgFeld.createGraphics();
        Roboter bester = this.getBester();
        int radius = (int) ((double) 60 * this.pars.getVerzerr());
       
        // Feld zeichnen.
        for (int i = 0; i < feld.length; i++) {
            for (int j = 0; j < feld[0].length; j++) {
                if (feld[i][j] == Konstanten.FARBE_ROB) {
                    g.setColor(Konstanten.C_VORDERGRUND);
                } else if (feld[i][j] == Konstanten.FARBE_RAHMEN) {
                    g.setColor(Konstanten.C_RAHMEN);
                } else if (feld[i][j] == Konstanten.FARBE_GGSTD) {
                    g.setColor(Konstanten.C_GEGENSTAND);
                } else if (feld[i][j] == Konstanten.FARBE_HGND) {
                    g.setColor(Konstanten.C_HINTERGRUND);
                } else if (feld[i][j] == Konstanten.FARBE_SEL) {
                    g.setColor(Konstanten.C_SPEZIAL);
                } else if (feld[i][j] == Konstanten.FARBE_DURCHLAESSIG) {
                    g.setColor(Konstanten.C_DURCHLAESSIG);
                } else {
                    g.setColor(Color.white);
                }
                g.drawLine(i, j, i, j);
            }
        }

        if (this.pars.getAutomatInGIFModus().equalsIgnoreCase(
                this.modusBester)) {
            g.setColor(Color.RED);
            g.setStroke(new BasicStroke(
                    2,
                    BasicStroke.CAP_ROUND,
                    BasicStroke.JOIN_ROUND));
            g.drawOval(
                    (int) bester.getPosition().x - radius / 2,
                    (int) bester.getPosition().y - radius / 2,
                    radius,
                    radius);
        } else if (this.pars.getAutomatInGIFModus().startsWith(
                this.modusEinzelRob)) {
            int num = Integer.parseInt(
                    this.pars.getAutomatInGIFModus().split(":")[1]);
            g.setColor(Color.RED);
            g.setStroke(new BasicStroke(
                    2,
                    BasicStroke.CAP_ROUND,
                    BasicStroke.JOIN_ROUND));
            g.drawOval(
                    (int) this.getAkteure().get(num).getPosition().x
                        - radius / 2,
                    (int) this.getAkteure().get(num).getPosition().y
                        - radius / 2,
                    radius,
                    radius);
        }

        // Feld beschriften.
        g.setColor(Color.BLUE);
        for (int i = 0; i < str.length; i++) {
            g.drawString(str[i], 10, 20 + 15 * i);
        }
       
        return buffImgFeld;
    }
   
    /**
     * @param modus  Der Modus.
     * @return  Das BufferedImage des Automaten.
     */
    private BufferedImage erzeugeAutBild(final String modus) {
        Roboter bester = this.getBester();
        BufferedImage buffImgAut = null;
        Graphics2D g;
       
        if (this.pars.getAutomatInGIFModus().equalsIgnoreCase(
                this.modusBester)
                || this.pars.getAutomatInGIFModus().startsWith(
                        this.modusEinzelRob)) {
            if (this.pars.getAutomatInGIFModus().startsWith(
                        this.modusEinzelRob)) {
                int num = Integer.parseInt(
                        this.pars.getAutomatInGIFModus().split(":")[1]);
                bester = this.akteure.get(num);
            }
            PfeilMaster master = new PfeilMaster(this.pars);
            Knoten aktKnot = bester.getAktZustand();
            if (aktKnot == null) {
                aktKnot = bester.getVAut()[0].holeStartzustand();
            }
            DargestellterGraph darstellung = new DarstModEA(
                    0,
                    0,
                    this.pars.getFeld()[0].length - 100,
                    this.pars.getFeld()[0].length - 100).erzeuge(
                            bester.vAuts()[0], aktKnot);
            List<Object> zeichenListe = master.graph(darstellung);
            buffImgAut = Geometrie2D.erzBuffImgAusObjekten(
                    zeichenListe,
                    this.pars);
           
            Polygon2D rahmen = Geometrie2D.rahmen(zeichenListe);
           
            BufferedImage zwisch = new BufferedImage(
                    this.pars.getFeld()[0].length,
                    this.pars.getFeld()[0].length,
                    BufferedImage.TYPE_INT_RGB);
           
            g = zwisch.createGraphics();
            g.setColor(Color.white);
            g.fillRect(0, 0, zwisch.getWidth(), zwisch.getHeight());
            g.drawImage(
                    buffImgAut,
                    0,
                    (int) ((zwisch.getHeight() - rahmen.getBoundingBox().getHoehe()) / 2),
                    null);
            g.setColor(Color.BLUE);
            g.drawString(
                    "Bester Roboter: "
                    + bester.getId()
                    + " ("
                    + bester.getFitString()
                    + ")",
                    90,
                    20);
            buffImgAut = zwisch;
        }
       
        return buffImgAut;
    }
   
    /**
     * Gibt ein Bild des aktuellen Feldes zur�ck.
     *
     * @param str  Links oben zu setzende Strings.
     *
     * @return  Ein Bild des aktuellen Feldes.
     */
    public BufferedImage erzeugeBild(final String[] str) {
        Graphics2D g;
        BufferedImage gesamtImg, autImg, feldImg;
       
        feldImg = this.erzeugeFeldBild(str, this.pars.getAutomatInGIFModus());
        autImg = this.erzeugeAutBild(this.pars.getAutomatInGIFModus());
       
        if (feldImg == null) {
            return autImg;
        }
        if (autImg == null) {
            return feldImg;
        }
       
        gesamtImg = new BufferedImage(
                feldImg.getWidth() + autImg.getWidth(),
                Math.max(feldImg.getHeight(), autImg.getHeight()),
                BufferedImage.TYPE_INT_RGB);
        g = gesamtImg.createGraphics();
        g.drawImage(
                feldImg,
                0,
                0,
                feldImg.getWidth(),
                feldImg.getHeight(),
                null);
        g.drawImage(
                autImg,
                feldImg.getWidth(),
                0,
                autImg.getWidth(),
                autImg.getHeight(),
                null);
       
        return gesamtImg;
    }

    /**
     * @return  Der bester Roboter.
     */
    private Roboter getBester() {
        long maxFit = Long.MIN_VALUE;
        Roboter bester = null;
       
        for (Roboter r : this.akteure) {
            if (r.getFitSum() > maxFit) {
                maxFit = r.getFitSum();
                bester = r;
            }
        }
       
        return bester;
    }
   
    /**
     * Setzt die Positionen der Roboter zuf�llig und setzt die Fitness zur�ck.
     */
    public void resetRobs() {
        ArrayList<Roboter> akt = new ArrayList<Roboter>(this.akteure.size());
        akt.addAll(this.akteure);
       
        for (Roboter r : akt) {
            r.resetAnzUnf();
            for (int i = 0; i < r.getVAut().length; i++) {
                r.resetAktivZyk(i);
                r.setFitness(i, 0);
            }
            this.loescheRoboter(r);
            this.hinzuRobotRand(r);
        }
    }
   
    /**
     * @return Returns the dynDrehMittPkt.
     */
    public Vektor2D[] getDynDrehMittPkte() {
        return this.dynDrehMittPkt;
    }

    /**
     * @param drehMittPkt  The dynDrehMittPkt to set.
     * @param wandNum      Die Nummer der Wand.
     */
    public void setDynDrehMittPkt(
            final int wandNum,
            final Vektor2D drehMittPkt) {
        this.dynDrehMittPkt[wandNum] = drehMittPkt;
    }

    /**
     * @return Returns the dynWaende.
     */
    public Polygon2D[] getDynWaende() {
        return this.dynWaende;
    }

    /**
     * @return Returns the dynVersch.
     */
    public Vektor2D[] getDynVersch() {
        return this.dynVersch;
    }

    /**
     * @return Returns the dynDrehWinkel.
     */
    public double[] getDynDrehWinkel() {
        return this.dynDrehWinkel;
    }
   
    /**
     * @return Returns the aktDynPixel.
     */
    public ArrayList<LinkedList<Point>> getAktDynPixel() {
        return this.aktDynPixel;
    }

    /**
     * @param ignorieren  The dynWaendeIgnor to set.
     */
    public void setDynWaendeIgnor(final boolean ignorieren) {
        this.dynWaendeIgnor = ignorieren;
    }

    /**
     * @return Returns the wandDynamik.
     */
    public Dynamik getWandDynamik() {
        return this.wandDynamik;
    }
}
TOP

Related Classes of fmg.fmg8.umgebung2D.Umgebung

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.