<repo_name>theblackunknown/creative-ecosystems<file_sep>/gui-ecosystem/src/main/java/org/blackpanther/ecosystem/gui/actions/SaveImageAction.java
package org.blackpanther.ecosystem.gui.actions;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import static org.blackpanther.ecosystem.gui.GUIMonitor.Monitor;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:58 CEST 2011
 */
public class SaveImageAction
        extends FileBrowserAction {

    private SaveImageAction() {
        super("Save current image",
                "Image files",
                "png", "bmp", "gif", "jpeg"
                );
    }

    private static class SaveImageHolder {
        private static final SaveImageAction instance =
                new SaveImageAction();
    }

    public static SaveImageAction getInstance() {
        return SaveImageHolder.instance;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Monitor.pauseEvolution();
        BufferedImage image = Monitor.dumpCurrentImage();
        if (image == null)
            return;

        Component parent = e.getSource() instanceof Component
                ? ((Component) e.getSource()).getParent()
                : null;
        switch (fc.showSaveDialog(parent)) {
            case JFileChooser.APPROVE_OPTION:
                File selectedFile = fc.getSelectedFile();
                int returnVal = JOptionPane.OK_OPTION;
                if (selectedFile.exists()) {
                    returnVal = JOptionPane.showConfirmDialog(
                            parent,
                            "Are you sure you want to overwrite : "
                                    + selectedFile.getName()
                                    + " ?",
                            "File collision !",
                            JOptionPane.YES_NO_OPTION
                    );
                }

                boolean gotExtension = selectedFile.getName().contains(".");

                String extension =
                        gotExtension
                                ? selectedFile.getName().substring(
                                selectedFile.getName().lastIndexOf(".") + 1,
                                selectedFile.getName().length()
                        )
                                : "png";


                File file = gotExtension ?
                        selectedFile
                        : new File(selectedFile.getAbsolutePath() + ".png");

                if (returnVal == JOptionPane.OK_OPTION) {
                    try {
                        ImageIO.write(
                                image,
                                extension,
                                file);
                        JOptionPane.showMessageDialog(
                                parent,
                                "File saved : " + file.getName(),
                                "Save operation",
                                JOptionPane.INFORMATION_MESSAGE);
                    } catch (IOException e1) {
                        JOptionPane.showMessageDialog(
                                parent,
                                "Couldn't save image file : "
                                        + e1.getLocalizedMessage(),
                                "Save operation",
                                JOptionPane.ERROR_MESSAGE);
                    }
                }
        }
    }
}
<file_sep>/gui-ecosystem/src/main/java/org/blackpanther/ecosystem/gui/settings/fields/IntegerSpinnerField.java
package org.blackpanther.ecosystem.gui.settings.fields;

import org.blackpanther.ecosystem.factory.fields.FieldMould;
import org.blackpanther.ecosystem.factory.fields.StateFieldMould;

import javax.swing.*;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:59 CEST 2011
 */
public class IntegerSpinnerField
        extends SettingField<Integer> {

    private JSpinner valueSelector;

    public IntegerSpinnerField(String name, SpinnerModel model){
        super(name);
        valueSelector.setModel(model);
    }

    @Override
    protected void initializeComponents(String fieldName) {
        valueSelector = new JSpinner();
        valueSelector.setName(fieldName);
    }

    @Override
    public JComponent getMainComponent() {
        return valueSelector;
    }

    @Override
    public void setValue(Integer newValue) {
        valueSelector.setValue(newValue);
    }

    @Override
    public Integer getValue() {
        return (Integer) valueSelector.getValue();
    }

    @Override
    public FieldMould<Integer> toMould() {
        return new StateFieldMould<Integer>(
                getMainComponent().getName(),
                new org.blackpanther.ecosystem.factory.generator.provided.IntegerProvider(getValue())
        );
    }
}<file_sep>/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.blackpanther</groupId>
    <artifactId>creative-ecosystems</artifactId>
    <version>1.0-alpha</version>

    <modules>
        <module>ecosystem-framework</module>
        <module>gui-ecosystem</module>
    </modules>

    <packaging>pom</packaging>

    <name>Creative Ecosystem Project</name>
    <url>https://github.com/blackpanther/creative-ecosystems</url>

    <!-- TODO Handle license -->
    <licenses>
    </licenses>


    <developers>
        <developer>
            <id>blackpanther</id>
            <name><NAME></name>
            <email><EMAIL></email>
            <roles>
                <role>developper</role>
            </roles>
            <timezone>+1</timezone>
        </developer>
    </developers>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <targetJVM>1.6</targetJVM>
        <junit.version>4.8.2</junit.version>
        <javadoc.version>2.7</javadoc.version>
        <checkstyle.version>2.6</checkstyle.version>
        <pmd.version>2.5</pmd.version>
        <jxr.version>2.2</jxr.version>
    </properties>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>${targetJVM}</source>
                        <target>${targetJVM}</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.0-beta-3</version>
                    <configuration>
                        <reportPlugins>
                            <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-javadoc-plugin</artifactId>
                                <version>${javadoc.version}</version>
                                <reportSets>
                                    <reportSet>
                                        <id>uml</id>
                                        <configuration>
                                            <doclet>gr.spinellis.umlgraph.doclet.UmlGraph</doclet>
                                            <docletArtifact>
                                                <groupId>gr.spinellis</groupId>
                                                <artifactId>UmlGraph</artifactId>
                                                <version>4.4</version>
                                            </docletArtifact>
                                            <additionalparam>-views</additionalparam>
                                            <destDir>target/uml</destDir>
                                            <show>private</show>
                                        </configuration>
                                        <reports>
                                            <report>javadoc</report>
                                        </reports>
                                    </reportSet>
                                    <reportSet>
                                        <id>html</id>
                                        <configuration>
                                            <show>private</show>
                                        </configuration>
                                        <reports>
                                            <report>javadoc</report>
                                        </reports>
                                    </reportSet>
                                </reportSets>
                                <configuration>
                                    <show>public</show>
                                    <links>
                                        <link>http://download.oracle.com/javase/6/docs/api/</link>
                                    </links>
                                    <javaApiLinks>
                                        <javaApiLinks>
                                            <property>
                                                <name>api_1.6</name>
                                                <value>http://download.oracle.com/javase/6/docs/api/</value>
                                            </property>
                                        </javaApiLinks>
                                    </javaApiLinks>
                                </configuration>
                            </plugin>
                            <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-checkstyle-plugin</artifactId>
                                <version>${checkstyle.version}</version>
                                <configuration>
                                    <consoleOutput>true</consoleOutput>
                                    <configLocation>checkstyle.xml</configLocation>
                                </configuration>
                            </plugin>
                            <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-pmd-plugin</artifactId>
                                <version>${pmd.version}</version>
                                <configuration>
                                    <targetJdk>${targetJVM}</targetJdk>
                                </configuration>
                            </plugin>
                            <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-jxr-plugin</artifactId>
                                <version>${jxr.version}</version>
                            </plugin>
                        </reportPlugins>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

    <distributionManagement>
        <site>
            <id>site</id>
            <name>Project Site</name>
            <url>file:///${user.dir}/target/deployed-site</url>
        </site>
    </distributionManagement>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>
<file_sep>/gui-ecosystem/src/main/resources/application.properties
space-width=900.0
space-height=900.0

max-agent-number=1200

resource-threshold=500.0
speed-threshold=10.0
curvature-threshold=0.05
sensor-radius-threshold=10.0
energy-threshold=1000.0
fecundation-consummation-threshold=100.0

probability-variation=0.01
curvature-variation=0.1
angle-variation=0.1
speed-variation=0.1
color-variation=50

line-obstruction=true
perlin-noise=true<file_sep>/gui-ecosystem/src/main/java/org/blackpanther/ecosystem/gui/settings/fields/mutable/SpinnerField.java
package org.blackpanther.ecosystem.gui.settings.fields.mutable;

import org.blackpanther.ecosystem.factory.fields.FieldMould;
import org.blackpanther.ecosystem.factory.fields.GeneFieldMould;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.beans.EventHandler;

import static org.blackpanther.ecosystem.helper.Helper.createLabeledField;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:59 CEST 2011
 */
