Java tutorial
/* * 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 Hernndez <kevinirobaynahdez@gmail.com> */ /** * @file SARulesAgent.java * @date 2/11/2014 */ package es.ull.mazesolver.agent; import java.awt.Color; import java.awt.Point; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import org.antlr.v4.runtime.ANTLRInputStream; import org.antlr.v4.runtime.CommonTokenStream; import es.ull.mazesolver.agent.rules.RuleAction; import es.ull.mazesolver.agent.rules.SituationActionRule; import es.ull.mazesolver.agent.rules.parser.SituationActionErrorHandler; import es.ull.mazesolver.agent.rules.parser.SituationActionLexer; import es.ull.mazesolver.agent.rules.parser.SituationActionParser; import es.ull.mazesolver.agent.rules.parser.SituationActionParser.Sa_ruleContext; import es.ull.mazesolver.gui.configuration.AgentConfigurationPanel; import es.ull.mazesolver.gui.configuration.SARulesAgentConfigurationPanel; import es.ull.mazesolver.gui.environment.Environment; import es.ull.mazesolver.maze.Maze; import es.ull.mazesolver.util.Direction; /** * Agente cuya lgica se basa en reglas de situacin-accin. Sigue una * arquitectura de subsuncin, donde se aplica la regla de mayor precedencia * para la cual la situacin se cumple. */ public class SARulesAgent extends Agent { private static final long serialVersionUID = -6154538349034427858L; public static final int MINIMUM_WIDTH = 300; public static final int MINIMUM_HEIGHT = 100; public static final String DEFAULT_AGENT_SRC = "// Reglas de mxima prioridad para salir del laberinto\n" + "DOWN OFFLIMITS -> MOVE DOWN.\n" + "RIGHT OFFLIMITS -> MOVE RIGHT.\n" + "LEFT OFFLIMITS -> MOVE LEFT.\n" + "UP OFFLIMITS -> MOVE UP.\n\n" + "// Reglas para moverse al primer sitio no visitado donde haya un hueco\n" + "// Siempre intenta acercarse a la esquina inferior derecha\n" + "DOWN FREE & DOWN ~VISITED => GO DOWN.\n" + "RIGHT FREE & RIGHT ~VISITED => GO RIGHT.\n" + "LEFT FREE & LEFT ~VISITED => GO LEFT.\n" + "UP FREE & UP ~VISITED => GO UP.\n\n" + "// Reglas para mover al agente si todo alrededor est visitado u\n" + "// ocupado. Utilizamos varias operaciones lgicas para demostrar\n" + "// la flexibilidad del lenguaje. Se pueden traducir como:\n" + "// <direccin> FREE -> MOVE <direccin>.\n" + "Up Not Wall and Up ~Agent -> MOVE up.\n" + "not (left wall OR left agent) -> move left.\n" + "right !wall And right !agent -> move right.\n" + "!(down wall or down agent) -> move down.\n"; private String m_code; private transient SituationActionErrorHandler m_error_handler; private transient ArrayList<SituationActionRule> m_rules; private transient boolean[][] m_visited; /** * Crea un agente basado en reglas de situacin-accin con el comportamiento * por defecto. * * @param env * Entorno donde se sita el agente. */ public SARulesAgent(Environment env) { super(env); m_error_handler = new SituationActionErrorHandler(); m_rules = new ArrayList<SituationActionRule>(); m_code = DEFAULT_AGENT_SRC; compileCode(); } /** * @return El cdigo fuente actualmente cargado en el agente. */ public String getCode() { return m_code; } /** * Cambia el cdigo fuente cargado. Se debe llamar a {@link #compileCode()} * para que el nuevo cdigo pueda ser ejecutado por el agente. * @param code * Nuevo cdigo fuente. */ public void setCode(String code) { m_code = code; } /** * Convierte el cdigo fuente guardado en m_code en la representacin de las * reglas de situacin-accin. * * @return {@code true} si la compilacin fue exitosa y {@code false} si no. */ public boolean compileCode() { m_error_handler.resetErrorList(); ArrayList<SituationActionRule> rules = new ArrayList<SituationActionRule>(); InputStream stream = new ByteArrayInputStream(m_code.getBytes(StandardCharsets.UTF_8)); try { ANTLRInputStream input = new ANTLRInputStream(stream); SituationActionLexer lexer = new SituationActionLexer(input); CommonTokenStream tokens = new CommonTokenStream(lexer); SituationActionParser parser = new SituationActionParser(tokens); lexer.removeErrorListeners(); parser.removeErrorListeners(); lexer.addErrorListener(m_error_handler); parser.addErrorListener(m_error_handler); rules = new ArrayList<SituationActionRule>(); for (Sa_ruleContext i : parser.program().sa_rule()) rules.add(SituationActionRule.createFromTree(i)); } catch (Exception e) { return false; } if (m_error_handler.hasErrors()) return false; else { m_rules = rules; return true; } } /** * @return La lista de errores de compilacin. */ public ArrayList<String> getCompilationErrors() { return m_error_handler.getErrors(); } /* * (non-Javadoc) * * @see agent.Agent#setEnvironment(Environment) */ public void setEnvironment(Environment env) { super.setEnvironment(env); Maze maze = m_env.getMaze(); m_visited = new boolean[maze.getHeight()][maze.getWidth()]; } /* * (non-Javadoc) * * @see agent.Agent#getAlgorithmName() */ @Override public String getAlgorithmName() { return "Situation-Action Rules"; } /* * (non-Javadoc) * * @see es.ull.mazesolver.agent.Agent#getAlgorithmColor() */ @Override public Color getAlgorithmColor() { return Color.MAGENTA; } /* * (non-Javadoc) * * @see agent.Agent#getNextMovement() */ @Override public Direction getNextMovement() { // Recorremos las reglas y nos quedamos con la primera accin para la // que se cumple la situacin (arquitectura de subsuncin). for (SituationActionRule r : m_rules) { RuleAction act = r.getAction(this); if (act != null) return act.getDirection(); } return Direction.NONE; } /* * (non-Javadoc) * * @see agent.Agent#doMovement(maze.Direction) */ @Override public void doMovement(Direction dir) { // Marcamos la celda actual como visitada m_visited[m_pos.y][m_pos.x] = true; super.doMovement(dir); } /* * (non-Javadoc) * * @see agent.Agent#resetMemory() */ public void resetMemory() { for (boolean[] i : m_visited) for (int j = 0; j < i.length; j++) i[j] = false; } /* * (non-Javadoc) * * @see agent.Agent#getConfigurationPanel() */ @Override public AgentConfigurationPanel getConfigurationPanel() { return new SARulesAgentConfigurationPanel(this); } /** * Indica si una celda adyacente al agente ha sido visitada ya por el mismo. * * @param dir * Direccin en la que hay que mirar. * @return Si la celda adyacente en esa direccin ha sido visitada o no. */ public boolean hasVisited(Direction dir) { Point p = dir.movePoint(m_pos); Maze maze = m_env.getMaze(); if (!maze.containsPoint(p)) return false; return m_visited[p.y][p.x]; } /* * (non-Javadoc) * * @see agent.Agent#duplicate() */ @Override public Object clone() { SARulesAgent ag = new SARulesAgent(m_env); ag.setAgentColor(getAgentColor()); ag.m_code = m_code; ag.m_rules = new ArrayList<SituationActionRule>(m_rules.size()); for (SituationActionRule r : m_rules) ag.m_rules.add((SituationActionRule) r.clone()); return ag; } /** * Extrae la informacin del objeto a partir de una forma serializada del * mismo. * * @param input * Flujo de entrada con la informacin del objeto. * @throws ClassNotFoundException * Si se trata de un objeto de otra clase. * @throws IOException * Si no se puede leer el flujo de entrada. */ private void readObject(ObjectInputStream input) throws ClassNotFoundException, IOException { input.defaultReadObject(); m_error_handler = new SituationActionErrorHandler(); m_rules = new ArrayList<SituationActionRule>(); compileCode(); } }