AntColonyPDP.GFAnt.java Source code

Java tutorial

Introduction

Here is the source code for AntColonyPDP.GFAnt.java

Source

package AntColonyPDP;
/*
 * Copyright (C) 2011-2015 Rinde van Lon, iMinds-DistriNet, KU Leuven
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*something*/

import java.util.ArrayList;
import java.util.List;

import com.github.rinde.rinsim.core.model.pdp.PDPModel;
import com.github.rinde.rinsim.core.model.pdp.Parcel;
import com.github.rinde.rinsim.core.model.pdp.PDPModel.VehicleState;
import com.github.rinde.rinsim.core.model.road.RoadModel;
import com.github.rinde.rinsim.core.model.time.TimeLapse;
import com.github.rinde.rinsim.geom.Point;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;

/**
 * Implementation of a very simple taxi agent. It moves to the closest customer,
 * picks it up, then delivers it, repeat.
 *
 * @author Rinde van Lon
 */
class GFAnt extends Ant {

    public static final double VISUAL_RANGE = 2.5d;
    private Optional<Parcel> curr;
    private Strategy energyStrategy;

    Optional<Point> destination;
    private boolean wantToRest;

    public GFAnt(Point startPosition, int capacity, boolean bold, boolean dynamic) {
        super(startPosition, capacity);
        curr = Optional.absent();
        energyStrategy = new Strategy(bold, dynamic);
    }

    @Override
    public void afterTick(TimeLapse timeLapse) {
    }

    //strategy for gas refilling and passenger acceptance

    @Override
    protected void tickImpl(TimeLapse time) {
        final RoadModel rm = getRoadModel();
        final PDPModel pm = getPDPModel();

        destination = Optional.absent();
        if (!time.hasTimeLeft()) {
            return;
        } //first check energy before hunting

        boolean inCargo = false;

        if (curr.isPresent())
            inCargo = pm.containerContains(this, curr.get());

        wantToRest = wantToRest(inCargo);

        if (wantToRest) {

            Colony colony = Environment.getColonyFromVisual(this);

            if (colony == null) { //find a colony and forget about the food
                Point gradientVector = MapUtil.rescale(Environment.getGradientField(this), 1);
                Point destinationPoint = MapUtil.addPoints(gradientVector, getPosition().get());
                destination = Optional.fromNullable(redirectInBounds(destinationPoint, rm));
                Point pos1 = getPosition().get();
                rm.moveTo(this, destination.get(), time);
                Point pos2 = getPosition().get();
                double distance = Point.distance(pos1, pos2);
                decreaseEnergy(distance);
            } else { // we found a colony, keep going until reach it
                Point pos1 = getPosition().get();
                rm.moveTo(this, colony, time);
                Point pos2 = getPosition().get();
                double distance = Point.distance(pos1, pos2);
                decreaseEnergy(distance);

                if (getEnergy() <= 0 && inCargo) {
                    Parcel it = curr.get();
                    pm.drop(this, it, time);
                    List<Point> positions = new ArrayList<Point>();
                    positions.add(0, this.getPosition().get());
                    positions.add(1, it.getDeliveryLocation());
                    Environment.dropFood((FoodElement) it, positions);
                }

                if (rm.getPosition(this).equals(colony.getPosition())) {
                    if (curr.isPresent() && rm.getPosition(this).equals(curr.get().getDeliveryLocation())
                            && pm.containerContains(this, curr.get())
                            && pm.getVehicleState(this).equals(VehicleState.IDLE)) {
                        pm.deliver(this, curr.get(), time);
                        curr = Optional.absent();
                        Environment.notifyDelivery();
                    }
                    rest(time.getTimeLeft());
                }
            }

            /*
                
             */
        } else { //hunt
            if (!curr.isPresent()) {

                //precheck: (alive) prey within half tick distance
                //if so: curr becomes the detected prey and we moveTo(curr)
                // if not: ask a gradient vector and move or moveTo
                FoodSource seen = Environment.getFoodFromVisual(this);
                curr = Optional.fromNullable((Parcel) seen);
            }

            if (!curr.isPresent()) { //we dont see food
                Point gradientVector = MapUtil.rescale(Environment.getGradientField(this), 1);
                Point destinationPoint = MapUtil.addPoints(gradientVector, getPosition().get());
                destination = Optional.fromNullable(redirectInBounds(destinationPoint, rm));
                Point pos1 = getPosition().get();
                rm.moveTo(this, destination.get(), time);
                Point pos2 = getPosition().get();
                double distance = Point.distance(pos1, pos2);
                decreaseEnergy(distance);
            }
            if (curr.isPresent()) {
                if (!inCargo && !rm.containsObject(curr.get())) { //sanity/consistency check
                    curr = Optional.absent();
                } else if (inCargo) {
                    // if it is in cargo, go to its destination
                    Point pos1 = getPosition().get();
                    rm.moveTo(this, curr.get().getDeliveryLocation(), time);
                    Point pos2 = getPosition().get();
                    double distance = Point.distance(pos1, pos2);
                    decreaseEnergy(distance * 2);
                    boolean dropping = false;
                    if (getEnergy() <= 0) {
                        //curr = Optional.absent();
                        Parcel it = curr.get();
                        ///Probably this is not the best way to do it. It should happen in the environment
                        pm.drop(this, it, time);
                        List<Point> positions = new ArrayList<Point>();
                        positions.add(0, this.getPosition().get());
                        positions.add(1, it.getDeliveryLocation());

                        Environment.dropFood((FoodElement) it, positions);
                        //System.out.println("Drop food element");
                        dropping = true;
                    }

                    if (!dropping && curr.isPresent()
                            && rm.getPosition(this).equals(curr.get().getDeliveryLocation())) {
                        // deliver when we arrive
                        pm.deliver(this, curr.get(), time);
                        Environment.notifyDelivery();
                    }
                } else {
                    // it is still available, go there as fast as possible
                    Point pos1 = getPosition().get();
                    rm.moveTo(this, curr.get(), time);
                    Point pos2 = getPosition().get();
                    double distance = Point.distance(pos1, pos2);
                    decreaseEnergy(distance);
                    if (rm.equalPosition(this, curr.get())) {
                        // pickup food element
                        curr = Optional.fromNullable((Parcel) Environment.pickup((FoodSource) curr.get())); // ugly
                        decreaseEnergy(((FoodElement) curr.get()).getFixedCost());
                        pm.pickup(this, curr.get(), time);
                    }
                }
            }
        }
    }