public class SpinnerField
        extends org.blackpanther.ecosystem.gui.settings.fields.randomable.SpinnerField
        implements Mutable {

    private JCheckBox mutable;

    public SpinnerField(String name, SpinnerModel model) {
        super(name, model);
    }

    @Override
    protected void initializeComponents(String fieldName) {
        super.initializeComponents(fieldName);

        mutable = new JCheckBox();

        mutable.addActionListener(EventHandler.create(
                ActionListener.class,
                mutable,
                "setSelected",
                "source.selected"
        ));
    }

    @Override
    protected void placeComponents(JPanel layout) {
        super.placeComponents(layout);

        GridBagConstraints constraints = new GridBagConstraints();

        layout.add(createLabeledField(
                "M",
                mutable,
                CHECKBOX_DIMENSION
        ), constraints);
    }

    @Override
    public boolean isMutable() {
        return mutable.isSelected();
    }

    @Override
    public void setMutable(boolean mutable) {
        this.mutable.setSelected(mutable);
    }

    @Override
    public FieldMould<Double> toMould() {
        SpinnerNumberModel model = (SpinnerNumberModel) valueSelector.getModel();
        Double min = (Double) model.getMinimum();
        Double max = (Double) model.getMaximum();
        return new GeneFieldMould<Double>(
                getMainComponent().getName(),
                isRandomized()
                        ? new org.blackpanther.ecosystem.factory.generator.random.DoubleProvider(min, max)
                        : new org.blackpanther.ecosystem.factory.generator.provided.DoubleProvider(getValue()),
                isMutable()
        );
    }
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/event/EvolutionListener.java
package org.blackpanther.ecosystem.event;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public interface EvolutionListener {
    public void update(EvolutionEvent e);
}
<file_sep>/gui-ecosystem/src/main/java/org/blackpanther/ecosystem/gui/actions/ToggleResources.java
package org.blackpanther.ecosystem.gui.actions;

import org.blackpanther.ecosystem.gui.GUIMonitor;
import org.blackpanther.ecosystem.gui.GraphicEnvironment;

import javax.swing.*;
import java.awt.event.ActionEvent;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:58 CEST 2011
 */
public class ToggleResources
    extends AbstractAction{

    private ToggleResources(){
        super("Toggle Resources painting");
    }

    private static class ToggleResourcesHolder {
        private static final ToggleResources instance =
            new ToggleResources();
    }

    public static ToggleResources getInstance(){
        return ToggleResourcesHolder.instance;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        GUIMonitor.Monitor.toggleOption(GraphicEnvironment.RESOURCE_OPTION);
    }
}
<file_sep>/gui-ecosystem/src/main/java/org/blackpanther/ecosystem/gui/actions/ToggleLineObstruction.java
package org.blackpanther.ecosystem.gui.actions;

import javax.swing.*;
import java.awt.event.ActionEvent;

import static org.blackpanther.ecosystem.ApplicationConstants.LINE_OBSTRUCTION_OPTION;
import static org.blackpanther.ecosystem.Configuration.Configuration;

/**
 * @author <NAME>
 * @version 26/05/11
 */
public class ToggleLineObstruction
        extends AbstractAction {

    private ToggleLineObstruction() {
        super("Toggle line obstruction");
    }

    private static class ToggleLineObstructionHolder {
        private static final ToggleLineObstruction instance =
                new ToggleLineObstruction();
    }

    public static ToggleLineObstruction getInstance() {
        return ToggleLineObstructionHolder.instance;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() instanceof JCheckBox) {
            Configuration.setParameter(
                    LINE_OBSTRUCTION_OPTION,
                    ((JCheckBox) e.getSource()).isSelected(),
                    Boolean.class
            );
        } else
            Configuration.setParameter(
                    LINE_OBSTRUCTION_OPTION,
                    !Configuration.getParameter(LINE_OBSTRUCTION_OPTION, Boolean.class),
                    Boolean.class
            );
    }
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/factory/EnvironmentFactory.java
package org.blackpanther.ecosystem.factory;

import org.blackpanther.ecosystem.factory.fields.FieldsConfiguration;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public abstract class EnvironmentFactory<T> {

    abstract public T createAgent(FieldsConfiguration config);

}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/Environment.java
package org.blackpanther.ecosystem;

import org.blackpanther.ecosystem.agent.Creature;
import org.blackpanther.ecosystem.agent.Resource;
import org.blackpanther.ecosystem.event.*;
import org.blackpanther.ecosystem.line.TraceHandler;
import org.blackpanther.ecosystem.math.Geometry;

import java.awt.geom.Dimension2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

import static org.blackpanther.ecosystem.ApplicationConstants.LINE_OBSTRUCTION_OPTION;
import static org.blackpanther.ecosystem.Configuration.Configuration;
import static org.blackpanther.ecosystem.SensorTarget.detected;
import static org.blackpanther.ecosystem.helper.Helper.EPSILON;
import static org.blackpanther.ecosystem.helper.Helper.computeOrientation;
import static org.blackpanther.ecosystem.math.Geometry.getIntersection;

/**
 * <p>
 * Component designed to represent an general ecosystem
 * But let's first use some basic non general features...
 * </p>
 * <ul>
 * <li>2D grid as space</li>
 * <li>fixed-size bounds (<i>size means number of case width</i>)</li>
 * <li>Trace timeline by cycle</li>
 * </ul>
 *
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public class Environment
        implements Serializable, Cloneable, AgentListener {

    /*
     *=========================================================================
     *                       STATIC PART
     *=========================================================================
     */
    private static final Logger logger =
            Logger.getLogger(
                    Environment.class.getCanonicalName()
            );

    private static final long serialVersionUID = 5L;

    private static long idGenerator = 0L;
    private static int AREA_COLUMN_NUMBER = 50;
    private static int AREA_ROW_NUMBER = 50;


    /*
    *=========================================================================
    *                       CLASS ATTRIBUTES
    *=========================================================================
    */

    private Long id = ++idGenerator;
    /**
     * Environment space
     */
    protected Area[][] space;
    private Rectangle2D bounds;
    /**
     * Time tracker
     */
    protected int timetracker;
    /**
     * Population
     */
    protected List<Creature> creaturePool = new ArrayList<Creature>();
    private Collection<Resource> resourcePool = new ArrayList<Resource>();

    /*
     *=========================================================================
     *                       MISCELLANEOUS
     *=========================================================================
     */
    /**
     * Component that can monitor an environment
     *
     * @see java.beans.PropertyChangeSupport
     */
    protected EnvironmentMonitor eventSupport;
    private Stack<Creature> nextGenerationBuffer = new Stack<Creature>();
    private Line2D[] boundLines = new Line2D[4];

    public Environment(double width, double height) {
        this(new Geometry.Dimension(width, height));
    }

    public Environment(Dimension2D dimension) {
        this.bounds = dimension == null
                ? new Rectangle2D.Double(
                -Double.MAX_VALUE / 2.0,
                -Double.MAX_VALUE / 2.0,
                Double.MAX_VALUE,
                Double.MAX_VALUE)
                : new Rectangle2D.Double(
                -dimension.getWidth() / 2.0,
                -dimension.getHeight() / 2.0,
                dimension.getWidth(),
                dimension.getHeight());
        //NORTH LINE
        boundLines[0] = new Line2D.Double(
                bounds.getX(), bounds.getY(),
                bounds.getX() + bounds.getWidth(), bounds.getY()
        );
        //EAST LINE
        boundLines[1] = new Line2D.Double(
                bounds.getX() + bounds.getWidth(), bounds.getY(),
                bounds.getX() + bounds.getWidth(), bounds.getY() + bounds.getHeight()
        );
        //SOUTH LINE
        boundLines[2] = new Line2D.Double(
                bounds.getX(), bounds.getY() + bounds.getHeight(),
                bounds.getX() + bounds.getWidth(), bounds.getY() + bounds.getHeight()
        );
        //WEST LINE
        boundLines[3] = new Line2D.Double(
                bounds.getX(), bounds.getY(),
                bounds.getX(), bounds.getY() + bounds.getHeight()
        );
        //initialize space
        space = new Area[AREA_ROW_NUMBER][AREA_COLUMN_NUMBER];
        double abscissaStartValue = bounds.getX();
        double ordinateStartValue = bounds.getY();
        double abscissaStep = bounds.getWidth() / AREA_COLUMN_NUMBER;
        double ordinateStep = bounds.getHeight() / AREA_ROW_NUMBER;

        double ordinateCursor = ordinateStartValue;
        double abscissaCursor;
        for (int rowIndex = 0;
             rowIndex < AREA_ROW_NUMBER;
             ordinateCursor += ordinateStep,
                     rowIndex++) {
            abscissaCursor = abscissaStartValue;
            for (int columnIndex = 0;
                 columnIndex < AREA_COLUMN_NUMBER;
                 abscissaCursor += abscissaStep,
                         columnIndex++) {
                space[rowIndex][columnIndex] = new Area(
                        abscissaCursor, ordinateCursor,
                        abscissaStep, ordinateStep
                );
            }
        }

        //initialize timeline
        timetracker = 0;

        getEventSupport().addAgentListener(this);
    }

    /**
     * Internal unique environment identifier
     *
     * @return environment identifier
     */
    public Long getId() {
        return id;
    }

    /**
     * Get current time (expressed as number of evolution's cycle)
     * since evolution has begun
     *
     * @return number of cycles since evolution's beginning
     */
    public final int getTime() {
        return timetracker;
    }

    public Rectangle2D getBounds() {
        return bounds;
    }

    /**
     * Dump the current global agent's creaturePool at the current state
     *
     * @return copy of agent's creaturePool
     */
    public final Collection<Creature> getCreaturePool() {
        return creaturePool;
    }

    /**
     * Get the whole environment draw's history
     *
     * @return environment's draw history
     */
    public Set<Line2D> getHistory() {
        Set<Line2D> wholeHistory = new HashSet<Line2D>();
        for (Area[] row : space)
            for (Area area : row)
                wholeHistory.addAll(area.getHistory());
        return wholeHistory;
    }

    public final Collection<Resource> getResources() {
        return resourcePool;
    }

    /**
     * Add an monster to the environment.
     * The added monster will be monitored by corresponding case
     * and that till its death or till it moves from there
     *
     * @param mosntergent the monster
     */
    public final void add(final Creature monster) {
        if (bounds.contains(monster.getLocation())) {
            monster.attachTo(this);
            creaturePool.add(monster);
        }
    }

    public final void add(final Resource resource) {
        if (bounds.contains(resource.getLocation())) {
            resource.attachTo(this);
            resourcePool.add(resource);
        }
    }


    /**
     * Add an agent collection to the environment.
     * The added agent will be monitored by corresponding case
     * and that till its death or till it moves from there
     *
     * @param monsters the agent collection
     */
    public final void addCreatures(Collection<Creature> monsters) {
        for (Creature monster : monsters)
            add(monster);
    }

    public final void addResources(
            final Collection<Resource> resources) {
        for (Resource resource : resources)
            add(resource);
    }

    private Set<Area> getCrossedArea(Point2D from, Point2D to) {
        Set<Area> crossedArea = new HashSet<Area>(
                AREA_ROW_NUMBER * AREA_COLUMN_NUMBER);
        for (Area[] row : space) {
            for (final Area area : row) {
                //line is totally contained by this area
                // OMG this is so COOL !
                if (area.contains(from) || area.contains(to)) {
                    crossedArea.add(area);
                }
            }
        }
        return crossedArea;
    }

    long totalComparison = 0;

    /**
     * <p>
     * Iterate over one cycle.
     * The current process is described below :
     * </p>
     * <ol>
     * <li>Update every agent in the creaturePool.</li>
     * <li>Remove all agent which died at this cycle</li>
     * <li>Increment timeline</li>
     * </ol>
     * <p>
     * Environment is ended if no more agents are alive at after the update step.
     * </p>
     */
    public final void runNextCycle() {
        if (timetracker == 0)
            getEventSupport().fireEvolutionEvent(EvolutionEvent.Type.STARTED);

        long start = System.nanoTime();
        //update environment state
        updatePool();
        logger.fine(String.format(
                "Pool updated in %d milliseconds",
                TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start)
        ));
        logger.fine(String.format(
                "%d comparisons made in this cycle",
                totalComparison
        ));
        totalComparison = 0;

        //update timeline
        logger.info(String.format(
                "%s 's cycle %d ended, %d agents remaining",
                this,
                timetracker,
                creaturePool.size()));
        timetracker++;
        getEventSupport().fireEvolutionEvent(EvolutionEvent.Type.CYCLE_END);

        if (creaturePool.size() == 0) {
            endThisWorld();
        }
    }

    /**
     * Update the environment's state
     * Internal process.
     */
    private void updatePool() {

        //update all agents
        //if they die, they are simply not kept in the next creaturePool
        for (Creature monster : creaturePool) {
            monster.update(this);
        }
        for (int i = 0; i < creaturePool.size(); )
            if (!creaturePool.get(i).isAlive())
                creaturePool.remove(i);
            else
                i++;

        creaturePool.addAll(nextGenerationBuffer);
        nextGenerationBuffer.clear();
    }

    /**
     * Method to end the evolution of this world
     * and freeze its state
     */
    public final void endThisWorld() {
        logger.info(String.format("The evolution's game paused. %s's statistics[%d cycle]", this, timetracker));
        getEventSupport().fireEvolutionEvent(EvolutionEvent.Type.ENDED);
    }

    @Override
    public String toString() {
        return String.format("Environment#%s", Long.toHexString(id));
    }

    @Override
    public Environment clone() {
        Environment copy = new Environment(getBounds().getWidth(), getBounds().getHeight());
        for (Creature monster : creaturePool)
            copy.add(monster.clone());
        for (Resource resource : resourcePool)
            copy.add(resource.clone());
        for (int i = 0; i < copy.space.length; i++)
            for (int j = 0; j < copy.space[0].length; j++)
                copy.space[i][j].internalDrawHistory.addAll(
                        space[i][j].internalDrawHistory);
        return copy;
    }

    /*=====================================================================
    *                   LISTENERS
    *=====================================================================
    */

    public void addAgentListener(AgentListener listener) {
        getEventSupport().addAgentListener(listener);
    }

    public void addLineListener(LineListener listener) {
        getEventSupport().addLineListener(listener);
    }

    public void addEvolutionListener(EvolutionListener listener) {
        getEventSupport().addEvolutionListener(listener);
    }

    public void nextGeneration(Creature child) {
        child.attachTo(this);
        nextGenerationBuffer.push(child);
    }

    long comparison = 0;

    public boolean move(Creature that, Point2D from, Point2D to) {
        Set<Area> crossedAreas = getCrossedArea(from, to);
        boolean collision = false;
        for (Area area : crossedAreas) {
            collision = area.trace(that, from, to) || collision;
        }
        logger.finer(String.format(
                "%d comparison to place a line",
                comparison
        ));
        totalComparison += comparison;
        comparison = 0;
        return collision;
    }

    public void removeAgentListener(AgentListener listener) {
        getEventSupport().removeAgentListener(listener);
    }

    public void removeEvolutionListener(EvolutionListener listener) {
        getEventSupport().removeEvolutionListener(listener);
    }

    public void removeLineListener(LineListener listener) {
        getEventSupport().removeLineListener(listener);
    }

    public EnvironmentMonitor getEventSupport() {
        if (eventSupport == null)
            eventSupport = new EnvironmentMonitor(this);
        return eventSupport;
    }

    public void clearAllExternalsListeners() {
        eventSupport.clearAllExternalsListeners();
    }

    @Override
    public void update(AgentEvent e) {
        switch (e.getType()) {
            case DEATH:
                if (e.getAgent() instanceof Resource) {
                    resourcePool.remove(e.getAgent());
                    break;
                }
        }
    }

    public SenseResult aggregateInformation(Geometry.Circle circle) {
        Collection<SensorTarget<Creature>> detectedAgents = new LinkedList<SensorTarget<Creature>>();
        for (Creature monster : creaturePool)
            if (circle.contains(monster.getLocation())
                    && !(monster.getLocation().distance(circle.getCenter()) < EPSILON)) {
                double agentOrientation =
                        computeOrientation(
                                circle.getCenter(),
                                monster.getLocation());
                detectedAgents.add(detected(agentOrientation, monster));
            }
        Collection<SensorTarget<Resource>> detectedResources = new LinkedList<SensorTarget<Resource>>();
        for (Resource resource : resourcePool)
            if (circle.contains(resource.getLocation())
                    && !(resource.getLocation().distance(circle.getCenter()) < EPSILON)) {
                double resourceOrientation =
                        computeOrientation(
                                circle.getCenter(),
                                resource.getLocation());
                detectedResources.add(detected(resourceOrientation, resource));
            }

        return new SenseResult(detectedAgents, detectedResources);
    }

    /**
     * <p>
     * Component designed to represent a state of a grid space
     * It can be consider as a small viewport of the global space.
     * It has the ability to monitor agent in its area,
     * for example it can provide useful information
     * - like the number of close agents
     * - how close they are
     * - which they are
     * to its own population within its area
     * </p>
     *
     * @author <NAME>
     * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
     */
    public class Area
            extends Rectangle2D.Double
            implements Serializable {

        private Collection<Line2D> internalDrawHistory = new LinkedList<Line2D>();

        public Area(double x, double y, double w, double h) {
            super(x, y, w, h);
        }

        public Collection<Line2D> getHistory() {
            return internalDrawHistory;
        }

        /**
         * Add a line to draw in the drawn line history.
         * It determines if the given line cross an already drawn one,
         * if that event happens, it will save a line from given line's origin to the intersection point
         *
         * @param line line to draw
         * @return <code>true</code> if draughtsman must be die after his movement,
         *         <code>false</code> otherwise.
         */
        public boolean trace(Creature that, Point2D from, Point2D to) {
            Line2D agentLine = TraceHandler.trace(from, to, that);
            //go fly away little birds, you no longer belong to me ...
            if (!bounds.contains(to)) {
                //detect which border has been crossed and where
                for (Line2D border : boundLines) {
                    Point2D intersection = getIntersection(border, agentLine);

                    if (intersection != null) {
                        Line2D realLine = TraceHandler.trace(from, intersection, that);
                        //We add a drawn line from agent's old location till intersection
                        internalDrawHistory.add(realLine);

                        getEventSupport().fireLineEvent(LineEvent.Type.ADDED, realLine);
                        //Yes, unfortunately, the agent died - this is Sparta here dude
                        return true;
                    }
                }
                throw new RuntimeException("Border detection failed");
            }

            //no intersection can happen with this option
            if (Configuration.getParameter(LINE_OBSTRUCTION_OPTION, Boolean.class)) {

                for (Line2D historyLine : internalDrawHistory) {
                    //check if this line can cross the history line before computing intersection (compute is cheaper)
                    if (!TraceHandler.canCross(agentLine, historyLine)) {
                        Point2D intersection = getIntersection(historyLine, agentLine);
                        if (intersection != null
                                //Intersection with the line's start is not an intersection
                                && !intersection.equals(from)) {
                            Line2D realLine = TraceHandler.trace(from, intersection, that);
                            //We add a drawn line from agent's old location till intersection
                            internalDrawHistory.add(realLine);
                            getEventSupport().fireLineEvent(LineEvent.Type.ADDED, realLine);
                            //Yes, unfortunately, the agent died - this is Sparta here dude
                            return true;
                        }
                    }
                }

            }

            //Everything went better than expected
            internalDrawHistory.add(agentLine);
            getEventSupport().fireLineEvent(LineEvent.Type.ADDED, agentLine);
            return false;
        }
    }


}<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/agent/AgentConstants.java
package org.blackpanther.ecosystem.agent;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public interface AgentConstants {

    public static final String AGENT_LOCATION = "agent-location";

    public static final String[] AGENT_STATE = new String[]{
            AGENT_LOCATION
    };
    public static final String[] BUILD_PROVIDED_AGENT_STATE = new String[]{
            AGENT_LOCATION,
    };

}
<file_sep>/gui-ecosystem/src/main/java/org/blackpanther/ecosystem/gui/actions/LoadConfigurationAction.java
package org.blackpanther.ecosystem.gui.actions;

