Package warbot.chevri_t

Source Code of warbot.chevri_t.Terminator

package warbot.chevri_t;

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.TreeMap;

import madkit.kernel.AgentAddress;
import warbot.kernel.Food;
import warbot.kernel.Percept;
import warbot.kernel.WarbotMessage;

/**
* @author chevri_t
*
*/
@SuppressWarnings("serial")
public final class Terminator extends Mobile
{
  boolean                     haveToEat    = false;
  boolean                     defend       = false;
  boolean                     explore      = false;
  Double                      attackDir    = null;
  int                         timeToReload = 0;
  MobileFoe                   foeToAttack  = null;
  HashMap<AgentAddress, Ally> allies       = new HashMap<AgentAddress, Ally>();

  public Terminator() {}

  @Override
  public void activate() {
    super.activate();
    specificRoleName = "Launcher";
    requestRole(groupName, specificRoleName, null);
    points.setPerceptRadius(Cst.DR.LauncherDR);
  }

  @Override
  public void doIt() {
    super.doIt();

    if (posToRef == null)
      return;

    if (timeToReload > 0)
      timeToReload--;

    haveToEat = false;
    hasAction = false;
    Percept[] perception = getPercepts();

    for (Percept element : perception) {
      String elmType = element.getPerceptType();
      Boolean foe = !element.getTeam().equals(getTeam());

      if (elmType.equals("RocketLauncher")) {
        int perceptRad = foe ? Cst.DR.LauncherDR : 20;
        if (foe) {
          nbEnnemis++;
          foeAttackPos = toWBPoint(element);
        }
        foes.put(element, posToRef, foe, perceptRad);
      } else if (elmType.equals("Explorer")) {
        int perceptRad = foe ? Cst.DR.ExplorerDR : 20;
        foes.put(element, posToRef, foe, perceptRad);
      } else if (elmType.equals("Food")) {
        if (!isNearABase(toWBPoint(element)))
          points.add(new InterestPoint(toWBPoint(element),
              InterestPoint.Type.Food));
        if ((getRocketNumber() == 0 || getEnergyLevel() * 1.5 < baseEnergyLevel)
            && getEnergyLevel() < getMaximumEnergy())
          eatFood((Food)element);
      } else if (elmType.equals("Home")) {
        if (foe) {
          points.add(new InterestPoint(toWBPoint(element),
              InterestPoint.Type.Base));
          foes.put(element, posToRef, foe, 60);
        } else
          homes.put(element.getAgent(), toWBPoint(element));
        obst.add(new Obstacle(toWBPoint(element), element.getRadius() - 13));
      } else if (elmType.equals("Obstacle"))
        obst.add(new Obstacle(toWBPoint(element), element.getRadius()));
      else if (elmType.equals("Rocket"))
        foes.put(element, posToRef, true, 70);
    }

    SelectTarget();

    UpdateFoesAndIP();

    PerformAction();

    allies.clear();

    SendMessages();
  }

  private boolean attack() {
    MobileFoe foe = foeToAttack;
    WBPoint attackPos = null;

    if (foe == null)
      return false;

    attackPos = calculateAttackPos(foe);

    if (posToRef.distance(foe.getPosition()) > 200)
      return false;

    for (Entry<AgentAddress, Ally> ally : allies.entrySet()) {
      if (posToRef.distance(ally.getValue().getPosition()) > 210)
        continue;

      if (GeoUtil.areCircleSegmentIntersected(posToRef, attackPos, ally
          .getValue().getPosition(), ally.getValue().getRadius() + 15)) {
        // TODO:select better tempTarget
        Say("Can't shoot, there is an ally, foe pos", attackPos.toString(),
            "ally pos", ally.getValue().getPosition().toString(), "my pos",
            posToRef.toString());
        double delta = Math.random() > 0.5 ? -90 : 90;
        if (tempTarget == null || tempTarget.equals(posToRef.x, posToRef.y))
          tempTarget = posToRef.getTargetPoint(100,
              getDeltaDir(posToRef.direction(attackPos), delta));

        return false;
      }
    }
    double dir = posToRef.direction(attackPos);

    shotRocket(dir);
    return true;
  }

