/*
* This file is part of MazeSolver.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright (c) 2014 MazeSolver
* Sergio M. Afonso Fumero <theSkatrak@gmail.com>
* Kevin I. Robayna Hernández <kevinirobaynahdez@gmail.com>
*/
/**
* @file PATableAgent.java
* @date 20/11/2014
*/
package es.ull.mazesolver.agent;
import java.awt.Color;
import es.ull.mazesolver.gui.configuration.AgentConfigurationPanel;
import es.ull.mazesolver.gui.configuration.PATableAgentConfigurationPanel;
import es.ull.mazesolver.gui.environment.Environment;
import es.ull.mazesolver.maze.MazeCell.Vision;
import es.ull.mazesolver.util.Direction;
/**
* Clase que representa a un agente basado en una tabla de percepción-acción.
*/
public class PATableAgent extends Agent {
private static final long serialVersionUID = -4993197615980679396L;
private Direction [][][][] m_table;
/**
* Crea el agente a partir de un entorno, con la configuración por defecto.
* @param env Entorno en el que crear el agente.
*/
public PATableAgent (Environment env) {
super(env);
m_table = new Direction[][][][]{
{
{
{Direction.DOWN, Direction.LEFT}, // 0,0,0,0 ; 0,0,0,1
{Direction.RIGHT, Direction.DOWN} // 0,0,1,0 ; 0,0,1,1
},
{
{Direction.UP, Direction.LEFT}, // 0,1,0,0 ; 0,1,0,1
{Direction.RIGHT, Direction.UP} // 0,1,1,0 ; 0,1,1,1
}
},
{
{
{Direction.DOWN, Direction.LEFT}, // 1,0,0,0 ; 1,0,0,1
{Direction.RIGHT, Direction.DOWN} // 1,0,1,0 ; 1,0,1,1
},
{
{Direction.RIGHT, Direction.LEFT}, // 1,1,0,0 ; 1,1,0,1
{Direction.RIGHT, Direction.NONE} // 1,1,1,0 ; 1,1,1,1
}
}
};
}
/**
* Cambia la tabla de percepción-acción del agente por otra. Cada dimensión
* del array debe tener 2 posiciones (EMPTY y WALL) y tiene una dimensión por
* cada dirección alrededor del agente (UP, DOWN, LEFT y RIGHT). El valor de
* cada celda de la tabla puede ser cualquier {@link Direction}.
*
* @param pa_table La nueva tabla de percepción-acción. Se almacenará una
* copia de la misma.
*/
public void setPerceptionActionTable (Direction[][][][] pa_table) {
m_table = deepDataCopy(pa_table);
}
/**
* @return Una copia de la tabla de percepción-acción del agente.
*/
public Direction[][][][] getPerceptionActionTable () {
return deepDataCopy(m_table);
}
/* (non-Javadoc)
* @see agent.Agent#getAlgorithmName()
*/
@Override
public String getAlgorithmName () {
return "Perception-Action Table";
}
/*
* (non-Javadoc)
*
* @see es.ull.mazesolver.agent.Agent#getAlgorithmColor()
*/
@Override
public Color getAlgorithmColor () {
return Color.GREEN;
}
/* (non-Javadoc)
* @see agent.Agent#getNextMovement()
*/
@Override
public Direction getNextMovement () {
// Cualquier lugar al que no nos podamos mover se considerará una "pared"
Vision up = m_env.movementAllowed(m_pos, Direction.UP)? Vision.EMPTY : Vision.WALL;
Vision down = m_env.movementAllowed(m_pos, Direction.DOWN)? Vision.EMPTY : Vision.WALL;
Vision left = m_env.movementAllowed(m_pos, Direction.LEFT)? Vision.EMPTY : Vision.WALL;
Vision right = m_env.movementAllowed(m_pos, Direction.RIGHT)? Vision.EMPTY : Vision.WALL;
return m_table[visionToIndex(up)][visionToIndex(down)]
[visionToIndex(left)][visionToIndex(right)];
}
/* (non-Javadoc)
* @see agent.Agent#resetMemory()
*/
@Override
public void resetMemory () {
// No tiene memoria, así que no hacemos nada
}
/* (non-Javadoc)
* @see agent.Agent#getConfigurationPanel()
*/
@Override
public AgentConfigurationPanel getConfigurationPanel () {
return new PATableAgentConfigurationPanel(this);
}
/* (non-Javadoc)
* @see agent.Agent#clone()
*/
@Override
public Object clone () {
PATableAgent ag = new PATableAgent(m_env);
ag.setAgentColor(getAgentColor());
ag.setPerceptionActionTable(m_table);
return ag;
}
/**
* Traduce una visión a índice entre 0 y 1.
*
* @param vision Visión a traducir.
* @return Índice asociado a la visión.
*/
private static int visionToIndex (Vision vision) {
switch (vision) {
case EMPTY:
case OFFLIMITS:
return 0;
case WALL:
case AGENT:
return 1;
default:
return -1;
}
}
/**
* Hace una copia profunda de la configuración de un agente.
*
* @param data Array tetra-dimensional con las direcciones asociadas a cada
* percepción del agente.
* @return Copia profunda del array de datos de entrada.
*/
private static Direction[][][][] deepDataCopy (Direction[][][][] data) {
Direction [][][][] result = new Direction[2][2][2][2];
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < 2; k++)
for (int l = 0; l < 2; l++)
result[i][j][k][l] = data[i][j][k][l];
return result;
}
}