-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
390 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
yardstick/src/main/java/nl/tudelft/opencraft/yardstick/bot/ai/task/FlyTaskExecutor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package nl.tudelft.opencraft.yardstick.bot.ai.task; | ||
|
||
import nl.tudelft.opencraft.yardstick.bot.Bot; | ||
import nl.tudelft.opencraft.yardstick.bot.world.ChunkNotLoadedException; | ||
import nl.tudelft.opencraft.yardstick.util.Vector3d; | ||
import nl.tudelft.opencraft.yardstick.util.Vector3i; | ||
|
||
/** | ||
* In order to avoid obstacles, the bot first flies to the maximum altitude, | ||
* then flies to the target (X, Z) coordinates, then descends to meet the Y target | ||
*/ | ||
public class FlyTaskExecutor extends AbstractTaskExecutor { | ||
|
||
public static final int maxY = 150; | ||
private static final double speedY = 1; | ||
private final double speedXZ; | ||
|
||
private Vector3i target; | ||
|
||
public FlyTaskExecutor(final Bot bot, Vector3i targetLocation, double speed) { | ||
super(bot); | ||
|
||
this.target = targetLocation; | ||
if (bot.getPlayer().getLocation().intVector().equals(target)) { | ||
logger.warning("Useless fly task. Bot and given target location equal."); | ||
} | ||
|
||
speedXZ = speed; | ||
} | ||
|
||
@Override | ||
protected TaskStatus onTick() { | ||
// todo: perform additional checks for flying into objects | ||
|
||
Vector3d nextLocation = bot.getPlayer().getLocation(); | ||
Vector3i currentLocation = nextLocation.intVector(); | ||
int currX = currentLocation.getX(), currZ = currentLocation.getZ(); | ||
|
||
// check we have arrived | ||
if (currentLocation.equals(target)) { | ||
return TaskStatus.forSuccess(); | ||
} | ||
|
||
// check if we have to descend | ||
if (currX == target.getX() && currZ == target.getZ()) { | ||
try { | ||
int highestY = bot.getWorld().getHighestBlockAt(currX, currZ).getY(); | ||
// check we can actually descend; if not, change target | ||
if (highestY > target.getY()) { | ||
target = new Vector3i(currX, highestY, currZ); | ||
} | ||
} catch (ChunkNotLoadedException ex) { | ||
return TaskStatus.forFailure(String.format("Chunk that contains block %s not loaded", currentLocation)); | ||
} | ||
|
||
double toDescend = -Math.min(nextLocation.getY() - (double) target.getY(), speedY); | ||
nextLocation = nextLocation.add(0, toDescend, 0); | ||
} else if (currentLocation.getY() < maxY) { | ||
// we have to ascend | ||
double toAscend = Math.min((double) maxY - nextLocation.getY(), speedY); | ||
nextLocation = nextLocation.add(0, toAscend, 0); | ||
} else { | ||
// calculate delta movement | ||
double diffX = Math.abs((double) target.getX() - nextLocation.getX()); | ||
double diffZ = Math.abs((double) target.getZ() - nextLocation.getZ()); | ||
double moveX = Math.min(diffX, speedXZ); | ||
double moveZ = Math.min(diffZ, speedXZ); | ||
|
||
// adjust for angle | ||
if (diffX < diffZ) { | ||
moveX *= diffX / diffZ; | ||
} else { | ||
moveZ *= diffZ / diffX; | ||
} | ||
|
||
// account for direction | ||
if (target.getX() < nextLocation.getX()) moveX *= -1; | ||
if (target.getZ() < nextLocation.getZ()) moveZ *= -1; | ||
|
||
nextLocation = nextLocation.add(moveX, 0, moveZ); | ||
} | ||
|
||
// report location to server | ||
bot.getController().updateLocation(nextLocation); | ||
return TaskStatus.forInProgress(); | ||
} | ||
|
||
@Override | ||
protected void onStop() {} | ||
} |
155 changes: 155 additions & 0 deletions
155
...main/java/nl/tudelft/opencraft/yardstick/experiment/Experiment10GenerationStressTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
package nl.tudelft.opencraft.yardstick.experiment; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
import java.util.UUID; | ||
import java.util.stream.Collectors; | ||
import nl.tudelft.opencraft.yardstick.bot.Bot; | ||
import nl.tudelft.opencraft.yardstick.bot.ai.task.FlyTaskExecutor; | ||
import nl.tudelft.opencraft.yardstick.bot.ai.task.TaskExecutor; | ||
import nl.tudelft.opencraft.yardstick.bot.ai.task.TaskStatus; | ||
import nl.tudelft.opencraft.yardstick.util.Vector3i; | ||
|
||
public class Experiment10GenerationStressTest extends Experiment { | ||
|
||
private final List<Bot> botList = Collections.synchronizedList(new ArrayList<>()); | ||
private final Set<Bot> targetSet = Collections.synchronizedSet(new HashSet<>()); | ||
|
||
private double angle = 0; | ||
private double increment; | ||
private double targetDistance; | ||
private double botSpeed; | ||
|
||
private long startMillis; | ||
private int durationInSeconds; | ||
private int delay; | ||
|
||
public Experiment10GenerationStressTest() { | ||
super(9, "Bots move away from the spawn location"); | ||
} | ||
|
||
@Override | ||
protected void before() { | ||
int botsTotal = Integer.parseInt(options.experimentParams.get("bots")); | ||
this.durationInSeconds = Integer.parseInt(options.experimentParams.getOrDefault("duration", "600")); | ||
this.delay = Integer.parseInt(options.experimentParams.getOrDefault("delay", "0")) * 1000; | ||
this.botSpeed = Double.parseDouble(options.experimentParams.getOrDefault("speed", "0.3")); | ||
this.startMillis = System.currentTimeMillis(); | ||
this.increment = 2 * Math.PI / botsTotal; | ||
this.targetDistance = ((int) (1000 / TICK_MS) * durationInSeconds) * botSpeed; | ||
|
||
// connect the bots; todo: synchronized? | ||
for (int i = 0; i < botsTotal; i++) { | ||
Bot bot = createBot(); | ||
Thread connector = new Thread(newBotConnector(bot)); | ||
connector.setName("Connector-" + bot.getName()); | ||
connector.setDaemon(false); | ||
connector.start(); | ||
botList.add(bot); | ||
} | ||
} | ||
|
||
@Override | ||
protected void tick() { | ||
if (System.currentTimeMillis() - startMillis < delay) { | ||
return; | ||
} | ||
|
||
synchronized (botList) { | ||
List<Bot> disconnectedBots = botList.stream() | ||
.filter(Bot::hasBeenDisconnected) | ||
.collect(Collectors.toList()); | ||
disconnectedBots.forEach(bot -> bot.disconnect("Bot is not connected")); | ||
if (disconnectedBots.size() > 0) { | ||
logger.warning("Bots disconnected: " | ||
+ disconnectedBots.stream().map(Bot::getName).reduce("", (a, b) -> a + ", " + b)); | ||
botList.removeAll(disconnectedBots); | ||
} | ||
} | ||
|
||
synchronized (botList) { | ||
for (Bot bot : botList) { | ||
botTick(bot); | ||
} | ||
} | ||
} | ||
|
||
private void botTick(Bot bot) { | ||
if (!bot.isJoined()) { | ||
return; | ||
} | ||
|
||
// calculate bot target location if not already done | ||
if (!targetSet.contains(bot)) { | ||
// calculate target | ||
Vector3i startLocation = bot.getPlayer().getLocation().intVector(); | ||
int finalX = (int) Math.floor(targetDistance * Math.cos(angle)) + startLocation.getX(); | ||
int finalZ = (int) Math.floor(targetDistance * Math.sin(angle)) + startLocation.getZ(); | ||
angle += increment; | ||
Vector3i botTarget = new Vector3i(finalX, FlyTaskExecutor.maxY, finalZ); | ||
|
||
// move bot towards target | ||
bot.getLogger().info(String.format("Moving bot towards final target (%d, %d)", finalX, finalZ)); | ||
bot.setTaskExecutor(new FlyTaskExecutor(bot, botTarget, botSpeed)); | ||
targetSet.add(bot); | ||
} | ||
|
||
// disconnect bot if arrived | ||
TaskExecutor t = bot.getTaskExecutor(); | ||
if (t == null || t.getStatus().getType() != TaskStatus.StatusType.IN_PROGRESS) { | ||
bot.disconnect("Arrived at destination"); | ||
} | ||
} | ||
|
||
private Runnable newBotConnector(Bot bot) { | ||
return () -> { | ||
bot.connect(); | ||
int sleep = 1000; | ||
int tries = 3; | ||
while (tries-- > 0 && (bot.getPlayer() == null || !bot.isJoined())) { | ||
try { | ||
Thread.sleep(sleep); | ||
} catch (InterruptedException e) { | ||
e.printStackTrace(); | ||
break; | ||
} | ||
} | ||
if (!bot.isJoined()) { | ||
logger.warning(String.format("Could not connect bot %s:%d.", options.host, options.port)); | ||
bot.disconnect("Make sure to close all connections."); | ||
} | ||
}; | ||
} | ||
|
||
@Override | ||
protected Bot createBot() { | ||
return newBot(UUID.randomUUID().toString().substring(0, 6)); | ||
} | ||
|
||
@Override | ||
protected boolean isDone() { | ||
boolean timeUp = System.currentTimeMillis() - this.startMillis > this.durationInSeconds * 1_000; | ||
if (timeUp) { | ||
return true; | ||
} else if (botList.size() > 0) { | ||
boolean allBotsDisconnected; | ||
synchronized (botList) { | ||
allBotsDisconnected = botList.stream().allMatch(Bot::hasBeenDisconnected); | ||
} | ||
if (allBotsDisconnected) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
@Override | ||
protected void after() { | ||
for (Bot bot : botList) { | ||
bot.disconnect("disconnect"); | ||
} | ||
} | ||
} |
Oops, something went wrong.