import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

import static org.blackpanther.ecosystem.Configuration.Configuration;
import static org.blackpanther.ecosystem.gui.GUIMonitor.Monitor;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:58 CEST 2011
 */
public class LoadConfigurationAction extends AbstractAction {

    private JFileChooser fileLoader = new JFileChooser("."); // Start in current directory

    private LoadConfigurationAction() {
        super("Load default parameters");
        fileLoader.setFileFilter(new FileNameExtensionFilter(
                "Application properties", "properties"
        ));
        fileLoader.setFileSelectionMode(JFileChooser.FILES_ONLY);
        fileLoader.setMultiSelectionEnabled(false);
    }

    private static class LoadConfigurationHolder {
        private static final LoadConfigurationAction instance =
                new LoadConfigurationAction();
    }

    public static LoadConfigurationAction getInstance() {
        return LoadConfigurationHolder.instance;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Monitor.pauseEvolution();
        Component parent = ((Component) e.getSource()).getParent();
        switch (fileLoader.showOpenDialog(parent)) {
            case JFileChooser.APPROVE_OPTION:
                try {
                    Properties loadedProperties = new Properties();
                    loadedProperties.load(
                            new FileReader(fileLoader.getSelectedFile())
                    );
                    Configuration.loadConfiguration(loadedProperties);
                    JOptionPane.showMessageDialog(
                            parent,
                            Configuration.toString(),
                            "Properties successfully loaded",
                            JOptionPane.INFORMATION_MESSAGE
                    );
                } catch (FileNotFoundException e1) {
                    JOptionPane.showMessageDialog(
                            parent,
                            "Property file not found" + e1.getLocalizedMessage(),
                            "Properties not loaded",
                            JOptionPane.ERROR_MESSAGE
                    );
                } catch (IOException e1) {
                    JOptionPane.showMessageDialog(
                            parent,
                            "Couldn't read your property file : " + e1.getLocalizedMessage(),
                            "Properties not loaded",
                            JOptionPane.ERROR_MESSAGE
                    );
                }
        }
    }
}
<file_sep>/gui-ecosystem/src/main/java/org/blackpanther/ecosystem/gui/actions/ChangeBackgroundColor.java
package org.blackpanther.ecosystem.gui.actions;

import org.blackpanther.ecosystem.gui.WorldFrame;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;

import static org.blackpanther.ecosystem.gui.GUIMonitor.Monitor;

/**
 * @author <NAME>
 * @version 27/05/11
 */
public class ChangeBackgroundColor
        extends AbstractAction {

    private ChangeBackgroundColor(){
        super("Change background color");
    }

    private static class ChangeBackgroundColorHolder {
        private static final ChangeBackgroundColor instance =
            new ChangeBackgroundColor();
    }

    public static ChangeBackgroundColor getInstance(){
        return ChangeBackgroundColorHolder.instance;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Color selectedColor = JColorChooser.showDialog(
                WorldFrame.getInstance(),
                "Choose agent identifier",
                Color.LIGHT_GRAY);
        if (selectedColor != null) {
            Monitor.setBackgroundColor(selectedColor);
        }
    }
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/behaviour/BehaviorManager.java
package org.blackpanther.ecosystem.behaviour;

import org.blackpanther.ecosystem.Environment;
import org.blackpanther.ecosystem.agent.Creature;

import java.io.Serializable;

/**
 * <p>
 * Strategy Pattern Design.
 * Agent's behavior delegate operations to this interface
 * to update at each cycle, and to interact with the {@link org.blackpanther.ecosystem.Environment}
 * and thus other {@link org.blackpanther.ecosystem.agent.Agent}
 * </p>
 *
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public interface BehaviorManager
        extends Serializable {

    /**
     * Update agent state in given {@link org.blackpanther.ecosystem.Environment}
     *
     * @param env  environment in which the agent evolves
     * @param that monitored agent
     */
    void update(Environment env, Creature that);

}
<file_sep>/gui-ecosystem/src/main/java/org/blackpanther/ecosystem/gui/formatter/RangeModels.java
package org.blackpanther.ecosystem.gui.formatter;

import org.blackpanther.ecosystem.math.Geometry;

import javax.swing.*;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:58 CEST 2011
 */
public final class RangeModels {

    private RangeModels() {
    }

    //Domain : [|0,POS_INF|]
    public static SpinnerNumberModel generatePositiveIntegerModel() {
        return generateIntegerModel(0,Integer.MAX_VALUE);
    }

    public static SpinnerNumberModel generateIntegerModel(int min, int max) {
        return new SpinnerNumberModel(
                min,
                min,
                max,
                1);
    }

    //Domain : [|0,POS_INF|]
    public static SpinnerNumberModel generatePositiveDoubleModel() {
        return generateDoubleModel(0.0, Double.MAX_VALUE);
    }

    //Domain : [|0,POS_INF|]
    public static SpinnerNumberModel generateDoubleModel() {
        return generateDoubleModel(null, null);
    }

    // Domain : Real
    public static SpinnerNumberModel generateDoubleModel(Double min, Double max) {
        return new SpinnerNumberModel(
                0.0,
                min == null ? -Double.MAX_VALUE : min,
                max == null ?  Double.MAX_VALUE : max,
                1.0);
    }

    // Domain : [0.0,1.0]
    public static SpinnerNumberModel generatePercentageModel() {
        return new SpinnerNumberModel(
                0.0,
                0.0,
                1.0,
                0.1);
    }

    // Domain : [0.0,2PI]
    public static SpinnerNumberModel generateAngleModel() {
        return new SpinnerNumberModel(
                0.0,
                0.0,
                Geometry.PI_2.doubleValue(),
                0.1);
    }
}
<file_sep>/gui-ecosystem/src/main/java/org/blackpanther/ecosystem/gui/GUIMonitor.java
package org.blackpanther.ecosystem.gui;

import org.blackpanther.ecosystem.Environment;
import org.blackpanther.ecosystem.agent.Creature;
import org.blackpanther.ecosystem.agent.Resource;
import org.blackpanther.ecosystem.factory.fields.FieldsConfiguration;
import org.blackpanther.ecosystem.gui.actions.EnvironmentSaveBackup;
import org.blackpanther.ecosystem.gui.commands.EnvironmentCommands;
import org.blackpanther.ecosystem.gui.lightweight.EnvironmentInformation;
import org.blackpanther.ecosystem.gui.settings.EnvironmentBoard;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Collection;

import static org.blackpanther.ecosystem.Configuration.*;
import static org.blackpanther.ecosystem.helper.Helper.require;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:58 CEST 2011
 */
public enum GUIMonitor {
    Monitor;

    private GraphicEnvironment drawPanel;
    private EnvironmentBoard environmentBoard;
    private EnvironmentCommands environmentCommandsPanel;

    /*=========================================================================
                             REGISTER
      =========================================================================*/

    public void registerEnvironmentCommandsPanel(EnvironmentCommands environmentCommands) {
        this.environmentCommandsPanel = environmentCommands;
    }

    public void registerDrawPanel(GraphicEnvironment panel) {
        this.drawPanel = panel;
    }

    public void registerEnvironmentInformationPanel(EnvironmentBoard environmentBoard) {
        this.environmentBoard = environmentBoard;
    }

    /*=========================================================================
                          MESSAGES
      =========================================================================*/

    /**
     * Update all panels that an environment has been removed
     */
    public void removeEnvironment() {
        require(drawPanel != null);
        require(environmentBoard != null);
        drawPanel.unsetEnvironment();
        environmentBoard.clearBoard();
        environmentCommandsPanel.environmentUnset();
    }

    /**
     * Update all panels that an environment has been set
     */
    public void setCurrentEnvironment(Environment env) {
        require(drawPanel != null);
        require(environmentBoard != null);
        drawPanel.setEnvironment(env);
        environmentBoard.updateInformation(
                EnvironmentInformation.dump(env, EnvironmentInformation.State.NOT_YET_STARTED));
        environmentBoard.updateInformation(Configuration);
        environmentCommandsPanel.environmentSet();
    }

    public void updateSettingFields(FieldsConfiguration configuration) {
        require(environmentBoard != null);
        environmentBoard.updateInformation(Configuration);
        environmentBoard.updateInformation(configuration);
    }

    /**
     * Notify information panel of current environment state
     */
    public void updateEnvironmentInformation(Environment env, EnvironmentInformation.State state) {
        require(environmentBoard != null);
        require(drawPanel != null);
        require(environmentCommandsPanel != null);
        environmentBoard.updateInformation(EnvironmentInformation.dump(env, state));
        switch (state) {
            case PAUSED:
            case FROZEN:
                environmentCommandsPanel.notifyPause();
                drawPanel.stopSimulation();
                break;
        }
    }

