From c79f40a5f13fd67e0956b067f7343877db0fcc32 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sat, 24 Nov 2018 11:01:23 -0800 Subject: [PATCH] tenor comms integration, and priority allocation caching --- .../QuantizedTaskPriorityAllocationCache.java | 112 ++++++++++++++++++ src/tenor/java/tenor/TaskNode.java | 3 + src/tenor/java/tenor/game/AquireItemTask.java | 7 +- src/tenor/java/tenor/game/DoCraft.java | 6 +- src/tenor/java/tenor/game/DoMine.java | 4 +- .../tenor/game/GetToCraftingTableTask.java | 14 ++- src/tenor/java/tenor/game/MineTask.java | 36 ++++-- .../java/tenor/game/MineWithToolTask.java | 25 +++- 8 files changed, 181 insertions(+), 26 deletions(-) create mode 100644 src/tenor/java/tenor/QuantizedTaskPriorityAllocationCache.java diff --git a/src/tenor/java/tenor/QuantizedTaskPriorityAllocationCache.java b/src/tenor/java/tenor/QuantizedTaskPriorityAllocationCache.java new file mode 100644 index 00000000..48941c57 --- /dev/null +++ b/src/tenor/java/tenor/QuantizedTaskPriorityAllocationCache.java @@ -0,0 +1,112 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package tenor; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public abstract class QuantizedTaskPriorityAllocationCache extends QuantizedTaskNode { + + private final Map allocationByQuantity; + + public QuantizedTaskPriorityAllocationCache(Bot bot, DependencyType type) { + super(bot, type); + this.allocationByQuantity = new HashMap<>(); + } + + @Override + public final double priorityAllocatedTo(IQuantizedParentTaskRelationship child, int quantity) { + return allocationByQuantity.computeIfAbsent(quantity, this::allocationStrategy).allocatedTo(child); + } + + protected Allocation allocationStrategy(int quantity) { // overridable + double amount = effectiveAllocationSize(quantity); + Allocation alloc = new Allocation(amount); + List children = childTasks(); + if (children.size() < 2) { + return new Allocation(amount).distributeEqually(); // 0 or 1 cannot be anything but equal distribution + } + double[] costs = new double[children.size()]; + for (int i = 0; i < costs.length; i++) { + costs[i] = children.get(i).cost().value(quantity); + } + switch (type) { + case ANY_ONE_OF: + // by default, give it all to the lowest cost + // this is stable + int lowestInd = 0; + for (int i = 1; i < costs.length; i++) { + if (costs[i] < costs[lowestInd]) { + lowestInd = i; + } + } + alloc.givePriority(lowestInd, alloc.unallocated()); + return alloc; + default: + throw new UnsupportedOperationException("Not implemented yet"); + } + } + + protected double effectiveAllocationSize(int quantity) { // overridable + return priority().value(quantity); + } + + protected class Allocation { + private final double[] priorities; + private final double total; + + public Allocation(double total) { + this.priorities = new double[childTasks().size()]; + this.total = total; + } + + public double unallocated() { + return total - allocated(); + } + + public double allocated() { + double sum = 0; + for (double d : priorities) { + sum += d; + } + return sum; + } + + public Allocation distributeEqually() { + int count = priorities.length; + double toDistribute = unallocated(); + double priorityToEach = toDistribute / count; + for (int i = 0; i < count; i++) { + priorities[i] += priorityToEach; + } + return this; + } + + public void givePriority(int childTaskIndex, double amount) { + if (amount > unallocated()) { + throw new IllegalStateException("not enough space"); + } + priorities[childTaskIndex] += amount; + } + + public double allocatedTo(IQuantizedParentTaskRelationship childRelationship) { + return priorities[childTasks().indexOf(childRelationship)]; + } + } +} diff --git a/src/tenor/java/tenor/TaskNode.java b/src/tenor/java/tenor/TaskNode.java index f4b4033d..efee099a 100644 --- a/src/tenor/java/tenor/TaskNode.java +++ b/src/tenor/java/tenor/TaskNode.java @@ -28,6 +28,9 @@ public abstract class TaskNode allocation; // allocation of what tasks have claim over what items in our inventory i guess String item; @@ -62,7 +61,7 @@ public class AquireItemTask extends QuantizedTaskNode implements IClaimProvider, } public int cachedCurrentQuantity() { - return allocation.entrySet().stream().mapToInt(Map.Entry::getValue).sum(); + return allocation.values().stream().mapToInt(x -> x).sum(); } @Override @@ -71,7 +70,7 @@ public class AquireItemTask extends QuantizedTaskNode implements IClaimProvider, } @Override - public double priorityAllocatedTo(IQuantizedParentTaskRelationship child, int quantity) { + public double effectiveAllocationSize(int quantity) { // how much of our priority would go to this child if it could provide us with quantity of the item we need // here's the thing honey, we *already have* some, so you're really asking what's the priority of getting quantity MORE diff --git a/src/tenor/java/tenor/game/DoCraft.java b/src/tenor/java/tenor/game/DoCraft.java index ea49408c..50f4e0af 100644 --- a/src/tenor/java/tenor/game/DoCraft.java +++ b/src/tenor/java/tenor/game/DoCraft.java @@ -20,7 +20,7 @@ package tenor.game; import tenor.ISingleParentSingularPriorityAllocator; import tenor.SingularTaskLeaf; -public class DoCraft extends SingularTaskLeaf implements ISingleParentSingularPriorityAllocator { +public class DoCraft extends SingularTaskLeaf implements ISingleParentSingularPriorityAllocator { // TODO this should be quantized! public final CraftingTask parent; @@ -32,6 +32,8 @@ public class DoCraft extends SingularTaskLeaf implements ISingleParentSingularPr @Override public double cost() { - return 420; + // this is a dummy task to represent actually completing the crafting, given that we have all the ingredients and are at a crafting table + // it's effectively free, so let's say it takes 1 second (20 ticks) + return 20D; } } diff --git a/src/tenor/java/tenor/game/DoMine.java b/src/tenor/java/tenor/game/DoMine.java index 1562e69a..3ca95d3a 100644 --- a/src/tenor/java/tenor/game/DoMine.java +++ b/src/tenor/java/tenor/game/DoMine.java @@ -22,9 +22,9 @@ import tenor.ISingleParentQuantizedPriorityAllocator; import tenor.QuantizedTaskLeaf; public class DoMine extends QuantizedTaskLeaf implements ISingleParentQuantizedPriorityAllocator { - final MineTask parent; + final MineWithToolTask parent; - public DoMine(MineTask parent) { + public DoMine(MineWithToolTask parent) { super(parent.bot); this.parent = parent; addParent(parent); diff --git a/src/tenor/java/tenor/game/GetToCraftingTableTask.java b/src/tenor/java/tenor/game/GetToCraftingTableTask.java index 75d43eab..dcb00a2e 100644 --- a/src/tenor/java/tenor/game/GetToCraftingTableTask.java +++ b/src/tenor/java/tenor/game/GetToCraftingTableTask.java @@ -17,20 +17,26 @@ package tenor.game; -import tenor.Bot; -import tenor.ISingularChildTaskRelationship; -import tenor.SingularTaskLeaf; +import tenor.*; public class GetToCraftingTableTask extends SingularTaskLeaf { + private final ComputationRequest craftingTable; + public GetToCraftingTableTask(Bot bot) { super(bot); registry().registerSingleton(this); + this.craftingTable = ComputationRequestManager.INSTANCE.getByGoal(this, "GoalGetToBlock crafting_table"); // idk } @Override public double cost() { - return 69; + Double d = craftingTable.cost(); + if (d == null) { + // unknown, has not been calculated yet either way + return 1000D; // estimate + } + return d; } @Override diff --git a/src/tenor/java/tenor/game/MineTask.java b/src/tenor/java/tenor/game/MineTask.java index 8969f28a..1ec3be0b 100644 --- a/src/tenor/java/tenor/game/MineTask.java +++ b/src/tenor/java/tenor/game/MineTask.java @@ -17,31 +17,41 @@ package tenor.game; -import tenor.*; +import tenor.DependencyType; +import tenor.IQuantizedDependentCostCalculator; +import tenor.ISingleParentQuantizedPriorityAllocator; +import tenor.QuantizedTaskPriorityAllocationCache; -public class MineTask extends QuantizedTaskNode implements ISingleParentQuantizedPriorityAllocator { +public class MineTask extends QuantizedTaskPriorityAllocationCache implements ISingleParentQuantizedPriorityAllocator, IQuantizedDependentCostCalculator { // TODO shared claims of block locations in the world across all mine tasks across all bots final AquireItemTask parent; - - final DoMine doMine; + final MineWithToolTask[] children; public MineTask(AquireItemTask parent) { super(parent.bot, DependencyType.ANY_ONE_OF); this.parent = parent; addParent(parent); - this.doMine = new DoMine(this); + String[] tools = getToolsCapableOfMining(parent.item); + children = new MineWithToolTask[tools.length]; + for (int i = 0; i < children.length; i++) { + children[i] = new MineWithToolTask(this, tools[i]); + } } - @Override - public IQuantityRelationship cost() { - return x -> x * 324232; - } - - @Override - public double priorityAllocatedTo(IQuantizedParentTaskRelationship child, int quantity) { - return 0; + static String[] getToolsCapableOfMining(String block) { + switch (block) { + case "iron_ore": + return new String[]{"stone_pickaxe"}; + case "stone": + case "cobblestone": + return new String[]{"wooden_pickaxe"}; + case "log": + return new String[]{"hand"}; + default: + throw new IllegalStateException(block); + } } } diff --git a/src/tenor/java/tenor/game/MineWithToolTask.java b/src/tenor/java/tenor/game/MineWithToolTask.java index e687aedb..6412653c 100644 --- a/src/tenor/java/tenor/game/MineWithToolTask.java +++ b/src/tenor/java/tenor/game/MineWithToolTask.java @@ -17,5 +17,28 @@ package tenor.game; -public class MineWithToolTask { +import tenor.DependencyType; +import tenor.IQuantizedDependentCostCalculator; +import tenor.ISingleParentQuantizedPriorityAllocator; +import tenor.QuantizedTaskPriorityAllocationCache; + +public class MineWithToolTask extends QuantizedTaskPriorityAllocationCache implements ISingleParentQuantizedPriorityAllocator, IQuantizedDependentCostCalculator { + + public final String tool; + MineTask parent; + + AquireItemTask aquireTool; + // TODO locate task? + DoMine doMine; + + + public MineWithToolTask(MineTask parent, String tool) { + super(parent.bot, DependencyType.SERIAL); + this.tool = tool; + this.parent = parent; + addParent(parent); + this.aquireTool = registry().getItemBased(AquireItemTask.class, tool); + aquireTool.addParent(this); // we aren't constructing this, so need to add us as a parent manually + this.doMine = new DoMine(this); + } }