Package eas.users.demos.tetris.automaticTetris

Source Code of eas.users.demos.tetris.automaticTetris.TetrisEnvAutomatic

/*
* File name:        TetrisEnvAutomatic.java (package eas.users.lukas.demos.tetris.automaticTetris)
* Author(s):        Lukas König
* Java version:     6.0
* Generation date:  17.02.2012 (11:37:57)
*
* (c) This file and the EAS (Easy Agent Simulation) framework containing it
* is protected by Creative Commons by-nc-sa license. Any altered or
* further developed versions of this file have to meet the agreements
* stated by the license conditions.
*
* In a nutshell
* -------------
* You are free:
* - to Share -- to copy, distribute and transmit the work
* - to Remix -- to adapt the work
*
* Under the following conditions:
* - Attribution -- You must attribute the work in the manner specified by the
*   author or licensor (but not in any way that suggests that they endorse
*   you or your use of the work).
* - Noncommercial -- You may not use this work for commercial purposes.
* - Share Alike -- If you alter, transform, or build upon this work, you may
*   distribute the resulting work only under the same or a similar license to
*   this one.
*
* + Detailed license conditions (Germany):
*   http://creativecommons.org/licenses/by-nc-sa/3.0/de/
* + Detailed license conditions (unported):
*   http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en
*
* This header must be placed in the beginning of any version of this file.
*/

package eas.users.demos.tetris.automaticTetris;

import java.io.Serializable;

import eas.math.geometry.Polygon2D;
import eas.math.geometry.Vector2D;
import eas.plugins.standard.visualization.chartPlugin.ChartEvent;
import eas.simulation.Wink;
import eas.startSetup.ParCollection;
import eas.users.demos.tetris.AbstractTetrisAgent;
import eas.users.demos.tetris.TetrisAgentI;
import eas.users.demos.tetris.TetrisAgentJ;
import eas.users.demos.tetris.TetrisAgentL;
import eas.users.demos.tetris.TetrisAgentO;
import eas.users.demos.tetris.TetrisAgentS;
import eas.users.demos.tetris.TetrisAgentT;
import eas.users.demos.tetris.TetrisAgentZ;
import eas.users.demos.tetris.TetrisEnvironment;

/**
* @author Lukas König
*/
public class TetrisEnvAutomatic extends TetrisEnvironment implements Runnable, Serializable {

    /**
     *
     */
    private static final long serialVersionUID = 4571125804876053675L;

    private Bewertung1 bewertung;
   
    public TetrisEnvAutomatic(int ident, ParCollection params) {
        super(ident, params);
        bewertung = new Bewertung1();
    }

    public boolean turnLeft() {
        double angle = this.getAgentAngle(0) - Math.PI / 2;
        if (angle < 0.1) {
            angle = Math.PI * 2;
        }
        return this.setAgentAngle(0, angle);
    }
   
    public boolean sink() {
        Vector2D newpos = new Vector2D(this.getAgentPosition(0));
        newpos.translate(new Vector2D(0, 1));
        boolean worked = this.setAgentPosition(0, newpos);
       
        if (worked) {
            deepness++;
        }
       
        return worked;
    }
   
    public boolean shiftLeft() {
        Vector2D newpos = new Vector2D(this.getAgentPosition(0));
        newpos.translate(new Vector2D(-1, 0));
        return this.setAgentPosition(0, newpos);
    }
   
    public boolean shiftRight() {
        Vector2D newpos = new Vector2D(this.getAgentPosition(0));
        newpos.translate(new Vector2D(1, 0));
        return this.setAgentPosition(0, newpos);
    }
   
    public boolean applyMove(TetrisMove move) {
        if (move.getMove() == TetrisMove.MOVE_LEFT) {return this.shiftLeft();}
        if (move.getMove() == TetrisMove.MOVE_RIGHT) {return this.shiftRight();}
        if (move.getMove() == TetrisMove.MOVE_SINK) {return this.sink();}
        if (move.getMove() == TetrisMove.MOVE_TURN) {return this.turnLeft();}
        return false;
    }