  private WBPoint calculateAttackPos(MobileFoe f) {
    if (f.getType().equals(MobileFoe.Type.Rocket) || f.getDirection() == -1)
      return f.getPosition();

    double vMag = Cst.CD.RocketCD;
    double x = posToRef.getX();
    double y = posToRef.getY();
    double Bx = f.getPosition().getX();
    double By = f.getPosition().getY();
    double ux = f.getVelocityVector().getX();
    double uy = f.getVelocityVector().getY();

    // Find the vector AB
    double ABx = Bx - x;
    double ABy = By - y;

    // Normalize it
    double ABmag = Math.sqrt(ABx * ABx + ABy * ABy);
    ABx /= ABmag;
    ABy /= ABmag;

    // Project u onto AB
    double uDotAB = ABx * ux + ABy * uy;
    double ujx = uDotAB * ABx;
    double ujy = uDotAB * ABy;

    // Subtract uj from u to get ui
    double uix = ux - ujx;
    double uiy = uy - ujy;

    // Set vi to ui (for clarity)
    double vix = uix;
    double viy = uiy;

    // Calculate the magnitude of vj
    double viMag = Math.sqrt(vix * vix + viy * viy);
    double vjMag = Math.sqrt(vMag * vMag - viMag * viMag);

    // Get vj by multiplying it's magnitude with the unit vector AB
    double vjx = ABx * vjMag;
    double vjy = ABy * vjMag;

    // Add vj and vi to get v
    double vx = vjx + vix;
    double vy = vjy + viy;

    WBPoint result = new WBPoint(x + vx * 120, y + vy * 120);
    return result;
  }

  /**
   * @param element
   */
  private void eatFood(Food p) {
    if (p.getDistance() < 10)
      Say("Distance to food", Double.toString(distanceTo(p)));
    if (p.getDistance() < 2) {
      eat(p);
      hasAction = true;
    } else {
      haveToEat = true;
      target = toWBPoint(p);
    }
  }

