monster #20

Merged
viud3133 merged 39 commits from monster into equipments 2025-10-30 12:05:40 +01:00
5 changed files with 81 additions and 64 deletions
Showing only changes of commit 7b74c03920 - Show all commits

View File

@@ -3,8 +3,8 @@ package Monster;
public enum Attacks { public enum Attacks {
CHILL(3, 2), STOMP(7, 5); CHILL(3, 2), STOMP(7, 5);
private int damage; public int damage;
private int cost; public int cost;
Attacks(int damage, int cost) { Attacks(int damage, int cost) {
this.damage = damage; this.damage = damage;

View File

@@ -4,6 +4,8 @@ import Entity.*;
public abstract class Monster implements CanMove { public abstract class Monster implements CanMove {
public static final Position DEFAULT_POSITION = new Position(1,1); 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 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 int energy; //Borde kanske beräknas genom en algoritm istället för att kunna sättas i konstruktorn... Så det alltid blir balanserat
@@ -44,8 +46,8 @@ public abstract class Monster implements CanMove {
return !isAlive; return !isAlive;
} }
abstract void heal(); abstract boolean heal();
abstract void takeDamage(int amount); abstract boolean takeDamage(int amount);
} }

View File

@@ -4,7 +4,7 @@ import Entity.Position;
import java.util.*; import java.util.*;
public enum MovementPatterns { public enum MovementPatterns {
ONE_DIAGONAL_STEP(1, 1); ONE_DIAGONAL_STEP(1, 1), TWO_STEPS_IN_STRAIGHT_LINE(2, 2);
public int cost; public int cost;
private int id; private int id;
@@ -16,14 +16,17 @@ public enum MovementPatterns {
public Set<Position> findLegalDestinations(Position position) { public Set<Position> findLegalDestinations(Position position) {
Set<Position> legalDestinations = new HashSet<>(); Set<Position> legalDestinations = new HashSet<>();
int x = position.x();
int y = position.y();
switch(id) { switch(id) {
case 1: case 1:
int x = position.x();
int y = position.y();
legalDestinations.addAll(Arrays.asList(new Position(x - 1, y + 1), new Position(x + 1, y + 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))); new Position(x - 1, y - 1), new Position(x + 1, y - 1)));
break; 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; return legalDestinations;

View File

@@ -20,26 +20,44 @@ public class Shade extends Monster implements CanMove, CanAttack {
super(MAX_HEALTH, MAX_ENERGY, Monster.DEFAULT_POSITION); super(MAX_HEALTH, MAX_ENERGY, Monster.DEFAULT_POSITION);
} }
public void heal() { public Shade(int health, int energy, Position position) {
if (isDead()) { super(health, energy, position);
throw new IllegalStateException("This shade is dead"); enforceHealthValueBoundries();
} enforceEnergyValueBoundries();
if (health < MAX_HEALTH) {
health += HEALTH_PER_HEAL;
energy -= ENERGY_COST_PER_HEAL;
enforceHealthMaximum();
}
} }
public void takeDamage(int amount) { 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) { if (amount < 0) {
throw new IllegalArgumentException("'amount' must be a positive integer"); return false;
} }
if (health - amount <= 0) { if (health - amount <= 0) {
kill(); kill();
return true;
} }
else { else {
health =- amount; health =- amount;
return true;
} }
} }
@@ -47,6 +65,9 @@ public class Shade extends Monster implements CanMove, CanAttack {
if (isDead()) { if (isDead()) {
return false; return false;
} }
if (attack.cost > energy) {
return false;
}
return true; return true;
} }
@@ -56,6 +77,9 @@ public class Shade extends Monster implements CanMove, CanAttack {
return false; return false;
} }
updateDestinations(position, world); updateDestinations(position, world);
if (validDestinations.isEmpty()) {
return false;
}
position = validDestinations.get(random.nextInt(validDestinations.size())); position = validDestinations.get(random.nextInt(validDestinations.size()));
updateDestinations(position, world); updateDestinations(position, world);
return true; return true;
@@ -65,9 +89,6 @@ public class Shade extends Monster implements CanMove, CanAttack {
if (isDead()) { if (isDead()) {
return false; return false;
} }
if (positionIsOutOfBounds(destination, world)) {
return false;
}
if (playerIsAtPosition(destination, world)) { if (playerIsAtPosition(destination, world)) {
return false; return false;
} }
@@ -77,23 +98,37 @@ public class Shade extends Monster implements CanMove, CanAttack {
return true; return true;
} }
private void enforceHealthMaximum() { private void enforceHealthValueBoundries() {
if (health > MAX_HEALTH) { if (health > MAX_HEALTH) {
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) { private void updateDestinations(Position position, World world) {
validDestinations.clear(); validDestinations.clear();
for (MovementPatterns move : MOVES) { for (MovementPatterns move : MOVES) {
if (move.cost <= energy) {
Set<Position> destinations = move.findLegalDestinations(position); Set<Position> destinations = move.findLegalDestinations(position);
for (Position destination : destinations) { for (Position destination : destinations) {
if (noPlayerIsAtPosition(destination, world) && positionIsInBounds(destination, world)) { if (noPlayerIsAtPosition(destination, world)) {
validDestinations.add(destination); validDestinations.add(destination);
} }
} }
} }
} }
}
private boolean playerIsAtPosition(Position position, World world) { private boolean playerIsAtPosition(Position position, World world) {
List<Entity> entitiesAtPosition = world.getPositionEntityMap().get(position); List<Entity> entitiesAtPosition = world.getPositionEntityMap().get(position);
@@ -111,19 +146,4 @@ public class Shade extends Monster implements CanMove, CanAttack {
private boolean noPlayerIsAtPosition(Position position, World world) { private boolean noPlayerIsAtPosition(Position position, World world) {
return !playerIsAtPosition(position, world); return !playerIsAtPosition(position, world);
} }
private boolean positionIsInBounds(Position position, World world) {
int upperX = world.getWidth();
int lowerX = 1;
int upperY = world.getHeight();
int lowerY = 1;
int x = position.x();
int y = position.y();
return x > upperX || x < lowerX || y > upperY || y < lowerY;
}
private boolean positionIsOutOfBounds(Position position, World world) {
return !positionIsInBounds(position, world);
}
} }

View File

@@ -46,7 +46,7 @@ public class MonsterTest {
@Test @Test
void monster_cannot_heal_after_death() { void monster_cannot_heal_after_death() {
defaultShade.kill(); defaultShade.kill();
assertThrows(IllegalStateException.class, () -> defaultShade.heal()); assertThat(false, equalTo(defaultShade.heal()));
} }
//Är denna för lång? //Är denna för lång?
@@ -90,36 +90,28 @@ public class MonsterTest {
assertThat(defaultShade.getPosition(), not(mockPlayer.getPosition())); assertThat(defaultShade.getPosition(), not(mockPlayer.getPosition()));
} }
//Flera assertThat i samma. Farligt????
@Test @Test
void method_move_places_monster_within_bounds() { void monster_cannot_heal_when_out_of_energy() {
worldGenerator.randomWorldGeneration(); Shade shade = new Shade(Shade.MAX_HEALTH, Shade.MIN_ENERGY, Shade.DEFAULT_POSITION);
World world = worldGenerator.getWorld(); assertThat(shade.heal(), equalTo(false));
/*when(mockWorld.getWidth()).thenReturn(5);
when(mockWorld.getHeight()).thenReturn(5);*/
defaultShade.move(world);
int newX = defaultShade.getPosition().x();
int newY = defaultShade.getPosition().y();
boolean positionCheck = newX > 0 ;
assertThat(true, equalTo(positionCheck));
} }
@Test @Test
void monster_cannot_do_anything_when_out_of_energy() { void monster_cannot_move_to_when_out_of_energy() {
Shade shade = new Shade(Shade.MAX_HEALTH, Shade.MIN_ENERGY, Shade.DEFAULT_POSITION);
assertThat(shade.move(mockWorld), equalTo(false));
} }
@Test @Test
void monster_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 only_moves_within_energy_budget_are_performed() { void only_moves_within_energy_budget_are_performed() {
Troll troll = new Troll(Troll.MAX_HEALTH)
} }*/
@Test
void move_to_invalid_destination_is_rejected() {
}
@Test @Test
void use_of_attack_not_in_arsenal_is_rejected() { void use_of_attack_not_in_arsenal_is_rejected() {