    /**
     * Update evolution flow according to user interaction on evolution's button
     */
    public void interceptEnvironmentEvolutionFlow(String buttonLabel) {
        require(drawPanel != null);
        if (buttonLabel.equals(EnvironmentCommands.START_ENVIRONMENT)) {
            drawPanel.runSimulation();
            environmentBoard.notifyRun();
        } else if (buttonLabel.equals(EnvironmentCommands.STOP_ENVIRONMENT)) {
            environmentBoard.notifyPause();
            drawPanel.stopSimulation();
        }
    }

    /**
     * Update panel option
     */
    public void updateOption(int option, boolean activated) {
        require(drawPanel != null);
        drawPanel.setOption(option, activated);
    }

    public void toggleOption(int option) {
        require(drawPanel != null);
        drawPanel.setOption(option, !drawPanel.isActivated(option));
    }

    public void paintBounds(boolean shouldBePainted) {
        updateOption(GraphicEnvironment.BOUNDS_OPTION, shouldBePainted);
    }

    public void paintResources(boolean shouldBePainted) {
        updateOption(GraphicEnvironment.RESOURCE_OPTION, shouldBePainted);
    }

    public void paintCreatures(boolean shouldBePainted) {
        updateOption(GraphicEnvironment.CREATURE_OPTION, shouldBePainted);
    }

    /**
     * delegator to fetch panel's image
     */
    public BufferedImage dumpCurrentImage() {
        return drawPanel.dumpCurrentImage();
    }

    /**
     * delegator to fetch panel's environment
     */
    public Environment dumpCurrentEnvironment() {
        return drawPanel.dumpCurrentEnvironment();
    }

    /**
     * delegator to fetch setting's configuration
     */
    public FieldsConfiguration fetchConfiguration() {
        require(environmentBoard != null);
        return environmentBoard.createConfiguration();
    }

    /**
     * Global pause action,
     * ordered by internal components
     */
    public void pauseEvolution() {
        require(drawPanel != null);
        require(environmentBoard != null);
        require(environmentCommandsPanel != null);
        drawPanel.stopSimulation();
        environmentBoard.notifyPause();
        environmentCommandsPanel.notifyPause();
    }

    /**
     * Set a new, clean environment
     */
    public void resetEnvironment() {
        require(environmentBoard != null);
        removeEnvironment();
        //pray for that instruction to make things more delightful
        System.gc();
        environmentBoard.updateConfiguration();
        Environment env = new Environment(
                Configuration.getParameter(SPACE_WIDTH, Double.class),
                Configuration.getParameter(SPACE_HEIGHT, Double.class)
        );
        setCurrentEnvironment(env);
    }

    /**
     * delegator to set panel's background color
     */
    public void setBackgroundColor(Color color) {
        require(drawPanel != null);
        drawPanel.applyBackgroundColor(color);
    }

    /**
     * delegator to set panel's agent drop mode
     */
    public void setDropMode(GraphicEnvironment.DropMode mode) {
        require(drawPanel != null);
        drawPanel.setDropMode(mode);
    }

    public void addCreatures(Collection<Creature> creatures) {
        require(drawPanel != null);
        drawPanel.addCreatures(creatures);
    }

    public void addResources(Collection<Resource> creatures) {
        require(drawPanel != null);
        drawPanel.addResources(creatures);
    }

    public void makeBackup(Environment env) {
        EnvironmentSaveBackup.getInstance().backup(
                env,
                Configuration,
                environmentBoard.createConfiguration()
        );
    }

    public FieldsConfiguration dumpFieldsConfiguration() {
        return environmentBoard.createConfiguration();
    }

    public void updateLineWidthLinear(double value) {
        drawPanel.changeLineWidthLinear(value);
    }

    public void updateLineWidthExponential(double value) {
        drawPanel.changeLineWidthExponential(value);
    }

