schrum2 / MM-NEAT

Modular Multiobjective (Hyper) Neuro-Evolution of Augmenting Topologies + MAP-Elites: Java code for evolving intelligent agents in Ms. Pac-Man, Tetris, and more, as well as code for Procedural Content Generation in Mario, Zelda, Minecraft, and more!
http://people.southwestern.edu/~schrum2/re/mm-neat.php
Other
50 stars 20 forks source link

Evolve Minecraft Block Lists Directly #899

Closed schrum2 closed 1 year ago

schrum2 commented 1 year ago

I think a lot of the problems we are having exploring the search space deals with a poor genome encoding. The steps from real-valued vector or even integer encoding make it difficult to manipulate the corresponding shape correctly. Some of the changes in issue #879 seem promising, but I think we can do better.

Make a MinecraftShapeGenotype class in edu.southwestern.tasks.evocraft.genotype (a new package).

This will represent a shape as two HashSets. One is a HashSet of Blocks in the shape. The other is a HashSet of MinecraftCoordinates that are empty, meaning that they are block positions that can potentially hold part of the shape. You will need to make a new ShapeGenerator class for this genotype, but it will be trivial: Just take the elements from the HashSet of Blocks and put them in a list.

The reason for this new encoding is that it allows us to define some mutation operators that are more appropriate for Minecraft and make it easier to search the space. Store these in a new package: edu.southwestern.tasks.evocraft.mutation

That's enough for now. We may have more later.

Each of these mutation types will need to have their own command line parameters indicating what their rate of occurrence is. We can discuss appropriate default values once you have a prototype running.

schrum2 commented 1 year ago

Actually, instead of two HashSets, let's have a HashMap<MinecraftCoordinates, Block> for the blocks and then a HashSet<MinecraftCoordinates> for the empty space

schrum2 commented 1 year ago

The type T for the Genotype<T> will be Pair<HashMap<MinecraftCoordinates, Block>, HashSet<MinecraftCoordinates>>

schrum2 commented 1 year ago

Make a helper method in this class: Block getBlockAtLocation(MinecraftCoordinates coord) that returns a Block from blocks if it exists, or creates an AIR block for those coordinates if the location is in the empty spaces. Also, make a method placeBlock(Block block) that puts a block into the shape. It replaces what is already there. If there is a block at the location, change the type and orientation to match the new one. If the space is empty, then remove the coordinates from the empty spaces.

Once you have these, implement crossover in the following way:

Save a copy of the input parameter genotype (you will modify this) Nest three loops to go through all the x, y, z coordinates. For each set of (x,y,z) coordinates, do a RandomNumbers coin flip. If true, then call this.getBlockAtLocation and copy.getBlockAtLocation and save the results in variables. Call this.placeBlock and copy.placeBlock, but swap the blocks returned from the previous calls so that the blocks from each shape go to the other.

This will make copy be roughly half from one parent, and half from the other. Return copy

schrum2 commented 1 year ago

Look at the mutate method of TWEANNGenotype.

There is a StringBuilder for logging purposes. Then you have classes being constructed that extend Mutation. However, you should make a new abstract class MinecraftShapeMutation that is sort of like the TWEANNMutation class. This class will be responsible for indicating that mutation will be performed if a random number is less than a "rate" associated with it. The "rate" for each specific type of mutation will be specified by a command line parameter in the individual classes that extend MinecraftShapeMutation (once again, similar to the mutation operations that extend TWEANNMutation)

TjRaffert commented 1 year ago

There is an issue with the fitness function we can't test further until #904 is resolved.

schrum2 commented 1 year ago

@TjRaffert You still need to add support for all the mutation operators in the mutate method

schrum2 commented 1 year ago

Assertion errors indicate that the placeBlock method is probably the source of the error with AIR blocks. This is probably causing other hidden errors as well. Basically, the behavior of placeBlock needs to depend on whether the input parameter is a block with type AIR or not. If the block being placed is AIR, then it needs to be handled differently than is currently being done.

TjRaffert commented 1 year ago

I think I fixed it with the last commit I got both back up and running again.

schrum2 commented 1 year ago

Once of the purposes behind this was the hope that directly manipulating the shape would make it easier to search the space of possible shapes. So, re-do these simple experiments with this encoding (neither requires simulation, so you can run it on a machine that already has a Minecraft server running).

These can stop running as soon as it is clear we are covering the whole archive, but if that does not happen, we have a problem. Either way, post pictures of the final archives in this issue thread to report.

TjRaffert commented 1 year ago

TESTING-AirVSPiston100_MAPElites.pdf

TjRaffert commented 1 year ago

TESTING-MEObserverVectorPistonOrientation100_MAPElites.pdf This is the WHD it is getting full coverage. The image above also shows the same results if not better compared to the encoding before.