  private void PerformAction() {
    if (foeToAttack != null && !haveToEat) {
      if (attack())
        return;

      if (/* target == null && */posToRef.distance(foeToAttack.getPosition()) >= 200)
        target = foeToAttack.getPosition();
      else
        target = null;
    }

    if (hasAction || (target == null || posToRef.equals(target.x, target.y))
        && tempTarget == null && !explore)
      return;

    if (explore
        && (tempTarget == null || tempTarget.equals(posToRef.x, posToRef.y)))
      if (target == null)
        tempTarget = posToRef.getTargetPoint(Cst.DR.ExplorerDR / 2,
            getDeltaDir(getHeading(), (Math.random() - 0.5) * 65));
      else
        tempTarget = new WBPoint(target.x, target.y);

    else if (!isMoving())
      tempTarget = posToRef.getTargetPoint(Cst.DR.ExplorerDR / 2,
          Math.random() * 360);

    TreeMap<Double, Point2D.Double> practicablePoints = new TreeMap<Double, Point2D.Double>();

    if (/*
         * (tempTarget == null || posToRef.equals(tempTarget.x, tempTarget.y))
         * &&
         */target != null)
      tempTarget = new WBPoint(target.x, target.y);

    // Say("TempTarget", tempTarget.toString());
    double direction = posToRef.direction(tempTarget);
    double newDirection = 0;
    double disTar = posToRef.distance(tempTarget);
    boolean isSafe = true;
    boolean isPracticable = true;
    Obstacles obsts = GeoUtil.getLocalObstacles(obst, 100, posToRef);
    ArrayList<MobileFoe> mfoes = GeoUtil.getLocalFoes(foes, Cst.DR.ExplorerDR,
        posToRef);

    double i = 1;
    boolean isNegatif = true;
    final double delta = 360 / 33;
    Point2D.Double practicablePoint = null;

    do {
      isSafe = true;
      isPracticable = true;
      for (Obstacle ob : obsts)
        if (ob.getPos().distance(tempTarget) < disTar
            && GeoUtil.areCircleLineIntersected(posToRef, tempTarget,
                ob.getPos(), ob.getRadius() + 11)) {
          isNegatif = !isNegatif;
          i = isNegatif ? i : i + 1;
          double mult = isNegatif ? i * delta : -i * delta;
          newDirection = getDeltaDir(direction, mult);
          tempTarget = posToRef.getTargetPoint(Cst.DR.ExplorerDR / 2,
              newDirection);
          isPracticable = false;
          break;
        }
      if (isPracticable)
        if (defend) {
          for (Entry<AgentAddress, Ally> al : allies.entrySet())
            if (al.getValue().getPosition().distance(tempTarget) < disTar
                && GeoUtil.areCircleLineIntersected(posToRef, tempTarget, al
                    .getValue().getPosition(), al.getValue().getRadius() + 11)) {
              isNegatif = !isNegatif;
              i = isNegatif ? i : i + 1;
              double mult = isNegatif ? i * delta : -i * delta;
              newDirection = getDeltaDir(direction, mult);
              tempTarget = posToRef.getTargetPoint(Cst.DR.ExplorerDR / 2,
                  newDirection);
              isPracticable = false;
              break;
            }
          continue;
        }
      practicablePoint = new Point2D.Double();
      practicablePoint.setLocation(tempTarget);

      double score = 0;
      for (MobileFoe mf : mfoes) {
        score += ScoreDirection(newDirection, mf);
        int maxDistance = mf.IsFoe() ? Cst.DR.LauncherDR + 20 : 88;
        if (!mf.getType().equals(MobileFoe.Type.Rocket)
            && (GeoUtil.areCircleLineIntersected(posToRef, tempTarget,
                mf.getPosition(), mf.getPerceptRadius() + 20) || GeoUtil
                .areLineLineIntersected(posToRef, tempTarget, mf.getPosition(),
                    mf.getTargetPoint(300), maxDistance))) {
          isNegatif = !isNegatif;
          i = isNegatif ? i : i + 1;
          double mult = isNegatif ? i * delta : -i * delta;
          newDirection = getDeltaDir(direction, mult);
          tempTarget = posToRef.getTargetPoint(Cst.DR.ExplorerDR / 2,
              newDirection);
          isSafe = false;
          break;
        }
        if (mf.getType().equals(MobileFoe.Type.Rocket)) {
          if (mf.getDirection() == -1 || !mf.isApproaching(posToRef))
            continue;
          // double step = i;
          while (GeoUtil.angleBetween2Lines(posToRef, tempTarget,
              mf.getPosition(), mf.getTargetPoint(2)) < 60
              && i < 360 / delta) {

            isNegatif = !isNegatif;
            i = isNegatif ? i : i + 1;
            double mult = isNegatif ? i * delta : -i * delta;
            newDirection = getDeltaDir(direction, mult);
            tempTarget = posToRef.getTargetPoint(Cst.DR.ExplorerDR / 2,
                newDirection);
          }
          break;
        }
      }
      practicablePoints.put(score, practicablePoint);
    }
    while ((!isSafe || !isPracticable) && i < 360 / delta);

    if (!isSafe) {
      Say("Take best practicable point");
      tempTarget.setLocation(practicablePoints.lastEntry().getValue());
    }

    setHeading(posToRef.direction(tempTarget));

    if (!isPracticable || !isMoving())
      randomHeading();

    move();
  }

  private Double ScoreDirection(double myDir, MobileFoe foe) {
    Point2D.Double newPos = posToRef.getTargetPoint(1, myDir);
    Point2D.Double foeNewPos = foe.getTargetPoint(1);

    if (foeNewPos == null)
      foeNewPos = foe.getPosition();

    return newPos.distance(foeNewPos);
  }

