All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sim.app.antsforage.Ant Maven / Gradle / Ivy

Go to download

MASON is a fast discrete-event multiagent simulation library core in Java, designed to be the foundation for large custom-purpose Java simulations, and also to provide more than enough functionality for many lightweight simulation needs. MASON contains both a model library and an optional suite of visualization tools in 2D and 3D.

The newest version!
/*
  Copyright 2006 by Sean Luke and George Mason University
  Licensed under the Academic Free License version 3.0
  See the file "LICENSE" for more information
*/

package sim.app.antsforage;

import sim.field.grid.*;
import sim.portrayal.*;
import sim.portrayal.simple.*;
import sim.util.*;
import sim.engine.*;
import java.awt.*;

public class Ant extends OvalPortrayal2D implements Steppable
    {
    private static final long serialVersionUID = 1;

    public boolean getHasFoodItem() { return hasFoodItem; }
    public void setHasFoodItem(boolean val) { hasFoodItem = val; }
    public boolean hasFoodItem = false;
    double reward = 0;
        
    int x;
    int y;
        
    Int2D last;
        
    public Ant(double initialReward) { reward = initialReward; }
        
        
    // at present we have only one algorithm: value iteration.  I might
    // revise this and add our alternate (TD) algorithm.  See the papers.
        
        
    public void depositPheromone( final SimState state)
        {
        final AntsForage af = (AntsForage)state;
                
        Int2D location = af.buggrid.getObjectLocation(this);
        int x = location.x;
        int y = location.y;
                
        if (AntsForage.ALGORITHM == AntsForage.ALGORITHM_VALUE_ITERATION)
            {
            // test all around
            if (hasFoodItem)  // deposit food pheromone
                {
                double max = af.toFoodGrid.field[x][y];
                for(int dx = -1; dx < 2; dx++)
                    for(int dy = -1; dy < 2; dy++)
                        {
                        int _x = dx+x;
                        int _y = dy+y;
                        if (_x < 0 || _y < 0 || _x >= AntsForage.GRID_WIDTH || _y >= AntsForage.GRID_HEIGHT) continue;  // nothing to see here
                        double m = af.toFoodGrid.field[_x][_y] * 
                            (dx * dy != 0 ? // diagonal corners
                            af.diagonalCutDown : af.updateCutDown) +
                            reward;
                        if (m > max) max = m;
                        }
                af.toFoodGrid.field[x][y] = max;
                }
            else
                {
                double max = af.toHomeGrid.field[x][y];
                for(int dx = -1; dx < 2; dx++)
                    for(int dy = -1; dy < 2; dy++)
                        {
                        int _x = dx+x;
                        int _y = dy+y;
                        if (_x < 0 || _y < 0 || _x >= AntsForage.GRID_WIDTH || _y >= AntsForage.GRID_HEIGHT) continue;  // nothing to see here
                        double m = af.toHomeGrid.field[_x][_y] * 
                            (dx * dy != 0 ? // diagonal corners
                            af.diagonalCutDown : af.updateCutDown) +
                            reward;
                        if (m > max) max = m;
                        }
                af.toHomeGrid.field[x][y] = max;
                }
            }
        reward = 0.0;
        }

    public void act( final SimState state )
        {
        final AntsForage af = (AntsForage)state;
                
        Int2D location = af.buggrid.getObjectLocation(this);
        int x = location.x;
        int y = location.y;
                
        if (hasFoodItem)  // follow home pheromone
            {
            double max = AntsForage.IMPOSSIBLY_BAD_PHEROMONE;
            int max_x = x;
            int max_y = y;
            int count = 2;
            for(int dx = -1; dx < 2; dx++)
                for(int dy = -1; dy < 2; dy++)
                    {
                    int _x = dx+x;
                    int _y = dy+y;
                    if ((dx == 0 && dy == 0) ||
                        _x < 0 || _y < 0 ||
                        _x >= AntsForage.GRID_WIDTH || _y >= AntsForage.GRID_HEIGHT || 
                        af.obstacles.field[_x][_y] == 1) continue;  // nothing to see here
                    double m = af.toHomeGrid.field[_x][_y];
                    if (m > max)
                        {
                        count = 2;
                        }
                    // no else, yes m > max is repeated
                    if (m > max || (m == max && state.random.nextBoolean(1.0 / count++)))  // this little magic makes all "==" situations equally likely
                        {
                        max = m;
                        max_x = _x;
                        max_y = _y;
                        }
                    }
            if (max == 0 && last != null)  // nowhere to go!  Maybe go straight
                {
                if (state.random.nextBoolean(af.momentumProbability))
                    {
                    int xm = x + (x - last.x);
                    int ym = y + (y - last.y);
                    if (xm >= 0 && xm < AntsForage.GRID_WIDTH && ym >= 0 && ym < AntsForage.GRID_HEIGHT && af.obstacles.field[xm][ym] == 0)
                        { max_x = xm; max_y = ym; }
                    }
                }
            else if (state.random.nextBoolean(af.randomActionProbability))  // Maybe go randomly
                {
                int xd = (state.random.nextInt(3) - 1);
                int yd = (state.random.nextInt(3) - 1);
                int xm = x + xd;
                int ym = y + yd;
                if (!(xd == 0 && yd == 0) && xm >= 0 && xm < AntsForage.GRID_WIDTH && ym >= 0 && ym < AntsForage.GRID_HEIGHT && af.obstacles.field[xm][ym] == 0)
                    { max_x = xm; max_y = ym; }
                }
            af.buggrid.setObjectLocation(this, new Int2D(max_x, max_y));
            if (af.sites.field[max_x][max_y] == AntsForage.HOME)  // reward me next time!  And change my status
                { reward = af.reward ; hasFoodItem = ! hasFoodItem; }
            }
        else
            {
            double max = AntsForage.IMPOSSIBLY_BAD_PHEROMONE;
            int max_x = x;
            int max_y = y;
            int count = 2;
            for(int dx = -1; dx < 2; dx++)
                for(int dy = -1; dy < 2; dy++)
                    {
                    int _x = dx+x;
                    int _y = dy+y;
                    if ((dx == 0 && dy == 0) ||
                        _x < 0 || _y < 0 ||
                        _x >= AntsForage.GRID_WIDTH || _y >= AntsForage.GRID_HEIGHT || 
                        af.obstacles.field[_x][_y] == 1) continue;  // nothing to see here
                    double m = af.toFoodGrid.field[_x][_y];
                    if (m > max)
                        {
                        count = 2;
                        }
                    // no else, yes m > max is repeated
                    if (m > max || (m == max && state.random.nextBoolean(1.0 / count++)))  // this little magic makes all "==" situations equally likely
                        {
                        max = m;
                        max_x = _x;
                        max_y = _y;
                        }
                    }
            if (max == 0 && last != null)  // nowhere to go!  Maybe go straight
                {
                if (state.random.nextBoolean(af.momentumProbability))
                    {
                    int xm = x + (x - last.x);
                    int ym = y + (y - last.y);
                    if (xm >= 0 && xm < AntsForage.GRID_WIDTH && ym >= 0 && ym < AntsForage.GRID_HEIGHT && af.obstacles.field[xm][ym] == 0)
                        { max_x = xm; max_y = ym; }
                    }
                }
            else if (state.random.nextBoolean(af.randomActionProbability))  // Maybe go randomly
                {
                int xd = (state.random.nextInt(3) - 1);
                int yd = (state.random.nextInt(3) - 1);
                int xm = x + xd;
                int ym = y + yd;
                if (!(xd == 0 && yd == 0) && xm >= 0 && xm < AntsForage.GRID_WIDTH && ym >= 0 && ym < AntsForage.GRID_HEIGHT && af.obstacles.field[xm][ym] == 0)
                    { max_x = xm; max_y = ym; }
                }
            af.buggrid.setObjectLocation(this, new Int2D(max_x, max_y));
            if (af.sites.field[max_x][max_y] == AntsForage.FOOD)  // reward me next time!  And change my status
                { reward = af.reward; hasFoodItem = ! hasFoodItem; }
            }
        last = location;
        }

    public void step( final SimState state )
        {
        depositPheromone(state);
        act(state);
        }

    // a few tweaks by Sean
    private Color noFoodColor = Color.black;
    private Color foodColor = Color.red;
    public final void draw(Object object, Graphics2D graphics, DrawInfo2D info)
        {
        if( hasFoodItem )
            graphics.setColor( foodColor );
        else
            graphics.setColor( noFoodColor );

        // this code was stolen from OvalPortrayal2D
        int x = (int)(info.draw.x - info.draw.width / 2.0);
        int y = (int)(info.draw.y - info.draw.height / 2.0);
        int width = (int)(info.draw.width);
        int height = (int)(info.draw.height);
        graphics.fillOval(x,y,width, height);

        }
    }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy