Change Cost Metrics for Pillaring, building adjacent and building down: consider build order options
HoratioGamer opened this issue ยท 2 comments
Some information
Operating system: Linux
Java version: 8
Minecraft version: 1.12
Baritone version: Latest in KAMI/Blue
Forge mods (if used):
Exception, error or logs
This is to correct non-minecraft behaviour. Baritone seems to love pillaring above all other means to lay blocks. When there is the option to sneak-extend, it will sometimes jump down into a hole and pillar up from the bottom. Same problem in trying to lay blocks near the netherroof -- it will pillar up into the roof. Then if the schematic advances, it will break down some of the pillar to get to the next location. The cost metrics for each different way of getting a block where it needs to be need to be overhauled, and perhaps the target build order for blocks. Perhaps the problem is, baritone orders the order in which it is trying to build from the bottom up only. When it wants to build a block adjacent to a current block, instead of sneak-extending, it thinks, I have to build upward and pillar a lot of blocks that do not need to be laid. Similarly, when working near the nether roof, it should consider building the highest blocks first and building down from the roof.
The specific problem is y=123 is the nether roof. If one wants to build a vertical column at y=118,119,120,121,122, baritone will always try to build the 118 block first. then the 119, then it will jump up on top of the 119 block and pillar the 120, 121, and 122 blocks, digging blocks out from between bedrock in the ceiling to do that. If it cannot get down without breaking more blocks at 123 and above, it will break the blocks it has just laid. Baritone should consider the build order: 118, 119, 120, 122, 121. Or 118,119, 122,121, 120.
It should get out of the habit of trying to pillar.
I think another solution which is simpler would be to add "customLayerOrder" settings (either on top of the "startAtLayer" or replacing it)
I do not believe that would solve the problem. You are replacing one strict rule with a programmable strict rule. Imagine one wants a forest of these pillars, like a particular pattern of solid build. It could even look like something similar to a huge backfill, but in a shape that cannot be done with a simple backfill command. Say this problem can only be solved with a buildrepeat and a schematic. The problem with your suggestion of changing the build order by layers is, it could easily substitute a reach problem for the original pillaring problem. Say I set it to build layers 118, 119 and then 122, 121 -- baritone completes all of these layers before starting the next. When it comes to the 120 layer, there is now a 1 block tall gap. Baritone cannot reach to the back of this gap, parts of the 120 layer can never be built.
I know that Baritone uses a modified A* Dijkstra's algorithm to find paths.... why not a simple Dijkstra's algorithm to decide in what order to build in when there are constraints on space ?
I would make a source point (first blocks to be laid) prioritized on the number of existing blocks around the target block. Start with a Dijkstra increment number of zero at step 5, and go in descending step numbers.
5 - So, blocks that are to go into a 1x1 hole have 5 existing blocks around them would be top of the list and all get the next Dijkstra increment number, 1 in the case of the start of the algorithm. If filling in any 1 increment block creates any more 5-sided targets, then they become 2, and so on, until there are no 5-sided targets left.
4 - Then 4 existing blocks would be next, and get the next increment, in rounds, until there are no 4-sided targets left.
3 - If the 3-sided target Dijkstra has not started, start at 3a). If it has started start at 3c)
3a) Targets with blocks now on 3 sides will be common and re-occurring. All that exist are set as independent starts for simultaneous Dijkstra spread, and these 3-sided targets all start with the next increment number.
3b) If after any increment of the 3-sided target algorithm (including 3a where start points were indicated), if any 5 or 4-sided targets are created, go back to 5) or 4) respectively.
3c) The next step in the 3-sided algorithm is to spread from all blocks of the last increment, check in all 6 directions from them and any target block encountered is labelled with the next increment. Go back to 3b.
2a) If there never were any 3-sided targets, but there is a line of 2-sided targets then by placing a block in the center 2-sided target location will create two 3-sided targets. Label this center block 1, and then go to 3).
2b) If are 2-sided targets but no 2 together, we are building something on the ground, maybe beside a block or pillar.
1 - If there are no 2-sided targets, only 1-sided targets, then we are building in free space at the top of a pillar, revert to the bottom up layer method.
0 - If there are no targets with any existing blocks, we are pillaring up to it anyway, go to 1.
Once all target blocks in the schematic have an increment number, consider these the definition of layers, do all the 1s, then all the 2s, etc using whatever existing logic there is to decide between the targets in a "layer".
If the members of a "layer" were prioritized in ascending y value then I believe there would be support at all times for the bot.
It is possible to have a dumbell shaped empty volume one is trying to fill that this algorithm will seal off the passage between the two larger volumes before completing the interior of one volume. Similarly it is possible that the algorithm will seal up a flask-shaped volume before filling it, requiring one to break blocks to escape. The algorithm is already good at stupidly breaking blocks to escape, so, no big problem I say.
If one wants to correct this problem, the 3c) algorithm must be modified to maintain a 2x1 escape route of air from all targets that have not been reached. During the run, the algorithm can rely on a combination of air that might be part of the schematic, or that exists because of the state of increments to this point. Any advances that are found to close a 2x1 tunnel are de-listed from an increment and their parent is given their increment instead. This creates a problem that some block might be reassigned later and later increments, say changing it from 20 to 21, then 22, then 23 as the door is being held open. The problem is, when a "parent" block was 20, its neighbors/children were assigned 21. Only one of those neighbors/children closed the escape route, the other neighbors retained the number 21. When the parent block gets renamed to 21, no problem it is now a sibling of its children. If the spread in the next cycle again threatens the escape route, and it gets reassigned to 22, then it has a higher number than its other children and conceivably there could be a problem with the build order. Again, this could only occur when trying to fill a bulbous flask-shaped volume, where the bulb was I think, 6 blocks bigger than the neck. Since the build order problems would be occurring in the neck, I find it hard to believe there is not another parent, another route to building the children even with this disrupted build order....
Yes, I am a programmer with path planning but no Java experience.