diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..7e25fbe
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+World.java
\ No newline at end of file
diff --git a/README.md b/README.md
index cccb987..4457fb8 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ The player object is a representation of the user and it's agency in the game wo
-- Warrior
-- Mage
- Spells
-- World generation
+- World.World generation
-- Terrain types
- Loot
- Equipment
diff --git a/pom.xml b/pom.xml
index 4954a6f..f3d4870 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,6 +13,7 @@
23
UTF-8
+
org.junit.jupiter
@@ -33,5 +34,5 @@
test
+
-
\ No newline at end of file
diff --git a/src/main/java/Attack.java b/src/main/java/Attack.java
deleted file mode 100644
index a292f3e..0000000
--- a/src/main/java/Attack.java
+++ /dev/null
@@ -1,22 +0,0 @@
-public abstract class Attack {
- //Namnet och bägge dessa siffror är helt lösryckta
- private static final String DEFAULT_NAME = "DEFAULT_NAME";
- private static final double DEFAULT_ENERGY_COST = 5d;
- private static final double DEFAULT_DAMAGE = 5d;
-
- private String name;
- private double energyCost;
- private double damage;
-
- public Attack() {
- name = DEFAULT_NAME;
- energyCost = DEFAULT_ENERGY_COST;
- damage = DEFAULT_DAMAGE;
- }
-
- public Attack(String name, double energyCost, double damage) {
- this.name = name;
- this.energyCost = energyCost;
- this.damage = damage;
- }
-}
diff --git a/src/main/java/Character.java b/src/main/java/Character.java
deleted file mode 100644
index 3125774..0000000
--- a/src/main/java/Character.java
+++ /dev/null
@@ -1,77 +0,0 @@
-import Entity.Position;
-
-//Vill inte göra så mycket med den här klassen, då jag vill påverka implementeringen av Player så lite som möjligt
-public abstract class Character {
- private static final double DEFAULT_HEALTH = 50d;
- private static final double DEFAULT_LEVEL = 1.0;
- private static final double DEFAULT_ENERGY = 50d; //Detta borde kanske egentligen beräknas och sättas automatiskt genom en algoritm som tar health och level i beaktskap?? Eller något sådant
- private static final Position DEFAULT_POSITION = new Position(0,0); //Är detta en bra idé?? Mest för att kunna ha defaultkonstruktor
-
- // Borde jag bara sätta allt till default direkt här????
- private double health;
- private double level;
- private double energy; //Borde kanske beräknas genom en algoritm istället för att kunna sättas i konstruktorn... Så det alltid blir balanserat
- private Position position;
-
- // Hur många varianter på konstruktorn behövs?
- public Character() {
- this.health = DEFAULT_HEALTH;
- this.level = DEFAULT_LEVEL;
- this.energy = DEFAULT_ENERGY;
- this.position = DEFAULT_POSITION;
- }
-
- // Jag antar att den som instansierar massa monster i världen ansvarar
- // för att kolla att "position" har ett tillåtet värde.
- // Just denna variant är bara för testning i min implementation av Monster
- public Character(Position position) {
- this.health = DEFAULT_HEALTH;
- this.level = DEFAULT_LEVEL;
- this.energy = DEFAULT_ENERGY;
- this.position = position;
- }
-
- public Character(double health, double level, double energy, Position position) {
- this.health = health;
- this.level = level;
- this.energy = energy;
- this.position = position;
- }
-
- //Returnerar true om attacken gick igenom, annars false
- //Tänker att positionen som skickas in är karaktärens egna
- //Kommer antagligen behöva diverse hjälpmetoder i implementeringen då det är många krav som måste uppfyllas för att attacken ska gå igenom
- abstract boolean attack(Position position, Character character);
-
- public double getHealth() {
- return health;
- }
-
- public void setHealth(int newHealth) {
- health = newHealth;
- }
-
- public double getLevel() {
- return level;
- }
-
- public void setLevel(int newLevel) {
- level = newLevel;
- }
-
- public double getEnergy() {
- return energy;
- }
-
- public void setEnergy(double newEnergy) {
- energy = newEnergy;
- }
-
- public Position getPosition() {
- return position;
- }
-
- public void setPosition(Position newPosition) {
- position = newPosition;
- }
-}
diff --git a/src/main/java/Monster.java b/src/main/java/Monster.java
deleted file mode 100644
index 9e1d6d7..0000000
--- a/src/main/java/Monster.java
+++ /dev/null
@@ -1,33 +0,0 @@
-import Entity.Position;
-import Terrain.Biome;
-
-import java.util.*;
-
-public abstract class Monster extends Character{
-
- private final List habitat = new ArrayList<>();
-
- public Monster() {
- habitat.addAll(Arrays.asList(Biome.GRASSLAND, Biome.MOUNTAIN, Biome.COAST, Biome.FOREST));
- }
-
- public Monster(Position position) {
- super(position);
- habitat.addAll(Arrays.asList(Biome.GRASSLAND, Biome.MOUNTAIN, Biome.COAST, Biome.FOREST));
- }
-
- public Monster(double health, double level, double energy, Position position) {
- super(health, level, energy, position);
- habitat.addAll(Arrays.asList(Biome.GRASSLAND, Biome.MOUNTAIN, Biome.COAST, Biome.FOREST));
- }
-
- public Monster(double health, double level, double energy, Position position, List habitat) {
- super(health, level, energy, position);
- this.habitat.addAll(habitat);
- }
-
- //Är detta bra??? Med unmodifiableList dvs
- public List getHabitat() {
- return Collections.unmodifiableList(habitat);
- }
-}
diff --git a/src/main/java/Monster/Attacks.java b/src/main/java/Monster/Attacks.java
new file mode 100644
index 0000000..6abda4a
--- /dev/null
+++ b/src/main/java/Monster/Attacks.java
@@ -0,0 +1,13 @@
+package Monster;
+
+public enum Attacks {
+ CHILL(3, 2), STOMP(7, 5);
+
+ public int damage;
+ public int cost;
+
+ Attacks(int damage, int cost) {
+ this.damage = damage;
+ this.cost = cost;
+ }
+}
diff --git a/src/main/java/Monster/Biomes.java b/src/main/java/Monster/Biomes.java
new file mode 100644
index 0000000..aeb46e3
--- /dev/null
+++ b/src/main/java/Monster/Biomes.java
@@ -0,0 +1,5 @@
+package Monster;
+
+public enum Biomes {
+ GRASSLAND, MOUNTAIN, COAST, FOREST //Är inte fäst vid dessa
+}
\ No newline at end of file
diff --git a/src/main/java/Monster/CanAttack.java b/src/main/java/Monster/CanAttack.java
new file mode 100644
index 0000000..76f92e5
--- /dev/null
+++ b/src/main/java/Monster/CanAttack.java
@@ -0,0 +1,7 @@
+package Monster;
+
+import Entity.Player;
+
+public interface CanAttack {
+ abstract boolean performAttack(Attacks attack, Player player);
+}
diff --git a/src/main/java/Monster/CanMove.java b/src/main/java/Monster/CanMove.java
new file mode 100644
index 0000000..c9a8dd6
--- /dev/null
+++ b/src/main/java/Monster/CanMove.java
@@ -0,0 +1,10 @@
+package Monster;
+import World.*;
+import Entity.Position;
+//Är detta ett ok namn?
+public interface CanMove {
+
+ abstract boolean move(World world);
+
+ abstract boolean moveTo(Position destination, World world);
+}
diff --git a/src/main/java/Monster/Monster.java b/src/main/java/Monster/Monster.java
new file mode 100644
index 0000000..7b1384a
--- /dev/null
+++ b/src/main/java/Monster/Monster.java
@@ -0,0 +1,53 @@
+package Monster;
+
+import Entity.*;
+
+public abstract class Monster implements CanMove {
+ public static final Position DEFAULT_POSITION = new Position(1,1);
+ public static final int MIN_HEALTH = 0;
+ public static final int MIN_ENERGY = 0;
+
+ protected int health;
+ protected int energy; //Borde kanske beräknas genom en algoritm istället för att kunna sättas i konstruktorn... Så det alltid blir balanserat
+ protected Position position;
+ protected boolean isAlive;
+
+ public Monster(int health, int energy, Position position) {
+ this.health = health;
+ this.energy = energy;
+ this.position = position;
+
+ isAlive = true;
+ }
+
+ public void kill() {
+ health = 0;
+ energy = 0;
+ isAlive = false;
+ }
+
+ public int getHealth() {
+ return health;
+ }
+
+ public int getEnergy() {
+ return energy;
+ }
+
+ public Position getPosition() {
+ return position;
+ }
+
+ public boolean isAlive() {
+ return isAlive;
+ }
+
+ public boolean isDead() {
+ return !isAlive;
+ }
+
+ abstract boolean heal();
+
+ abstract boolean takeDamage(int amount);
+
+}
diff --git a/src/main/java/Monster/MovementPatterns.java b/src/main/java/Monster/MovementPatterns.java
new file mode 100644
index 0000000..e4f8ea6
--- /dev/null
+++ b/src/main/java/Monster/MovementPatterns.java
@@ -0,0 +1,34 @@
+package Monster;
+
+import Entity.Position;
+import java.util.*;
+
+public enum MovementPatterns {
+ ONE_DIAGONAL_STEP(1, 1), TWO_STEPS_IN_STRAIGHT_LINE(2, 2);
+
+ public int cost;
+ private int id;
+
+ MovementPatterns(int cost, int id) {
+ this.cost = cost;
+ this.id = id;
+ }
+
+ public List findLegalDestinations(Position position) {
+ List legalDestinations = new ArrayList<>();
+ int x = position.x();
+ int y = position.y();
+
+ switch(id) {
+ case 1:
+ legalDestinations.addAll(Arrays.asList(new Position(x - 1, y + 1), new Position(x + 1, y + 1),
+ new Position(x - 1, y - 1), new Position(x + 1, y - 1)));
+ break;
+ case 2:
+ legalDestinations.addAll(Arrays.asList(new Position(x, y + 2), new Position(x, y - 2),
+ new Position(x + 2, y), new Position(x - 2, y)));
+ }
+
+ return legalDestinations;
+ }
+}
diff --git a/src/main/java/Monster/Shade.java b/src/main/java/Monster/Shade.java
new file mode 100644
index 0000000..51c376c
--- /dev/null
+++ b/src/main/java/Monster/Shade.java
@@ -0,0 +1,160 @@
+package Monster;
+import Entity.*;
+import World.*;
+import java.util.*;
+import static java.util.Objects.*;
+
+public class Shade extends Monster implements CanMove, CanAttack {
+ public static final List HABITAT = Collections.unmodifiableList(Arrays.asList(Biomes.COAST, Biomes.FOREST, Biomes.GRASSLAND, Biomes.MOUNTAIN));
+ public static final List MOVES = Collections.unmodifiableList(Arrays.asList(MovementPatterns.ONE_DIAGONAL_STEP));
+ public static final List ATTACKS = Collections.unmodifiableList(Arrays.asList(Attacks.CHILL));
+ public static final int MAX_HEALTH = 20;
+ public static final int MAX_ENERGY = 14;
+
+ private static final int HEALTH_PER_HEAL = 2;
+ private static final int ENERGY_COST_PER_HEAL = 1;
+
+ private Random random = new Random();
+ private List validDestinations = new ArrayList<>();
+
+ public Shade() {
+ super(MAX_HEALTH, MAX_ENERGY, DEFAULT_POSITION);
+ }
+
+ public Shade(int health, int energy, Position position) {
+ super(health, energy, position);
+ enforceHealthValueBoundries();
+ enforceEnergyValueBoundries();
+ }
+
+ public boolean heal() {
+ if (isDead()) {
+ return false;
+ }
+ if (health == MIN_HEALTH) {
+ return false;
+ }
+ if (health == MAX_HEALTH) {
+ return false;
+ }
+ if (energy < ENERGY_COST_PER_HEAL) {
+ return false;
+ }
+
+ health += HEALTH_PER_HEAL;
+ energy -= ENERGY_COST_PER_HEAL;
+ enforceHealthValueBoundries();
+
+ return true;
+ }
+
+ public boolean takeDamage(int amount) {
+ if (amount < 0) {
+ return false;
+ }
+ if (health - amount <= 0) {
+ kill();
+ return true;
+ }
+ else {
+ health =- amount;
+ return true;
+ }
+ }
+
+ public boolean performAttack(Attacks attack, Player player) {
+ if (isDead()) {
+ return false;
+ }
+ if (attack.cost > energy) {
+ return false;
+ }
+ if (attackIsNotInArsenal(attack)) {
+ return false;
+ }
+ player.setHealth(player.getHealth() - attack.cost);
+ return true;
+ }
+
+ public boolean move(World world) {
+ updateDestinations(position, world);
+
+ if (isDead()) {
+ return false;
+ }
+ if (validDestinations.isEmpty()) {
+ return false;
+ }
+ position = validDestinations.get(random.nextInt(validDestinations.size()));
+ return true;
+ }
+
+ public boolean moveTo(Position destination, World world) {
+ updateDestinations(position, world);
+
+ if (isDead()) {
+ return false;
+ }
+ if (playerIsAtPosition(destination, world)) {
+ return false;
+ }
+ if (validDestinations.isEmpty()) {
+ return false;
+ }
+ position = destination;
+ return true;
+ }
+
+ private void enforceHealthValueBoundries() {
+ if (health > MAX_HEALTH) {
+ health = MAX_HEALTH;
+ }
+ else if (health <= MIN_HEALTH) {
+ health = 1;
+ }
+ }
+
+ private void enforceEnergyValueBoundries() {
+ if (energy > MAX_ENERGY) {
+ energy = MAX_ENERGY;
+ }
+ else if (energy < MIN_ENERGY) {
+ energy = MIN_ENERGY;
+ }
+ }
+
+ private void updateDestinations(Position position, World world) {
+ validDestinations.clear();
+ for (MovementPatterns move : MOVES) {
+ if (move.cost <= energy) {
+ List destinations = move.findLegalDestinations(position);
+ for (Position destination : destinations) {
+ if (noPlayerIsAtPosition(destination, world)) {
+ validDestinations.add(destination);
+ }
+ }
+ }
+ }
+ }
+
+ private boolean playerIsAtPosition(Position position, World world) {
+ List entitiesAtPosition = world.getPositionEntityMap().get(position);
+ if (isNull(entitiesAtPosition)) {
+ return false;
+ }
+ for (Entity entity : entitiesAtPosition) {
+ if (entity instanceof Player) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean noPlayerIsAtPosition(Position position, World world) {
+ return !playerIsAtPosition(position, world);
+ }
+
+ private boolean attackIsNotInArsenal(Attacks attack) {
+ return !ATTACKS.contains(attack);
+ }
+}
diff --git a/src/main/java/Monster/Troll.java b/src/main/java/Monster/Troll.java
new file mode 100644
index 0000000..4489103
--- /dev/null
+++ b/src/main/java/Monster/Troll.java
@@ -0,0 +1,157 @@
+package Monster;
+
+import Entity.Entity;
+import Entity.Player;
+import Entity.Position;
+import World.*;
+
+import java.util.*;
+
+import static java.util.Objects.isNull;
+
+public class Troll extends Monster implements CanMove, CanAttack {
+ public static final List HABITAT = Collections.unmodifiableList(Arrays.asList(Biomes.FOREST, Biomes.MOUNTAIN));
+ public static final List MOVES = Collections.unmodifiableList(Arrays.asList(MovementPatterns.ONE_DIAGONAL_STEP, MovementPatterns.TWO_STEPS_IN_STRAIGHT_LINE));
+ public static final List ATTACKS = Collections.unmodifiableList(Arrays.asList(Attacks.STOMP));
+ public static final int MAX_HEALTH = 80;
+ public static final int MAX_ENERGY = 100;
+
+ private static final int HEALTH_PER_HEAL = 6;
+ private static final int ENERGY_COST_PER_HEAL = 3;
+
+ private Random random = new Random();
+ private List validDestinations = new ArrayList<>();
+
+ public Troll() {
+ super(MAX_HEALTH, MAX_ENERGY, DEFAULT_POSITION);
+ }
+
+ public Troll(int health, int energy, Position position) {
+ super(health, energy, position);
+ enforceHealthValueBoundries();
+ enforceEnergyValueBoundries();
+ }
+
+ public boolean heal() {
+ if (isDead()) {
+ return false;
+ }
+ if (health == MIN_HEALTH) {
+ return false;
+ }
+ if (health == MAX_HEALTH) {
+ return false;
+ }
+ if (energy < ENERGY_COST_PER_HEAL) {
+ return false;
+ }
+
+ health += HEALTH_PER_HEAL;
+ energy -= ENERGY_COST_PER_HEAL;
+ enforceHealthValueBoundries();
+
+ return true;
+ }
+
+ public boolean takeDamage(int amount) {
+ if (amount < 0) {
+ return false;
+ }
+ if (health - amount <= 0) {
+ kill();
+ return true;
+ }
+ else {
+ health =- amount;
+ return true;
+ }
+ }
+
+ public boolean performAttack(Attacks attack, Player player) {
+ if (isDead()) {
+ return false;
+ }
+ if (attack.cost > energy) {
+ return false;
+ }
+ if (attackIsNotInArsenal(attack)) {
+ return false;
+ }
+ player.setHealth(player.getHealth() - attack.cost);
+ return true;
+ }
+
+ public boolean move(World world) {
+ updateDestinations(position, world);
+
+ if (isDead()) {
+ return false;
+ }
+ if (validDestinations.isEmpty()) {
+ return false;
+ }
+ position = validDestinations.get(random.nextInt(validDestinations.size()));
+ return true;
+ }
+
+ public boolean moveTo(Position destination, World world) {
+ updateDestinations(position, world);
+
+ if (isDead()) {
+ return false;
+ }
+ if (tileHasWrongHabitat(destination, world)) {
+ return false;
+ }
+ if (validDestinations.isEmpty()) {
+ return false;
+ }
+ position = destination;
+ return true;
+ }
+
+ private void updateDestinations(Position position, World world) {
+ validDestinations.clear();
+ for (MovementPatterns move : MOVES) {
+ if (move.cost <= energy) {
+ List destinations = move.findLegalDestinations(position);
+ validDestinations.addAll(destinations);
+ }
+ }
+ }
+
+
+ private void enforceHealthValueBoundries() {
+ if (health > MAX_HEALTH) {
+ health = MAX_HEALTH;
+ }
+ else if (health <= MIN_HEALTH) {
+ health = 1;
+ }
+ }
+
+ private void enforceEnergyValueBoundries() {
+ if (energy > MAX_ENERGY) {
+ energy = MAX_ENERGY;
+ }
+ else if (energy < MIN_ENERGY) {
+ energy = MIN_ENERGY;
+ }
+ }
+
+ private boolean attackIsNotInArsenal(Attacks attack) {
+ return !ATTACKS.contains(attack);
+ }
+
+ private boolean tileHasWrongHabitat(Position position, World world) {
+ Tile destinationTile = world.getTileAtPosition(position);
+ if (Objects.isNull(destinationTile)) {
+ return false;
+ }
+ boolean hasWrongBiome = !HABITAT.contains(destinationTile.getBiome());
+ if (Objects.isNull(hasWrongBiome)) {
+ return false;
+ }
+ return hasWrongBiome;
+ }
+}
diff --git a/src/main/java/World/MapGenerator.java b/src/main/java/World/MapGenerator.java
new file mode 100644
index 0000000..f9f21ca
--- /dev/null
+++ b/src/main/java/World/MapGenerator.java
@@ -0,0 +1,51 @@
+package World;
+
+import java.util.Random;
+import Entity.*;
+import Monster.Biomes;
+
+public class MapGenerator {
+ private int x;
+ private int y;
+ private World gameWorld;
+
+ public MapGenerator(int x, int y) {
+ this.x = x;
+ this.y = y;
+ if (x <= 0 || y <= 0) {
+ throw new IllegalArgumentException("X and Y coordinates must be positive");
+ }
+ this.gameWorld = new World(x, y);
+ }
+
+ public void randomWorldGeneration() {
+ Random rand = new Random();
+ for (int i = 0; i < x; i++) {
+ for (int j = 0; j < y; j++) {
+ int tileDice = rand.nextInt(4);
+ if (tileDice == 0) {
+ Tile newTile = new Tile(Biomes.FOREST, 3, "Future development");
+ gameWorld.addTile(newTile, new Position(i, j));
+ } else if (tileDice == 1) {
+ Tile newTile = new Tile(Biomes.GRASSLAND, 1, "Future development");
+ gameWorld.addTile(newTile, new Position(i, j));
+ } else if (tileDice == 2) {
+ Tile newTile = new Tile(Biomes.MOUNTAIN, 2, "Future development");
+ gameWorld.addTile(newTile, new Position(i, j));
+ } else if (tileDice == 3) {
+ Tile newTile = new Tile(Biomes.COAST, 4, "Future development");
+ gameWorld.addTile(newTile, new Position(i, j));
+ }
+ }
+ }
+ }
+
+ public void addTile(Biomes biome, int staminaCost, String description, Position position) {
+ Tile newTile = new Tile(biome, staminaCost, description);
+ gameWorld.addTile(newTile, position);
+ }
+
+ public World getWorld() {
+ return gameWorld;
+ }
+}
diff --git a/src/main/java/World/Tile.java b/src/main/java/World/Tile.java
new file mode 100644
index 0000000..58aed8e
--- /dev/null
+++ b/src/main/java/World/Tile.java
@@ -0,0 +1,27 @@
+package World;
+
+import Monster.Biomes;
+
+public class Tile {
+ private Biomes biome;
+ private int staminaCost;
+ private String tileID;
+
+ public Tile(Biomes biome, int staminaCost, String tileID) {
+ this.biome = biome;
+ this.staminaCost = staminaCost;
+ this.tileID = tileID;
+ }
+ public void setStaminaCost(int newStaminaCost) {
+ staminaCost = newStaminaCost;
+ }
+ public Biomes getBiome() {
+ return biome;
+ }
+ public int getStaminaCost() {
+ return staminaCost;
+ }
+ public String getTileID() {
+ return tileID;
+ }
+}
diff --git a/src/main/java/World/World.java b/src/main/java/World/World.java
new file mode 100644
index 0000000..0edacab
--- /dev/null
+++ b/src/main/java/World/World.java
@@ -0,0 +1,129 @@
+package World;
+
+import Entity.*;
+import java.util.*;
+
+public class World {
+
+ private HashMap tileMap = new HashMap<>();
+ private HashMap entityMap = new HashMap<>();
+ private String[][] map;
+ private int width;
+ private int height;
+
+ public World(int x, int y) {
+ this.map = new String[(x * 2) + 1][y + 2];
+ addWorldToMap();
+ width = x;
+ height = y;
+ }
+
+ private void addWorldToMap() {
+ for (int i = 0; i < map.length; i++) {
+ for (int j = 0; j < map[i].length; j++) {
+ if (i == 0 || j == 0 || i == map.length || j == map[j].length) {
+ map[i][j] = "@";
+ } else if (j % 2 == 1) {
+ map[i][j] = " ";
+ } else {
+ map[i][j] = "|";
+ }
+ }
+ }
+ }
+
+ public void printWorld() {
+ for (Entity e : entityMap.keySet()) {
+ Position pos = entityMap.get(e);
+ if (e instanceof Player) {
+ map[pos.x()][pos.y()] = "X";
+ } /* else if (e instanceof Monster) {
+ map[pos.x()][pos.y()] = "M";
+ */
+ }
+ for (int i = 0; i < map.length; i++) {
+ System.out.println();
+ for (int j = 0; j < map[i].length; j++) {
+ System.out.print(map[i][j]);
+ }
+ }
+ }
+
+
+
+ public void addEntityToMap(Entity e) {
+ entityMap.put(e, e.getPosition());
+ }
+ public void addTile(Tile tile, Position pos) {
+ tileMap.put(pos, tile);
+ }
+ /*
+ M in array is monster
+ C in array is chest
+ X in array is player.
+ */
+ public void printMap() {
+ for (int i = 0; i < map.length; i++) {
+ for (int j = 0; j < map[i].length; j++) {
+ System.out.print(map[i][j]);
+ }
+ }
+ }
+
+ public String[][] getMap() {
+ return map;
+ }
+
+ public HashMap getEntityList() {
+ return entityMap;
+ }
+ public HashMap getTileMap() {
+ return tileMap;
+ }
+
+ public Tile getTileAtPosition(Position pos) {
+ return tileMap.get(pos);
+ }
+
+ public Entity getEntityAtPosition(Position position) {
+ for (HashMap.Entry entry : entityMap.entrySet()) {
+ Position pos = entry.getValue();
+ Entity e = entry.getKey();
+ if (pos.equals(position)) {
+ return e;
+ }
+ }
+ return null;
+ }
+
+ //Har inte testat denna så den kanske inte alls funkar
+ private Map> invertEntityMap() {
+ Map> entitysByPosition = new HashMap<>();
+
+ for (Position position : entityMap.values()) {
+ entitysByPosition.put(position, new ArrayList<>());
+ }
+
+ for (Entity entity : entityMap.keySet()) {
+ Position position = entityMap.get(entity);
+ entitysByPosition.get(position).add(entity);
+ }
+ return entitysByPosition;
+ }
+
+ public Map> getPositionEntityMap() {
+ return invertEntityMap();
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public void changePosition(Entity Character, Position newPosition) {
+ entityMap.put(Character, newPosition);
+ }
+}
diff --git a/src/test/java/MapGeneratorTest.java b/src/test/java/MapGeneratorTest.java
new file mode 100644
index 0000000..c6ef57b
--- /dev/null
+++ b/src/test/java/MapGeneratorTest.java
@@ -0,0 +1,38 @@
+import Monster.Biomes;
+import World.MapGenerator;
+import World.Tile;
+import World.World;
+import Entity.*;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class MapGeneratorTest {
+ private final int X_FIVE = 5;
+ private final int Y_FIVE = 5;
+ @Test
+ void mapBeingGeneratedTest() {
+ MapGenerator mapGenerate = new MapGenerator(X_FIVE, Y_FIVE);
+ mapGenerate.randomWorldGeneration();
+ World world = mapGenerate.getWorld();
+ HashMap map = world.getTileMap();
+ assertEquals(map.size(), X_FIVE * Y_FIVE);
+ }
+ // Valid klass
+ @Test
+ void addTileAtPositionTest() {
+ MapGenerator mapGenerate = new MapGenerator(X_FIVE, Y_FIVE);
+ mapGenerate.addTile(Biomes.MOUNTAIN, 10, "test description", new Position(2, 2));
+ World testWorld = mapGenerate.getWorld();
+ assertTrue(testWorld.getTileAtPosition(new Position(2, 2)) instanceof Tile);
+ assertFalse(testWorld.getTileAtPosition(new Position(2, 1)) instanceof Tile);
+ }
+ // Invalid klass
+ @Test
+ void negativeCoordinatesTest() {
+ assertThrows(IllegalArgumentException.class, () -> new MapGenerator(-1, 5));
+ assertThrows(IllegalArgumentException.class, () -> new MapGenerator(5, 0));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/MonsterTest.java b/src/test/java/MonsterTest.java
index cc75cd4..6acf0bb 100644
--- a/src/test/java/MonsterTest.java
+++ b/src/test/java/MonsterTest.java
@@ -1,50 +1,319 @@
-import static org.junit.jupiter.api.Assertions.*;
-import org.junit.jupiter.api.Test;
+import Entity.*;
+import Monster.*;
+import World.*;
+import org.junit.jupiter.api.*;
+
+import java.util.*;
+
+import static org.hamcrest.MatcherAssert.*;
+import static org.hamcrest.Matchers.*;
+import static org.mockito.Mockito.*;
public class MonsterTest {
- @Test
- void monster_cannot_attack_when_dead() {
- /*
- Monster someMonster = new Monster();
- someMonster.setHealth(-5d);
- Assert(false, someMonster.attack(someMonster.getPosition(), character));
- */
+ private Shade defaultShade;
+ private Troll defaultTroll;
+ private Position defaultDestination = new Position(2, 2);
+ private MapGenerator worldGenerator = new MapGenerator(5, 5);
+
+ private Player mockPlayer = mock(Player.class);
+ private World mockWorld = mock(World.class);
+ private Tile mockTile = mock(Tile.class);
+
+ @BeforeEach
+ void reset() {
+ defaultShade = new Shade();
+ defaultTroll = new Troll();
}
@Test
- void monster_cannot_be_attacked_when_dead() {
- /*
- Monster attackingMonster = new Monster();
- Monster deadMonster = new Monster();
- deadMonster.setHealth(-4d);
- Assert(false, attackingMonster.attack(attackingMonster.getPosition(), deadMonster));
- */
+ void shade_cannot_move_after_death() {
+ defaultShade.kill();
+ assertThat(false, equalTo(defaultShade.moveTo(defaultDestination, mockWorld)));
}
@Test
- void monster_cannot_attack_character_at_different_position() {
- /*
- Monster monsterAtOnePosition = new Monster(new Position(0,0));
- Monster monsterAtDifferentPosition = new Monster(new Position(1,1));
- Assert(false, monsterAtOnePosition.attack(monsterAtOnePosition.getPosition(), monsterAtDifferentPosition);
- */
+ void troll_cannot_move_after_death() {
+ defaultTroll.kill();
+ assertThat(false, equalTo(defaultTroll.moveTo(defaultDestination, mockWorld)));
}
@Test
- void monster_is_instantiated_correctly_from_default_constructor() {
- /*
- AssertAll????
- */
+ void shade_cannot_attack_after_death() {
+ defaultShade.kill();
+ assertThat(false, equalTo(defaultShade.performAttack(Attacks.CHILL, mockPlayer)));
}
@Test
- void monster_is_instantiated_correctly_from_position_only_constructor() {
-
+ void troll_cannot_attack_after_death() {
+ defaultTroll.kill();
+ assertThat(false, equalTo(defaultTroll.performAttack(Attacks.STOMP, mockPlayer)));
}
@Test
- void monster_is_instantiated_correctly_from_full_constructor() {
-
+ void reaching_zero_health_triggers_shade_to_die() {
+ defaultShade.takeDamage(Shade.MAX_HEALTH);
+ assertThat(false, equalTo(defaultShade.isAlive()));
}
+
+ @Test
+ void reaching_zero_health_triggers_troll_to_die() {
+ defaultTroll.takeDamage(Troll.MAX_HEALTH);
+ assertThat(false, equalTo(defaultTroll.isAlive()));
+ }
+
+ @Test
+ void shade_cannot_heal_after_death() {
+ defaultShade.kill();
+ assertThat(false, equalTo(defaultShade.heal()));
+ }
+
+ @Test
+ void troll_cannot_heal_after_death() {
+ defaultTroll.kill();
+ assertThat(false, equalTo(defaultTroll.heal()));
+ }
+
+ @Test
+ void method_move_places_shade_in_legal_position() {
+ Position startingPosition = defaultShade.getPosition();
+ List legalDestinations = new ArrayList<>();
+ List moves = defaultShade.MOVES;
+
+ for (MovementPatterns move : moves) {
+ legalDestinations.addAll(move.findLegalDestinations(startingPosition));
+ }
+
+ defaultShade.move(mockWorld);
+ assertThat(legalDestinations, hasItem(defaultShade.getPosition()));
+ }
+
+ @Test
+ void method_move_places_troll_in_legal_position() {
+ Position startingPosition = defaultTroll.getPosition();
+ List legalDestinations = new ArrayList<>();
+ List moves = defaultTroll.MOVES;
+
+ for (MovementPatterns move : moves) {
+ legalDestinations.addAll(move.findLegalDestinations(startingPosition));
+ }
+
+ defaultTroll.move(mockWorld);
+ assertThat(legalDestinations, hasItem(defaultTroll.getPosition()));
+ }
+
+ @Test
+ void method_moveTo_wont_move_shade_to_same_position_as_player() {
+ worldGenerator.randomWorldGeneration();
+ World world = worldGenerator.getWorld();
+
+ Position destination = new Position(2, 2);
+ when(mockPlayer.getPosition()).thenReturn(destination);
+ world.addEntityToMap(mockPlayer);
+
+ assertThat(defaultShade.moveTo(destination, world), equalTo(false));
+ }
+
+
+ @Test
+ void method_move_wont_move_shade_to_same_position_as_player() {
+ worldGenerator.randomWorldGeneration();
+ World world = worldGenerator.getWorld();
+
+ Position destination = new Position(2, 2);
+ when(mockPlayer.getPosition()).thenReturn(destination);
+ world.addEntityToMap(mockPlayer);
+
+ defaultShade.move(world);
+ assertThat(defaultShade.getPosition(), not(mockPlayer.getPosition()));
+ }
+
+ @Test
+ void shade_cannot_heal_when_out_of_energy() {
+ Shade shade = new Shade(Shade.MAX_HEALTH, Shade.MIN_ENERGY, Shade.DEFAULT_POSITION);
+ assertThat(shade.heal(), equalTo(false));
+ }
+
+ @Test
+ void troll_cannot_heal_when_out_of_energy() {
+ Troll troll = new Troll(Troll.MAX_HEALTH, Troll.MIN_ENERGY, Troll.DEFAULT_POSITION);
+ assertThat(troll.heal(), equalTo(false));
+ }
+
+ @Test
+ void shade_cannot_move_when_out_of_energy() {
+ Shade shade = new Shade(Shade.MAX_HEALTH, Shade.MIN_ENERGY, Shade.DEFAULT_POSITION);
+ assertThat(shade.move(mockWorld), equalTo(false));
+ }
+
+ @Test
+ void troll_cannot_move_when_out_of_energy() {
+ Troll troll = new Troll(Troll.MAX_HEALTH, Troll.MIN_ENERGY, Troll.DEFAULT_POSITION);
+ assertThat(troll.move(mockWorld), equalTo(false));
+ }
+
+ @Test
+ void shade_cannot_attack_when_out_of_energy() {
+ Shade shade = new Shade(Shade.MAX_HEALTH, Shade.MIN_ENERGY, Shade.DEFAULT_POSITION);
+ assertThat(shade.performAttack(Attacks.CHILL, mockPlayer), equalTo(false));
+ }
+
+ @Test
+ void troll_cannot_attack_when_out_of_energy() {
+ Troll troll = new Troll(Troll.MAX_HEALTH, Troll.MIN_ENERGY, Troll.DEFAULT_POSITION);
+ assertThat(troll.performAttack(Attacks.STOMP, mockPlayer), equalTo(false));
+ }
+
+ @Test
+ void only_moves_within_energy_budget_are_performed() {
+ Troll troll = new Troll(Troll.MAX_HEALTH, 1, Troll.DEFAULT_POSITION);
+ List movesWithinBudget = MovementPatterns.ONE_DIAGONAL_STEP.findLegalDestinations(troll.getPosition());
+ troll.move(mockWorld);
+
+ assertThat(movesWithinBudget, hasItem(troll.getPosition()));
+ }
+
+ @Test
+ void attack_rejected_when_not_in_arsenal_troll() {
+ assertThat(false, equalTo(defaultTroll.performAttack(Attacks.CHILL, mockPlayer)));
+ }
+
+ @Test
+ void attack_rejected_when_not_in_arsenal_shade() {
+ assertThat(false, equalTo(defaultShade.performAttack(Attacks.STOMP, mockPlayer)));
+ }
+
+ @Test
+ void troll_can_attack_player() {
+ assertThat(true, equalTo(defaultTroll.performAttack(Attacks.STOMP, mockPlayer)));
+ }
+
+ @Test
+ void shade_can_attack_player() {
+ assertThat(true, equalTo(defaultShade.performAttack(Attacks.CHILL, mockPlayer)));
+ }
+
+ @Test
+ void troll_wont_move_to_tile_with_wrong_biome() {
+ when(mockTile.getBiome()).thenReturn(Biomes.COAST);
+ Position destination = new Position(1, 3);
+
+ worldGenerator.randomWorldGeneration();
+ World world = worldGenerator.getWorld();
+ world.addTile(mockTile, destination);
+
+ assertThat(defaultTroll.moveTo(destination, world), equalTo(false));
+ }
+
+ @Test
+ void troll_can_move_to_tile_within_its_habitat() {
+ when(mockTile.getBiome()).thenReturn(Biomes.FOREST);
+ Position destination = new Position(1, 3);
+
+ worldGenerator.randomWorldGeneration();
+ World world = worldGenerator.getWorld();
+ world.addTile(mockTile, destination);
+
+ assertThat(defaultTroll.moveTo(destination, world), equalTo(true));
+ }
+
+ @Test
+ void get_health_returns_correct_value() {
+ defaultShade = new Shade(8, Shade.MAX_ENERGY, Shade.DEFAULT_POSITION);
+ assertThat(defaultShade.getHealth(), equalTo(8));
+ }
+
+ @Test
+ void get_energy_returns_correct_value() {
+ defaultShade = new Shade(Shade.MAX_HEALTH, 10, Shade.DEFAULT_POSITION);
+ assertThat(defaultShade.getEnergy(), equalTo(10));
+ }
+
+ @Test
+ void shade_can_heal() {
+ defaultShade = new Shade(8, Shade.MAX_ENERGY, Shade.DEFAULT_POSITION);
+ assertThat(defaultShade.heal(), equalTo(true));
+ }
+
+ @Test
+ void troll_can_heal() {
+ defaultTroll = new Troll(8, Troll.MAX_ENERGY, Troll.DEFAULT_POSITION);
+ assertThat(defaultTroll.heal(), equalTo(true));
+ }
+
+ @Test
+ void shade_can_take_damage() {
+ assertThat(defaultShade.takeDamage(5), equalTo(true));
+ }
+
+ @Test
+ void troll_can_take_damage() {
+ assertThat(defaultTroll.takeDamage(5), equalTo(true));
+ }
+
+ @Test
+ void troll_wont_heal_when_it_doesnt_have_enough_energy() {
+ defaultTroll = new Troll(8, 2, Troll.DEFAULT_POSITION);
+ assertThat(defaultTroll.heal(), equalTo(false));
+ }
+
+ // HÄR BÖRJAR BESLUTSTABELLSTESTERNA
+
+ @Test
+ void decision_table_t1() {
+ defaultTroll.kill();
+ assertThat(defaultTroll.moveTo(defaultDestination, mockWorld), equalTo(false));
+ }
+
+ @Test
+ void decision_table_t2() {
+ Monster shade = new Shade(Shade.MAX_HEALTH, 0, Shade.DEFAULT_POSITION);
+ assertThat(shade.moveTo(defaultDestination, mockWorld), equalTo(false));
+ }
+
+ @Test
+ void decision_table_t3() {
+ worldGenerator.randomWorldGeneration();
+ World world = worldGenerator.getWorld();
+
+ when(mockPlayer.getPosition()).thenReturn(defaultDestination);
+ world.addEntityToMap(mockPlayer);
+
+ assertThat(defaultShade.moveTo(defaultDestination, world), equalTo(false));
+ }
+
+ @Test
+ void decision_table_t4() {
+ worldGenerator.randomWorldGeneration();
+ World world = worldGenerator.getWorld();
+
+ when(mockPlayer.getPosition()).thenReturn(new Position(6, 8));
+ world.addEntityToMap(mockPlayer);
+
+ assertThat(defaultShade.moveTo(defaultDestination, world), equalTo(true));
+ }
+
+ @Test
+ void decision_table_t5() {
+ when(mockTile.getBiome()).thenReturn(Biomes.COAST);
+
+ worldGenerator.randomWorldGeneration();
+ World world = worldGenerator.getWorld();
+ world.addTile(mockTile, defaultDestination);
+
+ assertThat(defaultTroll.moveTo(defaultDestination, world), equalTo(false));
+ }
+
+ @Test
+ void decision_table_t6() {
+ when(mockTile.getBiome()).thenReturn(Biomes.FOREST);
+ when(mockPlayer.getPosition()).thenReturn(defaultDestination);
+
+ worldGenerator.randomWorldGeneration();
+ World world = worldGenerator.getWorld();
+ world.addTile(mockTile, defaultDestination);
+
+ assertThat(defaultTroll.moveTo(defaultDestination, world), equalTo(true));
+ }
+
}
diff --git a/src/test/java/TileTest.java b/src/test/java/TileTest.java
new file mode 100644
index 0000000..c053d0a
--- /dev/null
+++ b/src/test/java/TileTest.java
@@ -0,0 +1,33 @@
+import Monster.*;
+import World.Tile;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+class TileTest {
+ private final Biomes BIOME = Biomes.MOUNTAIN;
+ private final int STAMINA_COST = 1;
+ private final String ID_STRING = "Mountain test";
+ @Test
+ void getBiomeTest() {
+ Tile tileTest = new Tile(BIOME, STAMINA_COST, ID_STRING);
+ Biomes tileNameTwo = tileTest.getBiome();
+ assertEquals(BIOME, tileNameTwo);
+ }
+ @Test
+ void getStaminaCostTest() {
+ Tile tileTest = new Tile(BIOME, STAMINA_COST, ID_STRING);
+ assertEquals(STAMINA_COST, tileTest.getStaminaCost());
+ }
+ @Test
+ void printTileStringTest() {
+ Tile tileTest = new Tile(BIOME, STAMINA_COST, ID_STRING);
+ assertEquals(ID_STRING, tileTest.getTileID());
+ }
+ @Test
+ void setStaminaCostTest() {
+ Tile tileTest = new Tile(BIOME, STAMINA_COST, ID_STRING);
+ tileTest.setStaminaCost(10);
+ int newStaminaCost = tileTest.getStaminaCost();
+ assertEquals(10, newStaminaCost);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/WorldTest.java b/src/test/java/WorldTest.java
new file mode 100644
index 0000000..9ca607b
--- /dev/null
+++ b/src/test/java/WorldTest.java
@@ -0,0 +1,43 @@
+
+import World.Tile;
+import World.World;
+import org.junit.jupiter.api.Test;
+import Entity.*;
+
+import java.util.HashMap;
+
+import static org.junit.jupiter.api.Assertions.*;
+class WorldTest {
+ @Test
+ void addEntityToMapTest() {
+ World test = new World(5, 5);
+ Entity character = new Player("Name");
+ character.setPosition(new Position(2, 2));
+ test.addEntityToMap(character);
+ }
+ @Test
+ void getTileAtPositionTest() {
+ World test = new World(5, 5);
+ HashMap tileMap = new HashMap<>();
+ }
+ @Test
+ void worldCreationTest() {
+ World test = new World(5, 5);
+ String[][] mapTest = test.getMap();
+ int counter = 0;
+ for (int i = 0; i < mapTest.length; i++) {
+ for (int j = 0; j < mapTest[i].length; j++) {
+ counter += 1;
+ }
+ }
+ assertEquals(counter, 5 * 5);
+ }
+ @Test
+ void mapCreationTest() {
+ World test = new World(5, 5);
+ String[][] mapTest = test.getMap();
+ assertEquals(mapTest[1][1], " ");
+ assertEquals(mapTest[1][2], "|");
+ assertEquals(mapTest[0][0], "@");
+ }
+}
\ No newline at end of file