    public void changeColorRatio(double v) {
        drawPanel.changeRatio(v);
    }
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/factory/fields/StateFieldMould.java
package org.blackpanther.ecosystem.factory.fields;

import org.blackpanther.ecosystem.factory.generator.ValueProvider;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public class StateFieldMould<T>
        extends FieldMould<T> {

    public StateFieldMould(String name, ValueProvider<T> valueProvider) {
        super(name, valueProvider);
    }
}
<file_sep>/gui-ecosystem/src/main/java/org/blackpanther/ecosystem/gui/settings/fields/SettingField.java
package org.blackpanther.ecosystem.gui.settings.fields;

import org.blackpanther.ecosystem.factory.fields.FieldMould;

import javax.swing.*;
import java.awt.*;

import static org.blackpanther.ecosystem.helper.Helper.createLabeledField;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:59 CEST 2011
 */
public abstract class SettingField<T>
        extends JPanel {
    public static final Dimension CHECKBOX_DIMENSION = new Dimension(25, 50);
    public static final Dimension FIELD_DIMENSION = new Dimension(60, 50);


    protected SettingField(String name) {
        super();
        initializeComponents(name);
        setLayout(new GridBagLayout());
        placeComponents(this);
    }

    abstract protected void initializeComponents(String fieldName);

    protected void placeComponents(JPanel layout) {
        GridBagConstraints constraints = new GridBagConstraints();

        constraints.ipadx = 20;
        constraints.fill = GridBagConstraints.HORIZONTAL;
        layout.add(createLabeledField(
                getMainComponent().getName(),
                getMainComponent()
        ), constraints);
    }

    public abstract JComponent getMainComponent();

    abstract public void setValue(T newValue);

    abstract public T getValue();

    abstract public FieldMould<T> toMould();
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/event/EnvironmentMonitor.java
package org.blackpanther.ecosystem.event;

import org.blackpanther.ecosystem.agent.Agent;
import org.blackpanther.ecosystem.Environment;

import java.awt.geom.Line2D;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public class EnvironmentMonitor
        implements Serializable {
    /**
     * Line's event listeners
     */
    private Set<LineListener> lineListeners =
            new HashSet<LineListener>();
    private Set<EvolutionListener> evolutionListeners =
            new HashSet<EvolutionListener>();
    private Set<AgentListener> agentListeners =
            new HashSet<AgentListener>();

    private Environment source;

    public EnvironmentMonitor(Environment sourceEnvironment) {
        this.source = sourceEnvironment;
    }

    /*=========================================================================
                               SERIALIZATION
      =========================================================================*/

    public void clearAllExternalsListeners(){
        lineListeners.clear();
        evolutionListeners.clear();
        Iterator<AgentListener> it = agentListeners.iterator();
        while (it.hasNext())
            if (!(it.next() instanceof Environment))
                it.remove();
    }

    /*=========================================================================
                               LISTENER HOOK
      =========================================================================*/

    public void addAgentListener(AgentListener listener) {
        agentListeners.add(listener);
    }

    public void addLineListener(LineListener listener) {
        lineListeners.add(listener);
    }

    public void addEvolutionListener(EvolutionListener listener) {
        evolutionListeners.add(listener);
    }

    /*=========================================================================
                               EVENT DELEGATE
      =========================================================================*/


    public void fireAgentEvent(AgentEvent.Type eventType, Agent value) {
        AgentEvent event = new AgentEvent(eventType, source, value);
        for (AgentListener listener : agentListeners) {
            listener.update(event);
        }
    }

    public void fireLineEvent(LineEvent.Type eventType, Line2D value) {
        LineEvent event = new LineEvent(eventType, source, value);
        for (LineListener listener : lineListeners) {
            listener.update(event);
        }
    }

    public void fireEvolutionEvent(EvolutionEvent.Type eventType) {
        EvolutionEvent event = new EvolutionEvent(eventType, source);
        for (EvolutionListener listener : evolutionListeners) {
            listener.update(event);
        }
    }

    public void removeAgentListener(AgentListener listener) {
        agentListeners.remove(listener);
    }

    public void removeEvolutionListener(EvolutionListener listener) {
        evolutionListeners.remove(listener);
    }

    public void removeLineListener(LineListener listener) {
        lineListeners.remove(listener);
    }
}<file_sep>/gui-ecosystem/src/main/java/org/blackpanther/ecosystem/gui/settings/fields/randomable/Randomable.java
package org.blackpanther.ecosystem.gui.settings.fields.randomable;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:59 CEST 2011
 */
interface Randomable {
    public boolean isRandomized();
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/factory/generator/random/DoubleProvider.java
package org.blackpanther.ecosystem.factory.generator.random;

import org.blackpanther.ecosystem.Configuration;
import org.blackpanther.ecosystem.factory.generator.RandomProvider;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:58 CEST 2011
 */
public class DoubleProvider
        extends RandomProvider<Double> {

    private double min;
    private double max;

    public DoubleProvider(double min, double max) {
        this.min = min;
        this.max = max;
    }

    @Override
    public Double getValue() {
        return min +
                Configuration.Configuration.getRandom().nextDouble()
                        * (max - min);
    }
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/behaviour/PredatorBehaviour.java
package org.blackpanther.ecosystem.behaviour;

import org.blackpanther.ecosystem.Environment;
import org.blackpanther.ecosystem.SenseResult;
import org.blackpanther.ecosystem.SensorTarget;
import org.blackpanther.ecosystem.agent.Agent;
import org.blackpanther.ecosystem.agent.Creature;

import java.awt.geom.Point2D;
import java.util.Collection;
import java.util.Iterator;

import static java.lang.Math.PI;
import static org.blackpanther.ecosystem.agent.Agent.CREATURE_GREED;
import static org.blackpanther.ecosystem.agent.CreatureConstants.CREATURE_CONSUMMATION_RADIUS;
import static org.blackpanther.ecosystem.math.Geometry.PI_2;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public class PredatorBehaviour
        extends DraughtsmanBehaviour {

    private PredatorBehaviour(){}

    private static class PredatorBehaviourHolder {
        private static final PredatorBehaviour instance =
            new PredatorBehaviour();
    }

    public static PredatorBehaviour getInstance(){
        return PredatorBehaviourHolder.instance;
    }

    @Override
    protected void react(Environment env, Creature that, SenseResult analysis) {
        SensorTarget<Creature> closestPrey =
                getClosestPrey(that.getLocation(), analysis.getNearCreatures());

        //run after closest prey
        if (closestPrey != null && closestPrey.getTarget().isAlive()) {

            //check if we can still move and reach the target
            double resourceDistance = that.getLocation().distance(closestPrey.getTarget().getLocation());
            if (resourceDistance < that.getGene(CREATURE_CONSUMMATION_RADIUS, Double.class)) {

                //we eat it
                that.setEnergy(that.getEnergy() + closestPrey.getTarget().getEnergy());
                that.setColor(
                        ( that.getColor().getRed() + closestPrey.getTarget().getColor().getRed() ) / 2,
                        ( that.getColor().getGreen() + closestPrey.getTarget().getColor().getGreen() ) / 2,
                        ( that.getColor().getBlue() + closestPrey.getTarget().getColor().getBlue() ) / 2
                );
                closestPrey.getTarget().detachFromEnvironment(env);

            }

            //otherwise get closer
            else {
                double lust = that.getGene(CREATURE_GREED, Double.class);
                double alpha = (that.getOrientation() % PI_2);
                double beta = closestPrey.getOrientation();
                double resourceRelativeOrientation = (beta - alpha);
                if (resourceRelativeOrientation > PI)
                    resourceRelativeOrientation -= PI_2;
                else if (resourceRelativeOrientation < -PI)
                    resourceRelativeOrientation += PI_2;
                double newOrientation = (alpha + resourceRelativeOrientation * lust) % PI_2;

                that.setOrientation(newOrientation);
            }
        }

        //their only goals is to eat agent, not resources
    }

    private SensorTarget<Creature> getClosestPrey(Point2D source, Collection<SensorTarget<Creature>> agents) {
        Iterator<SensorTarget<Creature>> it = agents.iterator();
        SensorTarget<Creature> closest = null;
        double closestDistance = Double.MAX_VALUE;
        while (it.hasNext()) {
            SensorTarget<Creature> monster = it.next();

            //detect only preys
            if (PreyBehaviour.class.isInstance(
                    monster.getTarget()
                            .getGene(Agent.CREATURE_BEHAVIOR, BehaviorManager.class))) {

                double distance = source.distance(monster.getTarget().getLocation());

                if (closest == null) {
                    closest = monster;
                    closestDistance = distance;
                } else {
                    if (distance < closestDistance) {
                        closest = monster;
                        closestDistance = distance;
                    }
                }
            }
        }

        return closest;
    }
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/agent/Resource.java
package org.blackpanther.ecosystem.agent;

import org.blackpanther.ecosystem.Environment;
import org.blackpanther.ecosystem.factory.fields.FieldsConfiguration;

import static org.blackpanther.ecosystem.factory.fields.FieldsConfiguration.checkResourceConfiguration;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public class Resource
        extends Agent
        implements ResourceConstants {

    public Resource(FieldsConfiguration config) {
        super(config);
        checkResourceConfiguration(config);
        for (String stateTrait : BUILD_PROVIDED_RESOURCE_STATE)
            currentState.put(stateTrait, config.getValue(stateTrait));

        for (String genotypeTrait : RESOURCE_GENOTYPE) {
            genotype.put(genotypeTrait, config.getValue(genotypeTrait));
            mutableTable.put(genotypeTrait, config.isMutable(Resource.class, genotypeTrait));
        }
    }

    /**
     * A resource don't update
     */
    @Override
    public void update(Environment env) {
    }

    @Override
    public double getEnergy() {
        return getState(RESOURCE_ENERGY, Double.class);
    }

    @Override
    public void setEnergy(Double energy) {
        currentState.put(RESOURCE_ENERGY, energy < 0.0
                ? 0.0
                : energy);
    }

    @Override
    public Resource clone() {
        return (Resource) super.clone();
    }

    @Override
    public String toString() {
        return super.toString();
    }
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/factory/ResourceFactory.java
package org.blackpanther.ecosystem.factory;

import org.blackpanther.ecosystem.agent.Resource;
import org.blackpanther.ecosystem.factory.fields.FieldsConfiguration;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public class ResourceFactory
        extends EnvironmentFactory<Resource> {

    ResourceFactory() {
    }

    @Override
    public Resource createAgent(FieldsConfiguration config) {
        return new Resource(config);
    }

}
<file_sep>/gui-ecosystem/src/main/java/org/blackpanther/ecosystem/app/Launcher.java
package org.blackpanther.ecosystem.app;

import org.blackpanther.ecosystem.gui.WorldFrame;

import javax.swing.*;
import java.io.IOException;
import java.util.logging.LogManager;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:59 CEST 2011
 */
public class Launcher {

    public static void main(String[] args) {
        //Show them our wonderful GUI
        createAndShowGUI();
    }

    public static void createAndShowGUI() {
        try {
            LogManager.getLogManager().readConfiguration(
                    Launcher.class.getClassLoader().getResourceAsStream("logging.properties")
            );
        } catch (IOException e) {
            e.printStackTrace();
        }

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                WorldFrame.getInstance().setVisible(true);
                WorldFrame.getInstance().validate();
            }
        });
    }
}<file_sep>/gui-ecosystem/src/main/java/org/blackpanther/ecosystem/gui/commands/EnvironmentCommands.java
package org.blackpanther.ecosystem.gui.commands;

import org.blackpanther.ecosystem.gui.GraphicEnvironment;

import javax.swing.*;
import javax.swing.border.EtchedBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionListener;
import java.beans.EventHandler;

import static org.blackpanther.ecosystem.gui.GUIMonitor.Monitor;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:58 CEST 2011
 */
public class EnvironmentCommands
        extends JPanel {

    public static final String STOP_ENVIRONMENT = "Pause";
    public static final String START_ENVIRONMENT = "Start";
    public static final String NO_ENVIRONMENT = "No environment set";
    public static final String FROZEN_ENVIRONMENT = "Environment frozen";

    private JButton evolutionFlowButton;

    private JToggleButton noAction;
    private JToggleButton paintAgent;
    private JToggleButton paintResource;

    public EnvironmentCommands() {
        super();
        setLayout(new FlowLayout());


        JButton resetEnvironment = new JButton("Generate new environment");
        evolutionFlowButton = new JButton(NO_ENVIRONMENT);

        noAction = new JToggleButton("No action");
        paintAgent = new JToggleButton("Agent dropper");
        paintResource = new JToggleButton("Resource dropper");

        JSlider lineWidthLinear = new JSlider(1, 10, 1);
        JSlider lineWidthExponential = new JSlider(0, 10, 0);
        JSlider colorBlender = new JSlider(0, 1000000, 10000);

        ActionListener toggleListener = EventHandler.create(
                ActionListener.class,
                this,
                "updateDropMode",
                "source"
        );

        lineWidthLinear.addChangeListener(EventHandler.create(
                ChangeListener.class,
                this,
                "updateLineWidthLinear",
                ""
        ));

        lineWidthExponential.addChangeListener(EventHandler.create(
                ChangeListener.class,
                this,
                "updateLineWidthExponential",
                ""
        ));
        colorBlender.addChangeListener(EventHandler.create(
                ChangeListener.class,
                this,
                "updateColorRatio",
                ""
        ));

        noAction.setSelected(true);
        noAction.addActionListener(toggleListener);
        paintAgent.addActionListener(toggleListener);
        paintResource.addActionListener(toggleListener);
        resetEnvironment.addActionListener(EventHandler.create(
                ActionListener.class,
                Monitor,
                "resetEnvironment"
        ));
        evolutionFlowButton.setEnabled(false);
        evolutionFlowButton.addActionListener(EventHandler.create(
                ActionListener.class,
                this,
                "switchStartPause"
        ));
        evolutionFlowButton.addActionListener(EventHandler.create(
                ActionListener.class,
                Monitor,
                "interceptEnvironmentEvolutionFlow",
                "source.text"
        ));

        add(noAction);
        add(paintAgent);
        add(paintResource);
        add(Box.createVerticalStrut(40));
        add(resetEnvironment);
        add(evolutionFlowButton);
        add(Box.createVerticalStrut(40));
        add(lineWidthLinear);
        add(lineWidthExponential);
        add(colorBlender);

        setBorder(
                BorderFactory.createEtchedBorder(EtchedBorder.RAISED)
        );
    }

    public void updateLineWidthLinear(ChangeEvent e) {
        JSlider source = (JSlider) e.getSource();
        if (!source.getValueIsAdjusting()) {
            Monitor.updateLineWidthLinear(source.getValue());
        }
    }

    public void updateLineWidthExponential(ChangeEvent e) {
        JSlider source = (JSlider) e.getSource();
        if (!source.getValueIsAdjusting()) {
            Monitor.updateLineWidthExponential(source.getValue() / 10.0);
        }
    }

    public void updateColorRatio(ChangeEvent e) {
        JSlider source = (JSlider) e.getSource();
        if (!source.getValueIsAdjusting()) {
            Monitor.changeColorRatio(source.getValue() / 100.0);
        }
    }

    public void updateDropMode(JToggleButton button) {
        noAction.setSelected(false);
        paintAgent.setSelected(false);
        paintResource.setSelected(false);
        button.setSelected(true);

        GraphicEnvironment.DropMode mode = GraphicEnvironment.DropMode.NONE;
        if (noAction.isSelected()) {
            mode = GraphicEnvironment.DropMode.NONE;
        } else if (paintAgent.isSelected()) {
            mode = GraphicEnvironment.DropMode.AGENT;
        } else if (paintResource.isSelected()) {
            mode = GraphicEnvironment.DropMode.RESOURCE;
        }
        Monitor.setDropMode(mode);
    }

    public void switchStartPause() {
        if (evolutionFlowButton.getText()
                .equals(STOP_ENVIRONMENT)) {
            evolutionFlowButton.setText(START_ENVIRONMENT);
        } else if (evolutionFlowButton.getText()
                .equals(START_ENVIRONMENT)) {
            evolutionFlowButton.setText(STOP_ENVIRONMENT);
        } else {
            evolutionFlowButton.setText(NO_ENVIRONMENT);
        }
    }

    public void environmentSet() {
        evolutionFlowButton.setText(START_ENVIRONMENT);
        evolutionFlowButton.setEnabled(true);
    }

    public void environmentUnset() {
        evolutionFlowButton.setText(NO_ENVIRONMENT);
        evolutionFlowButton.setEnabled(false);
    }

    public void environmentFrozen() {
        evolutionFlowButton.setText(FROZEN_ENVIRONMENT);
        evolutionFlowButton.setEnabled(false);
    }

    public void notifyPause() {
        if (evolutionFlowButton.getText().equals(STOP_ENVIRONMENT)) {
            evolutionFlowButton.setText(START_ENVIRONMENT);
        }
    }
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/factory/generator/provided/IntegerProvider.java
package org.blackpanther.ecosystem.factory.generator.provided;

import org.blackpanther.ecosystem.factory.generator.StandardProvider;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:58 CEST 2011
 */
public class IntegerProvider
        extends StandardProvider<Integer> {

    public IntegerProvider(Integer provided) {
        super(provided);
    }
}
<file_sep>/gui-ecosystem/src/main/java/org/blackpanther/ecosystem/gui/WorldFrame.java
package org.blackpanther.ecosystem.gui;

import com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel;
import org.blackpanther.ecosystem.gui.actions.*;
import org.blackpanther.ecosystem.gui.commands.EnvironmentCommands;
import org.blackpanther.ecosystem.gui.settings.EnvironmentBoard;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.net.URL;

import static org.blackpanther.ecosystem.Configuration.*;
import static org.blackpanther.ecosystem.gui.GUIMonitor.Monitor;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:58 CEST 2011
 */
public class WorldFrame
        extends JFrame {

    public static final String ICON_PATH = "org/blackpanther/black-cat-icon.png";
    public static final Image APPLICATION_ICON = fetchApplicationIcon();
    private JCheckBox[] options;

    //Set UI Manager
    static {
        try {
            UIManager.setLookAndFeel(
                    new NimbusLookAndFeel()
            );
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }
    }

    private static Image fetchApplicationIcon() {
        try {
            URL resourceURL = WorldFrame.class.getClassLoader()
                    .getResource(ICON_PATH);
            return ImageIO.read(resourceURL);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    private WorldFrame() {
        super();
        setTitle("GUI Ecosystem Evolution Visualizer");
        if (APPLICATION_ICON != null)
            setIconImage(APPLICATION_ICON);

        GraphicEnvironment graphicEnvironment =
                new GraphicEnvironment();
        Monitor.registerDrawPanel(
                graphicEnvironment
        );

        EnvironmentBoard environmentBoard =
                new EnvironmentBoard();
        Monitor.registerEnvironmentInformationPanel(
                environmentBoard
        );

        EnvironmentCommands environmentCommands =
                new EnvironmentCommands();
        Monitor.registerEnvironmentCommandsPanel(
                environmentCommands
        );

        getContentPane().setLayout(new BorderLayout());
        getContentPane().add(
                wrapComponent(environmentBoard, BorderLayout.WEST),
                BorderLayout.WEST
        );
        getContentPane().add(
                graphicEnvironment,
                BorderLayout.CENTER
        );
        getContentPane().add(
                wrapComponent(environmentCommands, BorderLayout.CENTER),
                BorderLayout.SOUTH
        );

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        pack();
        setExtendedState(MAXIMIZED_BOTH);

        setJMenuBar(buildMenuBar());

        Monitor.resetEnvironment();
    }

    private static class WorldFrameHolder {
        private static final WorldFrame instance =
                new WorldFrame();
    }

    public static WorldFrame getInstance() {
        return WorldFrameHolder.instance;
    }

    private JMenuBar buildMenuBar() {
        JMenuBar menuBar = new JMenuBar();

        JMenu environment = new JMenu("Environment");
        JMenu painting = new JMenu("Paint options");

        environment.add(ConfigurationSave.getInstance());
        environment.add(ConfigurationLoad.getInstance());
        environment.addSeparator();
        environment.add(EnvironmentSave.getInstance());
        environment.add(EnvironmentSaveBackup.getInstance());
        environment.addSeparator();
        environment.add(EnvironmentLoad.getInstance());
        environment.add(EnvironmentFromFile.getInstance());
        environment.addSeparator();
        environment.add(SaveImageAction.getInstance());

        JCheckBox[] togglers = new JCheckBox[5];
        for (int i = 0; i < togglers.length; i++) {
            togglers[i] = new JCheckBox();
            togglers[i].setSelected(true);
        }

        togglers[0].setAction(ToggleBounds.getInstance());
        togglers[1].setAction(ToggleCreatures.getInstance());
        togglers[2].setAction(ToggleResources.getInstance());
        togglers[3].setAction(ToggleLineObstruction.getInstance());
        togglers[4].setAction(TogglePerlinNoise.getInstance());

        //change whether option is activated or not
        togglers[3].setSelected(
                Configuration.getParameter(LINE_OBSTRUCTION_OPTION, Boolean.class));
        togglers[4].setSelected(
                Configuration.getParameter(PERLIN_NOISE_OPTION, Boolean.class));

        //keep a reference to them
        options = new JCheckBox[]{
                togglers[3],
                togglers[4]
        };

        painting.add(togglers[0]);//bounds
        painting.add(togglers[1]);//creatures
        painting.add(togglers[2]);//resources
        painting.addSeparator();
        painting.add(togglers[3]);//line obstruction
        painting.add(togglers[4]);//perlin noise
        painting.addSeparator();
        painting.add(ChangeBackgroundColor.getInstance());

        menuBar.add(environment);
        menuBar.add(painting);

        return menuBar;
    }

    public void updateCheckBoxMenuItem(String checkboxName, boolean activated) {
        if (checkboxName.equals(LINE_OBSTRUCTION_OPTION))
            options[0].setSelected(activated);
        else if (checkboxName.equals(PERLIN_NOISE_OPTION))
            options[1].setSelected(activated);
    }

    /**
     * Convenience method.<br/>
     * Don't hate me because of the trick...
     */
    private static JPanel wrapComponent(final Component c, final String flag) {
        return new JPanel(new BorderLayout()) {{
            add(c, flag);
        }};
    }
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/factory/generator/provided/LocationProvider.java
package org.blackpanther.ecosystem.factory.generator.provided;

import org.blackpanther.ecosystem.factory.generator.StandardProvider;

import java.awt.geom.Point2D;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:58 CEST 2011
 */
public class LocationProvider
    extends StandardProvider<Point2D>{

    public LocationProvider(Point2D provided) {
        super(provided);
    }
}
<file_sep>/ecosystem-framework/src/test/java/org/blackpanther/ecosystem/math/GeometryTester.java
package org.blackpanther.ecosystem.math;

import org.junit.Test;

import java.awt.geom.Line2D;
import java.awt.geom.Point2D;

import static org.blackpanther.ecosystem.math.Geometry.getIntersection;
import static org.junit.Assert.*;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:58 CEST 2011
 */
public class GeometryTester {

    @Test
    public void intersectionPoint() {
        Point2D firstIntersection = new Point2D.Double(1.0, 1.0);
        Point2D secondIntersection = new Point2D.Double(1.0, 0.0);

        assertEquals(
                "Fail at basic intersection between " +
                        "[(0.0,2.0),(2.0,0.0) & (0.0,0.0),(2.0,2.0)]",
                firstIntersection,
                getIntersection(
                        new Line2D.Double(0.0, 2.0, 2.0, 0.0),
                        new Line2D.Double(0.0, 0.0, 2.0, 2.0)
                )
        );

        assertEquals(
                "Fail at basic intersection between " +
                        "[(0.0,1.0),(3.0,-2.0) & (0.0,0.0),(2.0,0.0)]",
                secondIntersection,
                getIntersection(
                        new Line2D.Double(0.0, 1.0, 3.0, -2.0),
                        new Line2D.Double(0.0, 0.0, 2.0, 0.0)
                )
        );

        assertNull(
                "Not intersection because liens are not infinite",
                getIntersection(
                        new Line2D.Double(0.0, -2.0, 2.0, -2.0),
                        new Line2D.Double(0.0, 1.0, 3.0, -2.0)
                )
        );

        assertNull(
                "Not intersection because liens are not infinite",
                getIntersection(
                        new Line2D.Double(0.0, 1.0, 3.0, -2.0),
                        new Line2D.Double(0.0, 0.0, 0.0, -2.0)
                )
        );

        assertNotNull(
                "???",
                getIntersection(
                        new Line2D.Double(198.0, 383.73, 199.82, 377.18),
                        new Line2D.Double(200.55, 383.55, 197.63, 377.72)
                )
        );

    }
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/event/EvolutionEvent.java
package org.blackpanther.ecosystem.event;

import org.blackpanther.ecosystem.Environment;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public class EvolutionEvent
        extends EnvironmentEvent {

    /**
     * Precise type of the event that happened
     */
    public enum Type {
        STARTED,
        CYCLE_END,
        ENDED
    }

    private Type type;

    /**
     * Constructs a prototypical Event.
     *
     * @param source The object on which the Event initially occurred.
     * @throws IllegalArgumentException if source is null.
     */
    public EvolutionEvent(Type eventType, Environment source) {
        super(source);
        this.type = eventType;
    }

    public Type getType() {
        return type;
    }
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/factory/EnvironmentAbstractFactory.java
package org.blackpanther.ecosystem.factory;

import org.blackpanther.ecosystem.agent.Agent;
import org.blackpanther.ecosystem.agent.Creature;
import org.blackpanther.ecosystem.agent.Resource;

import java.util.HashMap;
import java.util.Map;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public class EnvironmentAbstractFactory {

    private EnvironmentAbstractFactory() {
    }

    private static final Map<Class, EnvironmentFactory> factoryRegister = new HashMap<Class, EnvironmentFactory>(2) {{
        put(Creature.class, new CreatureFactory());
        put(Resource.class, new ResourceFactory());
    }};

    @SuppressWarnings("unchecked")
    public static <T extends Agent> EnvironmentFactory<T> getFactory(Class<T> agentType) {
        return factoryRegister.get(agentType);
    }

}
<file_sep>/gui-ecosystem/src/main/java/org/blackpanther/ecosystem/gui/settings/AgentParameterPanel.java
package org.blackpanther.ecosystem.gui.settings;

import org.blackpanther.ecosystem.factory.fields.FieldMould;
import org.blackpanther.ecosystem.factory.fields.FieldsConfiguration;
import org.blackpanther.ecosystem.factory.fields.GeneFieldMould;
import org.blackpanther.ecosystem.gui.settings.fields.SettingField;
import org.blackpanther.ecosystem.gui.settings.fields.mutable.Mutable;
import org.blackpanther.ecosystem.gui.settings.fields.randomable.RandomSettingField;

import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:59 CEST 2011
 */
public abstract class AgentParameterPanel
        extends ParameterPanel {

    protected AgentParameterPanel(String name) {
        super(name);
    }

    @Override
    protected void generateContent(Box layout) {
        Box state = Box.createVerticalBox();
        Box genotype = Box.createVerticalBox();

        state.setBorder(BorderFactory.createTitledBorder("State"));
        genotype.setBorder(BorderFactory.createTitledBorder("Genotype"));

        fillUpState(state);
        fillUpGenotype(genotype);

        if (state.getComponentCount() > 0)
            layout.add(state);
        if (genotype.getComponentCount() > 0)
            layout.add(genotype);
    }

    abstract void fillUpState(Box layout);

    abstract void fillUpGenotype(Box layout);

    @SuppressWarnings("unchecked")
    public void updateInformation(FieldsConfiguration information) {
        for (Map.Entry<String, SettingField> entry : parameters.entrySet()) {
            SettingField field = entry.getValue();
            FieldMould incomingMould = information.getField(entry.getKey());
            if( incomingMould instanceof GeneFieldMould) {
                GeneFieldMould geneMould = (GeneFieldMould) incomingMould;
                Mutable geneField = (Mutable) field;
                geneField.setMutable(
                        geneMould.isMutable());
            }
            RandomSettingField randomField = (RandomSettingField) field;
            randomField.setRandomized(
                    incomingMould.isRandomized());
            field.setValue(
                    information.getValue(entry.getKey()));
        }
    }

    public Collection<FieldMould> getMoulds() {
        Collection<FieldMould> moulds = new ArrayList<FieldMould>(parameters.size());
        for (SettingField field : parameters.values())
            moulds.add(field.toMould());
        return moulds;
    }
}
<file_sep>/gui-ecosystem/src/main/java/org/blackpanther/ecosystem/gui/actions/EnvironmentFromFile.java
package org.blackpanther.ecosystem.gui.actions;

import org.blackpanther.ecosystem.ApplicationConstants;
import org.blackpanther.ecosystem.Configuration;
import org.blackpanther.ecosystem.Environment;
import org.blackpanther.ecosystem.agent.Resource;
import org.blackpanther.ecosystem.agent.ResourceConstants;
import org.blackpanther.ecosystem.factory.fields.FieldsConfiguration;
import org.blackpanther.ecosystem.factory.fields.StateFieldMould;
import org.blackpanther.ecosystem.gui.GUIMonitor;
import org.blackpanther.ecosystem.gui.WorldFrame;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.beans.EventHandler;
import java.io.File;
import java.io.IOException;

import static javax.swing.BoxLayout.X_AXIS;
import static javax.swing.BoxLayout.Y_AXIS;
import static org.blackpanther.ecosystem.agent.AgentConstants.AGENT_LOCATION;
import static org.blackpanther.ecosystem.factory.generator.StandardProvider.StandardProvider;
import static org.blackpanther.ecosystem.gui.formatter.RangeModels.generateIntegerModel;
import static org.blackpanther.ecosystem.gui.formatter.RangeModels.generatePositiveDoubleModel;
import static org.blackpanther.ecosystem.gui.formatter.RangeModels.generatePositiveIntegerModel;
import static org.blackpanther.ecosystem.helper.Helper.require;

/**
 * @author <NAME>
 * @version 6/11/11
 */
public class EnvironmentFromFile
        extends FileBrowserAction {

    private EnvironmentWizard creationWizard = new EnvironmentWizard();

    private EnvironmentFromFile() {
        super("Create an environment from an image file",
                "Image files",
                "png",
                "jpg",
                "jpeg",
                "gif"
        );
    }

    private static class EnvironmentFromFileHolder {
        private static final EnvironmentFromFile instance =
                new EnvironmentFromFile();
    }

    public static EnvironmentFromFile getInstance() {
        return EnvironmentFromFileHolder.instance;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        creationWizard.setVisible(true);
    }

    public class EnvironmentWizard extends JDialog {

        private static final String NO_FILE_SELECTED = "No file selected.";

        private JLabel path = new JLabel(NO_FILE_SELECTED);
        private JSpinner defaultEnergy = new JSpinner(generatePositiveDoubleModel());
        private JSpinner dropperStep = new JSpinner(generateIntegerModel(1, Integer.MAX_VALUE));
        private boolean excludeWhite = false;

        JButton accept = new JButton("Accept");
        private File selectedFile = null;

        private EnvironmentWizard() {
            super(WorldFrame.getInstance());
            defaultEnergy.setValue(100.0);
            defaultEnergy.setPreferredSize(new Dimension(100, 30));
            dropperStep.setValue(1);
            dropperStep.setPreferredSize(new Dimension(100, 30));

            accept.setEnabled(false);

            path.setEnabled(false);
            path.setFont(new Font("Default", Font.ITALIC, 10));

            JButton chooseFile = new JButton("Select your image");
            JButton cancel = new JButton("Cancel");

            JLabel energyAmountLabel = new JLabel("Initial amount for resources : ");
            energyAmountLabel.setLabelFor(defaultEnergy);

            JLabel dropperStepLabel = new JLabel("Drop step (in pixels) : ");
            dropperStepLabel.setLabelFor(dropperStep);

            JCheckBox excludeWhite = new JCheckBox("Exclude white color ? ", false);
            excludeWhite.addActionListener(EventHandler.create(
                    ActionListener.class,
                    this,
                    "updateExcludeWhiteProperty",
                    "source.selected"
            ));

            chooseFile.addActionListener(EventHandler.create(
                    ActionListener.class,
                    this,
                    "updateFilePath"
            ));

            accept.addActionListener(EventHandler.create(
                    ActionListener.class,
                    this,
                    "generateEnvironment"
            ));

            cancel.addActionListener(EventHandler.create(
                    ActionListener.class,
                    this,
                    "cancelOperation"
            ));

            Box labeledEnergyField = new Box(X_AXIS);
            labeledEnergyField.add(energyAmountLabel);
            labeledEnergyField.add(defaultEnergy);

            Box labeledDropperField = new Box(X_AXIS);
            labeledDropperField.add(dropperStepLabel);
            labeledDropperField.add(dropperStep);

            Box top = new Box(Y_AXIS);
            top.add(chooseFile);
            top.add(path);
            top.add(labeledEnergyField);
            top.add(labeledDropperField);
            top.add(excludeWhite);

            Box commands = new Box(X_AXIS);
            commands.add(accept);
            commands.add(cancel);

            JPanel content = new JPanel(new BorderLayout());
            content.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));

            content.add(top, BorderLayout.CENTER);
            content.add(commands, BorderLayout.SOUTH);

            setContentPane(content);

            pack();
        }

        public void updateExcludeWhiteProperty(boolean shouldBeExcluded){
            excludeWhite = shouldBeExcluded;
        }

        public void updateFilePath() throws IOException {
            switch (fc.showOpenDialog(null)) {
                case JFileChooser.APPROVE_OPTION:
                    selectedFile = fc.getSelectedFile();
                    if (selectedFile != null) {
                        path.setText(selectedFile.getCanonicalPath());
                        accept.setEnabled(true);
                    } else {
                        path.setText(NO_FILE_SELECTED);
                        accept.setEnabled(false);
                    }
            }
        }

        @SuppressWarnings("unchecked")
        public void generateEnvironment() {
            require(selectedFile != null);
            try {
                BufferedImage inputImage = ImageIO.read(selectedFile);
                Dimension imageDimension = new Dimension(inputImage.getWidth(), inputImage.getHeight());
                Configuration.Configuration.setParameter(
                        ApplicationConstants.SPACE_WIDTH,
                        imageDimension.getWidth(),
                        Double.class
                );
                Configuration.Configuration.setParameter(
                        ApplicationConstants.SPACE_HEIGHT,
                        imageDimension.getHeight(),
                        Double.class
                );
                Environment imageEnvironment = new Environment(imageDimension);
                Double resourceEnergyAmount = (Double) defaultEnergy.getValue();
                Integer dropStep = (Integer) dropperStep.getValue();

                FieldsConfiguration resourceConfiguration = new FieldsConfiguration(
                        new StateFieldMould<Double>(
                                ResourceConstants.RESOURCE_ENERGY,
                                StandardProvider(resourceEnergyAmount))
                );

                for (int i = 0; i < imageDimension.getWidth(); i+= dropStep)
                    for (int j = 0; j < imageDimension.getHeight(); j+= dropStep) {
                        Color pixelColor = new Color(inputImage.getRGB(i, j));

                        if( pixelColor.equals(Color.WHITE) && excludeWhite )
                            continue;

                        resourceConfiguration.updateMould(new StateFieldMould(
                                AGENT_LOCATION,
                                StandardProvider(
                                        imageToEnvironment(i, j, imageDimension))
                        ));
                        resourceConfiguration.updateMould(new StateFieldMould(
                                ResourceConstants.RESOURCE_NATURAL_COLOR,
                                StandardProvider(
                                        pixelColor
                                )
                        ));
                        imageEnvironment.add(new Resource(resourceConfiguration));
                    }

                GUIMonitor.Monitor.setCurrentEnvironment(imageEnvironment);
                setVisible(false);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public void cancelOperation() {
            setVisible(false);
        }

        private Point2D imageToEnvironment(int imageAbscissa, int imageOrdinate, Dimension imageDimension) {
            double environmentAbscissa = imageAbscissa - (imageDimension.getWidth() / 2.0);
            double environmentOrdinate = (imageDimension.getHeight() / 2.0) - imageOrdinate;

            return new Point2D.Double(
                    environmentAbscissa,
                    environmentOrdinate
            );
        }
    }
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/factory/PopulationFactory.java
package org.blackpanther.ecosystem.factory;

import org.blackpanther.ecosystem.agent.Agent;
import org.blackpanther.ecosystem.agent.Creature;
import org.blackpanther.ecosystem.factory.fields.FieldsConfiguration;
import org.blackpanther.ecosystem.factory.fields.StateFieldMould;

import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collection;

import static org.blackpanther.ecosystem.Configuration.*;
import static org.blackpanther.ecosystem.agent.AgentConstants.AGENT_LOCATION;
import static org.blackpanther.ecosystem.agent.CreatureConstants.CREATURE_ORIENTATION;
import static org.blackpanther.ecosystem.factory.generator.StandardProvider.StandardProvider;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public class PopulationFactory {
    private static final java.util.logging.Logger logger =
            java.util.logging.Logger.getLogger(PopulationFactory.class.getCanonicalName());

    @SuppressWarnings("unchecked")
    public static <T extends Agent> Collection<T> generatePool(
            Class<T> species,
            FieldsConfiguration agentConfiguration,
            Integer agentNumber) {
        Collection<T> pool = new ArrayList<T>(agentNumber);
        for (long number = agentNumber; number-- > 0; ) {
            //update location
            agentConfiguration.updateMould(new StateFieldMould(
                    AGENT_LOCATION,
                    StandardProvider(new Point2D.Double(
                            Configuration.getParameter(SPACE_WIDTH, Double.class) * Configuration.getRandom().nextDouble()
                                    - Configuration.getParameter(SPACE_WIDTH, Double.class) / 2.0,
                            Configuration.getParameter(SPACE_HEIGHT, Double.class) * Configuration.getRandom().nextDouble()
                                    - Configuration.getParameter(SPACE_HEIGHT, Double.class) / 2.0
                    ))
            ));
            //add specific agent in the pool
            pool.add(EnvironmentAbstractFactory
                    .getFactory(species)
                    .createAgent(agentConfiguration));
        }
        return pool;
    }

    @SuppressWarnings("unchecked")
    public static <T extends Agent> Collection<T> generateGridPool(
            Class<T> species,
            FieldsConfiguration agentConfiguration,
            Dimension2D gridDimension,
            double step) {
        Collection<T> pool = new ArrayList<T>(
                (int) ((gridDimension.getHeight() * gridDimension.getWidth()) / step));
        double widthBy2 = gridDimension.getWidth() / 2.0;
        double heightBy2 = gridDimension.getHeight() / 2.0;
        for (double abscissa = -widthBy2;
             abscissa < widthBy2;
             abscissa += step) {
            for (double ordinate = -heightBy2;
                 ordinate < heightBy2;
                 ordinate += step) {
                //update location
                agentConfiguration.updateMould(new StateFieldMould(
                        AGENT_LOCATION,
                        StandardProvider(new Point2D.Double(abscissa, ordinate))
                ));
                //add specific agent in the pool
                pool.add(species.cast(
                        EnvironmentAbstractFactory
                                .getFactory(species)
                                .createAgent(agentConfiguration)));
            }
        }
        return pool;
    }

    @SuppressWarnings("unchecked")
    public static <T extends Agent> Collection<T> generateCirclePool(
            Class<T> species,
            FieldsConfiguration agentConfiguration,
            Integer agentNumber,
            Double circleRadius) {
        Collection<T> pool = new ArrayList<T>(agentNumber);
        double incrementation = (2.0 * Math.PI) / agentNumber;
        double orientation = 0.0;
        for (long number = agentNumber; number-- > 0; orientation += incrementation) {
            //update location
            agentConfiguration.updateMould(new StateFieldMould(
                    AGENT_LOCATION,
                    StandardProvider(new Point2D.Double(
                            circleRadius * Math.cos(orientation),
                            circleRadius * Math.sin(orientation)))
            ));
            //add specific agent in the pool
            pool.add(EnvironmentAbstractFactory
                    .getFactory(species)
                    .createAgent(agentConfiguration));
        }
        return pool;
    }

    @SuppressWarnings("unchecked")
    public static Collection<Creature> generateCreatureCirclePool(
            FieldsConfiguration agentConfiguration,
            Integer agentNumber,
            Double circleRadius) {
        Collection<Creature> pool = new ArrayList<Creature>(agentNumber);
        double incrementation = (2.0 * Math.PI) / agentNumber;
        double orientation = 0.0;
        for (long number = agentNumber; number-- > 0; orientation += incrementation) {
            //update location
            agentConfiguration.updateMould(new StateFieldMould(
                    AGENT_LOCATION,
                    StandardProvider(new Point2D.Double(
                            circleRadius * Math.cos(orientation),
                            circleRadius * Math.sin(orientation)))
            ));
            //update orientation
            agentConfiguration.updateMould(new StateFieldMould(
                    CREATURE_ORIENTATION,
                    StandardProvider(orientation)
            ));
            //add specific agent in the pool
            pool.add(EnvironmentAbstractFactory
                    .getFactory(Creature.class)
                    .createAgent(agentConfiguration));
        }
        return pool;
    }

}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/factory/fields/FieldsConfiguration.java
package org.blackpanther.ecosystem.factory.fields;

import org.blackpanther.ecosystem.behaviour.BehaviorManager;
import org.blackpanther.ecosystem.math.Geometry;

import java.awt.*;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import static org.blackpanther.ecosystem.agent.CreatureConstants.*;
import static org.blackpanther.ecosystem.agent.ResourceConstants.*;
import static org.blackpanther.ecosystem.factory.generator.StandardProvider.StandardProvider;
import static org.blackpanther.ecosystem.helper.Helper.isGene;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public class FieldsConfiguration
        implements Serializable, Cloneable {

    private static final long serialVersionUID = 1L;

    public static final String[] UNBOUNDED_FIELDS = new String[]{
            CREATURE_CURVATURE,
    };

    public static final String[] ANGLE_FIELDS = new String[]{
            CREATURE_ORIENTATION,
            CREATURE_ORIENTATION_LAUNCHER,
    };

    public static final String[] POSITIVE_FIELDS = new String[]{
            CREATURE_ENERGY,
            RESOURCE_ENERGY,
            CREATURE_SPEED,
            CREATURE_SPEED_LAUNCHER,
            CREATURE_FECUNDATION_COST,
            CREATURE_SENSOR_RADIUS,
            CREATURE_CONSUMMATION_RADIUS,
    };

    public static final String[] PROBABILITY_FIELDS = new String[]{
            CREATURE_MOVEMENT_COST,
            CREATURE_FECUNDATION_LOSS,
            CREATURE_GREED,
            CREATURE_FLEE,
            CREATURE_IRRATIONALITY,
            CREATURE_MORTALITY,
            CREATURE_FECUNDITY,
            CREATURE_MUTATION
    };

    public static final String[] COLOR_FIELDS = new String[]{
            CREATURE_NATURAL_COLOR,
            RESOURCE_NATURAL_COLOR,
            CREATURE_COLOR
    };

    public static final String[] BEHAVIOR_FIELDS = new String[]{
            CREATURE_BEHAVIOR
    };

    static {
        Arrays.sort(UNBOUNDED_FIELDS);
        Arrays.sort(ANGLE_FIELDS);
        Arrays.sort(POSITIVE_FIELDS);
        Arrays.sort(PROBABILITY_FIELDS);
        Arrays.sort(COLOR_FIELDS);
        Arrays.sort(BEHAVIOR_FIELDS);
    }

    private Map<String, FieldMould> wrappedFieldProvider = new HashMap<String, FieldMould>();

    public FieldsConfiguration(FieldMould... moulds) {
        for (FieldMould mould : moulds)
            wrappedFieldProvider.put(mould.getName(), mould);
    }

    @SuppressWarnings("unchecked")
    public FieldsConfiguration(Properties props) {
        for (String field : UNBOUNDED_FIELDS) {
            Double fieldValue = Double.parseDouble((String) props.get(field));
            FieldMould mould =
                    isGene(field)
                            ? new GeneFieldMould(field, StandardProvider(fieldValue), false)
                            : new StateFieldMould(field, StandardProvider(fieldValue));
            wrappedFieldProvider.put(mould.getName(), mould);
        }
        for (String field : ANGLE_FIELDS) {
            Double fieldValue = Double.parseDouble((String) props.get(field)) % Geometry.PI_2;
            FieldMould mould =
                    isGene(field)
                            ? new GeneFieldMould(field, StandardProvider(fieldValue), false)
                            : new StateFieldMould(field, StandardProvider(fieldValue));
            wrappedFieldProvider.put(mould.getName(), mould);
        }
        for (String field : POSITIVE_FIELDS) {
            Double fieldValue = Math.max(
                    0.0,
                    Double.parseDouble((String) props.get(field)));
            FieldMould mould =
                    isGene(field)
                            ? new GeneFieldMould(field, StandardProvider(fieldValue), false)
                            : new StateFieldMould(field, StandardProvider(fieldValue));
            wrappedFieldProvider.put(mould.getName(), mould);
        }
        for (String field : PROBABILITY_FIELDS) {
            Double fieldValue = Math.max(
                    0.0,
                    Math.min(
                            1.0,
                            Double.parseDouble((String) props.get(field))));
            FieldMould mould =
                    isGene(field)
                            ? new GeneFieldMould(field, StandardProvider(fieldValue), false)
                            : new StateFieldMould(field, StandardProvider(fieldValue));
            wrappedFieldProvider.put(mould.getName(), mould);
        }
        for (String field : COLOR_FIELDS) {
            Color fieldValue = new Color(
                    Integer.parseInt(
                            (String) props.get(field),
                            16));
            FieldMould mould =
                    isGene(field)
                            ? new GeneFieldMould(field, StandardProvider(fieldValue), false)
                            : new StateFieldMould(field, StandardProvider(fieldValue));
            wrappedFieldProvider.put(mould.getName(), mould);
        }
        for (String field : BEHAVIOR_FIELDS) {
            try {
                BehaviorManager fieldValue = (BehaviorManager) Class.forName(
                        (String) props.get(field)
                ).newInstance();
                FieldMould mould =
                        isGene(field)
                                ? new GeneFieldMould(field, StandardProvider(fieldValue), false)
                                : new StateFieldMould(field, StandardProvider(fieldValue));
                wrappedFieldProvider.put(mould.getName(), mould);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    public void updateMould(FieldMould mould) {
        if (mould != null)
            wrappedFieldProvider.put(mould.getName(), mould);
    }

    public Object getValue(String traitName) {
        FieldMould mould = wrappedFieldProvider.get(traitName);
        if (mould == null)
            throw new IllegalStateException(traitName + " is not bundled in this configuration");
        return mould.getValue();
    }

    public FieldMould getField(String traitName) {
        return wrappedFieldProvider.get(traitName);
    }

    public boolean isMutable(Class species, String trait) {
        isGene(species, trait);
        try {
            GeneFieldMould mould = (GeneFieldMould) wrappedFieldProvider.get(trait);
            return mould.isMutable();
        } catch (Throwable e) {
            return false;
        }
    }

    public static void checkResourceConfiguration(FieldsConfiguration configuration) {
        for (String stateTrait : BUILD_PROVIDED_RESOURCE_STATE)
            if (!configuration.wrappedFieldProvider.containsKey(stateTrait))
                throw new IllegalStateException("Given configuration is incomplete to build a resource : " +
                        "missing trait '" + stateTrait + "'");

        for (String genotypeTrait : RESOURCE_GENOTYPE)
            if (!configuration.wrappedFieldProvider.containsKey(genotypeTrait))
                throw new IllegalStateException("Given configuration is incomplete to build a resource : " +
                        "missing trait '" + genotypeTrait + "'");
    }

    public static void checkCreatureConfiguration(FieldsConfiguration configuration) {
        for (String stateTrait : BUILD_PROVIDED_CREATURE_STATE)
            if (!configuration.wrappedFieldProvider.containsKey(stateTrait))
                throw new IllegalStateException("Given configuration is incomplete to build a creature : " +
                        "missing trait '" + stateTrait + "'");

        for (String genotypeTrait : CREATURE_GENOTYPE)
            if (!configuration.wrappedFieldProvider.containsKey(genotypeTrait))
                throw new IllegalStateException("Given configuration is incomplete to build a creature : " +
                        "missing trait '" + genotypeTrait + "'");
    }

    @Override
    public FieldsConfiguration clone() {
        try {
            return (FieldsConfiguration) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new Error("unexpected error");
        }
    }
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/agent/CreatureConstants.java
package org.blackpanther.ecosystem.agent;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public interface CreatureConstants
        extends AgentConstants {

    public static final String CREATURE_ENERGY = "creature-energy";
    public static final String CREATURE_COLOR = "creature-color";
    public static final String CREATURE_AGE = "creature-age";
    public static final String CREATURE_ORIENTATION = "creature-orientation";
    public static final String CREATURE_CURVATURE = "creature-curvature";
    public static final String CREATURE_SPEED = "creature-speed";

    public static final String CREATURE_NATURAL_COLOR = "creature-natural-color";
    public static final String CREATURE_MOVEMENT_COST = "creature-movement-cost";
    public static final String CREATURE_FECUNDATION_COST = "creature-fecundation-cost";
    public static final String CREATURE_FECUNDATION_LOSS = "creature-fecundation-loss";
    public static final String CREATURE_GREED = "creature-greed";
    public static final String CREATURE_FLEE = "creature-flee";
    public static final String CREATURE_SENSOR_RADIUS = "creature-sensor-radius";
    public static final String CREATURE_CONSUMMATION_RADIUS = "creature-consummation-radius";
    public static final String CREATURE_IRRATIONALITY = "creature-irrationality";
    public static final String CREATURE_MORTALITY = "creature-mortality";
    public static final String CREATURE_FECUNDITY = "creature-fecundity";
    public static final String CREATURE_MUTATION = "creature-mutation";
    public static final String CREATURE_ORIENTATION_LAUNCHER = "creature-orientation-launcher";
    public static final String CREATURE_SPEED_LAUNCHER = "creature-speed-launcher";
    public static final String CREATURE_BEHAVIOR = "creature-behavior";

    public static final String[] CREATURE_STATE = new String[]{
            CREATURE_AGE,
            CREATURE_COLOR,
            CREATURE_CURVATURE,
            CREATURE_ENERGY,
            AGENT_LOCATION,
            CREATURE_ORIENTATION,
            CREATURE_SPEED
    };

    public static final String[] CREATURE_GENOTYPE = new String[]{
            CREATURE_NATURAL_COLOR,
            CREATURE_MOVEMENT_COST,
            CREATURE_FECUNDATION_COST,
            CREATURE_FECUNDATION_LOSS,
            CREATURE_GREED,
            CREATURE_FLEE,
            CREATURE_SENSOR_RADIUS,
            CREATURE_CONSUMMATION_RADIUS,
            CREATURE_IRRATIONALITY,
            CREATURE_MORTALITY,
            CREATURE_FECUNDITY,
            CREATURE_MUTATION,
            CREATURE_ORIENTATION_LAUNCHER,
            CREATURE_SPEED_LAUNCHER,
            CREATURE_BEHAVIOR
    };

    /**
     * Trait provided to create an creature
     */
    public static final String[] BUILD_PROVIDED_CREATURE_STATE = new String[]{
            CREATURE_COLOR,
            CREATURE_CURVATURE,
            CREATURE_ENERGY,
            AGENT_LOCATION,
            CREATURE_ORIENTATION,
            CREATURE_SPEED
    };

    public static final String[] CUSTOMIZABLE_CREATURE_STATE = new String[]{
            CREATURE_COLOR,
            CREATURE_CURVATURE,
            CREATURE_ENERGY,
            CREATURE_ORIENTATION,
            CREATURE_SPEED
    };
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/agent/Agent.java
package org.blackpanther.ecosystem.agent;

import org.blackpanther.ecosystem.Environment;
import org.blackpanther.ecosystem.event.AgentEvent;
import org.blackpanther.ecosystem.factory.fields.FieldsConfiguration;

import java.awt.geom.Point2D;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import static org.blackpanther.ecosystem.helper.Helper.require;

/**
 * <p>
 * Component which represent an agent within an ecosystem.
 * It implements all basic features for an agent,
 * specific behaviour are left to subclasses
 * </p>
 *
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public abstract class Agent
        implements Serializable, Cloneable, CreatureConstants {

    /**
     * Serializable identifier
     */

    private static final long serialVersionUID = 6L;
    private static long idGenerator = 0;

    /*=========================================
     *                 GENOTYPE
     *=========================================
     */
    protected Map<String, Object> genotype = new HashMap<String, Object>();
    protected Map<String, Boolean> mutableTable = new HashMap<String, Boolean>();

    /*=========================================
     *                 PHENOTYPE
     *=========================================
     */
    protected Map<String, Object> currentState = new HashMap<String, Object>(AGENT_STATE.length);

    /*=========================================================================
                                    MISCELLANEOUS
      =========================================================================*/
    /**
     * Agent's area listener
     */
    private Long id = ++idGenerator;

    protected Agent(FieldsConfiguration config) {
        for (String stateTrait : BUILD_PROVIDED_AGENT_STATE)
            currentState.put(stateTrait, config.getValue(stateTrait));
    }

    abstract public void update(final Environment env);


    public void attachTo(Environment env) {
        require(env != null);
        env.getEventSupport().fireAgentEvent(AgentEvent.Type.BORN, this);
    }

    /**
     * Unset the current area listener if any
     */
    public void detachFromEnvironment(Environment env) {
        env.getEventSupport().fireAgentEvent(AgentEvent.Type.DEATH, this);
    }

    /* ================================================
     *               GETTERS
     * ================================================
     */

    @SuppressWarnings("unchecked")
    public <T> T getGene(String geneName, Class<T> geneType) {
        Object correspondingGene = genotype.get(geneName);
        if (correspondingGene != null) {
            if (geneType.isInstance(correspondingGene)) {
                return (T) correspondingGene;
            } else {
                throw new IllegalArgumentException(
                        String.format("%s gene does not match given type, please check again",
                                geneName)
                );
            }
        } else {
            throw new IllegalArgumentException(String.format(
                    "'%s'  parameter is not provided by the current configuration, "
                            + "maybe you should register it before",
                    geneName
            ));
        }
    }

    @SuppressWarnings("unchecked")
    public <T> T getState(String stateName, Class<T> stateType) {
        Object correspondingGene = currentState.get(stateName);
        if (correspondingGene != null) {
            if (stateType.isInstance(correspondingGene)) {
                return (T) correspondingGene;
            } else {
                throw new IllegalArgumentException(
                        String.format("%s state does not match given type, please check again",
                                stateName)
                );
            }
        } else {
            throw new IllegalArgumentException(String.format(
                    "'%s'  parameter is not provided by the current configuration, "
                            + "maybe you should register it before",
                    stateName
            ));
        }
    }

    public boolean isMutable(String genotypeTrait) {
        return mutableTable.get(genotypeTrait);
    }

    abstract public double getEnergy();


    /**
     * Get current agent's location in its environment
     *
     * @return current agent's position
     */
    public Point2D getLocation() {
        return getState(AGENT_LOCATION, Point2D.class);
    }

    /*=========================================================================
     *                 SETTERS
     * Visibility is set to package because
     * they are meant to be modified by nothing except the behaviour manager
     *=========================================================================
     */

    public void setLocation(double abscissa, double ordinate) {
        currentState.put(AGENT_LOCATION, new Point2D.Double(abscissa, ordinate));
    }

    abstract public void setEnergy(Double energy);

    @Override
    public Agent clone() {
        try {
            Agent copy = (Agent) super.clone();
            copy.currentState = new HashMap<String, Object>(this.currentState);
            copy.genotype = new HashMap<String, Object>(this.genotype);
            copy.mutableTable = new HashMap<String, Boolean>(this.mutableTable);
            return copy;
        } catch (CloneNotSupportedException e) {
            throw new Error(e);
        }
    }

    @Override
    public String toString() {
        return super.toString() + "[Agent" + Long.toHexString(id) + "]";
    }
}<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/event/EnvironmentEvent.java
package org.blackpanther.ecosystem.event;

import org.blackpanther.ecosystem.Environment;

import java.util.EventObject;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public abstract class EnvironmentEvent
        extends EventObject {

    public EnvironmentEvent(Environment source) {
        super(source);
    }

    public Environment getSource() {
        return (Environment) super.getSource();
    }
}
<file_sep>/ecosystem-framework/src/main/java/org/blackpanther/ecosystem/line/AgentLine.java
package org.blackpanther.ecosystem.line;

import org.blackpanther.ecosystem.agent.Creature;
import org.blackpanther.ecosystem.behaviour.BehaviorManager;

import java.awt.*;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;

import static org.blackpanther.ecosystem.agent.CreatureConstants.CREATURE_NATURAL_COLOR;

/**
 * @author <NAME>
 * @version 1.0-alpha - Tue May 24 23:49:57 CEST 2011
 */
public class AgentLine
    extends Line2D.Double{

    private Color genotypeColor;
    private Color phenotypeColor;
    private Class<? extends BehaviorManager> species;
    private java.lang.Double power;

    public AgentLine(Point2D x, Point2D y,
                     Creature agent) {
        super(x, y);
        this.genotypeColor = agent.getGene(CREATURE_NATURAL_COLOR,Color.class);
        this.phenotypeColor = agent.getColor();
        this.species = agent.getBehaviour().getClass();
        this.power = agent.getEnergy();
    }

    public Color getGenotypeColor() {
        return genotypeColor;
    }

    public Color getPhenotypeColor() {
        return phenotypeColor;
    }

    public Class<? extends BehaviorManager> getSpecies() {
        return species;
    }

    public java.lang.Double getPower() {
        return power;
    }
}