  private InterestPoint selectBestTargetToAttack() {
    InterestPoint ip = points.getNearest(InterestPoint.Type.Base, posToRef);

    if (ip != null) {
      if (posToRef.distance(ip) < 230) {
        String[] args = new String[] { Cst.Priority.High,
            Double.toString(ip.getX()), Double.toString(ip.getY()) };
        Messenger(groupName, "Explorer", Cst.Msg.Goal.attack, args);
      }
      return ip;
    }
    Messenger(groupName, "Explorer", Cst.Msg.cancel, Cst.Msg.Goal.attack);

    Comparator<InterestPoint> comp = new Comparator<InterestPoint>() {

      @Override
      public int compare(InterestPoint o1, InterestPoint o2) {
        if (o1.distance(posToRef) > o2.distance(posToRef))
          return 1;
        else if (o1.distance(posToRef) < o2.distance(posToRef))
          return -1;
        else
          return 0;
      }
    };
    Collections.sort(points, comp);

    for (InterestPoint spot : points)
      if (spot.getType().equals(InterestPoint.Type.Food))
        for (MobileFoe foe : foes)
          if (spot.distance(foe.getPosition()) < 50)
            return spot;
    return null;

  }

  private WBPoint selectBestTargetToHelp(Mission top) {
    int priority = Integer.parseInt(top.getPriority());

    if (priority < 3 || points.size() == 0)
      return top.getLocation();

    return selectBestTargetToAttack();
  }

  private void SelectTarget() {
    TreeMap<Double, MobileFoe> rocket = new TreeMap<Double, MobileFoe>();
    TreeMap<Double, MobileFoe> foe = new TreeMap<Double, MobileFoe>();

    if (getRocketNumber() == 0 || getEnergyLevel() * 1.5 < baseEnergyLevel) {
      int currentEnergy = getEnergyLevel();
      int maxEnergy = baseEnergyLevel;
      if (currentEnergy * 1.5 < maxEnergy) {
        Messenger(groupName, "Explorer", Cst.Msg.Goal.help,
            String.valueOf(maxEnergy - currentEnergy));
        foeToAttack = null;
        return;
      } else {
        Messenger(groupName, "Explorer", Cst.Msg.cancel, Cst.Msg.Goal.help);
        buildRocket();
        if (getRocketNumber() != 0)
          hasAction = true;
      }
    }

    if (!defend)
      for (InterestPoint ip : points)
        if (ip.getType().equals(InterestPoint.Type.Base)
            && ip.distance(posToRef) < 150) {
          MobileFoe mf = new MobileFoe(MobileFoe.Type.Default, ip.x, ip.y,
              12000, true, 200);
          foe.put(mf.getPosition().distance(posToRef) * mf.getHitPoint() / 2,
              mf);
        }

    for (MobileFoe f : foes)
      if (f.IsFoe() && f.getRefreshed())
        if (f.getType().equals(MobileFoe.Type.Rocket)
            && f.getDirection() != -1
            && f.isApproaching(posToRef)
            && GeoUtil.areCircleSegmentIntersected(f.getPosition(),
                f.getTargetPoint(80), posToRef, 12))
          rocket.put(f.getDistance(posToRef), f);
        else if (!f.getType().equals(MobileFoe.Type.Rocket)) {
          double factor;
          if (f.getType().equals(MobileFoe.Type.Explorer))
            factor = f.getHitPoint() * 80 / 1000;
          else
            factor = f.getHitPoint() * 80 / 4000;
          foe.put(f.getDistance(posToRef) * factor, f);
        }

    if (!rocket.isEmpty())
      foeToAttack = rocket.firstEntry().getValue();
    else if (!foe.isEmpty())
      foeToAttack = foe.firstEntry().getValue();
    else
      foeToAttack = null;

    if (foeToAttack != null)
      broadcast(groupName, "Robot", Cst.Msg.ping);
  }

