diff --git a/pom.xml b/pom.xml
index a427f23..4954a6f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
org.mockito
mockito-core
- 5.12.0
+ 5.20.0
test
diff --git a/src/main/java/Action/DigAction.java b/src/main/java/Action/DigAction.java
index 4d652e2..d657191 100644
--- a/src/main/java/Action/DigAction.java
+++ b/src/main/java/Action/DigAction.java
@@ -2,12 +2,17 @@ package Action;
import Job.HasJob;
import Job.Miner;
+import Terrain.Biome;
public class DigAction implements Action {
+ Biome biome;
+ public DigAction(Biome biome) {
+ this.biome = biome;
+ }
@Override
public void execute(Actor actor) {
Miner miner = requireMiner(actor);
- miner.dig(actor);
+ miner.dig(biome);
}
private Miner requireMiner(Actor actor) {
diff --git a/src/main/java/Biomes.java b/src/main/java/Biomes.java
deleted file mode 100644
index 3c61251..0000000
--- a/src/main/java/Biomes.java
+++ /dev/null
@@ -1,3 +0,0 @@
-public enum Biomes {
- GRASSLAND, MOUNTAIN, COAST, FOREST //Är inte fäst vid dessa
-}
diff --git a/src/main/java/Inventory/Inventory.java b/src/main/java/Inventory/Inventory.java
index 786cfda..6d65070 100644
--- a/src/main/java/Inventory/Inventory.java
+++ b/src/main/java/Inventory/Inventory.java
@@ -1,20 +1,23 @@
package Inventory;
+import Item.Item;
+
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
public class Inventory {
- List items;
+ List- items;
public Inventory() {
items = new ArrayList<>();
}
- List getItems() {
- return items;
+ public List
- getItems() {
+ return Collections.unmodifiableList(items);
}
- public void addItem(String item) {
+ public void addItem(Item item) {
items.add(item);
}
diff --git a/src/main/java/Item/BasicItem.java b/src/main/java/Item/BasicItem.java
new file mode 100644
index 0000000..863776a
--- /dev/null
+++ b/src/main/java/Item/BasicItem.java
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/Item/Item.java b/src/main/java/Item/Item.java
new file mode 100644
index 0000000..6d88ff4
--- /dev/null
+++ b/src/main/java/Item/Item.java
@@ -0,0 +1,6 @@
+package Item;
+
+public interface Item {
+ String getId();
+ String getName();
+}
\ No newline at end of file
diff --git a/src/main/java/Job/Miner.java b/src/main/java/Job/Miner.java
index 79c56ec..f731381 100644
--- a/src/main/java/Job/Miner.java
+++ b/src/main/java/Job/Miner.java
@@ -1,17 +1,23 @@
package Job;
-import Action.Actor;
import Inventory.HasInventory;
+import Terrain.Biome;
public class Miner extends Job {
- public Miner() {
+ HasInventory actor;
+
+ public Miner(HasInventory actor) {
super("Miner");
+ this.actor = actor;
}
- public void dig(Actor actor) {
- if (actor instanceof HasInventory a) {
- a.getInventory().addItem("Stone");
- }
+ public HasInventory getActor() {
+ return actor;
+ }
+
+ public void dig(Biome biome) {
+ var item = biome.getLootTable().roll();
+ actor.getInventory().addItem(item);
}
}
diff --git a/src/main/java/Monster.java b/src/main/java/Monster.java
index a9b3efc..9e1d6d7 100644
--- a/src/main/java/Monster.java
+++ b/src/main/java/Monster.java
@@ -1,32 +1,33 @@
import Entity.Position;
+import Terrain.Biome;
import java.util.*;
public abstract class Monster extends Character{
- private final List habitat = new ArrayList<>();
+ private final List habitat = new ArrayList<>();
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) {
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) {
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 habitat) {
+ 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() {
+ public List getHabitat() {
return Collections.unmodifiableList(habitat);
}
}
diff --git a/src/main/java/Shared/DefaultRandomProvider.java b/src/main/java/Shared/DefaultRandomProvider.java
new file mode 100644
index 0000000..2cc40fe
--- /dev/null
+++ b/src/main/java/Shared/DefaultRandomProvider.java
@@ -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);
+ }
+}
diff --git a/src/main/java/Shared/LootEntry.java b/src/main/java/Shared/LootEntry.java
new file mode 100644
index 0000000..1586bb4
--- /dev/null
+++ b/src/main/java/Shared/LootEntry.java
@@ -0,0 +1,4 @@
+package Shared;
+
+public record LootEntry(T item, int weight) {
+}
diff --git a/src/main/java/Shared/LootTable.java b/src/main/java/Shared/LootTable.java
new file mode 100644
index 0000000..3b02763
--- /dev/null
+++ b/src/main/java/Shared/LootTable.java
@@ -0,0 +1,46 @@
+package Shared;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+public class LootTable {
+ private RandomProvider random;
+ private final List> entries = new ArrayList<>();
+
+
+ public LootTable() {
+ this.random = new DefaultRandomProvider();
+ }
+
+ public LootTable(List> 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 entry : entries) {
+ current += entry.weight();
+ if (roll < current) {
+ return entry.item();
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/src/main/java/Shared/RandomProvider.java b/src/main/java/Shared/RandomProvider.java
new file mode 100644
index 0000000..bbaf10d
--- /dev/null
+++ b/src/main/java/Shared/RandomProvider.java
@@ -0,0 +1,5 @@
+package Shared;
+
+public interface RandomProvider {
+ int nextInt(int bound);
+}
diff --git a/src/main/java/Terrain/Biome.java b/src/main/java/Terrain/Biome.java
new file mode 100644
index 0000000..185871d
--- /dev/null
+++ b/src/main/java/Terrain/Biome.java
@@ -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;
+ }
+}
diff --git a/src/test/java/InventoryTest.java b/src/test/java/InventoryTest.java
new file mode 100644
index 0000000..1d143db
--- /dev/null
+++ b/src/test/java/InventoryTest.java
@@ -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"))
+ ));
+ }
+}
diff --git a/src/test/java/LootTableTest.java b/src/test/java/LootTableTest.java
new file mode 100644
index 0000000..f91bcab
--- /dev/null
+++ b/src/test/java/LootTableTest.java
@@ -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 defaultLootTable() {
+ LootTable lootTable = new LootTable<>();
+ lootTable.addEntry("Stone", 90);
+ lootTable.addEntry("Iron", 10);
+ return lootTable;
+ }
+
+ @Test
+ void returns_an_item_was_added() {
+ LootTable 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 loot = new LootTable<>(mockRandomProvider);
+ loot.addEntry("Stone", 90);
+ loot.addEntry("Iron", 10);
+ String result = loot.roll();
+ assertThat(result, equalTo("Iron"));
+ }
+}
diff --git a/src/test/java/MinerTest.java b/src/test/java/MinerTest.java
index cb187fb..177d65a 100644
--- a/src/test/java/MinerTest.java
+++ b/src/test/java/MinerTest.java
@@ -1,13 +1,19 @@
+import Entity.Player;
import Job.Miner;
+import Shared.RandomProvider;
+import Terrain.Biome;
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.mockito.Mockito.mock;
public class MinerTest {
-
+ private Player defaultPlayer() {return new Player("John"); }
@Test
void can_level_up() {
- var job = new Miner();
+ var job = new Miner(defaultPlayer());
assertEquals(1, job.getLevel());
job.levelUp();
assertEquals(2, job.getLevel());
@@ -15,32 +21,42 @@ public class MinerTest {
@Test
void can_gain_xp() {
- var job = new Miner();
+ var job = new Miner(defaultPlayer());
job.gainExperience(25);
assertEquals(25, job.getExperience());
}
@Test
void level_up_when_experience_cap_is_reached() {
- var job = new Miner();
+ var job = new Miner(defaultPlayer());
job.gainExperience(job.remainingXpUntilLevelUp());
assertEquals(2, job.getLevel());
}
@Test
void additional_xp_carries_over_on_level_up() {
- var job = new Miner();
+ var job = new Miner(defaultPlayer());
job.gainExperience(job.remainingXpUntilLevelUp() + 10);
assertEquals(10, job.getExperience());
}
-
@Test
- void dig_on_ice_require_ice_pick() {
-
+ 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
+ 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"))));
+ }
}
diff --git a/src/test/java/PlayerTest.java b/src/test/java/PlayerTest.java
index 970f0f9..593629f 100644
--- a/src/test/java/PlayerTest.java
+++ b/src/test/java/PlayerTest.java
@@ -4,10 +4,15 @@ import Combat.OffensiveDamageSpell;
import Entity.Position;
import Job.Miner;
import Entity.Player;
+import Terrain.Biome;
import org.junit.jupiter.api.Test;
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.mockito.Mockito.*;
class PlayerTest {
private Player defaultPlayer() {
@@ -45,17 +50,18 @@ class PlayerTest {
var p = defaultPlayer();
assertNull(p.getJob());
- var job = new Miner();
+ var job = new Miner(p);
p.learnJob(job);
- assertEquals(new Miner(), p.getJob());
+ assertThat(p.getJob(), instanceOf(Miner.class));
}
@Test
void miner_can_dig() {
var p = new Player("John");
- p.learnJob(new Miner());
- p.performAction(new DigAction());
- assertTrue(p.getInventory().containsItem("Stone"));
+ p.learnJob(new Miner(p));
+ var mockAction = mock(DigAction.class);
+ p.performAction(mockAction);
+ verify(mockAction, times(1)).execute(any());
}
@Test