Job terrain #12
2
pom.xml
2
pom.xml
@ -29,7 +29,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mockito</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
<artifactId>mockito-core</artifactId>
|
<artifactId>mockito-core</artifactId>
|
||||||
<version>5.12.0</version>
|
<version>5.20.0</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|||||||
@ -2,12 +2,17 @@ package Action;
|
|||||||
|
|
||||||
import Job.HasJob;
|
import Job.HasJob;
|
||||||
import Job.Miner;
|
import Job.Miner;
|
||||||
|
import Terrain.Biome;
|
||||||
|
|
||||||
public class DigAction implements Action {
|
public class DigAction implements Action {
|
||||||
|
Biome biome;
|
||||||
|
public DigAction(Biome biome) {
|
||||||
|
this.biome = biome;
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public void execute(Actor actor) {
|
public void execute(Actor actor) {
|
||||||
Miner miner = requireMiner(actor);
|
Miner miner = requireMiner(actor);
|
||||||
miner.dig(actor);
|
miner.dig(biome);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Miner requireMiner(Actor actor) {
|
private Miner requireMiner(Actor actor) {
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
public enum Biomes {
|
|
||||||
GRASSLAND, MOUNTAIN, COAST, FOREST //Är inte fäst vid dessa
|
|
||||||
}
|
|
||||||
@ -1,20 +1,23 @@
|
|||||||
package Inventory;
|
package Inventory;
|
||||||
|
|
||||||
|
import Item.Item;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Inventory {
|
public class Inventory {
|
||||||
List<String> items;
|
List<Item> items;
|
||||||
|
|
||||||
public Inventory() {
|
public Inventory() {
|
||||||
items = new ArrayList<>();
|
items = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> getItems() {
|
public List<Item> getItems() {
|
||||||
return items;
|
return Collections.unmodifiableList(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addItem(String item) {
|
public void addItem(Item item) {
|
||||||
items.add(item);
|
items.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
src/main/java/Item/BasicItem.java
Normal file
13
src/main/java/Item/BasicItem.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package Item;
|
||||||
|
|
||||||
|
public record BasicItem(String id, String name) implements Item {
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
6
src/main/java/Item/Item.java
Normal file
6
src/main/java/Item/Item.java
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package Item;
|
||||||
|
|
||||||
|
public interface Item {
|
||||||
|
String getId();
|
||||||
|
String getName();
|
||||||
|
}
|
||||||
@ -1,17 +1,23 @@
|
|||||||
package Job;
|
package Job;
|
||||||
|
|
||||||
import Action.Actor;
|
|
||||||
import Inventory.HasInventory;
|
import Inventory.HasInventory;
|
||||||
|
import Terrain.Biome;
|
||||||
|
|
||||||
|
|
||||||
public class Miner extends Job {
|
public class Miner extends Job {
|
||||||
public Miner() {
|
HasInventory actor;
|
||||||
|
|
||||||
|
public Miner(HasInventory actor) {
|
||||||
super("Miner");
|
super("Miner");
|
||||||
|
this.actor = actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dig(Actor actor) {
|
public HasInventory getActor() {
|
||||||
if (actor instanceof HasInventory a) {
|
return actor;
|
||||||
a.getInventory().addItem("Stone");
|
}
|
||||||
}
|
|
||||||
|
public void dig(Biome biome) {
|
||||||
|
var item = biome.getLootTable().roll();
|
||||||
|
actor.getInventory().addItem(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,32 +1,33 @@
|
|||||||
import Entity.Position;
|
import Entity.Position;
|
||||||
|
import Terrain.Biome;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public abstract class Monster extends Character{
|
public abstract class Monster extends Character{
|
||||||
|
|
||||||
private final List<Biomes> habitat = new ArrayList<>();
|
private final List<Biome> habitat = new ArrayList<>();
|
||||||
|
|
||||||
public Monster() {
|
public Monster() {
|
||||||
habitat.addAll(Arrays.asList(Biomes.GRASSLAND, Biomes.MOUNTAIN, Biomes.COAST, Biomes.FOREST));
|
habitat.addAll(Arrays.asList(Biome.GRASSLAND, Biome.MOUNTAIN, Biome.COAST, Biome.FOREST));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Monster(Position position) {
|
public Monster(Position position) {
|
||||||
super(position);
|
super(position);
|
||||||
habitat.addAll(Arrays.asList(Biomes.GRASSLAND, Biomes.MOUNTAIN, Biomes.COAST, Biomes.FOREST));
|
habitat.addAll(Arrays.asList(Biome.GRASSLAND, Biome.MOUNTAIN, Biome.COAST, Biome.FOREST));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Monster(double health, double level, double energy, Position position) {
|
public Monster(double health, double level, double energy, Position position) {
|
||||||
super(health, level, energy, position);
|
super(health, level, energy, position);
|
||||||
habitat.addAll(Arrays.asList(Biomes.GRASSLAND, Biomes.MOUNTAIN, Biomes.COAST, Biomes.FOREST));
|
habitat.addAll(Arrays.asList(Biome.GRASSLAND, Biome.MOUNTAIN, Biome.COAST, Biome.FOREST));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Monster(double health, double level, double energy, Position position, List<Biomes> habitat) {
|
public Monster(double health, double level, double energy, Position position, List<Biome> habitat) {
|
||||||
super(health, level, energy, position);
|
super(health, level, energy, position);
|
||||||
this.habitat.addAll(habitat);
|
this.habitat.addAll(habitat);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Är detta bra??? Med unmodifiableList dvs
|
//Är detta bra??? Med unmodifiableList dvs
|
||||||
public List<Biomes> getHabitat() {
|
public List<Biome> getHabitat() {
|
||||||
return Collections.unmodifiableList(habitat);
|
return Collections.unmodifiableList(habitat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/main/java/Shared/DefaultRandomProvider.java
Normal file
11
src/main/java/Shared/DefaultRandomProvider.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package Shared;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class DefaultRandomProvider implements RandomProvider {
|
||||||
|
private final Random random = new Random();
|
||||||
|
@Override
|
||||||
|
public int nextInt(int bound) {
|
||||||
|
return random.nextInt(bound);
|
||||||
|
}
|
||||||
|
}
|
||||||
4
src/main/java/Shared/LootEntry.java
Normal file
4
src/main/java/Shared/LootEntry.java
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
package Shared;
|
||||||
|
|
||||||
|
public record LootEntry<T>(T item, int weight) {
|
||||||
|
}
|
||||||
46
src/main/java/Shared/LootTable.java
Normal file
46
src/main/java/Shared/LootTable.java
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package Shared;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class LootTable<T> {
|
||||||
|
private RandomProvider random;
|
||||||
|
private final List<LootEntry<T>> entries = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
public LootTable() {
|
||||||
|
this.random = new DefaultRandomProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LootTable(List<LootEntry<T>> entries) {
|
||||||
|
this.random = new DefaultRandomProvider();
|
||||||
|
this.entries.addAll(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRandomProvider(RandomProvider random) {
|
||||||
|
this.random = random;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LootTable(RandomProvider random) {
|
||||||
|
this.random = random;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEntry(T entry, int weight) {
|
||||||
|
entries.add(new LootEntry<>(entry,weight));
|
||||||
|
}
|
||||||
|
|
||||||
|
public T roll() {
|
||||||
|
int totalWeight = entries.stream().mapToInt(LootEntry::weight).sum();
|
||||||
|
int roll = random.nextInt(totalWeight);
|
||||||
|
int current = 0;
|
||||||
|
for(LootEntry<T> entry : entries) {
|
||||||
|
current += entry.weight();
|
||||||
|
if (roll < current) {
|
||||||
|
return entry.item();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
5
src/main/java/Shared/RandomProvider.java
Normal file
5
src/main/java/Shared/RandomProvider.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package Shared;
|
||||||
|
|
||||||
|
public interface RandomProvider {
|
||||||
|
int nextInt(int bound);
|
||||||
|
}
|
||||||
51
src/main/java/Terrain/Biome.java
Normal file
51
src/main/java/Terrain/Biome.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package Terrain;
|
||||||
|
|
||||||
|
import Item.BasicItem;
|
||||||
|
import Item.Item;
|
||||||
|
import Shared.LootEntry;
|
||||||
|
import Shared.LootTable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public enum Biome {
|
||||||
|
GRASSLAND("Grassland", new LootTable<>(new ArrayList<>(List.of(
|
||||||
|
new LootEntry<>(new BasicItem("mud", "Mud"), 10),
|
||||||
|
new LootEntry<>(new BasicItem("earth_root", "Earth Root"), 50),
|
||||||
|
new LootEntry<>(new BasicItem("crystal_core", "Crystal core"), 180)
|
||||||
|
)) {
|
||||||
|
})),
|
||||||
|
MOUNTAIN("Mountain", new LootTable<>(new ArrayList<>(List.of(
|
||||||
|
new LootEntry<>(new BasicItem("rock", "Rock"), 10),
|
||||||
|
new LootEntry<>(new BasicItem("iron", "Iron"), 50),
|
||||||
|
new LootEntry<>(new BasicItem("diamond", "Diamond"), 180)
|
||||||
|
)) {
|
||||||
|
})),
|
||||||
|
COAST("Coast", new LootTable<>(new ArrayList<>(List.of(
|
||||||
|
new LootEntry<>(new BasicItem("sand", "Sand"), 10),
|
||||||
|
new LootEntry<>(new BasicItem("shell", "Shell"), 50),
|
||||||
|
new LootEntry<>(new BasicItem("sandfish", "Sandfish"), 180)
|
||||||
|
)) {
|
||||||
|
})),
|
||||||
|
FOREST("Forest", new LootTable<>(new ArrayList<>(List.of(
|
||||||
|
new LootEntry<>(new BasicItem("moss", "Moss"), 10),
|
||||||
|
new LootEntry<>(new BasicItem("fairy_rock", "Fairy rock"), 50),
|
||||||
|
new LootEntry<>(new BasicItem("unicorn_horn", "Unicorn horn"), 230)
|
||||||
|
)) {
|
||||||
|
}));
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final LootTable<? extends Item> lootTable;
|
||||||
|
Biome(String name, LootTable<? extends Item> lootTable) {
|
||||||
|
this.name = name;
|
||||||
|
this.lootTable = lootTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LootTable<? extends Item> getLootTable() {
|
||||||
|
return lootTable;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/test/java/InventoryTest.java
Normal file
17
src/test/java/InventoryTest.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import Inventory.Inventory;
|
||||||
|
import Item.BasicItem;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
|
public class InventoryTest {
|
||||||
|
@Test
|
||||||
|
void can_add_item_to_inventory() {
|
||||||
|
var inventory = new Inventory();
|
||||||
|
inventory.addItem(new BasicItem("iron_sword", "Iron Sword"));
|
||||||
|
assertThat(inventory.getItems(), hasItem(
|
||||||
|
hasProperty("id", equalTo("iron_sword"))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/test/java/LootTableTest.java
Normal file
39
src/test/java/LootTableTest.java
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import Shared.LootTable;
|
||||||
|
import Shared.RandomProvider;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.anyOf;
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
public class LootTableTest {
|
||||||
|
LootTable<String> defaultLootTable() {
|
||||||
|
LootTable<String> lootTable = new LootTable<>();
|
||||||
|
lootTable.addEntry("Stone", 90);
|
||||||
|
lootTable.addEntry("Iron", 10);
|
||||||
|
return lootTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void returns_an_item_was_added() {
|
||||||
|
LootTable<String> loot = defaultLootTable();
|
||||||
|
String result = loot.roll();
|
||||||
|
assertThat(result, anyOf(equalTo("Stone"), equalTo("Iron")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void respects_weight_when_rolling() {
|
||||||
|
var mockRandomProvider = mock(RandomProvider.class);
|
||||||
|
when(mockRandomProvider.nextInt(anyInt())).thenReturn(94);
|
||||||
|
LootTable<String> loot = new LootTable<>(mockRandomProvider);
|
||||||
|
loot.addEntry("Stone", 90);
|
||||||
|
loot.addEntry("Iron", 10);
|
||||||
|
String result = loot.roll();
|
||||||
|
assertThat(result, equalTo("Iron"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,13 +1,19 @@
|
|||||||
|
import Entity.Player;
|
||||||
import Job.Miner;
|
import Job.Miner;
|
||||||
|
import Shared.RandomProvider;
|
||||||
|
import Terrain.Biome;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
public class MinerTest {
|
public class MinerTest {
|
||||||
|
private Player defaultPlayer() {return new Player("John"); }
|
||||||
@Test
|
@Test
|
||||||
void can_level_up() {
|
void can_level_up() {
|
||||||
var job = new Miner();
|
var job = new Miner(defaultPlayer());
|
||||||
assertEquals(1, job.getLevel());
|
assertEquals(1, job.getLevel());
|
||||||
job.levelUp();
|
job.levelUp();
|
||||||
assertEquals(2, job.getLevel());
|
assertEquals(2, job.getLevel());
|
||||||
@ -15,32 +21,42 @@ public class MinerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void can_gain_xp() {
|
void can_gain_xp() {
|
||||||
var job = new Miner();
|
var job = new Miner(defaultPlayer());
|
||||||
job.gainExperience(25);
|
job.gainExperience(25);
|
||||||
assertEquals(25, job.getExperience());
|
assertEquals(25, job.getExperience());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void level_up_when_experience_cap_is_reached() {
|
void level_up_when_experience_cap_is_reached() {
|
||||||
var job = new Miner();
|
var job = new Miner(defaultPlayer());
|
||||||
job.gainExperience(job.remainingXpUntilLevelUp());
|
job.gainExperience(job.remainingXpUntilLevelUp());
|
||||||
assertEquals(2, job.getLevel());
|
assertEquals(2, job.getLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void additional_xp_carries_over_on_level_up() {
|
void additional_xp_carries_over_on_level_up() {
|
||||||
var job = new Miner();
|
var job = new Miner(defaultPlayer());
|
||||||
job.gainExperience(job.remainingXpUntilLevelUp() + 10);
|
job.gainExperience(job.remainingXpUntilLevelUp() + 10);
|
||||||
assertEquals(10, job.getExperience());
|
assertEquals(10, job.getExperience());
|
||||||
}
|
}
|
||||||
|
@Test
|
||||||
|
void dig_in_coast_use_coast_loot() {
|
||||||
|
RandomProvider random = bound -> 9;
|
||||||
|
var job = new Miner(defaultPlayer());
|
||||||
|
Biome.COAST.getLootTable().setRandomProvider(random);
|
||||||
|
job.dig(Biome.COAST);
|
||||||
|
assertThat(job.getActor().getInventory().getItems(), hasItem(
|
||||||
|
hasProperty("id", equalTo("sand"))));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void dig_on_ice_require_ice_pick() {
|
void dig_in_mountain_use_mountain_loot() {
|
||||||
|
RandomProvider random = bound -> 15;
|
||||||
}
|
var job = new Miner(defaultPlayer());
|
||||||
|
Biome.MOUNTAIN.getLootTable().setRandomProvider(random);
|
||||||
|
job.dig(Biome.MOUNTAIN);
|
||||||
|
assertThat(job.getActor().getInventory().getItems(), hasItem( hasProperty("id", equalTo("iron"))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -4,10 +4,15 @@ import Combat.OffensiveDamageSpell;
|
|||||||
import Entity.Position;
|
import Entity.Position;
|
||||||
import Job.Miner;
|
import Job.Miner;
|
||||||
import Entity.Player;
|
import Entity.Player;
|
||||||
|
import Terrain.Biome;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import Job.Wizard;
|
import Job.Wizard;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
|
import static org.hamcrest.Matchers.instanceOf;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
class PlayerTest {
|
class PlayerTest {
|
||||||
private Player defaultPlayer() {
|
private Player defaultPlayer() {
|
||||||
@ -45,17 +50,18 @@ class PlayerTest {
|
|||||||
var p = defaultPlayer();
|
var p = defaultPlayer();
|
||||||
assertNull(p.getJob());
|
assertNull(p.getJob());
|
||||||
|
|
||||||
var job = new Miner();
|
var job = new Miner(p);
|
||||||
p.learnJob(job);
|
p.learnJob(job);
|
||||||
assertEquals(new Miner(), p.getJob());
|
assertThat(p.getJob(), instanceOf(Miner.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void miner_can_dig() {
|
void miner_can_dig() {
|
||||||
var p = new Player("John");
|
var p = new Player("John");
|
||||||
p.learnJob(new Miner());
|
p.learnJob(new Miner(p));
|
||||||
p.performAction(new DigAction());
|
var mockAction = mock(DigAction.class);
|
||||||
assertTrue(p.getInventory().containsItem("Stone"));
|
p.performAction(mockAction);
|
||||||
|
verify(mockAction, times(1)).execute(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user