Skip to content

Commit

Permalink
Started adding maps and implementing observers
Browse files Browse the repository at this point in the history
  • Loading branch information
MatiPl01 committed Dec 18, 2021
1 parent a7a5755 commit f8ffaf2
Show file tree
Hide file tree
Showing 15 changed files with 201 additions and 38 deletions.
6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/main/java/my/project/simulation/IObserver.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@ public interface IObserver {
* @return
* A map element which position was changed
*/
ISprite changedSpritePosition();
void changeSpritePosition(ISprite sprite);

/**
* A method which allows an observed element to send notification
* to its observer after being spawned on the map
*
* @return
*/
ISprite spawnedSprite();
void addSprite(ISprite sprite);

/**
* A method which allows an observed element to send notification
* to its observer after being removed from the map
*
* @return
*/
ISprite removedSprite();
void removeSprite(ISprite sprite);
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public Node<T> getParent() {
}
}

public class PrefixTree<T> { // inserted data must be an iterable
public class PrefixTree<T> { // inserted data must be a list
private final Node<T> root;
private final Map<T, Integer> mappedValues;
private final Set<Node<T>> maxCountLeaves = new HashSet<>();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package my.project.simulation.utils;
package my.project.simulation.enums;

public enum MapArea {
JUNGLE,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
package my.project.simulation.utils;
package my.project.simulation.enums;

import my.project.simulation.utils.Vector2D;

public enum MapDirection {
NORTH,
Expand Down
95 changes: 95 additions & 0 deletions src/main/java/my/project/simulation/maps/AbstractMap.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package my.project.simulation.maps;

import my.project.simulation.IObserver;
import my.project.simulation.enums.MapArea;
import my.project.simulation.sprites.Animal;
import my.project.simulation.sprites.Grass;
import my.project.simulation.sprites.ISprite;
import my.project.simulation.utils.EnergyComparator;
import my.project.simulation.utils.Vector2D;

import java.util.*;

public abstract class AbstractMap implements IMap, IObserver {
private final int totalWidth;
private final int totalHeight;
private final int jungleWidth;
private final int jungleHeight;

protected final Map<Vector2D, SortedSet<Animal>> mapAnimals = new HashMap<>();
protected final Map<Vector2D, Grass> mapGrass = new HashMap<>();

AbstractMap(int totalWidth, int totalHeight, int jungleWidth, int jungleHeight) {
this.totalWidth = totalWidth;
this.totalHeight = totalHeight;
this.jungleWidth = jungleWidth;
this.jungleHeight = jungleHeight;
}

@Override
public void changeSpritePosition(ISprite sprite) throws IllegalArgumentException, NoSuchElementException {
if (!(sprite instanceof Animal)) {
throw new IllegalArgumentException("Cannot change position of a sprite which is not an animal");
} else {
Vector2D prevPosition = ((Animal) sprite).getPrevPosition();
SortedSet<Animal> animals = mapAnimals.get(prevPosition);
if (animals == null || !animals.remove(sprite)) {
throw new NoSuchElementException("Sprite " + sprite + " is not on the map");
}
addSprite(sprite);
}
}

@Override
public void removeSprite(ISprite sprite) throws NoSuchElementException {
Vector2D position;
// If a sprite is an animal object
if (sprite instanceof Animal) {
position = ((Animal) sprite).getCurrPosition();
SortedSet<Animal> animals = mapAnimals.get(position);
if (animals == null || !animals.remove(sprite)) {
throw new NoSuchElementException("Sprite " + sprite + " is not on the map");
}
// If a sprite is a grass object
} else if (sprite instanceof Grass) {
position = ((Grass) sprite).getPosition();
if (mapGrass.remove(position) == null) {
throw new NoSuchElementException("Sprite " + sprite + " is not on the map");
}
}
}

@Override
public void addSprite(ISprite sprite) throws IllegalArgumentException {
Vector2D position;
// If a sprite is an animal object
if (sprite instanceof Animal) {
position = ((Animal) sprite).getCurrPosition();
// Create the new animals list if there is no animals list on the specified position
if (mapAnimals.get(position) == null) {
mapAnimals.put(position, new TreeSet<>(new EnergyComparator()));
}
// Add an animal to the list
mapAnimals.get(position).add((Animal)sprite);
// If a sprite is a grass object
} else if (sprite instanceof Grass) {
position = ((Grass) sprite).getPosition();
// Place grass on a field only if there is no other element occupying this field
if (mapGrass.get(position) != null || mapAnimals.get(position) != null) {
String message = "Cannot place grass on field: " + position + ". Field is not empty.";
throw new IllegalArgumentException(message);
}
mapGrass.put(position, (Grass)sprite);
}
}

@Override
public MapArea getAreaType(Vector2D position) {
int x = position.getX();
int y = position.getY();
if (Math.abs(x) < (jungleWidth + 1) / 2 && Math.abs(y) < (jungleHeight + 1) / 2) {
return MapArea.JUNGLE;
}
return MapArea.STEPPE;
}
}
14 changes: 14 additions & 0 deletions src/main/java/my/project/simulation/maps/FencedMap.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package my.project.simulation.maps;

import my.project.simulation.utils.Vector2D;

public class FencedMap extends AbstractMap {
FencedMap(int totalWidth, int totalHeight, int jungleWidth, int jungleHeight) {
super(totalWidth, totalHeight, jungleWidth, jungleHeight);
}

@Override
public Vector2D getNextPosition(Vector2D currPosition, Vector2D moveVector) {
return null;
}
}
14 changes: 14 additions & 0 deletions src/main/java/my/project/simulation/maps/FoldingMap.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package my.project.simulation.maps;

import my.project.simulation.utils.Vector2D;

public class FoldingMap extends AbstractMap {
FoldingMap(int totalWidth, int totalHeight, int jungleWidth, int jungleHeight) {
super(totalWidth, totalHeight, jungleWidth, jungleHeight);
}

@Override
public Vector2D getNextPosition(Vector2D currPosition, Vector2D moveVector) {
return null;
}
}
13 changes: 13 additions & 0 deletions src/main/java/my/project/simulation/maps/IMap.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
package my.project.simulation.maps;

import my.project.simulation.enums.MapArea;
import my.project.simulation.sprites.ISprite;
import my.project.simulation.utils.Vector2D;

public interface IMap {
void addSprite(ISprite sprite);

void removeSprite(ISprite sprite);

void changeSpritePosition(ISprite sprite);

MapArea getAreaType(Vector2D position);

Vector2D getNextPosition(Vector2D currPosition, Vector2D moveVector);
}
16 changes: 6 additions & 10 deletions src/main/java/my/project/simulation/sprites/AbstractSprite.java
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
package my.project.simulation.sprites;

import my.project.simulation.IObserver;
import my.project.simulation.utils.Vector2D;
import my.project.simulation.maps.IMap;

import java.util.HashSet;
import java.util.Set;

public abstract class AbstractSprite implements ISprite {
protected Vector2D currPosition;
protected final IMap map;
protected final Set<IObserver> observers = new HashSet<>();

public AbstractSprite(Vector2D position) {
this.currPosition = position;
}

@Override
public Vector2D getPosition() {
return currPosition;
protected AbstractSprite(IMap map) {
this.map = map;
addObserver((IObserver) map);
}

@Override
public void remove() {
observers.forEach(IObserver::removedSprite);
for (IObserver observer: observers) observer.removeSprite(this);
}

@Override
Expand Down
32 changes: 22 additions & 10 deletions src/main/java/my/project/simulation/sprites/Animal.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import my.project.simulation.IObserver;
import my.project.simulation.maps.IMap;
import my.project.simulation.utils.MapDirection;
import my.project.simulation.enums.MapDirection;
import my.project.simulation.utils.Random;
import my.project.simulation.utils.Vector2D;

Expand All @@ -20,29 +20,29 @@ public class Animal extends AbstractSprite {
private static final double BREED_ENERGY_LOSS_PERC = .25;
private final String IMG_PATH = "/images/animals/leopard.png";

private Vector2D currPosition;
private Vector2D prevPosition = null;
private MapDirection direction;
private final IMap map;

private final int[] genome;
private final int[] genesCounts;
private int energy;
private int daysAlive = 0;
private List<Animal> children = new ArrayList<>();

public Animal(IMap map, Vector2D initialPosition, int energy) {
super(initialPosition);
this.map = map;
super(map);
this.genome = generateRandomGenome();
this.energy = energy;
this.currPosition = initialPosition;
this.direction = generateRandomDirection();
this.genesCounts = createRotationPreferences(genome);
}

public Animal(IMap map, Vector2D initialPosition, int energy, int[] genome) {
super(initialPosition);
this.map = map;
super(map);
this.genome = genome;
this.energy = energy;
this.currPosition = initialPosition;
this.direction = generateRandomDirection();
this.genesCounts = createRotationPreferences(genome);
}
Expand All @@ -66,6 +66,14 @@ public String getImagePath() {
return IMG_PATH;
}

public Vector2D getCurrPosition() {
return currPosition;
}

public Vector2D getPrevPosition() {
return prevPosition;
}

public int getEnergy() {
return energy;
}
Expand Down Expand Up @@ -108,14 +116,18 @@ private boolean canMove(int angleNum) {
}

public void move() {
Vector2D newPosition = direction.toUnitVector();
if (map.canMoveTo(newPosition)) {
Vector2D moveVector = direction.toUnitVector();
Vector2D nextPosition = map.getNextPosition(currPosition, moveVector);
// Move an animal only if a new position will be different to the current one
if (nextPosition != currPosition) {
prevPosition = currPosition;
currPosition = nextPosition;
notifyPositionChanged();
}
}

private void notifyPositionChanged() {
observers.forEach(IObserver::changedSpritePosition);
for (IObserver observer: observers) observer.changeSpritePosition(this);
}

private int[] createRotationPreferences(int[] currGenome) {
Expand Down
15 changes: 11 additions & 4 deletions src/main/java/my/project/simulation/sprites/Grass.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package my.project.simulation.sprites;

import my.project.simulation.utils.MapArea;
import my.project.simulation.enums.MapArea;
import my.project.simulation.maps.IMap;
import my.project.simulation.utils.Random;
import my.project.simulation.utils.Vector2D;

Expand All @@ -11,6 +12,7 @@

public class Grass extends AbstractSprite {
private final String IMG_PATH;
private final Vector2D position;
private static final Map<MapArea, List<String>> images = new HashMap<>(){{
put(MapArea.STEPPE, new ArrayList<>() {{
add("/images/steppe/grass-1.png");
Expand All @@ -24,9 +26,10 @@ public class Grass extends AbstractSprite {
}};
private static final String sign = "*";

public Grass(MapArea areaType, Vector2D position) {
super(position);
this.IMG_PATH = getRandomImagePath(areaType);
public Grass(IMap map, Vector2D position) {
super(map);
this.position = position;
this.IMG_PATH = getRandomImagePath(map.getAreaType(position));
}

@Override
Expand All @@ -39,6 +42,10 @@ public String getImagePath() {
return IMG_PATH;
}

public Vector2D getPosition() {
return position;
}

private String getRandomImagePath(MapArea areaType) {
List<String> paths = images.get(areaType);
return paths.get(Random.randInt(paths.size() - 1));
Expand Down
8 changes: 0 additions & 8 deletions src/main/java/my/project/simulation/sprites/ISprite.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
package my.project.simulation.sprites;

import my.project.simulation.IObserver;
import my.project.simulation.utils.Vector2D;

public interface ISprite {
/**
* Get the position of the map element.
*
* @return The position vector of the map element.
*/
Vector2D getPosition();

/**
* Get String representation of an element,
*
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/my/project/simulation/utils/EnergyComparator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package my.project.simulation.utils;

import my.project.simulation.sprites.Animal;

import java.util.Comparator;

public class EnergyComparator implements Comparator<Animal> {
@Override
public int compare(Animal o1, Animal o2) {
return o1.getEnergy() - o2.getEnergy();
}
}
Empty file added src/main/resources/config.json
Empty file.

0 comments on commit f8ffaf2

Please sign in to comment.