monster #20
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
Reference in New Issue
Block a user