    public boolean wantToRest() {
        return wantToRest;
    }

    private boolean wantToRest(boolean inCargo) {
        if (isResting())
            return true;
        boolean result = false;
        if (energyStrategy.bold == false && energyStrategy.dynamic == false) {
            result = getEnergy() < getMaxEnergy() / 10;
        }
        if (energyStrategy.bold == true && energyStrategy.dynamic == false) {
            result = getEnergy() < getMaxEnergy() / 20;
        }
        if (energyStrategy.bold == false && energyStrategy.dynamic == true) {
            if (curr.isPresent()) {
                if (!inCargo) {
                    double expectedCost = Point.distance(this.getPosition().get(), curr.get().getPickupLocation())
                            + Point.distance(curr.get().getDeliveryLocation(), curr.get().getPickupLocation()) * 2;
                    if (expectedCost > (getEnergy() + 1)) {
                        result = true;
                    }
                } else { //food in cargo: determine if we expect to need resting when we deliver
                    if (getEnergy() < 3) {
                        result = true;
                    }
                }
            } else { //roaming the gradient field without parcel
                //In GF we cannot just calculate the nearest colony, the ant should be able to 'see' the colony an go back to it
                // so ant should just wander around until it sees a colony.
                if (getEnergy() < getMaxEnergy() / 10) {
                    result = true;
                }
            }
        }

        if (energyStrategy.bold == true && energyStrategy.dynamic == true) {
            if (curr.isPresent()) {
                if (!inCargo) {
                    double expectedCost = Point.distance(this.getPosition().get(), curr.get().getPickupLocation())
                            + Point.distance(curr.get().getDeliveryLocation(), curr.get().getPickupLocation()) * 2;
                    if (expectedCost > (getEnergy() + 2)) {
                        result = true;
                    }
                } else { //food in cargo: determine if we expect to need resting when we deliver
                    if (getEnergy() < 0) {
                        result = true;
                    }
                }
            } else { //roaming the gradient field without parcel
                /****************************************************************/
                //In GF we cannot just calculate the nearest colony, the ant should be able to 'see' the colony an go back to it
                // so ant should just wander around until it sees a colony. Without picking up a food element?
                if (getEnergy() < getMaxEnergy() / 25) {
                    // sizes of the map
                    result = true;
                }

                if (Point.distance(this.getPosition().get(),
                        Environment.getNearestColony(this).getPosition()) > getEnergy() + 0.2) {
                    result = true;
                }

            }
        }
        return result;
    }

    private Point redirectInBounds(Point point, RoadModel rm) {
        ImmutableList<Point> bounds = rm.getBounds();
        if (point.x < bounds.get(0).x)
            point = new Point(0, point.y);
        if (point.x > bounds.get(1).x)
            point = new Point(10, point.y);
        if (point.y < bounds.get(0).y)
            point = new Point(point.x, 0);
        if (point.y > bounds.get(1).y)
            point = new Point(point.x, 10);
        return point;
    }

    public class Strategy {
        boolean bold;
        boolean dynamic;

        Strategy(boolean bold, boolean dynamic) {
            this.bold = bold;
            this.dynamic = dynamic;
        }
    }
}