    private boolean[][] oldField = null;

    private void copyFeld(boolean[][] quelle, boolean[][] ziel) {
        for (int i = 0; i < quelle.length; i++) {
            for (int j = 0; j < quelle[0].length; j++) {
                ziel[i][j] = quelle[i][j];
            }
        }
    }
   
    /**
     * Wendet eine Move-Sequenz auf das Feld an.
     *
     * @param seq  Die anzuwendende Sequenz. Es werden die nicht möglichen
     *             Moves herausgelöscht.
     * @return  Die anzahl der gelöschten Zeilen.
     */
    public int applySequence(TetrisMoveSequence seq) {
        TetrisMoveSequence seqNeu = new TetrisMoveSequence();
       
        for (TetrisMove tm : seq) {
            if (applyMove(tm)) {
                seqNeu.add(tm);
            }
        }
       
        seq.clear();
        seq.addAll(seqNeu);
        int lines = this.fixiereAgenten();
        return lines;
    }
   
    public boolean addTile(int tileType) {
        AbstractTetrisAgent nextAgent;
        Vector2D pos = new Vector2D(this.getFeld().length / 2, 2);
        this.removeAgent(0);
       
        switch (tileType) {
        case 0: nextAgent = new TetrisAgentI(0, this, this.getParCollection()); break;
        case 1: nextAgent = new TetrisAgentZ(0, this, this.getParCollection()); break;
        case 2: nextAgent = new TetrisAgentS(0, this, this.getParCollection()); break;
        case 3: nextAgent = new TetrisAgentL(0, this, this.getParCollection()); break;
        case 4: nextAgent = new TetrisAgentJ(0, this, this.getParCollection()); break;
        case 5: nextAgent = new TetrisAgentO(0, this, this.getParCollection()); break;
        case 6: nextAgent = new TetrisAgentT(0, this, this.getParCollection()); break;
        default: nextAgent = null; break;
        }
       
        this.addAgent(nextAgent, pos, Math.PI * 2);
       
        boolean full = false;
        for (int j = 0; j < this.getFeld().length && !full; j++) {
            if (this.getFeld()[j][3]) {
                return false;
            }
        }
       
        return true;
    }
   
    private void senkeKomplettAb() {
        while (this.sink()) {}
    }
   
    public int fixiereAgenten() {
        this.senkeKomplettAb();
        Vector2D aktPos = this.getAgentPosition(0);
        Polygon2D pol = this.getAgentShape(0);
        double angle = this.getAgentAngle(0);
        this.removeAgent(0);
        this.drawTile(pol, aktPos, angle, true);
        return this.deleteLines();
    }
   
    private int deepness;
   
    public double bewerteSequenz(int tileType, TetrisMoveSequence sequenz) {
        double bewertung = 0;

        this.hoehenPunkte = null;
       
        // Altes Feld sichern.
        if (oldField == null) {
            oldField = new boolean[this.getFeld().length][this.getFeld()[0].length];
        }
       
        this.bewertung.setHoeheVorher(this.getFuellHoehe());
        this.bewertung.setLueckenVorher(this.getLueckenSophisticated());
        this.bewertung.setHoehenDiffVorher(this.getHoehenDifferenz());
       
        copyFeld(this.getFeld(), oldField);
        this.addTile(tileType);
        deepness = 0;
        int lines = this.applySequence(sequenz);

        bewertung = this.bewertung.bewerte(this, lines, deepness, tileType);
       
        copyFeld(oldField, this.getFeld());
       
        return bewertung;
    }
   
    public int getFuellHoehe() {
        for (int i = 3; i < this.getFeld()[0].length - 5; i++) {
            for (int j = 0; j < this.getFeld().length; j++) {
                if (this.getFeld()[j][i]) {
                    return this.getFeld()[0].length - i - 1;
                }
            }
        }
       
        return 0;
    }
   
    /**
     * xx
     * xxxxx
     * x xxx
     * x xxx
     * x xxx
     *
     * ==> 3 + 2 = 5.
     *
     * @return
     */
    public int getLueckenSophisticated() {
        int anzahl = 0;
        int zwischAnzahl = 0;
        boolean toggle = true;
        boolean start = false;
        int anzahlLuecken;
       
        for (int j = 0; j < this.getFeld().length; j++) {
            zwischAnzahl = 0;
            start = false;
            anzahlLuecken = 1;
           
            for (int i = this.getFeld()[0].length - 2; i >= 3; i--) {
                if (toggle && !this.getFeld()[j][i]) {
                    anzahl += zwischAnzahl * anzahlLuecken; // Je weiter oben, desto schlimmer.
                    zwischAnzahl = 0;
                    toggle = false;
                    start = true;
//                    anzahlLuecken++;
                }
                if (!toggle && !this.getFeld()[j][i]) {
                    zwischAnzahl++;
                    start = true;
                }
                if (!toggle && this.getFeld()[j][i]) {
                    toggle = true;
                }
                if (start && toggle && this.getFeld()[j][i]) {
                    zwischAnzahl++;
                }
            }
        }
       
        return anzahl;
    }
   
    public int getLueckenSimple() {
        int anzahl = 0;
       
        for (int i = 3; i < this.getFeld()[0].length; i++) {
            for (int j = 0; j < this.getFeld().length; j++) {
                if (!this.getFeld()[j][i]) {
                    if (this.getFeld()[j][i - 1]) {
                        anzahl++;
                    }
                }
            }
        }
       
        return anzahl;
    }
   
    protected Integer[] hoehenPunkte = null;
   
    public int getHoehenDifferenz() {
        int min = Integer.MAX_VALUE;
        int min2 = Integer.MAX_VALUE;
        int max = Integer.MIN_VALUE;
       
        if (hoehenPunkte == null) {
            hoehenPunkte = new Integer[this.getFeld().length];
            for (int i = 0; i < hoehenPunkte.length; i++) {
                for (int j = 0; j < this.getFeld()[0].length; j++) {
                    if (this.getFeld()[i][j]) {
                        hoehenPunkte[i] = this.getFeld()[0].length - j - 1;
                        break;
                    }
                }
            }
        }
       
        for (int i = 0; i < hoehenPunkte.length - 1; i++) {
            if (max < hoehenPunkte[i]) {
                max = hoehenPunkte[i];
            }
            if (min > hoehenPunkte[i]) {
                min2 = min;
                min = hoehenPunkte[i];
            }
        }

        return max - min2;
    }
   
    /**
     * @param zweitschlucht  Ob die größte oder zweitgrößte Schlucht zurückgegeben wird.
     */
    public int getSchluchtenPunkte(boolean zweitschlucht) {
        int maxSchlucht1 = 0;
        int maxSchlucht2 = 0;
       
        int zwisch1, zwisch2;
       
        if (hoehenPunkte == null) {
            hoehenPunkte = new Integer[this.getFeld().length];
            for (int i = 0; i < hoehenPunkte.length; i++) {
                for (int j = 0; j < this.getFeld()[0].length; j++) {
                    if (this.getFeld()[i][j]) {
                        hoehenPunkte[i] = this.getFeld()[0].length - j - 1;
                        break;
                    }
                }
            }
        }
       
        for (int i = 0; i < hoehenPunkte.length - 1; i++) {
            if (i == 0) {
                zwisch1 = hoehenPunkte[hoehenPunkte.length - 1] - hoehenPunkte[i];
                zwisch2 = hoehenPunkte[i + 1] - hoehenPunkte[i];
            } else {
                zwisch1 = hoehenPunkte[i - 1] - hoehenPunkte[i];
                zwisch2 = hoehenPunkte[i + 1] - hoehenPunkte[i];
            }
           
            if (zwisch2 < zwisch1) {
                zwisch1 = zwisch2;
            }
           
            if (zwisch1 > maxSchlucht1) {
                maxSchlucht2 = maxSchlucht1;
                maxSchlucht1 = zwisch1;
            } else if (zwisch1 > maxSchlucht2) {
                maxSchlucht2 = zwisch1;
            }
        }
       
        // Zweitgrößte Schlucht.
        if (zweitschlucht) {
            return maxSchlucht2;
        } else {
            return maxSchlucht1;
        }
    }
   
