Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions assets/saves/oct26-24/best-calculator-54.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"isAddBias":true,"inputs":[{"id":0,"x":0.1,"incoming":[]},{"id":1,"x":0.1,"incoming":[]},{"id":2,"x":0.1,"incoming":[]},{"id":3,"x":0.1,"incoming":[]},{"id":4,"x":0.1,"incoming":[]},{"id":5,"x":0.1,"incoming":[]}],"hidden":[{"id":74,"x":0.29999998,"incoming":[{"fromId":3,"weight":-0.37314704,"enabled":true},{"fromId":0,"weight":0.8162622,"enabled":true}]},{"id":11,"x":0.49999997,"incoming":[{"fromId":2,"weight":-1.157696,"enabled":true},{"fromId":0,"weight":0.3541963,"enabled":true},{"fromId":1,"weight":-1.0224278,"enabled":true},{"fromId":3,"weight":0.89229345,"enabled":false},{"fromId":74,"weight":0.2990567,"enabled":true}]},{"id":14,"x":0.49999997,"incoming":[{"fromId":2,"weight":-0.81584185,"enabled":true},{"fromId":0,"weight":-0.042585194,"enabled":true},{"fromId":4,"weight":-1.4656955,"enabled":true},{"fromId":1,"weight":-0.09649596,"enabled":true}]},{"id":18,"x":0.49999997,"incoming":[{"fromId":0,"weight":1.5510042,"enabled":true},{"fromId":5,"weight":0.43764776,"enabled":true},{"fromId":2,"weight":-2.4097707,"enabled":true},{"fromId":3,"weight":-0.5127861,"enabled":true}]},{"id":20,"x":0.49999997,"incoming":[{"fromId":3,"weight":0.5058794,"enabled":true},{"fromId":0,"weight":0.29272223,"enabled":true}]},{"id":21,"x":0.49999997,"incoming":[{"fromId":4,"weight":-0.96691656,"enabled":true},{"fromId":0,"weight":-0.068776384,"enabled":true},{"fromId":5,"weight":0.32340524,"enabled":true}]},{"id":25,"x":0.49999997,"incoming":[{"fromId":0,"weight":0.018183842,"enabled":true}]},{"id":26,"x":0.49999997,"incoming":[{"fromId":4,"weight":2.020965,"enabled":true},{"fromId":0,"weight":-0.16840616,"enabled":true},{"fromId":1,"weight":-0.79746705,"enabled":true}]}],"outputs":[{"id":6,"x":0.9,"incoming":[{"fromId":0,"weight":0.9054105,"enabled":false},{"fromId":1,"weight":1.5771793,"enabled":true},{"fromId":2,"weight":0.14717299,"enabled":true},{"fromId":3,"weight":-0.0753781,"enabled":true},{"fromId":4,"weight":-1.4294635,"enabled":true},{"fromId":5,"weight":0.1094358,"enabled":true},{"fromId":25,"weight":-0.04603158,"enabled":true},{"fromId":26,"weight":0.67224014,"enabled":true},{"fromId":21,"weight":-0.5874126,"enabled":true}]},{"id":7,"x":0.9,"incoming":[{"fromId":0,"weight":-0.46224558,"enabled":true},{"fromId":1,"weight":-0.0057393014,"enabled":true},{"fromId":2,"weight":1.1695952,"enabled":true},{"fromId":3,"weight":-0.6527127,"enabled":true},{"fromId":4,"weight":-0.55665445,"enabled":true},{"fromId":5,"weight":-1.2065308,"enabled":true},{"fromId":11,"weight":1.2276976,"enabled":true}]},{"id":8,"x":0.9,"incoming":[{"fromId":0,"weight":-0.52592695,"enabled":true},{"fromId":1,"weight":-1.5387636,"enabled":true},{"fromId":2,"weight":-0.59676635,"enabled":false},{"fromId":3,"weight":1.5684181,"enabled":true},{"fromId":4,"weight":0.17544484,"enabled":false},{"fromId":5,"weight":-0.49801335,"enabled":true},{"fromId":14,"weight":-0.55363,"enabled":true},{"fromId":21,"weight":0.59678996,"enabled":true},{"fromId":11,"weight":1.3646356,"enabled":true}]},{"id":9,"x":0.9,"incoming":[{"fromId":0,"weight":-1.023434,"enabled":false},{"fromId":1,"weight":-0.755333,"enabled":true},{"fromId":2,"weight":1.2019314,"enabled":true},{"fromId":3,"weight":-0.7064687,"enabled":false},{"fromId":4,"weight":0.17284171,"enabled":true},{"fromId":5,"weight":1.2035238,"enabled":true},{"fromId":18,"weight":-1.0536759,"enabled":true},{"fromId":20,"weight":-0.5421704,"enabled":true},{"fromId":26,"weight":-1.4912953,"enabled":true}]}]}
1 change: 1 addition & 0 deletions assets/saves/oct26-24/generation-54.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion core/src/main/java/com/buaisociety/pacman/Tournament.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public class Tournament extends ApplicationAdapter {
*/
public Behavior setupBehavior() {
// TODO: Choose your best client here
File file = new File("saves" + File.separator + "oct20-4" + File.separator + "best-calculator-127.json");
File file = new File("saves" + File.separator + "oct26-24" + File.separator + "best-calculator-54.json");
if (!file.exists()) {
System.err.println("Could not find the file: " + file.getAbsolutePath());
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@
import com.buaisociety.pacman.entity.Direction;
import com.buaisociety.pacman.entity.Entity;
import com.buaisociety.pacman.entity.PacmanEntity;
import com.buaisociety.pacman.maze.Maze;
import com.buaisociety.pacman.maze.Tile;
import com.buaisociety.pacman.maze.TileState;
import com.cjcrafter.neat.compute.Calculator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.RoundingMode;
import org.joml.Vector2i;
import org.joml.Vector2ic;

import java.util.ArrayList;

public class TournamentBehavior implements Behavior {

Expand All @@ -15,6 +23,17 @@ public class TournamentBehavior implements Behavior {
private int previousScore = 0;
private int framesSinceScoreUpdate = 0;

private int scoreModifier = 10;

private int lastScoreUpdate = 0;
private int lastScore = 0;

Direction[] DIRECTIONS = Direction.values();

private ArrayList<Tile> hotspot = new ArrayList<>();
private int frameCounter = 0;

private Tile lastPosition;
public TournamentBehavior(Calculator calculator) {
this.calculator = calculator;
}
Expand Down Expand Up @@ -49,8 +68,104 @@ public Direction getDirection(@NotNull Entity entity) {

// TODO: Put all your code for info into the neural network here

// SPECIAL TRAINING CONDITIONS
int latestScore = pacman.getMaze().getLevelManager().getScore();
if (latestScore > lastScore) {
lastScore = latestScore;
lastScoreUpdate = 0;
}

// Check if the score doesn't change for 20 seconds on a 60 FPS
if (lastScoreUpdate++ > (60 * 15)){
pacman.kill();
return Direction.RIGHT;
}

// Set direction a known Pellet location
Direction pelletDirection = null;
Vector2ic dimensions = pacman.getMaze().getDimensions();
boolean foundOne = false;
for (int y = 0; y < dimensions.y() && !foundOne; y++) {
for (int x = 0; x < dimensions.x() && !foundOne; x++) {
Tile tile = pacman.getMaze().getTile(x, y);
if (tile.getState() == TileState.PELLET || tile.getState() == TileState.POWER_PELLET) {
foundOne = true;
pelletDirection = getDirection(tile, pacman);
break;
}
}
}

// Get neighboring Tile, then check if it has pellet
Tile currentPosition = pacman.getMaze().getTile(pacman.getTilePosition());
Tile upTile = currentPosition.getNeighbor(Direction.UP);
Tile downTile = currentPosition.getNeighbor(Direction.DOWN);
Tile leftTile = currentPosition.getNeighbor(Direction.LEFT);
Tile rightTile = currentPosition.getNeighbor(Direction.RIGHT);

// Kill when the position is stagnant
// if (currentPosition == lastPosition) {
// pacman.kill();
// return Direction.RIGHT;
// }else{
// lastPosition = currentPosition;
// }

// END OF SPECIAL TRAINING CONDITIONS

// We are going to use these directions a lot for different inputs. Get them all once for clarity and brevity
Direction forward = pacman.getDirection();
Direction left = pacman.getDirection().left();
Direction right = pacman.getDirection().right();
Direction behind = pacman.getDirection().behind();

// Input nodes 1, 2, 3, and 4 show if the pacman can move in the forward, left, right, and behind directions
float canMoveForward = pacman.canMove(forward) ? .75f : 0f ;
float canMoveLeft = pacman.canMove(left)? .75f : 0f;
float canMoveRight = pacman.canMove(right)? .75f : 0f;
float canMoveBehind = pacman.canMove(behind)? .75f : 0f;

// Reward if the direction is going towards a pellet
switch (pelletDirection){
case UP -> canMoveForward += .10;
case DOWN -> canMoveBehind += .10;
case LEFT -> canMoveLeft += .10;
case RIGHT -> canMoveRight += .10;
}

// Reward if neighboring tile has Pellet
if (isTileContainsPellet(upTile)){
canMoveForward += .10;
}else if (isTileContainsPellet(downTile)){
canMoveBehind += .10;
}else if (isTileContainsPellet(leftTile)){
canMoveLeft += .10;
}else if (isTileContainsPellet(rightTile)){
canMoveRight += .10;
}

// Punish if the next tile is a hotspot
frameCounter++;
if (frameCounter % 100 == 0){
hotspot.add(currentPosition);
}
if (hotspot.contains(upTile)){
canMoveForward -= .35;
}else if (hotspot.contains(downTile)){
canMoveBehind -= .35;
}else if (hotspot.contains(leftTile)){
canMoveLeft -= .35;
}else if (hotspot.contains(rightTile)){
canMoveRight -= .35;
}

float[] inputs = new float[] {
// TODO: Add your inputs here
canMoveForward,
canMoveLeft,
canMoveRight,
canMoveBehind,
// ThreadLocalRandom.current().nextFloat(),
(pelletDirection == null) ? direction2float(pelletDirection) : 0f ,
};
float[] outputs = calculator.calculate(inputs).join();

Expand All @@ -73,4 +188,57 @@ public Direction getDirection(@NotNull Entity entity) {
default -> throw new IllegalStateException("Unexpected value: " + index);
};
}


private Direction getDirection(Tile tile,Entity entity) {
Vector2i target = new Vector2i(tile.getPosition().x(), tile.getPosition().y());
Direction temp = null;
int smallest = Integer.MAX_VALUE;

Tile current = tile;
for (Direction direction : DIRECTIONS) {

Tile next = current.getNeighbor(direction);
if (!next.getState().isPassable())
continue;

Vector2i location = new Vector2i(entity.getPosition().div(Maze.TILE_SIZE), RoundingMode.TRUNCATE).add(direction.asVector());
int distance = (int) location.distanceSquared(target);

if (distance <= smallest) {
smallest = distance;
temp = direction;
}
}

if (temp == null)
return entity.getDirection();

return temp;
}

private float direction2float (Direction direction){
float f;
switch(direction) {
case Direction.UP:
f = 1.0f;
break;
case Direction.DOWN:
f= 2.0f;
break;
case Direction.LEFT:
f = 3.0f;
break;
case Direction.RIGHT:
f = 4.0f;
break;
default:
return 0.0f;
}
return f;
}

private boolean isTileContainsPellet(Tile tile){
return tile.getState() == TileState.PELLET || tile.getState() == TileState.POWER_PELLET;
}
}