package warbot.chevri_t;
import java.awt.geom.Point2D;
import java.util.ArrayList;
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 Explorer extends Mobile
{
private boolean explore = false;
private boolean help = false;
private boolean recolt = false;
public Explorer() {}
@Override
public void activate() {
super.activate();
specificRoleName = "Explorer";
requestRole(groupName, specificRoleName, null);
points.setPerceptRadius(Cst.DR.ExplorerDR);
}
@Override
public void doIt() {
super.doIt();
if (posToRef == null)
return;
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 : 25;
if (foe) {
nbEnnemis++;
foeAttackPos = toWBPoint(element);
} else if (help)
if (posToRef.distance(missions.first().getLocation()) < 70)
putFood(element, 50);
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))
&& !isNearWeakAlly(toWBPoint(element))) {
points.add(new InterestPoint(toWBPoint(element),
InterestPoint.Type.Food));
if (recolt && !isBagFull())
takeFood((Food)element);
} else {
if (isNearABase(toWBPoint(element)))
points.add(new InterestPoint(toWBPoint(element),
InterestPoint.Type.Pantry));
if (help && isBagEmpty())
takeFood((Food)element);
}
} else if (elmType.equals("Home")) {
if (foe)
points.add(new InterestPoint(toWBPoint(element),
InterestPoint.Type.Base));
else if (!isBagEmpty() && !help) {
homes.put(element.getAgent(), toWBPoint(element));
putFood(element, 2);
} else
homes.put(element.getAgent(), toWBPoint(element));
} else if (elmType.equals("Obstacle"))
obst.add(new Obstacle(toWBPoint(element), element.getRadius()));
else if (elmType.equals("Rocket"))
foes.put(element, posToRef, true, 70);
}
UpdateFoesAndIP();
PerformAction();
SendMessages();
}
/**
* @param wbPoint
* Position to test
* @return true if a weak ally is near the position
*/
private boolean isNearWeakAlly(WBPoint wbPoint) {
for (MobileFoe ally : foes)
if (!ally.IsFoe() && ally.getType().equals(MobileFoe.Type.RocketLauncher)
&& wbPoint.distance(ally.getPosition()) < 25)
return true;
return false;
}
private void PerformAction() {
TreeMap<Double, Point2D.Double> practicablePoints = new TreeMap<Double, Point2D.Double>();
if (hasAction || target == null && !explore)
return;
else if (explore || !isMoving())
if (tempTarget == null || !isMoving())
tempTarget = posToRef.getTargetPoint(Cst.DR.ExplorerDR / 2,
Math.random() * 360);
else if (posToRef.equals(tempTarget.x, tempTarget.y))
tempTarget = posToRef.getTargetPoint(Cst.DR.ExplorerDR / 2,
getDeltaDir(getHeading(), (Math.random() - 0.5) * 65));
if (tempTarget == null || posToRef.equals(tempTarget.x, tempTarget.y))
tempTarget = new WBPoint(target.x, target.y);
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 - 8, 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) {
practicablePoint = new Point2D.Double();
practicablePoint.setLocation(tempTarget);
double score = 0;
for (MobileFoe mf : mfoes) {
if (mf.IsFoe())
score += ScoreDirection(newDirection, mf);
int maxDistance = mf.IsFoe() ? Cst.DR.LauncherDR + 20 : 20;
int radiusBonus = mf.IsFoe() ? 20 : 5;
if (!mf.getType().equals(MobileFoe.Type.Rocket)
&& (GeoUtil.areCircleSegmentIntersected(posToRef, tempTarget,
mf.getPosition(), mf.getPerceptRadius() + radiusBonus) || 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 (GeoUtil.angleBetween2Lines(posToRef, tempTarget,
mf.getPosition(), mf.getTargetPoint(2)) < 60
&& GeoUtil.areSegmentSegmentIntersected(posToRef, tempTarget,
mf.getPosition(), mf.getTargetPoint(150))) {
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;
}
}
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));
move();
}
private void putFood(Percept home, double minDist) {
if (home.getDistance() < minDist) {
dropAll();
if (!isBagEmpty())
drop(0);
hasAction = true;
} else
target = toWBPoint(home);
}
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 void takeFood(Food p) {
if (p.getDistance() < 2) {
if (baseEnergyLevel > getEnergyLevel() * 2)
eat(p);
else
take(p);
hasAction = true;
} else
target = toWBPoint(p);
}
@Override
protected void CheckMessages() {
WarbotMessage msg = null;
TreeMap<KnightCandidate, Mission> boss = new TreeMap<KnightCandidate, Mission>();
// TODO: Check Message
while (!isMessageBoxEmpty()) {
msg = readMessage();
if (msg.getSender() == msg.getReceiver())
continue;
if (!MessageRefPos(msg) && !CommonMessages(msg) && posToRef != null)
if (msg.getAct().equals(Cst.Msg.goalRep)) {
if (msg.getLength() <= 1)
continue;
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("Explorer receive goal response");
} else if (msg.getAct().equals(Cst.Msg.Goal.attack)) {
if (msg.getLength() < 1)
continue;
Say("Receive Mission : attack");
if (missions.isEmpty()
|| Cst.Priority.compareTo(missions.first().getPriority(),
msg.getArg1()) > 0) {
WBPoint pos;
if (msg.getLength() > 2)
pos = new WBPoint(Double.parseDouble(msg.getArgN(2)),
Double.parseDouble(msg.getArgN(3)));
else
pos = 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.attackRT);
} else if (!missions.isEmpty()
&& msg.getSender() == missions.first().getNakamaAddress())
send(msg.getSender(), Cst.Msg.attackRT);
} else if (msg.getAct().equals(Cst.Msg.Goal.help)) {
Mission mission = new Mission("1", msg.getSender(),
Cst.Msg.Goal.help, toWBPoint(msg));
if (!missions.add(mission))
Say("Didn't add mission.");
else if (mission != null) {
double score = posToRef.distance(mission.getLocation());;
InterestPoint pantry = points.getNearest(InterestPoint.Type.Pantry,
posToRef);
if (bagSize() == 0 && pantry != null)
score = score * 2 + pantry.distance(posToRef);
send(msg.getSender(), Cst.Msg.foodRT, Double.toString(score));
}
}
}
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() {
help = false;
if (missions.isEmpty())
return;
Mission m = missions.first();
if (m.incrementTick().getTick() > 100) {
send(m.getNakamaAddress(), Cst.Msg.refreshMission, m.getMissionString());
m.incrementTick().resetTick();
}
switch (m.getMissionType()) {
case HELP:
help = true;
if (isBagEmpty()) {
recolt = true;
InterestPoint ip = points.getNearest(InterestPoint.Type.Pantry,
posToRef);
if (ip == null) {
explore = true;
target = null;
} else {
target = new WBPoint(ip);
explore = false;
}
} else {
recolt = false;
explore = false;
target = m.getLocation();
}
break;
case ATTACK:
target = m.getLocation();
Obstacle newObst = new Obstacle(target, 170);
obst.add(newObst);
recolt = false;
break;
case EXPLORE:
explore = true;
recolt = false;
break;
case RECOLT:
recolt = true;
if (isBagFull()) {
recolt = false;
target = m.getLocation();
} else {
InterestPoint ip = points.getNearestWithoutFoe(InterestPoint.Type.Food,
posToRef, foes);
if (ip == null) {
explore = true;
target = null;
} else {
target = new WBPoint(ip);
explore = false;
}
}
break;
default:
break;
}
}
}