    public TetrisMoveSequence bestMove(int tileType) {
        double best;
        TetrisMoveSequence tms;
        TetrisMoveSequence bestSequenz = new TetrisMoveSequence();
        double zwischBew;
       
        best = Double.NEGATIVE_INFINITY;
       
        int drehungen = 4;
      
        switch (tileType) {
        case 0: drehungen = 2; break; // I
        case 1: drehungen = 2; break; // Z
        case 2: drehungen = 2; break; // S
        case 3: drehungen = 4; break; // L
        case 4: drehungen = 4; break; // J
        case 5: drehungen = 1; break; // O
        case 6: drehungen = 4; break; // T
        default: break;
        }

        // Drehen.
        for (int h = 0; h < drehungen; h++) {
            // Horizontal 1.
            for (int i = 1; i < this.getFeld().length; i++) {
                // Vertikal.
                for (int j = 1; j < this.getFeld()[0].length; j++) {
                    // Horizontal 2.
                    for (int k = -1; k <= 1; k++) {
                        if (k != 0) {
                            tms = erzeugeSequenzAusCode(h, i, j, k);
                           
                            zwischBew = this.bewerteSequenz(tileType, tms);

                            if (zwischBew > best) {
                                best = zwischBew;
                                bestSequenz = tms;
                            }
                        }
                    }
                }
            }
        }
       
        if (this.getSimTime() != null) {
            if (Double.POSITIVE_INFINITY == best) {
                this.getSimTime().broadcastEvent(new ChartEvent("TetrisAutomaticChart", "Bewertung", 1000));
            } else {
                this.getSimTime().broadcastEvent(new ChartEvent("TetrisAutomaticChart", "Bewertung", best));
            }
        }
       
        return bestSequenz;
    }
   
    private TetrisMoveSequence erzeugeSequenzAusCode(int d, int h1, int v, int h2) {
        TetrisMoveSequence tms = new TetrisMoveSequence();

        // Drehen.
        for (int i = 0; i < d; i++) {
            tms.add(new TetrisMove(TetrisMove.MOVE_TURN));
        }
       
        // Horizontal 1.
        if (h1 < 0) {
            for (int i = 0; i > h1; i--) {
                tms.add(new TetrisMove(TetrisMove.MOVE_LEFT));
            }
        } else {
            for (int i = 0; i < h1; i++) {
                tms.add(new TetrisMove(TetrisMove.MOVE_RIGHT));
            }
        }
       
        // Vertikal.
        for (int i = 0; i < v; i++) {
            tms.add(new TetrisMove(TetrisMove.MOVE_SINK));
        }
       
        // Horizontal 2.
        if (h2 < 0) {
            for (int i = 0; i > h2; i--) {
                tms.add(new TetrisMove(TetrisMove.MOVE_LEFT));
            }
        } else {
            for (int i = 0; i < h2; i++) {
                tms.add(new TetrisMove(TetrisMove.MOVE_RIGHT));
            }
        }
       
        return tms;
    }
   
    @Override
    public void step(Wink cyc) {
    }

    private TetrisMoveSequence seq;
   
    private int tileType;

    public void setSeq(TetrisMoveSequence seq) {
        this.seq = seq;
    }
   
    public void setTileType(int tileType) {
        this.tileType = tileType;
    }
   
    public TetrisMoveSequence getSeq() {
        return this.seq;
    }
   
    @Override
    public void run() {
        this.addTile(tileType);
        seq = null;
        seq = bestMove(tileType);
    }
}
TOP

Related Classes of eas.users.demos.tetris.automaticTetris.TetrisEnvAutomatic

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.