diff --git a/.classpath b/.classpath
index 63d2139..0f640cf 100644
--- a/.classpath
+++ b/.classpath
@@ -13,5 +13,6 @@
+
diff --git a/fullWindow.jpg b/fullWindow.jpg
new file mode 100644
index 0000000..ab2c08f
Binary files /dev/null and b/fullWindow.jpg differ
diff --git a/src/CameraCalibrator.java b/src/CameraCalibrator.java
index 3704f19..fca9164 100644
--- a/src/CameraCalibrator.java
+++ b/src/CameraCalibrator.java
@@ -8,15 +8,12 @@ import java.util.ArrayList;
public class CameraCalibrator {
Robot robot;
- Randomizer randomizer;
public CameraCalibrator() throws AWTException {
robot = new Robot();
- randomizer = new Randomizer();
}
- public void rotateUntilObjectFound(String objectNameToLookFor) throws Exception {
- ObjectDetector objectDetector = new ObjectDetector();
+ public void rotateUntilObjectFound(ObjectDetector objectDetector, String objectNameToLookFor) throws Exception {
BufferedImage screenCapture = objectDetector.captureScreenshotGameWindow();
ArrayList detectedObjects = objectDetector.getObjectsInImage(screenCapture, 0.30);
@@ -30,11 +27,10 @@ public class CameraCalibrator {
}
private void randomlyRotateKeyboard() throws InterruptedException {
- Randomizer randomizer = new Randomizer();
- int keyPressLength = randomizer.nextGaussianWithinRange(350, 1105);
+ int keyPressLength = Randomizer.nextGaussianWithinRange(150, 505);
robot.keyPress(KeyEvent.VK_LEFT);
Thread.sleep(keyPressLength);
robot.keyRelease(KeyEvent.VK_LEFT);
- Thread.sleep(randomizer.nextGaussianWithinRange(120, 250));
+ Thread.sleep(Randomizer.nextGaussianWithinRange(120, 250));
}
}
diff --git a/src/Constants.java b/src/Constants.java
index d86b6b5..bc80a71 100644
--- a/src/Constants.java
+++ b/src/Constants.java
@@ -1,12 +1,19 @@
+import java.awt.Point;
+import java.awt.Rectangle;
public class Constants {
+ public static final int FULL_WINDOW_WIDTH = 960;
+ public static final int FULL_WINDOW_HEIGHT = 1080;
+
public static final int GAME_WINDOW_OFFSET_X = 103;
public static final int GAME_WINDOW_OFFSET_Y = 85;
public static final int GAME_WINDOW_WIDTH = 510;
public static final int GAME_WINDOW_HEIGHT = 330;
+ public static final int CHARACTER_CENTER_X = 356;
+ public static final int CHARACTER_CENTER_Y = 247;
- public static final int INVENTORY_WINDOW_OFFSET_X = 655; //top left corner of inventory, fromm top left corner of screen
+ public static final int INVENTORY_WINDOW_OFFSET_X = 655;
public static final int INVENTORY_WINDOW_OFFSET_Y = 290;
public static final int INVENTORY_WINDOW_WIDTH = 171;
public static final int INVENTORY_WINDOW_HEIGHT = 350;
@@ -14,4 +21,49 @@ public class Constants {
public static final int INVENTORY_SLOT_HEIGHT = 254 / 7;
public static final int INVENTORY_NUM_ROWS = 4;
public static final int INVENTORY_NUM_COLUMNS = 7;
+
+
+ // ---------------------------------- ICONS ----------------------------------------------
+
+ public static final int STATS_ICON_OFFSET_X = 660;
+ public static final int STATS_ICON_OFFSET_Y = 250;
+ public static final int STATS_ICON_WIDTH = 25;
+ public static final int STATS_ICON_HEIGHT = 25;
+
+ public static final int INVENTORY_ICON_OFFSET_X = 728;
+ public static final int INVENTORY_ICON_OFFSET_Y = 250;
+ public static final int INVENTORY_ICON_WIDTH = 25;
+ public static final int INVENTORY_ICON_HEIGHT = 25;
+
+ public static final int LOGOUT_ICON_OFFSET_X = 728;
+ public static final int LOGOUT_ICON_OFFSET_Y = 528;
+ public static final int LOGOUT_ICON_WIDTH = 25;
+ public static final int LOGOUT_ICON_HEIGHT = 25;
+
+ // ---------------------------------- STATS ----------------------------------------------
+
+ public static final int MINING_XP_STAT_OFFSET_X = 777;
+ public static final int MINING_XP_STAT_OFFSET_Y = 288;
+ public static final int MINING_XP_STAT_WIDTH = 50;
+ public static final int MINING_XP_STAT_HEIGHT = 23;
+
+ public static Point getCharacterLocation() {
+ return new Point(CHARACTER_CENTER_X, CHARACTER_CENTER_Y);
+ }
+
+ public static Rectangle getStatsIconRectangle() {
+ return new Rectangle(STATS_ICON_OFFSET_X, STATS_ICON_OFFSET_Y, STATS_ICON_WIDTH, STATS_ICON_HEIGHT);
+ }
+
+ public static Rectangle getInventoryIconRectangle() {
+ return new Rectangle(INVENTORY_ICON_OFFSET_X, INVENTORY_ICON_OFFSET_Y, INVENTORY_ICON_WIDTH, INVENTORY_ICON_HEIGHT);
+ }
+
+ public static Rectangle getLogoutIconRectangle() {
+ return new Rectangle(LOGOUT_ICON_OFFSET_X, LOGOUT_ICON_OFFSET_Y, LOGOUT_ICON_WIDTH, LOGOUT_ICON_HEIGHT);
+ }
+
+ public static Rectangle getMiningXPRectangle() {
+ return new Rectangle(MINING_XP_STAT_OFFSET_X, MINING_XP_STAT_OFFSET_Y, MINING_XP_STAT_WIDTH, MINING_XP_STAT_HEIGHT);
+ }
}
diff --git a/src/Cursor.java b/src/Cursor.java
index f9f9b44..6bc2ad4 100644
--- a/src/Cursor.java
+++ b/src/Cursor.java
@@ -4,6 +4,7 @@ import java.awt.AWTException;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
+import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.io.BufferedReader;
@@ -16,6 +17,8 @@ import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.opencv.core.Rect2d;
+
public class Cursor {
public static final int NUMBER_OF_DISTANCES = 2203; // For 1080p screen
@@ -107,6 +110,24 @@ public class Cursor {
return randomizedGoalPoint; // Return the point we moved to in case we need precise movement afterwards
}
+ public Point moveInsideBoundingRectangle(Rectangle boundingRectangle) throws Exception {
+ Point randomizedGoalPoint = getRandomPointInBoundingRectangle(boundingRectangle);
+ moveCursorToCoordinates(randomizedGoalPoint);
+ return randomizedGoalPoint;
+ }
+
+ public Point moveAndLeftClickInBoundingRectangle(Rectangle boundingRectangle) throws Exception {
+ Point randomizedGoalPoint = getRandomPointInBoundingRectangle(boundingRectangle);
+ moveAndLeftClickAtCoordinates(randomizedGoalPoint);
+ return randomizedGoalPoint;
+ }
+
+ private Point getRandomPointInBoundingRectangle(Rectangle boundingRectangle) {
+ int x = randomizer.nextGaussianWithinRange(boundingRectangle.x, boundingRectangle.x + boundingRectangle.width);
+ int y = randomizer.nextGaussianWithinRange(boundingRectangle.y, boundingRectangle.y + boundingRectangle.height);
+ return new Point(x, y);
+ }
+
public Point moveAndLeftClickAtCoordinatesWithRandomness(Point goalPoint, int xToleranceLeft, int xToleranceRight, int yTolerance) throws Exception {
Point randomizedGoalPoint = randomizePoint(goalPoint, xToleranceLeft, xToleranceRight, yTolerance);
moveAndLeftClickAtCoordinates(randomizedGoalPoint);
diff --git a/src/HumanBehavior.java b/src/HumanBehavior.java
new file mode 100644
index 0000000..97afa03
--- /dev/null
+++ b/src/HumanBehavior.java
@@ -0,0 +1,30 @@
+
+public class HumanBehavior {
+
+ private int minimumTimeTillXPCheck = 35;
+ private int maximumTimeTillXPCheck = 75;
+
+ long nextTimeToCheckMiningXP;
+
+ public HumanBehavior() {
+ nextTimeToCheckMiningXP = System.currentTimeMillis() + getNextTimeTillXPCheck();
+ }
+
+ public void checkMiningXP(Cursor cursor) throws Exception {
+ cursor.moveAndLeftClickInBoundingRectangle(Constants.getStatsIconRectangle());
+ cursor.moveInsideBoundingRectangle(Constants.getMiningXPRectangle());
+ Thread.sleep(Randomizer.nextGaussianWithinRange(1750, 3420));
+ cursor.moveAndLeftClickInBoundingRectangle(Constants.getInventoryIconRectangle());
+ }
+
+ public void randomlyCheckMiningXP(Cursor cursor) throws Exception {
+ if (System.currentTimeMillis() > nextTimeToCheckMiningXP) {
+ checkMiningXP(cursor);
+ nextTimeToCheckMiningXP = System.currentTimeMillis() + getNextTimeTillXPCheck();
+ }
+ }
+
+ private int getNextTimeTillXPCheck() {
+ return Randomizer.nextGaussianWithinRange(1000 * 60 * minimumTimeTillXPCheck, 1000 * 60 * maximumTimeTillXPCheck);
+ }
+}
diff --git a/src/ImageCollector.java b/src/ImageCollector.java
index a183d55..b1e4b02 100644
--- a/src/ImageCollector.java
+++ b/src/ImageCollector.java
@@ -12,6 +12,7 @@ public class ImageCollector {
public String screenshotOutputDirectory;
public Rectangle gameWindowRectangle;
+ public Rectangle fullWindowRectangle;
public Robot robot;
/*
@@ -26,6 +27,7 @@ public class ImageCollector {
public ImageCollector(String screenshotOutputDirectory) throws AWTException {
initializeGameWindowRectangle();
+ initializeFullWindowRectangle();
this.screenshotOutputDirectory = screenshotOutputDirectory;
this.robot = new Robot();
}
@@ -34,6 +36,10 @@ public class ImageCollector {
this.gameWindowRectangle = new Rectangle(Constants.GAME_WINDOW_OFFSET_X, Constants.GAME_WINDOW_OFFSET_Y, Constants.GAME_WINDOW_WIDTH, Constants.GAME_WINDOW_HEIGHT);
}
+ private void initializeFullWindowRectangle() {
+ this.fullWindowRectangle = new Rectangle(0, 0, Constants.FULL_WINDOW_WIDTH, Constants.FULL_WINDOW_HEIGHT);
+ }
+
public void collectImages(String itemName) throws IOException, InterruptedException, AWTException {
int itemCounter = getItemCounter(itemName);
int numImagesToCapture = 50;
@@ -74,6 +80,12 @@ public class ImageCollector {
System.out.println("Wrote file: " + fileName);
}
+ public void captureAndSaveFullWindow() throws IOException {
+ BufferedImage imageCaptured = robot.createScreenCapture(fullWindowRectangle);
+ ImageIO.write(imageCaptured, "jpg", new File(getFileName("fullWindow", 0)));
+ System.out.println("Wrote file.");
+ }
+
private String getFileName(String itemName, int counter) {
return screenshotOutputDirectory + itemName + "_" + counter + ".jpg";
}
@@ -85,8 +97,9 @@ public class ImageCollector {
public static void main(String[] args) throws Exception
{
- ImageCollector imageCollector = new ImageCollector("/home/dpapp/Desktop/RunescapeAI/TensorFlow/Ores/Images/");
- imageCollector.collectImages("ore");
+ ImageCollector imageCollector = new ImageCollector("/home/dpapp/Desktop/RunescapeAI/Images/");
+ //imageCollector.collectImages("ore");
//imageCollector.generateInventoryImages();
+ imageCollector.captureAndSaveFullWindow();
}
}
diff --git a/src/IronMiner.java b/src/IronMiner.java
index d2b267b..4405811 100644
--- a/src/IronMiner.java
+++ b/src/IronMiner.java
@@ -25,14 +25,14 @@ public class IronMiner {
public static final int IRON_ORE_MINING_TIME_MILLISECONDS = 1320;
public static final int MAXIMUM_DISTANCE_TO_WALK_TO_IRON_ORE = 400;
- public static final Point GAME_WINDOW_CENTER = new Point(Constants.GAME_WINDOW_WIDTH / 2, Constants.GAME_WINDOW_HEIGHT / 2);
Cursor cursor;
CursorTask cursorTask;
Inventory inventory;
ObjectDetector objectDetector;
Robot robot;
- Randomizer randomizer;
+ HumanBehavior humanBehavior;
+ CameraCalibrator cameraCalibrator;
public IronMiner() throws AWTException, IOException
{
@@ -41,34 +41,19 @@ public class IronMiner {
inventory = new Inventory();
objectDetector = new ObjectDetector();
robot = new Robot();
- randomizer = new Randomizer();
+ humanBehavior = new HumanBehavior();
+ cameraCalibrator = new CameraCalibrator();
}
public void run() throws Exception {
long startTime = System.currentTimeMillis();
- long garbageCollectionTime = System.currentTimeMillis() + 60 * 5 * 1000;
- int framesWithoutObjects = 0;
while (((System.currentTimeMillis() - startTime) / 1000.0 / 60) < 85) {
- long frameStartTime = System.currentTimeMillis();
BufferedImage screenCapture = objectDetector.captureScreenshotGameWindow();
- System.out.println("looking for iron ores");
ArrayList detectedObjects = objectDetector.getObjectsInImage(screenCapture, 0.30);
ArrayList ironOres = objectDetector.getObjectsOfClassInList(detectedObjects, "ironOre");
- System.out.println("Found " + detectedObjects.size() + " objects.");
- if (ironOres.size() == 0) {
- framesWithoutObjects++;
- System.out.println("no objects found!");
- }
- else {
- framesWithoutObjects = 0;
- }
- if (framesWithoutObjects > 50) {
- CameraCalibrator cameraCalibrator = new CameraCalibrator();
- cameraCalibrator.rotateUntilObjectFound("ironOre");
- }
DetectedObject closestIronOre = getClosestObjectToCharacter(ironOres);
if (closestIronOre != null) {
@@ -78,7 +63,7 @@ public class IronMiner {
cursor.moveAndLeftClickAtCoordinatesWithRandomness(closestIronOre.getCenterForClicking(), 10, 10);
long miningStartTime = System.currentTimeMillis();
- int maxTimeToMine = randomizer.nextGaussianWithinRange(3400, 4519);
+ int maxTimeToMine = Randomizer.nextGaussianWithinRange(3400, 4519);
boolean objectTrackingFailure = false;
boolean oreAvailable = true;
@@ -101,13 +86,7 @@ public class IronMiner {
}
}
-
- // Garbage Collection
- if (((System.currentTimeMillis() - garbageCollectionTime) / 1000.0 / 60) > 0) {
- System.out.println("Running garbage collection.");
- System.gc();
- garbageCollectionTime = System.currentTimeMillis() + randomizer.nextGaussianWithinRange(8500, 19340) * 60;
- }
+ humanBehavior.randomlyCheckMiningXP(cursor);
dropInventoryIfFull();
}
}
@@ -116,6 +95,7 @@ public class IronMiner {
inventory.updateLastSlot();
if (inventory.isLastSlotInInventoryFull()) {
cursorTask.optimizedDropAllItemsInInventory(cursor, inventory);
+ Thread.sleep(Randomizer.nextGaussianWithinRange(1104, 1651));
}
}
@@ -128,7 +108,7 @@ public class IronMiner {
DetectedObject closestObjectToCharacter = null;
for (DetectedObject detectedObject : detectedObjects) {
- int objectDistanceToCharacter = getDistanceBetweenPoints(GAME_WINDOW_CENTER, detectedObject.getCenterForClicking());
+ int objectDistanceToCharacter = getDistanceBetweenPoints(Constants.getCharacterLocation(), detectedObject.getCenterForClicking());
if (objectDistanceToCharacter < closestDistanceToCharacter) {
closestDistanceToCharacter = objectDistanceToCharacter;
closestObjectToCharacter = detectedObject;
diff --git a/src/ObjectDetector.java b/src/ObjectDetector.java
index e94651b..b8161a4 100644
--- a/src/ObjectDetector.java
+++ b/src/ObjectDetector.java
@@ -53,11 +53,9 @@ public class ObjectDetector {
this.robot = new Robot();
}
- // Goal: reduce this to < 50 ms
public ArrayList getObjectsInImage(BufferedImage image, double scoreThreshold) throws Exception {
List> outputs = null;
ArrayList detectedObjectsInImage = new ArrayList();
- //int count = 0;
makeImageTensor(image);
try (Tensor input = makeImageTensor(image)) {
outputs =
@@ -69,6 +67,7 @@ public class ObjectDetector {
.fetch("detection_classes")
.fetch("detection_boxes")
.run();
+ input.close();
}
try (Tensor scoresT = outputs.get(0).expect(Float.class);
@@ -82,17 +81,14 @@ public class ObjectDetector {
for (int i = 0; i < scores.length; ++i) {
if (scores[i] > scoreThreshold) {
- //count++;
detectedObjectsInImage.add(new DetectedObject(scores[i], classes[i], boxes[i]));
}
}
- }
- // return count;
+ }
+ outputs = null;
return detectedObjectsInImage;
}
-
- // This is too slow -> running object detection each time reduces the framerate to 3fps, which messses up object tracking
public boolean isObjectPresentInBoundingBoxInImage(ArrayList detectedObjects, Rect2d boundingBox, String objectClass) throws Exception {
for (DetectedObject detectedObject : detectedObjects) {
if (detectedObject.getDetectionClass().equals(objectClass)) {
@@ -117,7 +113,7 @@ public class ObjectDetector {
return detectedObjectsOfType;
}
- private static Tensor makeImageTensor(BufferedImage image) throws IOException {
+ private Tensor makeImageTensor(BufferedImage image) throws IOException {
BufferedImage formattedImage = convertBufferedImage(image, BufferedImage.TYPE_3BYTE_BGR);
byte[] data = ((DataBufferByte) formattedImage.getData().getDataBuffer()).getData();
bgr2rgb(data);
@@ -127,7 +123,7 @@ public class ObjectDetector {
return Tensor.create(UInt8.class, shape, ByteBuffer.wrap(data));
}
- private static BufferedImage convertBufferedImage(BufferedImage sourceImage, int bufferedImageType) {
+ private BufferedImage convertBufferedImage(BufferedImage sourceImage, int bufferedImageType) {
BufferedImage image = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), bufferedImageType);
Graphics2D g2d = image.createGraphics();
g2d.drawImage(sourceImage, 0, 0, null);
@@ -135,16 +131,16 @@ public class ObjectDetector {
return image;
}
- private static void bgr2rgb(byte[] data) {
- for (int i = 0; i < data.length; i += 3) {
- byte tmp = data[i];
- data[i] = data[i + 2];
- data[i + 2] = tmp;
- }
- }
+ private void bgr2rgb(byte[] data) {
+ for (int i = 0; i < data.length; i += 3) {
+ byte tmp = data[i];
+ data[i] = data[i + 2];
+ data[i + 2] = tmp;
+ }
+ }
public BufferedImage captureScreenshotGameWindow() throws IOException, AWTException {
- Rectangle area = new Rectangle(Constants.GAME_WINDOW_OFFSET_X, Constants.GAME_WINDOW_OFFSET_Y, Constants.GAME_WINDOW_WIDTH, Constants.GAME_WINDOW_HEIGHT);
- return robot.createScreenCapture(area);
- }
+ Rectangle area = new Rectangle(Constants.GAME_WINDOW_OFFSET_X, Constants.GAME_WINDOW_OFFSET_Y, Constants.GAME_WINDOW_WIDTH, Constants.GAME_WINDOW_HEIGHT);
+ return robot.createScreenCapture(area);
+ }
}
\ No newline at end of file
diff --git a/src/ObjectTrackerTest.java b/src/ObjectTrackerTest.java
index 8f91216..57da966 100644
--- a/src/ObjectTrackerTest.java
+++ b/src/ObjectTrackerTest.java
@@ -31,7 +31,7 @@ class ObjectTrackerTest {
@Test
- void testObjectTrackingWithAllVideosInDirectory() {
+ void testObjectTrackingWithAllVideosInDirectory() throws Exception {
String videoDirectory = "/home/dpapp/Videos/";
for (File video : getListOfFilesFromDirectory(videoDirectory)) {
if (video.isFile()) {
@@ -75,14 +75,13 @@ class ObjectTrackerTest {
boolean trackingSuccess = objectTrackers.get(i).update(frame, boundingBoxes.get(i));
assertTrue(trackingSuccess);
- g.drawRect((int) boundingBoxes.get(i).x, (int) boundingBoxes.get(i).y, (int) boundingBoxes.get(i).width, (int) boundingBoxes.get(i).height);
+ //g.drawRect((int) boundingBoxes.get(i).x, (int) boundingBoxes.get(i).y, (int) boundingBoxes.get(i).width, (int) boundingBoxes.get(i).height);
}
ImageIO.write(screencapture, "jpg", new File(videoDirectory + "/frame_" + videoFileName + counter + ".jpg"));
counter++;
}
}
-
private BufferedImage Mat2BufferedImage(Mat matrix)throws Exception {
MatOfByte mob=new MatOfByte();
Imgcodecs.imencode(".jpg", matrix, mob);
diff --git a/src/Randomizer.java b/src/Randomizer.java
index 9dbf829..e5c9b2f 100644
--- a/src/Randomizer.java
+++ b/src/Randomizer.java
@@ -3,43 +3,22 @@ import java.util.Random;
//import Jama.Matrix;
public class Randomizer {
-
- Random random;
- public Randomizer() {
- random = new Random();
- }
-
- public int nextGaussianWithinRange(double rangeBegin, double rangeEnd) {
+ public static int nextGaussianWithinRange(double rangeBegin, double rangeEnd) {
+ Random random = new Random();
double rangeMean = (rangeEnd + rangeBegin) / 2.0;
double rangeSTD = (rangeEnd - rangeMean) / 3.0;
+
double result = random.nextGaussian() * rangeSTD + rangeMean;
while (result > rangeEnd || result < rangeBegin) {
- System.out.println("Gaussian result out of range...");
- System.out.println(rangeMean + ", std: " + rangeSTD);
result = random.nextGaussian() * rangeSTD + rangeMean;
}
return (int) result;
}
- public Point generatePeakForTransformationParabola(int pathDistance) {
+ public static Point generatePeakForTransformationParabola(int pathDistance) {
double maxTransformationScale = 0.2;
int peakX = nextGaussianWithinRange(0, pathDistance);
int peakY = nextGaussianWithinRange(0, pathDistance * maxTransformationScale);
return new Point(peakX, peakY);
}
-
- /*public double[] generateParabolaEquation(int pathDistance) {
- Point peakPoint = generatePeakForTransformationParabola(pathDistance);
- double[][] lhsMatrix = {{0, 0, 1}, {peakPoint.x * peakPoint.x, peakPoint.x, 1}, {pathDistance * pathDistance, pathDistance, 1}};
- double[][] rhsMatrix = {{0, peakPoint.y, 0}};
-
- Matrix lhs = new Matrix(lhsMatrix);
- Matrix rhs = new Matrix(rhsMatrix);
- Matrix ans = lhs.solve(rhs);
-
- double[] result = {ans.get(0, 0), ans.get(1, 0), ans.get(2, 0)};
- return result;
- }*/
-
- //public Point transformPoint
}
diff --git a/target/classes/CameraCalibrator.class b/target/classes/CameraCalibrator.class
index 5c38d75..33a40c5 100644
Binary files a/target/classes/CameraCalibrator.class and b/target/classes/CameraCalibrator.class differ
diff --git a/target/classes/Constants.class b/target/classes/Constants.class
index a4c61c2..7f9c051 100644
Binary files a/target/classes/Constants.class and b/target/classes/Constants.class differ
diff --git a/target/classes/Cursor.class b/target/classes/Cursor.class
index d706b87..701333f 100644
Binary files a/target/classes/Cursor.class and b/target/classes/Cursor.class differ
diff --git a/target/classes/CursorPathTest.class b/target/classes/CursorPathTest.class
index 0d520b4..04d5091 100644
Binary files a/target/classes/CursorPathTest.class and b/target/classes/CursorPathTest.class differ
diff --git a/target/classes/CursorPointTest.class b/target/classes/CursorPointTest.class
index f9340f3..10d9c8e 100644
Binary files a/target/classes/CursorPointTest.class and b/target/classes/CursorPointTest.class differ
diff --git a/target/classes/CursorTest.class b/target/classes/CursorTest.class
index bb6aa4e..b2c49d7 100644
Binary files a/target/classes/CursorTest.class and b/target/classes/CursorTest.class differ
diff --git a/target/classes/HumanBehavior.class b/target/classes/HumanBehavior.class
new file mode 100644
index 0000000..880b5ee
Binary files /dev/null and b/target/classes/HumanBehavior.class differ
diff --git a/target/classes/ImageCollector$1.class b/target/classes/ImageCollector$1.class
index 1681850..2a64d34 100644
Binary files a/target/classes/ImageCollector$1.class and b/target/classes/ImageCollector$1.class differ
diff --git a/target/classes/ImageCollector.class b/target/classes/ImageCollector.class
index f007ae4..eb7f026 100644
Binary files a/target/classes/ImageCollector.class and b/target/classes/ImageCollector.class differ
diff --git a/target/classes/InventoryItemsTest.class b/target/classes/InventoryItemsTest.class
index f12e0ad..c8d8d23 100644
Binary files a/target/classes/InventoryItemsTest.class and b/target/classes/InventoryItemsTest.class differ
diff --git a/target/classes/InventoryTest.class b/target/classes/InventoryTest.class
index a2d4e5c..be6914f 100644
Binary files a/target/classes/InventoryTest.class and b/target/classes/InventoryTest.class differ
diff --git a/target/classes/IronMiner.class b/target/classes/IronMiner.class
index 0a5cc45..4029d43 100644
Binary files a/target/classes/IronMiner.class and b/target/classes/IronMiner.class differ
diff --git a/target/classes/ObjectDetector.class b/target/classes/ObjectDetector.class
index 4980977..ea4dbc2 100644
Binary files a/target/classes/ObjectDetector.class and b/target/classes/ObjectDetector.class differ
diff --git a/target/classes/ObjectDetectorTest.class b/target/classes/ObjectDetectorTest.class
index b47e04d..ebd9863 100644
Binary files a/target/classes/ObjectDetectorTest.class and b/target/classes/ObjectDetectorTest.class differ
diff --git a/target/classes/ObjectTrackerTest.class b/target/classes/ObjectTrackerTest.class
index 0723cc3..399e9c1 100644
Binary files a/target/classes/ObjectTrackerTest.class and b/target/classes/ObjectTrackerTest.class differ
diff --git a/target/classes/PointTest.class b/target/classes/PointTest.class
index ebfa96e..c5d156f 100644
Binary files a/target/classes/PointTest.class and b/target/classes/PointTest.class differ
diff --git a/target/classes/Randomizer.class b/target/classes/Randomizer.class
index 3dcca13..cfd3bb6 100644
Binary files a/target/classes/Randomizer.class and b/target/classes/Randomizer.class differ
diff --git a/target/classes/RandomizerTest.class b/target/classes/RandomizerTest.class
index 0f210bf..14cf1c7 100644
Binary files a/target/classes/RandomizerTest.class and b/target/classes/RandomizerTest.class differ