  private boolean shotRocket(double dir) {
    if (getRocketNumber() > 0)
      if (timeToReload == 0) {
        attackDir = dir;
        launchRocket(dir);
        hasAction = true;
        timeToReload = 3;
        return true;
      }
    return false;
  }

  @Override
  protected void CheckMessages() {
    WarbotMessage msg = null;

    TreeMap<KnightCandidate, Mission> boss = new TreeMap<KnightCandidate, Mission>();
    ArrayList<KnightCandidate> candidatesAttack = new ArrayList<KnightCandidate>();
    ArrayList<KnightCandidate> candidatesHelp = new ArrayList<KnightCandidate>();
    ArrayList<KnightCandidate> candidatesFood = new ArrayList<KnightCandidate>();

    // TODO: Check Message
    while (!isMessageBoxEmpty()) {
      msg = readMessage();
      if (msg.getSender() == msg.getReceiver())
        continue;
      if (!MessageRefPos(msg) && !CommonMessages(msg))
        if (msg.getAct().equals(Cst.Msg.goalRep)) {
          AgentAddress k_aa = msg.getSender();
          double k_x = msg.getFromX();
          double k_y = msg.getFromY();
          double k_score = DefinePriority(k_x, k_y, 1);
          KnightCandidate k = new KnightCandidate(k_aa, k_score + 100
              * Double.parseDouble(msg.getArg1()));
          boss.put(k, new Mission(msg.getArg1(), msg.getSender(),
              msg.getArg2(), toWBPoint(msg)));
          Say("RLauncher receive goal response");
        } else if (msg.getAct().equals(Cst.Msg.Goal.help)) {
          if (missions.isEmpty()
              || Cst.Priority.compareTo(missions.first().getPriority(),
                  msg.getArg1()) > 0) {
            WBPoint pos = msg.getLength() > 1 ? new WBPoint(
                Double.parseDouble(msg.getArgN(2)), Double.parseDouble(msg
                    .getArgN(3))) : toWBPoint(msg);
            Mission mission = new Mission(msg.getArg1(), msg.getSender(),
                Cst.Msg.Goal.help, pos);
            if (!missions.add(mission))
              Say("Didn't add mission.");
            else
              send(msg.getSender(), Cst.Msg.helpRT,
                  new String[] { Integer.toString(getEnergyLevel()) });
          } else if (msg.getSender() == missions.first().getNakamaAddress())
            send(msg.getSender(), Cst.Msg.helpRT,
                new String[] { Integer.toString(getEnergyLevel()) });
        } else if (msg.getAct().equals(Cst.Msg.pong)) {
          double radius = msg.getArg1().equals("Mobile") ? 22 : 32;
          allies.put(msg.getSender(), new Ally(toWBPoint(msg), radius));
        } else if (msg.getAct().equals(Cst.Msg.refreshMission)) {
          if (msg.getArg1().equals(Cst.Msg.Goal.attack)
              && !missions.first().getMissionType()
                  .equals(Mission.MissionType.ATTACK))
            send(msg.getSender(), Cst.Msg.cancel, Cst.Msg.Goal.attack);

        } else if (msg.getAct().equals(Cst.Msg.attackRT)) {
          double k_score = DefinePriority(msg.getFromX(), msg.getFromY(), 1);
          KnightCandidate k = new KnightCandidate(msg.getSender(), k_score);
          candidatesAttack.add(k);
        } else if (msg.getAct().equals(Cst.Msg.helpRT)) {
          int k_hp = Integer.parseInt(msg.getArg1());
          double k_score = DefinePriority(msg.getFromX(), msg.getFromY(), k_hp);
          KnightCandidate k = new KnightCandidate(msg.getSender(), k_score);
          candidatesHelp.add(k);
        } else if (msg.getAct().equals(Cst.Msg.helpRT)) {
          double k_score = Integer.parseInt(msg.getArg1());
          KnightCandidate k = new KnightCandidate(msg.getSender(), k_score);
          candidatesFood.add(k);
        } else if (msg.getAct().equals(Cst.Msg.Goal.explore))
          explore = true;
    }
    if (candidatesAttack.size() > 0) {
      Collections.sort(candidatesAttack);

      int i = 1;
      for (; i < candidatesAttack.size(); ++i)
        send(candidatesAttack.get(i).getAgentAddr(), Cst.Msg.cancel,
            new String[] { Cst.Msg.Goal.attack });
    }

    if (candidatesFood.size() > 0) {
      Collections.sort(candidatesFood);

      int i = 1;
      for (; i < candidatesFood.size(); ++i)
        send(candidatesFood.get(i).getAgentAddr(), Cst.Msg.cancel,
            new String[] { Cst.Msg.Goal.help });
    }

    if (candidatesHelp.size() > 0) {
      int i = 0;
      for (; i < nbEnnemis && i < candidatesHelp.size(); ++i)
        send(candidatesHelp.get(i).getAgentAddr(), Cst.Msg.ok,
            new String[] { Cst.Msg.Goal.help });
      for (; i < candidatesHelp.size(); ++i)
        send(candidatesHelp.get(i).getAgentAddr(), Cst.Msg.ko,
            new String[] { Cst.Msg.Goal.help });
    }

    if (boss.size() > 0) {
      send(boss.lastKey().getAgentAddr(), Cst.Msg.ok,
          new String[] { Cst.Msg.goalRep });
      missions.add(boss.remove(boss.lastKey()));
      for (Entry<KnightCandidate, Mission> k : boss.entrySet())
        send(k.getKey().getAgentAddr(), Cst.Msg.ko,
            new String[] { Cst.Msg.goalRep });
    }
  }

