Back
/*
 * (C) 2003-2009 Spolecne s.r.o.
 * Author: Tomas Straka
 * www.spoledge.com
 *
 * Written permission must be obtained in advance from Spolecne s.r.o for any form of
 * reproduction, use or distribution.
 */
package ants.models.thrakia;

import ants.Ant;
import ants.DPoint;
import ants.EventQueue;
import ants.OrientedRectangle;
import ants.World;
import ants.WorldObject;

import vb.util.AdvancedPropertiesParser;
import vb.util.ParsingException;

import java.util.HashMap;

/**
 * The implementation of the Thrakia ant.
 */
public class ThrakiaAnt extends Ant {

    /**
     * The time frame for the ant to collect the result of the neural network
     * and perform the desired activity. see FireLaw, this number must be significantly
     * higher than tm. In seconds. Smaller number = smooth walk. Bigger number = faster
     * simulation.
     */
    private static final double dTime = 0.2;
    
    /**
     * The neural network. All the logic of the ants behaviour is implemented there
     */
    private ThrakiaNetwork network;
    
    /**
     * The constructor
     */
    public ThrakiaAnt(AdvancedPropertiesParser app, String prefixthrows ParsingException {
        superapp, prefix );
    }

    /**
     * Tests position of antenas against all objects in the world.
     * It does not test tail of the ant - so it can go back inside another
     * world object.
     *
     @param lt left antena
     @param rt right antena
     */
    protected boolean [] testCrashFront(DPoint lt, DPoint rt) {
        boolean left = false;
        boolean right = false;

        for (WorldObject wo : world.getObjects()) {
            if (wo == thiscontinue;
            OrientedRectangle bb = wo.getBoundingBox();

            if(!leftleft = bb.containslt.x, lt.y );
            if(!rightright = bb.containsrt.x, rt.y );
            if(left && rightbreak;  // optimisation
        }

        return new boolean [] { left, right };
    }

    /**
     * Read the world's environment. See makePath for the reverse method.
     */
    protected void fillRemainingEnvironmentDPoint tentacle, HashMap<Odour, Double> environment ) {
        environment.put(Odour.HOME,  new Double(world.get(tentacle.x, tentacle.y, World.MRAVSLINT)));
        environment.put(Odour.LEAVE, new Double(world.get(tentacle.x, tentacle.y, World.LEAVE)));
        environment.put(Odour.WATER, new Double(world.get(tentacle.x, tentacle.y, World.WATER)));
    }

    /**
     * Read the world and fill the tentacles. See max and min intensity in the Tentacle.
     */
    protected void fillTentacles() {
        DPoint leftTentacle = boundingBox.getLT();
        DPoint riteTentacle = boundingBox.getRT();

        HashMap<Odour, Double> leftEnvironment = new HashMap<Odour, Double>();
        HashMap<Odour, Double> riteEnvironment = new HashMap<Odour, Double>();
        
        boolean [] crashed = testCrashFront(leftTentacle, riteTentacle);
        ifcrashed[0] ) leftEnvironment.put(Odour.STONE, Tentacle.getMaxIntensity());
        ifcrashed[1] ) riteEnvironment.put(Odour.STONE, Tentacle.getMaxIntensity());

        fillRemainingEnvironment(leftTentacle, leftEnvironment);
        fillRemainingEnvironment(riteTentacle, riteEnvironment);
        
        network.getLeftTentacle().acceptleftEnvironment );
        network.getRightTentacle().acceptriteEnvironment );
    }

    /**
     * Put some odour into the world, make paths. See fillRemainingEnvironment for
     * the reverse method.
     @param amount in 0..1
     */
    protected void makePathDPoint leg, Odour o, double amount ) {
        if (o == nullreturn;
        double putVol = amount * Tentacle.getMaxIntensity();
    
        switch) {
            case HOME:  world.put(leg.x, leg.y, World.MRAVSLINT, putVol );
                        break;
        }
    }

    /**
     * Walk according to the network output
     */
    protected void walk() {
        OutputDBC [] out = new OutputDBC [] { network.getLeftLegFwd(),
                                              network.getLeftLegBackwd(),
                                              network.getRightLegFwd(),
                                              network.getRightLegBackwd() };
        for int i = 0; i < out.length; i++ ) {
            out[i].compute();
            out[i].clean();     // for the next step
        }

        makePathboundingBox.getLB(), out[0].getOdour(), out[0].getAmount() );
        makePathboundingBox.getRB(), out[2].getOdour(), out[2].getAmount() );
        makePathboundingBox.getLB(), out[1].getOdour(), out[1].getAmount() );  // in fact void
        makePathboundingBox.getRB(), out[3].getOdour(), out[3].getAmount() );  // in fact void
        
        double leftWards = out[0].getAmount() - out[1].getAmount();  // -1 .. +1
        double riteWards = out[2].getAmount() - out[3].getAmount();
        
        ifleftWards > 0.0 && riteWards > 0.0 ) {
            ifleftWards > riteWards ) {
                moveLeftLeg(leftWards - riteWards);
                moveBothLegs(riteWards);
            else {
                moveRightLeg(riteWards - leftWards);
                moveBothLegs(leftWards);
            }
        else ifleftWards < 0.0 && riteWards < 0.0 ) {
            ifleftWards > riteWards ) {
                moveRightLeg(riteWards - leftWards);
                moveBothLegs(leftWards);
            else {
                moveLeftLeg(leftWards - riteWards);
                moveBothLegs(riteWards);
            }
        else {
            moveLeftLeg(leftWards);
            moveRightLeg(riteWards);
        }
    }

    /**
     * One step in the life
     */
    public void simulate(EventQueue.Item item) {
        EventQueue eq = item.getEventQueue();
        
        ifnetwork == null ) {     // We are at the beginning of the simulation
            network = new ThrakiaNetworkeq );
        else {      
            walk();
        }
        
        fillTentacles();
        
        // schedule the next step
        eq.schedule(dTime, this);
    }

    /**
     * Return the interval between actions
     */
    public static double getInterval() {
        return dTime;
    }
}
Back