monster #20

Merged
viud3133 merged 39 commits from monster into equipments 2025-10-30 12:05:40 +01:00
21 changed files with 1063 additions and 164 deletions

1
.idea/.name generated Normal file
View File

@ -0,0 +1 @@
World.java

View File

@ -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

View File

@ -13,6 +13,7 @@
<maven.compiler.target>23</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
@ -33,5 +34,5 @@
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -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;
}
}

View File

@ -1,77 +0,0 @@
import Entity.Position;
//Vill inte göra mycket med den här klassen, jag vill påverka implementeringen av Player 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... det alltid blir balanserat
private Position position;
// Hur många varianter 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 det är många krav som måste uppfyllas för att attacken ska 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;
}
}

View File

@ -1,33 +0,0 @@
import Entity.Position;
import Terrain.Biome;
import java.util.*;
public abstract class Monster extends Character{
private final List<Biome> 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<Biome> habitat) {
super(health, level, energy, position);
this.habitat.addAll(habitat);
}
//Är detta bra??? Med unmodifiableList dvs
public List<Biome> getHabitat() {
return Collections.unmodifiableList(habitat);
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,5 @@
package Monster;
public enum Biomes {
GRASSLAND, MOUNTAIN, COAST, FOREST //Är inte fäst vid dessa
}

View File

@ -0,0 +1,7 @@
package Monster;
import Entity.Player;
public interface CanAttack {
abstract boolean performAttack(Attacks attack, Player player);
}

View File

@ -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);
}

View File

@ -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... 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);
}

View File

@ -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<Position> findLegalDestinations(Position position) {
List<Position> 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;
}
}

View File

@ -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<Biomes> HABITAT = Collections.unmodifiableList(Arrays.asList(Biomes.COAST, Biomes.FOREST, Biomes.GRASSLAND, Biomes.MOUNTAIN));
public static final List<MovementPatterns> MOVES = Collections.unmodifiableList(Arrays.asList(MovementPatterns.ONE_DIAGONAL_STEP));
public static final List<Attacks> 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<Position> 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<Position> destinations = move.findLegalDestinations(position);
for (Position destination : destinations) {
if (noPlayerIsAtPosition(destination, world)) {
validDestinations.add(destination);
}
}
}
}
}
private boolean playerIsAtPosition(Position position, World world) {
List<Entity> 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);
}
}

View File

@ -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<Biomes> HABITAT = Collections.unmodifiableList(Arrays.asList(Biomes.FOREST, Biomes.MOUNTAIN));
public static final List<MovementPatterns> MOVES = Collections.unmodifiableList(Arrays.asList(MovementPatterns.ONE_DIAGONAL_STEP, MovementPatterns.TWO_STEPS_IN_STRAIGHT_LINE));
public static final List<Attacks> 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<Position> 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<Position> 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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,129 @@
package World;
import Entity.*;
import java.util.*;
public class World {
private HashMap<Position, Tile> tileMap = new HashMap<>();
private HashMap<Entity, Position> 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<Entity, Position> getEntityList() {
return entityMap;
}
public HashMap<Position, Tile> getTileMap() {
return tileMap;
}
public Tile getTileAtPosition(Position pos) {
return tileMap.get(pos);
}
public Entity getEntityAtPosition(Position position) {
for (HashMap.Entry<Entity, Position> entry : entityMap.entrySet()) {
Position pos = entry.getValue();
Entity e = entry.getKey();
if (pos.equals(position)) {
return e;
}
}
return null;
}
//Har inte testat denna den kanske inte alls funkar
private Map<Position, List<Entity>> invertEntityMap() {
Map<Position, List<Entity>> 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<Position, List<Entity>> getPositionEntityMap() {
return invertEntityMap();
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public void changePosition(Entity Character, Position newPosition) {
entityMap.put(Character, newPosition);
}
}

View File

@ -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<Position, Tile> 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));
}
}

View File

@ -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<Position> legalDestinations = new ArrayList<>();
List<MovementPatterns> 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<Position> legalDestinations = new ArrayList<>();
List<MovementPatterns> 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<Position> 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));
}
}

View File

@ -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);
}
}

View File

@ -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<Integer, Tile> 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], "@");
}
}