  @Override
  protected void ManageMissions() {
    if (missions.isEmpty())
      return;
    Mission top = missions.first();
    if (top.incrementTick().getTick() > 100) {
      send(top.getNakamaAddress(), Cst.Msg.refreshMission,
          top.getMissionString());
      top.incrementTick().resetTick();
    }
    switch (top.getMissionType()) {
    case ATTACK:

      defend = false;
      InterestPoint ip = selectBestTargetToAttack();
      if (ip == null)
        target = null;
      else
        target = new WBPoint(ip);
      break;
    case EXPLORE:
      break;
    case HELP:
      defend = true;
      target = selectBestTargetToHelp(top);
      break;
    case RECOLT:
      break;
    default:
      break;
    }
  }

  @Override
  protected void SendHelp() {
    WBPoint pos = foeAttackPos == null ? posToRef : foeAttackPos;
    String[] args = new String[] { Cst.Priority.High, Double.toString(pos.x),
        Double.toString(pos.y) };

    if (getShot() || foeToAttack != null
        && foeToAttack.getType().equals(MobileFoe.Type.RocketLauncher))
      Messenger(groupName, "Launcher", Cst.Msg.Goal.help, args);

    if (!foeNear && !estAttaquee && foeToAttack == null)
      Messenger(groupName, "Launcher", Cst.Msg.cancel, Cst.Msg.Goal.help);

    int currentEnergy = getEnergyLevel();
    int maxEnergy = baseEnergyLevel;
    if (currentEnergy * 2 < maxEnergy)
      Messenger(groupName, "Explorer", Cst.Msg.Goal.help,
          String.valueOf(maxEnergy - currentEnergy));
    else
      Messenger(groupName, "Explorer", Cst.Msg.cancel, Cst.Msg.Goal.help);
  }

  @Override
  protected void toDoWhenDead(AgentAddress dead) {
    if (dead == null)
      Say("Agent Address of the dead is dead");
    allies.remove(dead);
    return;
  }
}
TOP

Related Classes of warbot.chevri_t.Terminator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.