> getComparatorMap() {
30 | return comparatorMap;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/achievements/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * The achievements package stores all achievement-related functionality of the game.
3 | *
4 | * AchievementTracker and UnlockedAchievement are the only serializable classes. The hero has an achievement tracker
5 | * that contains a variable number of unlocked achievements.
6 | */
7 |
8 | package org.mafagafogigante.dungeon.achievements;
9 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/commands/Command.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.commands;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | /**
6 | * Command abstract class that defines a type for command objects.
7 | *
8 | *
Make anonymous classes from this one to define commands.
9 | */
10 | public abstract class Command {
11 |
12 | private final CommandDescription description;
13 |
14 | /**
15 | * Creates a new Command object with the provided name and info.
16 | *
17 | * @param name a String for name, lowercase
18 | * @param info a String for info
19 | */
20 | Command(@NotNull String name, @NotNull String info) {
21 | description = new CommandDescription(name, info);
22 | }
23 |
24 | public CommandDescription getDescription() {
25 | return description;
26 | }
27 |
28 | /**
29 | * Indicates whether a Command is "equal to" this one.
30 | *
31 | *
Two Commands are considered to be equal when their names are equal.
32 | */
33 | @Override
34 | public boolean equals(Object object) {
35 | if (this == object) {
36 | return true;
37 | }
38 | if (object == null || getClass() != object.getClass()) {
39 | return false;
40 | }
41 | Command command = (Command) object;
42 | return description.getName().equals(command.description.getName());
43 | }
44 |
45 | @Override
46 | public int hashCode() {
47 | return description.getName().hashCode();
48 | }
49 |
50 | /**
51 | * Executes this Command, given an IssuedCommand object.
52 | */
53 | public abstract void execute(@NotNull String[] arguments);
54 |
55 | @Override
56 | public String toString() {
57 | return description.toString();
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/commands/CommandDescription.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.commands;
2 |
3 | import org.mafagafogigante.dungeon.logging.DungeonLogger;
4 |
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | import java.util.Locale;
8 |
9 | /**
10 | * Simple wrapper for a name and info of a Command.
11 | */
12 | public class CommandDescription {
13 |
14 | private final String name;
15 | private final String info;
16 |
17 | /**
18 | * Creates a CommandDescription with the provided name and info.
19 | *
20 | * @param name a String for name, not null, lowercase
21 | * @param info a String for info, nullable
22 | */
23 | CommandDescription(@NotNull String name, String info) {
24 | if (isNotLowercase(name)) {
25 | DungeonLogger.warning("Passed a String that was not lowercase as name for a CommandDescription.");
26 | name = name.toLowerCase(Locale.ENGLISH);
27 | }
28 | this.name = name;
29 | this.info = info;
30 | }
31 |
32 | /**
33 | * Checks if a String is not lowercase.
34 | *
35 | * @param string the String to be tested, not null
36 | * @return true if the String is not lowercase, false if it is lowercase
37 | */
38 | private static boolean isNotLowercase(String string) {
39 | for (char c : string.toCharArray()) {
40 | if (!Character.isLowerCase(c)) {
41 | return true;
42 | }
43 | }
44 | return false;
45 | }
46 |
47 | public String getName() {
48 | return name;
49 | }
50 |
51 | public String getInfo() {
52 | return info;
53 | }
54 |
55 | @Override
56 | public String toString() {
57 | return getName() + " : " + getInfo();
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/commands/CommandLimits.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.commands;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | class CommandLimits {
6 |
7 | /**
8 | * An arbitrary maximum command length.
9 | *
10 | *
This value is used for input validation and to prevent that slower and memory-consuming methods ever get feed
11 | * too much input.
12 | */
13 | private static final int MAXIMUM_COMMAND_LENGTH = 2048;
14 |
15 | static boolean isWithinMaximumCommandLength(@NotNull final String candidate) {
16 | return candidate.length() <= MAXIMUM_COMMAND_LENGTH;
17 | }
18 |
19 | static boolean isValidSource(@NotNull final String source) {
20 | return isWithinMaximumCommandLength(source);
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/commands/IssuedCommand.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.commands;
2 |
3 | import org.apache.commons.lang3.StringUtils;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | import java.util.Arrays;
7 | import java.util.Collections;
8 | import java.util.List;
9 |
10 | /**
11 | * IssuedCommand class that processes a command entered by the player and provides useful query methods.
12 | *
13 | *
IssuedCommands are case-unsensitive and granted to have at least one word (the command).
14 | */
15 | public final class IssuedCommand {
16 |
17 | private final String stringRepresentation;
18 | private final List tokens; // An unmodifiable list.
19 |
20 | /**
21 | * Creates a new IssuedCommand from a string.
22 | *
23 | * @param source a string with at least one character that is not whitespace.
24 | */
25 | public IssuedCommand(@NotNull String source) {
26 | if (!isValidSource(source)) {
27 | throw new IllegalArgumentException("invalid source, command limits violated.");
28 | }
29 | tokens = Collections.unmodifiableList(Arrays.asList(StringUtils.split(source)));
30 | if (tokens.isEmpty()) {
31 | throw new IllegalArgumentException("invalid source, no tokens obtained.");
32 | }
33 | this.stringRepresentation = StringUtils.join(tokens, ' ');
34 | }
35 |
36 | public static boolean isValidSource(String text) {
37 | return CommandLimits.isValidSource(text);
38 | }
39 |
40 | public String getStringRepresentation() {
41 | return stringRepresentation;
42 | }
43 |
44 | /**
45 | * Returns an unmodifiable view of the list of tokens.
46 | */
47 | public List getTokens() {
48 | return tokens; // tokens is already unmodifiable.
49 | }
50 |
51 | @Override
52 | public String toString() {
53 | return getStringRepresentation();
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/commands/IssuedCommandEvaluation.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.commands;
2 |
3 | import java.util.Collections;
4 | import java.util.List;
5 |
6 | public class IssuedCommandEvaluation {
7 |
8 | private final boolean valid;
9 | private final List suggestions;
10 |
11 | IssuedCommandEvaluation(boolean valid, List suggestions) {
12 | this.valid = valid;
13 | this.suggestions = suggestions;
14 | }
15 |
16 | public boolean isValid() {
17 | return valid;
18 | }
19 |
20 | public List getSuggestions() {
21 | return Collections.unmodifiableList(suggestions);
22 | }
23 |
24 | @Override
25 | public String toString() {
26 | return "IssuedCommandEvaluation{" +
27 | "valid=" + valid +
28 | ", suggestions=" + suggestions +
29 | '}';
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/commands/PreparedIssuedCommand.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.commands;
2 |
3 | /**
4 | * An issued command that is ready to be executed.
5 | */
6 | public class PreparedIssuedCommand {
7 |
8 | private final Command specifiedCommand;
9 | private final String[] arguments;
10 |
11 | PreparedIssuedCommand(Command specifiedCommand, String[] arguments) {
12 | this.specifiedCommand = specifiedCommand;
13 | this.arguments = arguments;
14 | }
15 |
16 | /**
17 | * Calls this PreparedIssuedCommand to execute its underlying command.
18 | */
19 | public void execute() {
20 | specifiedCommand.execute(arguments);
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/commands/StringDistanceMetrics.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.commands;
2 |
3 | import org.apache.commons.lang3.StringUtils;
4 |
5 | class StringDistanceMetrics {
6 |
7 | static int levenshteinDistance(final String a, final String b) {
8 | if (!CommandLimits.isWithinMaximumCommandLength(a)) {
9 | throw new IllegalArgumentException("input is too big.");
10 | }
11 | if (!CommandLimits.isWithinMaximumCommandLength(b)) {
12 | throw new IllegalArgumentException("input is too big.");
13 | }
14 | return StringUtils.getLevenshteinDistance(a, b);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/commands/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Contains the classes related to the representation and processing of player input.
3 | */
4 |
5 | package org.mafagafogigante.dungeon.commands;
6 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/date/DungeonTimeUnit.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.date;
2 |
3 | /**
4 | * The time units of the Dungeon calendar.
5 | */
6 | public enum DungeonTimeUnit {
7 |
8 | MILLISECOND(1), SECOND(1000 * MILLISECOND.milliseconds), MINUTE(60 * SECOND.milliseconds),
9 | HOUR(60 * MINUTE.milliseconds), DAY(24 * HOUR.milliseconds), MONTH(10 * DAY.milliseconds),
10 | YEAR(10 * MONTH.milliseconds);
11 |
12 | public final long milliseconds;
13 |
14 | DungeonTimeUnit(long milliseconds) {
15 | this.milliseconds = milliseconds;
16 | }
17 |
18 | /**
19 | * Returns how many of the specified unit are equivalent to one of this unit.
20 | *
21 | * @param unit a DungeonTimeUnit that is smaller than this one, not null
22 | * @return a long bigger than one
23 | */
24 | public long as(DungeonTimeUnit unit) {
25 | if (this.milliseconds <= unit.milliseconds) {
26 | throw new IllegalArgumentException("unit is bigger than or equal to the caller.");
27 | } else {
28 | return this.milliseconds / unit.milliseconds;
29 | }
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/date/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Defines all Dungeon in-game date utilities.
3 | */
4 |
5 | package org.mafagafogigante.dungeon.date;
6 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/Damage.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class Damage {
7 |
8 | private final List amounts = new ArrayList<>();
9 |
10 | public List getAmounts() {
11 | return amounts;
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/DamageAmount.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | import java.io.Serializable;
6 |
7 | public class DamageAmount implements Serializable {
8 |
9 | private static final long serialVersionUID = Version.MAJOR;
10 |
11 | private final DamageType type;
12 | private final int amount;
13 |
14 | public DamageAmount(DamageType type, int amount) {
15 | this.type = type;
16 | this.amount = amount;
17 | }
18 |
19 | public DamageType getType() {
20 | return type;
21 | }
22 |
23 | public int getAmount() {
24 | return amount;
25 | }
26 |
27 | public String getDescription() {
28 | return amount + " " + type.getName() + " damage";
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/DamageType.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | public enum DamageType {
6 |
7 | SLASHING("Slashing"), PIERCING("Piercing"), BLUDGEONING("Bludgeoning"), CRUSHING("Crushing"), ACID("Acid"),
8 | COLD("Cold"), ELECTRICITY("Electricity"), FIRE("Fire"), POISON("Poison"), SONIC("Sonic"), DIVINE("Divine"),
9 | MAGIC("Magic"), NEGATIVE("Negative"), Positive("Positive");
10 |
11 | private static final long serialVersionUID = Version.MAJOR;
12 | private final String name;
13 |
14 | DamageType(String name) {
15 | this.name = name;
16 | }
17 |
18 | public String getName() {
19 | return name;
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/Enchantment.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity;
2 |
3 | public interface Enchantment {
4 | String getName();
5 |
6 | String getDescription();
7 |
8 | void modifyAttackDamage(Damage damage);
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/EnchantmentFactory.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity;
2 |
3 | import org.mafagafogigante.dungeon.game.Id;
4 | import org.mafagafogigante.dungeon.io.JsonObjectFactory;
5 | import org.mafagafogigante.dungeon.io.Version;
6 |
7 | import com.eclipsesource.json.JsonObject;
8 | import com.eclipsesource.json.JsonValue;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 | import java.io.Serializable;
12 | import java.util.HashMap;
13 | import java.util.Map;
14 |
15 | public class EnchantmentFactory implements Serializable {
16 |
17 | private static final long serialVersionUID = Version.MAJOR;
18 |
19 | private Map presets = new HashMap<>();
20 |
21 | /**
22 | * Construct an EnchantmentFactory from a JSON file.
23 | */
24 | public EnchantmentFactory(String filename) {
25 | JsonObject objects = JsonObjectFactory.makeJsonObject(filename);
26 | for (JsonValue value : objects.get("enchantments").asArray()) {
27 | JsonObject object = value.asObject();
28 | JsonObject damageObject = object.get("damage").asObject();
29 | Id id = new Id(object.get("id").asString());
30 | String name = object.get("name").asString();
31 | DamageType type = DamageType.valueOf(damageObject.get("type").asString());
32 | int amount = damageObject.get("amount").asInt();
33 | presets.put(id, new WeaponEnchantmentPreset(name, type, amount));
34 | }
35 | }
36 |
37 | public Enchantment makeEnchantment(@NotNull Id id) {
38 | return presets.get(id).makeEnchantment();
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/LightSource.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | import java.io.Serializable;
6 |
7 | /**
8 | * A source of Luminosity.
9 | */
10 | public class LightSource implements Serializable {
11 |
12 | private static final long serialVersionUID = Version.MAJOR;
13 | private final Luminosity luminosity;
14 | private boolean enabled = true;
15 |
16 | public LightSource(Luminosity luminosity) {
17 | this.luminosity = luminosity;
18 | }
19 |
20 | /**
21 | * Enables this source until disable is called.
22 | */
23 | public void enable() {
24 | this.enabled = true;
25 | }
26 |
27 | /**
28 | * Disables this source until enable is called.
29 | */
30 | public void disable() {
31 | this.enabled = false;
32 | }
33 |
34 | /**
35 | * Returns the luminosity of this light source.
36 | */
37 | public Luminosity getLuminosity() {
38 | if (enabled) {
39 | return luminosity;
40 | } else {
41 | return Luminosity.ZERO;
42 | }
43 | }
44 |
45 | @Override
46 | public String toString() {
47 | return (enabled ? "Enabled" : "Disabled") + " LightSource of luminosity of " + luminosity.toPercentage();
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/Luminosity.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 | import org.mafagafogigante.dungeon.util.Percentage;
5 |
6 | import java.io.Serializable;
7 | import java.util.Collection;
8 |
9 | /**
10 | * A luminosity value.
11 | */
12 | public class Luminosity implements Serializable {
13 |
14 | private static final long serialVersionUID = Version.MAJOR;
15 | public static final Luminosity ZERO = new Luminosity(new Percentage(0.0));
16 |
17 | private final Percentage value;
18 |
19 | public Luminosity(Percentage value) {
20 | this.value = value;
21 | }
22 |
23 | /**
24 | * Returns a Luminosity value equal to the resultant luminosity of a collection of entities.
25 | */
26 | public static Luminosity resultantLuminosity(Collection entities) {
27 | double total = 0;
28 | for (Entity entity : entities) {
29 | total += entity.getLuminosity().toPercentage().toDouble();
30 | }
31 | return new Luminosity(new Percentage(Math.min(total, 1.0)));
32 | }
33 |
34 | public Percentage toPercentage() {
35 | return value;
36 | }
37 |
38 | @Override
39 | public String toString() {
40 | return "Luminosity of " + value;
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/Preset.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity;
2 |
3 | import org.mafagafogigante.dungeon.game.Id;
4 | import org.mafagafogigante.dungeon.game.Name;
5 | import org.mafagafogigante.dungeon.util.Percentage;
6 |
7 | /**
8 | * An interface that simplifies Entity instantiation.
9 | */
10 | public interface Preset {
11 |
12 | Id getId();
13 |
14 | String getType();
15 |
16 | Name getName();
17 |
18 | Weight getWeight();
19 |
20 | Percentage getVisibility();
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/WeaponEnchantment.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | import java.io.Serializable;
6 |
7 | public class WeaponEnchantment implements Enchantment, Serializable {
8 |
9 | private static final long serialVersionUID = Version.MAJOR;
10 | private final String name;
11 | private final DamageAmount amount;
12 |
13 | WeaponEnchantment(String name, DamageAmount amount) {
14 | this.name = name;
15 | this.amount = amount;
16 | }
17 |
18 | @Override
19 | public String getName() {
20 | return name;
21 | }
22 |
23 | @Override
24 | public String getDescription() {
25 | return "+" + amount.getDescription();
26 | }
27 |
28 | @Override
29 | public void modifyAttackDamage(Damage damage) {
30 | damage.getAmounts().add(amount);
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/WeaponEnchantmentPreset.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | import java.io.Serializable;
6 |
7 | public class WeaponEnchantmentPreset implements Serializable {
8 |
9 | private static final long serialVersionUID = Version.MAJOR;
10 | private final String name;
11 | private final DamageAmount damageAmount;
12 |
13 | public WeaponEnchantmentPreset(String name, DamageType type, int amount) {
14 | this.name = name;
15 | this.damageAmount = new DamageAmount(type, amount);
16 | }
17 |
18 | Enchantment makeEnchantment() {
19 | return new WeaponEnchantment(name, damageAmount);
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/AttackAlgorithm.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | /**
6 | * An interface that defines a single renderAttack method that is invoked when a creature attacks another.
7 | */
8 | interface AttackAlgorithm {
9 |
10 | /**
11 | * Renders an attack of the attacker on the defender.
12 | *
13 | * If any creature dies due to the invocation of this method, it will have its causeOfDeath field set.
14 | *
15 | * @param attacker the attacker
16 | * @param defender the defender
17 | */
18 | void renderAttack(@NotNull Creature attacker, @NotNull Creature defender);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/AttackAlgorithmId.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | /**
4 | * A valid ID for an AttackAlgorithm.
5 | */
6 | public enum AttackAlgorithmId {
7 |
8 | BAT, CRITTER, DUMMY, ORC, SIMPLE
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/BatAttackAlgorithm.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import org.mafagafogigante.dungeon.util.DungeonMath;
4 | import org.mafagafogigante.dungeon.util.Percentage;
5 |
6 | import org.jetbrains.annotations.NotNull;
7 |
8 | /**
9 | * The AttackAlgorithm bats that use echolocation should use.
10 | *
11 | *
Both the hit rate and the critical chance of bats are inversely proportional to the location's luminosity.
12 | */
13 | class BatAttackAlgorithm extends SimpleAttackAlgorithm {
14 |
15 | private static final double BAT_MAX_HIT_RATE = 0.9;
16 | private static final double BAT_MIN_HIT_RATE = 0.1;
17 |
18 | private static final double BAT_MAX_CRITICAL_CHANCE = 0.8;
19 | private static final double BAT_MIN_CRITICAL_CHANCE = 0.0;
20 |
21 | @Override
22 | Percentage getHitRate(@NotNull Creature creature) {
23 | Percentage luminosity = creature.getLocation().getLuminosity().toPercentage();
24 | return new Percentage(DungeonMath.weightedAverage(BAT_MAX_HIT_RATE, BAT_MIN_HIT_RATE, luminosity));
25 | }
26 |
27 | @Override
28 | Percentage getCriticalChance(@NotNull Creature creature) {
29 | Percentage luminosity = creature.getLocation().getLuminosity().toPercentage();
30 | return new Percentage(DungeonMath.weightedAverage(BAT_MAX_CRITICAL_CHANCE, BAT_MIN_CRITICAL_CHANCE, luminosity));
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/BattleLog.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | public interface BattleLog {
4 |
5 | /**
6 | * Increments the inflicted damage by the specified amount.
7 | *
8 | * @param damage a nonnegative long
9 | */
10 | void incrementInflicted(long damage);
11 |
12 | /**
13 | * Increments the taken damage by the specified amount.
14 | *
15 | * @param damage a nonnegative long
16 | */
17 | void incrementTaken(long damage);
18 |
19 | /**
20 | * Gets and resets the inflicted damage.
21 | */
22 | long getAndResetInflicted();
23 |
24 | /**
25 | * Gets and resets the taken damage.
26 | */
27 | long getAndResetTaken();
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/ColoredString.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | import java.awt.Color;
6 |
7 | /**
8 | * A wrapper for a String and a Color.
9 | */
10 | final class ColoredString {
11 |
12 | private final String string;
13 | private final Color color;
14 |
15 | public ColoredString(@NotNull String string, @NotNull Color color) {
16 | this.string = string;
17 | this.color = color;
18 | }
19 |
20 | @NotNull
21 | public String getString() {
22 | return string;
23 | }
24 |
25 | @NotNull
26 | public Color getColor() {
27 | return color;
28 | }
29 |
30 | @Override
31 | public boolean equals(Object object) {
32 | if (this == object) {
33 | return true;
34 | }
35 | if (object == null || getClass() != object.getClass()) {
36 | return false;
37 | }
38 |
39 | ColoredString that = (ColoredString) object;
40 | return string.equals(that.string) && color.equals(that.color);
41 | }
42 |
43 | @Override
44 | public int hashCode() {
45 | return 31 * string.hashCode() + (color.hashCode());
46 | }
47 |
48 | @Override
49 | public String toString() {
50 | return String.format("'%s' written in %s.", string, color);
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/Condition.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import org.mafagafogigante.dungeon.date.Date;
4 | import org.mafagafogigante.dungeon.io.Version;
5 | import org.mafagafogigante.dungeon.util.Percentage;
6 |
7 | import java.io.Serializable;
8 |
9 | abstract class Condition implements Serializable {
10 |
11 | private static final long serialVersionUID = Version.MAJOR;
12 |
13 | abstract Date getExpirationDate();
14 |
15 | abstract Effect getEffect();
16 |
17 | abstract String getDescription();
18 |
19 | @Override
20 | public boolean equals(Object object) {
21 | if (this == object) {
22 | return true;
23 | }
24 | if (object == null) {
25 | return false;
26 | }
27 | return getClass().getCanonicalName().equals(object.getClass().getCanonicalName());
28 | }
29 |
30 | @Override
31 | public int hashCode() {
32 | return getClass().getCanonicalName().hashCode();
33 | }
34 |
35 | final boolean hasExpired(Date date) {
36 | return getExpirationDate().compareTo(date) < 0;
37 | }
38 |
39 | int modifyAttack(int currentAttack) {
40 | return currentAttack;
41 | }
42 |
43 | Percentage modifyHitRate(Percentage hitRate) {
44 | return hitRate;
45 | }
46 |
47 | Percentage modifyFishingProficiency(Percentage proficiency) {
48 | return proficiency;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/CreaturePresetFactory.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import java.util.Collection;
4 |
5 | /**
6 | * A factory of CreaturePresets.
7 | */
8 | public interface CreaturePresetFactory {
9 | Collection getCreaturePresets();
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/CritterAttackAlgorithm.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import org.mafagafogigante.dungeon.game.DungeonString;
4 | import org.mafagafogigante.dungeon.game.Random;
5 | import org.mafagafogigante.dungeon.io.Writer;
6 |
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | import java.awt.Color;
10 |
11 | /**
12 | * An implementation of AttackAlgorithm that just writes to the screen.
13 | */
14 | public class CritterAttackAlgorithm implements AttackAlgorithm {
15 |
16 | @Override
17 | public void renderAttack(@NotNull Creature attacker, @NotNull Creature defender) {
18 | if (Random.nextBoolean()) {
19 | Writer.writeAndWait(new DungeonString(attacker.getName() + " does nothing.\n", Color.YELLOW));
20 | } else {
21 | Writer.writeAndWait(new DungeonString(attacker.getName() + " tries to run away.\n", Color.YELLOW));
22 | }
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/DamageHandler.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | /**
4 | * The class responsible for inflicting damage from one creature onto another.
5 | */
6 | class DamageHandler {
7 |
8 | private DamageHandler() {
9 | }
10 |
11 | static void inflictDamage(Creature attacker, Creature defender, int damage) {
12 | defender.getHealth().decrementBy(damage);
13 | attacker.getBattleLog().incrementInflicted(damage);
14 | defender.getBattleLog().incrementTaken(damage);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/DateOfBirthGenerator.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import static org.mafagafogigante.dungeon.date.DungeonTimeUnit.SECOND;
4 | import static org.mafagafogigante.dungeon.date.DungeonTimeUnit.YEAR;
5 |
6 | import org.mafagafogigante.dungeon.date.Date;
7 | import org.mafagafogigante.dungeon.game.Random;
8 | import org.mafagafogigante.dungeon.util.DungeonMath;
9 |
10 | import org.jetbrains.annotations.NotNull;
11 |
12 | /**
13 | * A class that generates pseudorandom dates of birth.
14 | */
15 | class DateOfBirthGenerator {
16 |
17 | private static final int SECONDS_IN_YEAR = DungeonMath.safeCastLongToInteger(YEAR.as(SECOND));
18 | private final Date today;
19 | private final int age;
20 |
21 | /**
22 | * Constructs a new DateOfBirthGenerator for a specified date and age.
23 | *
24 | * @param now the current date of the World
25 | * @param age the desired age
26 | */
27 | DateOfBirthGenerator(@NotNull Date now, int age) {
28 | this.today = now;
29 | if (age < 0) {
30 | throw new IllegalArgumentException("age must be nonnegative.");
31 | }
32 | this.age = age;
33 | }
34 |
35 | /**
36 | * Generates a new random date of birth.
37 | */
38 | Date generateDateOfBirth() {
39 | Date minimumDate = today.minus(age + 1, YEAR).plus(1, SECOND);
40 | // Will add up to SECONDS_IN_YEAR - 1 seconds to the minimum date, which should respect the year.
41 | return minimumDate.plus(Random.nextInteger(SECONDS_IN_YEAR - 1) + 1, SECOND);
42 | }
43 |
44 | @Override
45 | public String toString() {
46 | return "DateOfBirthGenerator{" + "today=" + today + ", age=" + age + '}';
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/DeathHandler.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import org.mafagafogigante.dungeon.entity.items.Item;
4 | import org.mafagafogigante.dungeon.game.Location;
5 | import org.mafagafogigante.dungeon.game.World;
6 | import org.mafagafogigante.dungeon.logging.DungeonLogger;
7 |
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | final class DeathHandler {
11 |
12 | private DeathHandler() {
13 | throw new AssertionError();
14 | }
15 |
16 | public static void handleDeath(@NotNull Creature creature) {
17 | if (creature.getHealth().isAlive()) {
18 | throw new IllegalStateException("creature is alive.");
19 | }
20 | Location defeatedLocation = creature.getLocation();
21 | defeatedLocation.removeCreature(creature);
22 | if (creature.hasTag(Creature.Tag.CORPSE)) {
23 | World world = creature.getLocation().getWorld();
24 | Item item = world.getItemFactory().makeCorpse(creature, defeatedLocation.getWorld().getWorldDate());
25 | defeatedLocation.addItem(item);
26 | }
27 | creature.getDropper().dropEverything();
28 | DungeonLogger.fine("Disposed of " + creature.getName() + " at " + creature.getLocation() + ".");
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/Drop.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import org.mafagafogigante.dungeon.game.Id;
4 | import org.mafagafogigante.dungeon.game.Random;
5 | import org.mafagafogigante.dungeon.io.Version;
6 | import org.mafagafogigante.dungeon.util.Percentage;
7 |
8 | import java.io.Serializable;
9 |
10 | /**
11 | * This class represents an item drop law.
12 | */
13 | class Drop implements Serializable {
14 |
15 | private static final long serialVersionUID = Version.MAJOR;
16 | private final Id itemId;
17 | private final Percentage probability;
18 |
19 | public Drop(Id itemId, Percentage probability) {
20 | this.itemId = itemId;
21 | this.probability = probability;
22 | }
23 |
24 | public Id getItemId() {
25 | return itemId;
26 | }
27 |
28 | public boolean rollForDrop() {
29 | return Random.roll(probability);
30 | }
31 |
32 | @Override
33 | public String toString() {
34 | return "Drop{" +
35 | "itemId=" + itemId +
36 | ", probability=" + probability +
37 | '}';
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/DummyAttackAlgorithm.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import org.mafagafogigante.dungeon.game.DungeonString;
4 | import org.mafagafogigante.dungeon.io.Writer;
5 |
6 | import org.jetbrains.annotations.NotNull;
7 |
8 | import java.awt.Color;
9 |
10 | /**
11 | * An implementation of AttackAlgorithm that just writes to the screen.
12 | */
13 | public class DummyAttackAlgorithm implements AttackAlgorithm {
14 |
15 | @Override
16 | public void renderAttack(@NotNull Creature attacker, @NotNull Creature defender) {
17 | Writer.writeAndWait(new DungeonString(attacker.getName() + " stands still.\n", Color.YELLOW));
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/DummyBattleLog.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | import java.io.Serializable;
6 |
7 | /**
8 | * A dummy implementation of the BattleLog interface.
9 | */
10 | public class DummyBattleLog implements BattleLog, Serializable {
11 |
12 | private static final long serialVersionUID = Version.MAJOR;
13 |
14 | private static final DummyBattleLog INSTANCE = new DummyBattleLog();
15 |
16 | // Do not allow instantiation by other classes.
17 | private DummyBattleLog() {
18 |
19 | }
20 |
21 | public static DummyBattleLog getInstance() {
22 | return INSTANCE;
23 | }
24 |
25 | @Override
26 | public void incrementInflicted(long damage) {
27 | }
28 |
29 | @Override
30 | public void incrementTaken(long damage) {
31 | }
32 |
33 | @Override
34 | public long getAndResetInflicted() {
35 | return 0;
36 | }
37 |
38 | @Override
39 | public long getAndResetTaken() {
40 | return 0;
41 | }
42 |
43 | @Override
44 | public String toString() {
45 | return "DummyBattleLog";
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/Effect.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import java.io.Serializable;
4 |
5 | public abstract class Effect implements Serializable {
6 |
7 | @Override
8 | public boolean equals(Object object) {
9 | if (this == object) {
10 | return true;
11 | }
12 | if (object == null) {
13 | return false;
14 | }
15 | return getClass().getCanonicalName().equals(object.getClass().getCanonicalName());
16 | }
17 |
18 | @Override
19 | public int hashCode() {
20 | return getClass().getCanonicalName().hashCode();
21 | }
22 |
23 | /**
24 | * Affects a creature with this effect.
25 | *
26 | * It is guaranteed that an effect cannot add multiple Condition objects of the same class to a creature.
27 | */
28 | public abstract void affect(Creature creature);
29 |
30 | /**
31 | * Returns the maximum number of simultaneous identical conditions that can be caused by this effect.
32 | *
33 | *
Zero indicates that there is no limit.
34 | */
35 | public int getMaximumStack() {
36 | return 0;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/EffectTemplate.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | import java.io.Serializable;
6 | import java.util.List;
7 |
8 | abstract class EffectTemplate implements Serializable {
9 |
10 | private static final long serialVersionUID = Version.MAJOR;
11 |
12 | abstract Effect instantiate(List parameters);
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/HealthState.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | /**
4 | * HealthState enum that defines the six stages of healthiness.
5 | */
6 | public enum HealthState {
7 |
8 | UNINJURED("Uninjured"),
9 | BARELY_INJURED("Barely Injured"),
10 | INJURED("Injured"),
11 | BADLY_INJURED("Badly Injured"),
12 | NEAR_DEATH("Near Death"),
13 | DEAD("Dead");
14 |
15 | private final String stringRepresentation;
16 |
17 | HealthState(String stringRepresentation) {
18 | this.stringRepresentation = stringRepresentation;
19 | }
20 |
21 | @Override
22 | public String toString() {
23 | return stringRepresentation;
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/OrcAttackAlgorithm.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import org.mafagafogigante.dungeon.util.DungeonMath;
4 | import org.mafagafogigante.dungeon.util.Percentage;
5 |
6 | import org.jetbrains.annotations.NotNull;
7 |
8 | /**
9 | * An implementation of AttackAlgorithm that takes into account the increased brutality of Orcs when endangered.
10 | *
11 | * The critical chance increases as the creature gets closer to dying.
12 | */
13 | class OrcAttackAlgorithm extends SimpleAttackAlgorithm {
14 |
15 | private static final double MIN_CRITICAL_CHANCE = 0.1;
16 | private static final double MAX_CRITICAL_CHANCE = 0.5;
17 |
18 | @Override
19 | Percentage getCriticalChance(@NotNull Creature creature) {
20 | Percentage healthiness = creature.getHealth().toPercentage();
21 | return new Percentage(DungeonMath.weightedAverage(MAX_CRITICAL_CHANCE, MIN_CRITICAL_CHANCE, healthiness));
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/SimpleBattleLog.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | import java.io.Serializable;
6 |
7 | /**
8 | * The simplest possible implementation of a BattleLog.
9 | */
10 | public class SimpleBattleLog implements BattleLog, Serializable {
11 |
12 | private static final long serialVersionUID = Version.MAJOR;
13 |
14 | private long inflicted;
15 | private long taken;
16 |
17 | @Override
18 | public void incrementInflicted(long damage) {
19 | this.inflicted += damage;
20 | }
21 |
22 | @Override
23 | public void incrementTaken(long damage) {
24 | this.taken += damage;
25 | }
26 |
27 | @Override
28 | public long getAndResetInflicted() {
29 | long inflicted = this.inflicted;
30 | this.inflicted = 0;
31 | return inflicted;
32 | }
33 |
34 | @Override
35 | public long getAndResetTaken() {
36 | long taken = this.taken;
37 | this.taken = 0;
38 | return taken;
39 | }
40 |
41 | @Override
42 | public String toString() {
43 | return "SimpleBattleLog{" + "taken=" + taken + ", inflicted=" + inflicted + '}';
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/creatures/Spellcaster.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import org.mafagafogigante.dungeon.spells.Spell;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * An interface that defines a few common things a spellcaster should be able to do.
9 | */
10 | public interface Spellcaster {
11 |
12 | List getSpellList();
13 |
14 | boolean knowsSpell(Spell spell);
15 |
16 | void learnSpell(Spell spell);
17 |
18 | void parseCast(String[] arguments);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/items/BreakageHandler.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.items;
2 |
3 | import org.mafagafogigante.dungeon.game.Game;
4 |
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | /**
8 | * Uninstantiable class that handles item breakage via a handleBreakage(Item) method.
9 | */
10 | final class BreakageHandler {
11 |
12 | private BreakageHandler() {
13 | }
14 |
15 | /**
16 | * Handles an item breakage.
17 | *
18 | * @param item the Item object that just broke, not null, broken
19 | */
20 | public static void handleBreakage(@NotNull Item item) {
21 | if (!item.isBroken()) {
22 | throw new IllegalArgumentException("item should be broken.");
23 | }
24 | if (!item.hasTag(Item.Tag.REPAIRABLE)) {
25 | item.getInventory().removeItem(item);
26 | return; // The Item object will disappear from the game, don't worry about its state.
27 | }
28 | if (item.hasTag(Item.Tag.CLOCK)) {
29 | // A clock just broke! Update its last time record.
30 | item.getClockComponent().setLastTime(Game.getGameState().getWorld().getWorldDate());
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/items/ClockComponent.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.items;
2 |
3 | import org.mafagafogigante.dungeon.date.Date;
4 | import org.mafagafogigante.dungeon.game.Game;
5 | import org.mafagafogigante.dungeon.game.Random;
6 | import org.mafagafogigante.dungeon.io.Version;
7 |
8 | import java.io.Serializable;
9 |
10 | /**
11 | * The clock component.
12 | */
13 | public class ClockComponent implements Serializable {
14 |
15 | private static final long serialVersionUID = Version.MAJOR;
16 | private final Item master;
17 |
18 | /**
19 | * Used to store the date the clock had when it was broken.
20 | */
21 | private Date lastTime;
22 |
23 | ClockComponent(Item master) {
24 | this.master = master;
25 | }
26 |
27 | public void setLastTime(Date lastTime) {
28 | // Create a new Date object so that this field is not affected by changes in the rest of the program.
29 | this.lastTime = lastTime;
30 | }
31 |
32 | /**
33 | * Returns a string that represents a clock reading.
34 | */
35 | public String getTimeString() {
36 | if (master.isBroken()) {
37 | if (lastTime == null) {
38 | if (Random.nextBoolean()) {
39 | return "The clock is pure junk.";
40 | } else {
41 | return "The clock is completely smashed.";
42 | }
43 | } else {
44 | return "The clock is broken. Still, it displays " + lastTime.toTimeString() + ".";
45 | }
46 | } else {
47 | String timeString = Game.getGameState().getWorld().getWorldDate().toTimeString();
48 | return "The clock displays " + timeString + ".";
49 | }
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/items/DrinkableComponent.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.items;
2 |
3 | import org.mafagafogigante.dungeon.entity.creatures.Creature;
4 | import org.mafagafogigante.dungeon.entity.creatures.Effect;
5 | import org.mafagafogigante.dungeon.io.Version;
6 |
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | import java.io.Serializable;
10 | import java.util.List;
11 |
12 | public class DrinkableComponent implements Serializable {
13 |
14 | private static final long serialVersionUID = Version.MAJOR;
15 | private final List effects;
16 | private final int integrityDecrementPerDose;
17 | private int doses;
18 |
19 | DrinkableComponent(List effects, int integrityDecrementPerDose, int doses) {
20 | this.effects = effects;
21 | this.integrityDecrementPerDose = integrityDecrementPerDose;
22 | this.doses = doses;
23 | }
24 |
25 | /**
26 | * Affect a creature with a dose. This automatically decrements the number of remaining doses.
27 | */
28 | public void affect(@NotNull Creature creature) {
29 | if (isDepleted()) {
30 | throw new IllegalStateException("attempted to drink a depleted item");
31 | }
32 | doses--;
33 | for (Effect effect : effects) {
34 | effect.affect(creature);
35 | }
36 | }
37 |
38 | public boolean isDepleted() {
39 | return doses == 0;
40 | }
41 |
42 | int getIntegrityDecrementPerDose() {
43 | return integrityDecrementPerDose;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/items/EnchantmentRules.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.items;
2 |
3 | import org.mafagafogigante.dungeon.game.Id;
4 | import org.mafagafogigante.dungeon.game.Random;
5 | import org.mafagafogigante.dungeon.io.Version;
6 |
7 | import java.io.Serializable;
8 | import java.util.ArrayList;
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 | import java.util.Map.Entry;
13 |
14 | public class EnchantmentRules implements Serializable {
15 |
16 | private static final long serialVersionUID = Version.MAJOR;
17 |
18 | private final Map rules = new HashMap<>();
19 |
20 | public void add(Id id, double probability) {
21 | rules.put(id, probability);
22 | }
23 |
24 | List randomRoll() {
25 | List chosenRules = new ArrayList<>();
26 | for (Entry rule : rules.entrySet()) {
27 | if (Random.roll(rule.getValue())) {
28 | chosenRules.add(rule.getKey());
29 | }
30 | }
31 | return chosenRules;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/items/FoodComponent.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.items;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | import java.io.Serializable;
6 |
7 | /**
8 | * The food component of some items.
9 | */
10 | public class FoodComponent implements Serializable {
11 |
12 | private static final long serialVersionUID = Version.MAJOR;
13 | private final int nutrition;
14 | private final int integrityDecrementOnEat;
15 |
16 | public FoodComponent(int nutrition, int integrityDecrementOnEat) {
17 | this.nutrition = nutrition;
18 | this.integrityDecrementOnEat = integrityDecrementOnEat;
19 | }
20 |
21 | public int getNutrition() {
22 | return nutrition;
23 | }
24 |
25 | public int getIntegrityDecrementOnEat() {
26 | return integrityDecrementOnEat;
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/items/IntegrityState.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.items;
2 |
3 | /**
4 | * IntegrityState enumerated type that defines some constants to humanize the representation of the state of an Item.
5 | */
6 | public enum IntegrityState {
7 |
8 | PERFECT(""),
9 | SLIGHTLY_DAMAGED("Slightly Damaged"),
10 | DAMAGED("Damaged"),
11 | SEVERELY_DAMAGED("Severely Damaged"),
12 | BROKEN("Broken");
13 |
14 | private final String stringRepresentation;
15 |
16 | IntegrityState(String stringRepresentation) {
17 | this.stringRepresentation = stringRepresentation;
18 | }
19 |
20 | /**
21 | * Returns the IntegrityState that corresponds to the specified fraction.
22 | */
23 | public static IntegrityState getIntegrityState(int curIntegrity, int maxIntegrity) {
24 | if (curIntegrity > maxIntegrity) {
25 | throw new IllegalArgumentException("curIntegrity is greater than maxIntegrity.");
26 | } else if (curIntegrity == maxIntegrity) {
27 | return PERFECT;
28 | } else if (curIntegrity >= maxIntegrity * 0.65) {
29 | return SLIGHTLY_DAMAGED;
30 | } else if (curIntegrity >= maxIntegrity * 0.3) {
31 | return DAMAGED;
32 | } else if (curIntegrity > 0) {
33 | return SEVERELY_DAMAGED;
34 | } else {
35 | return BROKEN;
36 | }
37 | }
38 |
39 | @Override
40 | public String toString() {
41 | return stringRepresentation;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/items/ItemFactoryRestrictions.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.items;
2 |
3 | import org.mafagafogigante.dungeon.game.Id;
4 |
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | /**
8 | * Restrictions imposed upon an ItemFactory.
9 | *
10 | * It is of the ItemFactory discretion to call {@code registerItem()} on an ItemFactoryRestriction.
11 | */
12 | interface ItemFactoryRestrictions {
13 |
14 | /**
15 | * Evaluates if an item with the provided Id may be made.
16 | */
17 | boolean canMakeItem(@NotNull Id id);
18 |
19 | /**
20 | * Registers a new Item made by the ItemFactory.
21 | */
22 | void registerItem(@NotNull Id id);
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/items/ItemPresetFactory.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.items;
2 |
3 | import java.util.Collection;
4 |
5 | /**
6 | * A factory of ItemPresets.
7 | */
8 | public interface ItemPresetFactory {
9 | Collection getItemPresets();
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/items/ItemUsageEffect.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.items;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | import java.io.Serializable;
6 |
7 | public class ItemUsageEffect implements Serializable {
8 |
9 | private static final long serialVersionUID = Version.MAJOR;
10 | private final int healing;
11 |
12 | public ItemUsageEffect(int healing) {
13 | this.healing = healing;
14 | }
15 |
16 | public int getHealing() {
17 | return healing;
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/items/LimitedInventory.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.items;
2 |
3 | import org.mafagafogigante.dungeon.entity.Weight;
4 |
5 | interface LimitedInventory {
6 |
7 | int getItemLimit();
8 |
9 | Weight getWeightLimit();
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/items/LocationInventory.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.items;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | /**
6 | * The inventory used by Location objects.
7 | */
8 | public class LocationInventory extends BaseInventory {
9 |
10 | private static final long serialVersionUID = Version.MAJOR;
11 |
12 | public void addItem(Item item) {
13 | items.add(item);
14 | item.setInventory(this);
15 | }
16 |
17 | public void removeItem(Item item) {
18 | items.remove(item);
19 | item.setInventory(null);
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/items/Rarity.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.items;
2 |
3 | import java.awt.Color;
4 |
5 | public enum Rarity {
6 |
7 | POOR("Poor", Palette.POOR), COMMON("Common", Palette.COMMON), UNCOMMON("Uncommon", Palette.UNCOMMON),
8 | RARE("Rare", Palette.RARE), LEGENDARY("Legendary", Palette.LEGENDARY), UNIQUE("Unique", Palette.UNIQUE);
9 |
10 | private final String name;
11 | private final Color color;
12 |
13 | Rarity(String name, Color color) {
14 | this.name = name;
15 | this.color = color;
16 | }
17 |
18 | public String getName() {
19 | return name;
20 | }
21 |
22 | public Color getColor() {
23 | return color;
24 | }
25 |
26 | private static class Palette {
27 | static final Color POOR = new Color(112, 112, 112);
28 | static final Color COMMON = new Color(192, 192, 192);
29 | static final Color UNCOMMON = new Color(30, 255, 0);
30 | static final Color RARE = new Color(0, 112, 255);
31 | static final Color LEGENDARY = new Color(163, 53, 238);
32 | static final Color UNIQUE = new Color(255, 128, 0);
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/entity/items/UniquenessRestrictions.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.items;
2 |
3 | import org.mafagafogigante.dungeon.game.Id;
4 | import org.mafagafogigante.dungeon.io.Version;
5 |
6 | import org.jetbrains.annotations.NotNull;
7 |
8 | import java.io.Serializable;
9 | import java.util.Collection;
10 | import java.util.HashSet;
11 | import java.util.Set;
12 |
13 | /**
14 | * A set of uniqueness restrictions regarding the items produced by a factory.
15 | */
16 | class UniquenessRestrictions implements ItemFactoryRestrictions, Serializable {
17 |
18 | private static final long serialVersionUID = Version.MAJOR;
19 | private final Set uniqueIds;
20 | private final Set alreadyCreatedUniqueIds = new HashSet<>();
21 |
22 | public UniquenessRestrictions(Collection uniqueIds) {
23 | this.uniqueIds = new HashSet<>(uniqueIds);
24 | }
25 |
26 | @Override
27 | public boolean canMakeItem(@NotNull Id id) {
28 | return !alreadyCreatedUniqueIds.contains(id);
29 | }
30 |
31 | @Override
32 | public void registerItem(@NotNull Id id) {
33 | if (uniqueIds.contains(id)) {
34 | if (alreadyCreatedUniqueIds.contains(id)) {
35 | throw new IllegalStateException("Created a unique item again");
36 | }
37 | alreadyCreatedUniqueIds.add(id);
38 | }
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/game/BaseName.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | * BaseName immutable class that stores the singular and plural forms of a name.
11 | */
12 | public final class BaseName extends Name implements Serializable {
13 |
14 | private static final long serialVersionUID = Version.MAJOR;
15 | private final String singular;
16 | private final String plural;
17 |
18 | /**
19 | * Constructs a name based on the specified forms. Names should be created through NameFactory and not through this
20 | * constructor.
21 | *
22 | * @param singular the singular form, not null
23 | * @param plural the plural form, not null
24 | */
25 | BaseName(@NotNull String singular, @NotNull String plural) {
26 | this.singular = singular;
27 | this.plural = plural;
28 | }
29 |
30 | @Override
31 | public String getSingular() {
32 | return singular;
33 | }
34 |
35 | @Override
36 | public String getPlural() {
37 | return plural;
38 | }
39 |
40 | @Override
41 | public boolean equals(Object object) {
42 | if (this == object) {
43 | return true;
44 | }
45 | if (object == null || getClass() != object.getClass()) {
46 | return false;
47 | }
48 |
49 | BaseName name = (BaseName) object;
50 |
51 | return singular.equals(name.singular) && plural.equals(name.plural);
52 | }
53 |
54 | @Override
55 | public int hashCode() {
56 | int result = singular.hashCode();
57 | result = 31 * result + plural.hashCode();
58 | return result;
59 | }
60 |
61 | @Override
62 | public String toString() {
63 | return getSingular();
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/game/BlockedEntrances.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 | import org.mafagafogigante.dungeon.logging.DungeonLogger;
5 | import org.mafagafogigante.dungeon.util.Utils;
6 |
7 | import java.io.Serializable;
8 | import java.util.Arrays;
9 | import java.util.HashSet;
10 | import java.util.Set;
11 |
12 | /**
13 | * BlockedEntrances class that defines a allows blocking the entrances of a Locations.
14 | */
15 | public class BlockedEntrances implements Serializable {
16 |
17 | private static final long serialVersionUID = Version.MAJOR;
18 | private Set setOfBlockedEntrances = new HashSet<>();
19 |
20 | public BlockedEntrances() {
21 | }
22 |
23 | /**
24 | * Copy constructor.
25 | *
26 | * @param source the object to be copied.
27 | */
28 | public BlockedEntrances(BlockedEntrances source) {
29 | setOfBlockedEntrances = new HashSet<>(source.setOfBlockedEntrances);
30 | }
31 |
32 | /**
33 | * Blocks a given direction. Logs a warning if the direction was already blocked.
34 | */
35 | public void block(Direction direction) {
36 | if (isBlocked(direction)) {
37 | DungeonLogger.warning("Tried to block an already blocked direction.");
38 | } else {
39 | setOfBlockedEntrances.add(direction);
40 | }
41 | }
42 |
43 | public boolean isBlocked(Direction direction) {
44 | return setOfBlockedEntrances.contains(direction);
45 | }
46 |
47 | @Override
48 | public String toString() {
49 | if (setOfBlockedEntrances.isEmpty()) {
50 | return "None";
51 | } else {
52 | return Utils.enumerate(Arrays.asList(setOfBlockedEntrances.toArray()));
53 | }
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/game/ColoredString.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | import java.awt.Color;
6 |
7 | /**
8 | * A colored string, this is, a pair of a string and a color.
9 | */
10 | public class ColoredString {
11 |
12 | private final String string;
13 | private final Color color;
14 |
15 | public ColoredString(@NotNull String string, @NotNull Color color) {
16 | this.string = string;
17 | this.color = color;
18 | }
19 |
20 | @NotNull
21 | public String getString() {
22 | return string;
23 | }
24 |
25 | @NotNull
26 | public Color getColor() {
27 | return color;
28 | }
29 |
30 | @Override
31 | public String toString() {
32 | return "ColoredString{" +
33 | "string='" + string + '\'' +
34 | ", color=" + color +
35 | '}';
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/game/Examinable.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | interface Examinable {
6 |
7 | /**
8 | * Retrieves the information available about something.
9 | *
10 | * @return a String, not null
11 | */
12 | @NotNull
13 | String getInfo();
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/game/InstanceInformation.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.mafagafogigante.dungeon.util.Utils;
4 |
5 | /**
6 | * Information about an instance of the game.
7 | */
8 | class InstanceInformation {
9 |
10 | private final long startingTimeMillis;
11 | private int acceptedCommandCount;
12 |
13 | public InstanceInformation() {
14 | this.startingTimeMillis = System.currentTimeMillis();
15 | }
16 |
17 | /**
18 | * Returns a string representing the duration of this instance.
19 | */
20 | public String getDurationString() {
21 | return Utils.makePeriodString(System.currentTimeMillis() - startingTimeMillis);
22 | }
23 |
24 | public int getAcceptedCommandCount() {
25 | return acceptedCommandCount;
26 | }
27 |
28 | public void incrementAcceptedCommandCount() {
29 | this.acceptedCommandCount++;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/game/LocationDescription.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | import java.awt.Color;
8 | import java.io.Serializable;
9 |
10 | /**
11 | * The description of a Location object.
12 | */
13 | public class LocationDescription implements Examinable, Serializable {
14 |
15 | private static final long serialVersionUID = Version.MAJOR;
16 | private final char symbol;
17 | private final Color color;
18 | private String info = "You don't discover anything.";
19 |
20 | public LocationDescription(char symbol, Color color) {
21 | this.symbol = symbol;
22 | this.color = color;
23 | }
24 |
25 | public char getSymbol() {
26 | return symbol;
27 | }
28 |
29 | public Color getColor() {
30 | return color;
31 | }
32 |
33 | @NotNull
34 | @Override
35 | public String getInfo() {
36 | return info;
37 | }
38 |
39 | public void setInfo(String info) {
40 | this.info = info;
41 | }
42 |
43 | @Override
44 | public String toString() {
45 | return "LocationDescription{" +
46 | "symbol=" + symbol +
47 | ", color=" + color +
48 | ", info='" + info + '\'' +
49 | '}';
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/game/MinimumBoundingRectangle.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | import java.io.Serializable;
6 |
7 | public class MinimumBoundingRectangle implements Serializable {
8 |
9 | private static final long serialVersionUID = Version.MAJOR;
10 | private final int width;
11 | private final int height;
12 |
13 | public MinimumBoundingRectangle(int width, int height) {
14 | this.width = width;
15 | this.height = height;
16 | }
17 |
18 | public int getWidth() {
19 | return width;
20 | }
21 |
22 | public int getHeight() {
23 | return height;
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/game/Numeral.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.mafagafogigante.dungeon.logging.DungeonLogger;
4 |
5 | /**
6 | * Numeral enumerated type.
7 | */
8 | public enum Numeral {
9 |
10 | ONE("One"), TWO("Two"), THREE("Three"), FOUR("Four"), FIVE("Five"), MORE_THAN_FIVE("A few");
11 |
12 | final String stringRepresentation;
13 |
14 | Numeral(String stringRepresentation) {
15 | this.stringRepresentation = stringRepresentation;
16 | }
17 |
18 | /**
19 | * Returns a corresponding Numeral of an integer or null if there is not such Numeral.
20 | */
21 | public static Numeral getCorrespondingNumeral(int integer) {
22 | if (integer < 1) {
23 | DungeonLogger.warning("Tried to get nonpositive numeral.");
24 | return null;
25 | } else if (integer >= values().length) {
26 | return values()[values().length - 1];
27 | } else {
28 | return values()[integer - 1];
29 | }
30 | }
31 |
32 | @Override
33 | public String toString() {
34 | return stringRepresentation;
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/game/QuantificationMode.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | /**
4 | * QuantificationMode helper enumerated type.
5 | */
6 | public enum QuantificationMode {
7 |
8 | WORD, NUMBER
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/game/River.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | import java.io.Serializable;
6 |
7 | /**
8 | * River class that implements a river (a line of water in the World).
9 | */
10 | class River implements Serializable {
11 |
12 | private static final long serialVersionUID = Version.MAJOR;
13 | private static final int MIN_BRIDGE_DIST = 4;
14 | private static final int MAX_BRIDGE_DIST = 20;
15 |
16 | private final ExpandableIntegerSet bridges;
17 |
18 | /**
19 | * Make a river.
20 | */
21 | River() {
22 | bridges = new ExpandableIntegerSet(MIN_BRIDGE_DIST, MAX_BRIDGE_DIST);
23 | }
24 |
25 | /**
26 | * Expand the set of bridges towards a value of y until there is a bridge at y or after y.
27 | *
28 | * @param y the y coordinate
29 | */
30 | private void expand(int y) {
31 | bridges.expand(y);
32 | }
33 |
34 | /**
35 | * Evaluates if a given value of y corresponds to a bridge.
36 | *
37 | * @param y the y coordinate
38 | * @return true if there should be a bridge in this y coordinate
39 | */
40 | boolean isBridge(int y) {
41 | expand(y);
42 | return bridges.contains(y);
43 | }
44 |
45 | @Override
46 | public String toString() {
47 | return "River with bridges in " + bridges;
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/game/SpawnerPreset.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.mafagafogigante.dungeon.date.DungeonTimeUnit;
4 |
5 | class SpawnerPreset {
6 |
7 | public final Id id;
8 | public final int minimumPopulation;
9 | public final int maximumPopulation;
10 | public final int spawnDelay;
11 |
12 | /**
13 | * Default SpawnerPreset constructor.
14 | *
15 | * @param id the creature ID string
16 | * @param minimumPopulation the minimum maximum population for spawners
17 | * @param maximumPopulation the maximum maximum population for spawners
18 | * @param delayInHours the spawn delay, in hours
19 | */
20 | public SpawnerPreset(String id, int minimumPopulation, int maximumPopulation, int delayInHours) {
21 | if (minimumPopulation < 1) {
22 | throw new IllegalArgumentException("minimumPopulation must be positive");
23 | }
24 | if (minimumPopulation > maximumPopulation) {
25 | throw new IllegalArgumentException("minimumPopulation must be smaller than or equal to maximumPopulation");
26 | }
27 | this.id = new Id(id);
28 | this.minimumPopulation = minimumPopulation;
29 | this.maximumPopulation = maximumPopulation;
30 | this.spawnDelay = delayInHours * (int) DungeonTimeUnit.HOUR.milliseconds;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/game/Writable.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Defines a single toColoredStringList method that Writer uses to write text to the screen.
7 | */
8 | public abstract class Writable {
9 |
10 | public abstract List toColoredStringList();
11 |
12 | /**
13 | * Converts all writable text of this Writable object to a plain Java String.
14 | */
15 | protected String toJavaString() {
16 | StringBuilder builder = new StringBuilder();
17 | for (ColoredString coloredString : toColoredStringList()) {
18 | builder.append(coloredString.getString());
19 | }
20 | return builder.toString();
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/gui/SharedConstants.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.gui;
2 |
3 | import java.awt.Color;
4 |
5 | /**
6 | * Constants shared among the classes in the gui package.
7 | */
8 | final class SharedConstants {
9 |
10 | static final Color MARGIN_COLOR = Color.BLACK;
11 | static final Color INSIDE_COLOR = new Color(20, 20, 20);
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/gui/WritingSpecifications.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.gui;
2 |
3 | import org.mafagafogigante.dungeon.util.NonNegativeInteger;
4 |
5 | /**
6 | * A series of specifications for a text pane write.
7 | */
8 | public final class WritingSpecifications {
9 |
10 | private final boolean scrollDown;
11 | private final NonNegativeInteger wait;
12 |
13 | /**
14 | * Constructs a new WritingSpecifications object.
15 | *
16 | * @param scrollDown if the pane should scroll down
17 | * @param wait how many milliseconds the application should wait before returning, nonnegative
18 | */
19 | public WritingSpecifications(boolean scrollDown, int wait) {
20 | this.scrollDown = scrollDown;
21 | this.wait = new NonNegativeInteger(wait);
22 | }
23 |
24 | boolean shouldScrollDown() {
25 | return scrollDown;
26 | }
27 |
28 | public boolean shouldWait() {
29 | return getWait() != 0;
30 | }
31 |
32 | public int getWait() {
33 | return wait.toInteger();
34 | }
35 |
36 | @Override
37 | public String toString() {
38 | return "WritingSpecifications{scrollDown=" + scrollDown + "}";
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/io/Converter.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | /**
4 | * Uninstantiable Converter class that defines methods for IO related data conversion.
5 | */
6 | public class Converter {
7 |
8 | private Converter() {
9 | throw new AssertionError();
10 | }
11 |
12 | /**
13 | * Converts a given number of bytes to a human readable format.
14 | *
15 | * @return a String
16 | */
17 | public static String bytesToHuman(long bytes) {
18 | if (bytes < 1024) {
19 | return bytes + " B";
20 | }
21 | // 2 ^ 10 (1 KiB) has (63 - 10) = 53 leading zeros.
22 | // 2 ^ 20 (1 MiB) has (63 - 20) = 43 leading zeros.
23 | // And so forth.
24 | // Bits used to represent the number of bytes = number of bits available - number of leading zeros.
25 | int bitsUsed = 63 - Long.numberOfLeadingZeros(bytes);
26 | // (1L << (bitsUsed - bitsUsed % 10)) shifts the one (in binary) to the left by a multiple of 10.
27 | // This is a fast way to get the power of 1024 by which we must divide the number of bytes.
28 | double significand = (double) bytes / (1L << (bitsUsed - bitsUsed % 10));
29 | // By dividing the number of bits used by 10, get the prefix that should be used.
30 | // Subtract one as Strings are zero indexed.
31 | char prefix = "KMGTPE".charAt(bitsUsed / 10 - 1);
32 | return String.format("%.1f %siB", significand, prefix);
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/io/DungeonCharset.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | import java.nio.charset.Charset;
4 |
5 | class DungeonCharset {
6 |
7 | static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/io/DungeonFilenameFilters.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | import java.io.File;
4 | import java.io.FilenameFilter;
5 |
6 | /**
7 | * This class provides getters for FilenameFilter implementations used by the application for input and output.
8 | */
9 | final class DungeonFilenameFilters {
10 |
11 | private static final FilenameFilter extensionFilter = new FilenameFilter() {
12 | @Override
13 | public boolean accept(File dir, String name) {
14 | return name.endsWith(".dungeon");
15 | }
16 | };
17 |
18 | private DungeonFilenameFilters() {
19 | throw new AssertionError();
20 | }
21 |
22 | public static FilenameFilter getExtensionFilter() {
23 | return extensionFilter;
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/io/DungeonResource.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | public enum DungeonResource {
4 |
5 | ACHIEVEMENTS("achievements.json"), CREATURES("creatures.json"), DREAMS("dreams.json"),
6 | ENCHANTMENTS("enchantments.json"), HINTS("hints.json"), ITEMS("items.json"), LOCATIONS("locations.json"),
7 | POEMS("poems.json"), PREFACE("preface.json"), TUTORIAL("tutorial.json"), WIKI("wiki.json");
8 |
9 | private static final long serialVersionUID = Version.MAJOR;
10 |
11 | private final String filename;
12 |
13 | DungeonResource(String filename) {
14 | this.filename = filename;
15 | }
16 |
17 | String getFilename() {
18 | return filename;
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/io/FileLastModifiedComparator.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | import java.io.File;
4 | import java.io.Serializable;
5 | import java.util.Comparator;
6 |
7 | /**
8 | * A Comparator function that compares the last modification times of Files. This comparator orders files from newest to
9 | * oldest, which is, in terms of last modified timestamps, from largest to smallest.
10 | *
11 | * This is not consistent with equals.
12 | *
13 | *
Serializable is not implemented by design. This Comparator was devised to be used by Arrays.sort and nothing
14 | * else.
15 | */
16 | class FileLastModifiedComparator implements Comparator, Serializable {
17 |
18 | private static final long serialVersionUID = Version.MAJOR;
19 |
20 | @Override
21 | public int compare(File left, File right) {
22 | return Long.compare(right.lastModified(), left.lastModified());
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/io/JsonObjectFactory.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | import com.eclipsesource.json.Json;
4 | import com.eclipsesource.json.JsonObject;
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | import java.io.IOException;
8 | import java.io.Reader;
9 |
10 | public class JsonObjectFactory {
11 |
12 | private static final String JSON_EXTENSION = ".json";
13 |
14 | /**
15 | * Makes a new JsonObject from the resource file pointed to by the specified filename.
16 | *
17 | * @param filename the name of the JSON file, must end with .json, not null
18 | * @return a JsonObject that reads from the specified file
19 | * @throws IllegalFilenameExtensionException if the provided filename does not end with .json
20 | */
21 | public static JsonObject makeJsonObject(@NotNull String filename) {
22 | if (!filename.endsWith(JSON_EXTENSION)) {
23 | throw new IllegalFilenameExtensionException("filename must end with " + JSON_EXTENSION + ".");
24 | }
25 | // Using a BufferedReader here does not improve performance as the library is already buffered.
26 | try (Reader reader = ResourceStreamFactory.getInputStreamReader(filename)) {
27 | return Json.parse(reader).asObject();
28 | } catch (IOException fatal) {
29 | throw new RuntimeException(fatal);
30 | }
31 | }
32 |
33 | public static class IllegalFilenameExtensionException extends IllegalArgumentException {
34 |
35 | IllegalFilenameExtensionException(@NotNull String string) {
36 | super(string);
37 | }
38 |
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/io/ResourceNameResolver.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | public class ResourceNameResolver {
6 |
7 | private ResourceNameResolver() {
8 | }
9 |
10 | public static String resolveName(@NotNull DungeonResource resource) {
11 | return resource.getFilename();
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/io/ResourceStreamFactory.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | import java.io.InputStreamReader;
4 |
5 | class ResourceStreamFactory {
6 |
7 | private static final ClassLoader CLASS_LOADER = Thread.currentThread().getContextClassLoader();
8 |
9 | static InputStreamReader getInputStreamReader(String name) {
10 | return new InputStreamReader(CLASS_LOADER.getResourceAsStream(name), DungeonCharset.DEFAULT_CHARSET);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/io/Sleeper.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | import org.mafagafogigante.dungeon.logging.DungeonLogger;
4 |
5 | /**
6 | * Sleeper class that handles Thread sleeping.
7 | */
8 | public final class Sleeper {
9 |
10 | private static final int MILLISECONDS_IN_MINUTE = 60000;
11 |
12 | private Sleeper() {
13 | throw new AssertionError();
14 | }
15 |
16 | /**
17 | * Sleeps for a specified amount of milliseconds.
18 | *
19 | * @param milliseconds how many milliseconds should this thread sleep for, between 1 and 60000
20 | */
21 | public static void sleep(long milliseconds) {
22 | if (milliseconds <= 0) {
23 | DungeonLogger.warning("Tried to sleep a nonpositive amount of milliseconds.");
24 | } else if (milliseconds > MILLISECONDS_IN_MINUTE) {
25 | DungeonLogger.warning("Tried to sleep for more than a minute.");
26 | } else { // If milliseconds is in range, sleep.
27 | try {
28 | Thread.sleep(milliseconds);
29 | } catch (InterruptedException logged) {
30 | DungeonLogger.warning("Sleeper was interrupted.");
31 | }
32 | }
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/io/Split.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | import java.util.Collections;
4 | import java.util.List;
5 |
6 | /**
7 | * The result of a split operation. Has two lists - before and after - that contain the tokens before the split and
8 | * after the split, respectively.
9 | */
10 | public final class Split {
11 |
12 | private final List before;
13 | private final List after;
14 |
15 | private Split(List before, List after) {
16 | this.before = before;
17 | this.after = after;
18 | }
19 |
20 | /**
21 | * Splits a List of tokens into two lists. The first of which will contain all the tokens that appeared before the
22 | * first "on" occurrence and whose second list will have all tokens that appeared after this "on" token.
23 | */
24 | public static Split splitOnOn(List tokens) {
25 | int separator = tokens.indexOf("on");
26 | if (separator != -1) {
27 | return new Split(tokens.subList(0, separator), tokens.subList(separator + 1, tokens.size()));
28 | } else {
29 | return new Split(tokens, Collections.emptyList());
30 | }
31 | }
32 |
33 | public List getBefore() {
34 | return before;
35 | }
36 |
37 | public List getAfter() {
38 | return after;
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/io/TagSetParser.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | import org.mafagafogigante.dungeon.entity.TagSet;
4 | import org.mafagafogigante.dungeon.entity.TagSet.InvalidTagException;
5 |
6 | import com.eclipsesource.json.JsonValue;
7 |
8 | /**
9 | * A parser for TagSets from JSON objects.
10 | */
11 | public class TagSetParser> {
12 |
13 | private final Class enumClass;
14 | private final JsonValue jsonValue;
15 |
16 | /**
17 | * Creates a TagSetParser for a JsonObject which must be either null or a JsonArray of uppercase strings.
18 | */
19 | public TagSetParser(Class enumClass, JsonValue jsonValue) {
20 | this.enumClass = enumClass;
21 | this.jsonValue = jsonValue;
22 | }
23 |
24 | /**
25 | * Effectively parses the JsonValue and produces a TagSet.
26 | */
27 | public TagSet parse() {
28 | TagSet tagSet = TagSet.makeEmptyTagSet(enumClass);
29 | if (jsonValue != null) {
30 | if (jsonValue.isArray()) {
31 | for (JsonValue value : jsonValue.asArray()) {
32 | if (value.isString()) {
33 | String tag = value.asString();
34 | try {
35 | tagSet.addTag(Enum.valueOf(enumClass, tag));
36 | } catch (IllegalArgumentException fatal) {
37 | // Guarantee that bugged resource files are not going to make it to a release.
38 | String message = "invalid tag '" + tag + "' found.";
39 | throw new InvalidTagException(message, fatal);
40 | }
41 | } else {
42 | throw new InvalidTagException("tag value is not a string.");
43 | }
44 | }
45 | } else {
46 | throw new InvalidTagException("JsonObject is neither null or an array");
47 | }
48 | }
49 | return tagSet;
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/io/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Handles all Input and Output functionality, such as loading and saving games, loading JSON data, and writing to the
3 | * screen.
4 | */
5 |
6 | package org.mafagafogigante.dungeon.io;
7 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/logging/DungeonFormatter.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.logging;
2 |
3 | import java.text.SimpleDateFormat;
4 | import java.util.logging.Formatter;
5 | import java.util.logging.LogRecord;
6 |
7 | /**
8 | * The Formatter used by the Logger to pretty format dates.
9 | */
10 | class DungeonFormatter extends Formatter {
11 |
12 | private static final String LINE_SEPARATOR = System.lineSeparator();
13 |
14 | @Override
15 | public String format(LogRecord record) {
16 | final SimpleDateFormat timestampFormat = new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss]");
17 | String timestamp = timestampFormat.format(record.getMillis());
18 | return timestamp + " (" + record.getLevel() + "): " + record.getMessage() + LINE_SEPARATOR;
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/logging/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Provides the DungeonLogger class that should be used throughout the application to log events.
3 | */
4 |
5 | package org.mafagafogigante.dungeon.logging;
6 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/map/IterationLimits.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.map;
2 |
3 | import org.mafagafogigante.dungeon.game.Point;
4 |
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | class IterationLimits {
8 |
9 | final int minX;
10 | final int maxX;
11 | final int minY;
12 | final int maxY;
13 |
14 | /**
15 | * Constructs new iteration limits based on the center of the map, the number of columns and the number of rows.
16 | *
17 | * @param center the Point at the center of the map, not null
18 | * @param rows the number of rows
19 | */
20 | IterationLimits(@NotNull Point center, int rows, int columns) {
21 | minX = center.getX() - (columns - 1) / 2;
22 | maxX = minX + columns - 1;
23 | minY = center.getY() + (rows - 1) / 2;
24 | maxY = minY - rows + 1;
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/map/WorldMapSymbolFactory.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.map;
2 |
3 | import org.mafagafogigante.dungeon.game.Point;
4 | import org.mafagafogigante.dungeon.game.World;
5 | import org.mafagafogigante.dungeon.stats.ExplorationStatistics;
6 |
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | final class WorldMapSymbolFactory {
10 |
11 | private final World world;
12 | private final Point heroPosition;
13 | private final ExplorationStatistics explorationStatistics;
14 |
15 | /**
16 | * Constructs a new WorldMapSymbolFactory for the specified World and Hero position. All locations will have their
17 | * symbols revealed.
18 | */
19 | WorldMapSymbolFactory(World world, Point heroPosition) {
20 | this.world = world;
21 | this.heroPosition = heroPosition;
22 | this.explorationStatistics = null;
23 | }
24 |
25 | /**
26 | * Constructs a new WorldMapSymbolFactory for the specified World and Hero position. Just the locations that the
27 | * player has already seen will have their symbols revealed.
28 | */
29 | WorldMapSymbolFactory(World world, Point heroPosition, @NotNull ExplorationStatistics explorationStatistics) {
30 | this.world = world;
31 | this.heroPosition = heroPosition;
32 | this.explorationStatistics = explorationStatistics;
33 | }
34 |
35 | WorldMapSymbol getSymbol(Point position) {
36 | if (position.equals(heroPosition)) {
37 | return WorldMapSymbol.getHeroSymbol();
38 | } else if (explorationStatistics == null || explorationStatistics.hasBeenSeen(position)) {
39 | return WorldMapSymbol.makeSymbol(world.getLocation(position));
40 | } else {
41 | return WorldMapSymbol.getNotYetGeneratedSymbol();
42 | }
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/map/WorldMapWriter.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.map;
2 |
3 | import org.mafagafogigante.dungeon.game.DungeonString;
4 | import org.mafagafogigante.dungeon.gui.GameWindow;
5 | import org.mafagafogigante.dungeon.io.Writer;
6 |
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | public final class WorldMapWriter {
10 |
11 | private WorldMapWriter() {
12 | throw new AssertionError();
13 | }
14 |
15 | public static void writeMap() {
16 | renderMap(WorldMap.makeWorldMap(getMapRows(), getMapColumns(), true));
17 | }
18 |
19 | public static void writeDebugMap() {
20 | renderMap(WorldMap.makeWorldMap(getMapRows(), getMapColumns(), false));
21 | }
22 |
23 | private static int getMapRows() {
24 | return GameWindow.getRows() - 1;
25 | }
26 |
27 | private static int getMapColumns() {
28 | return GameWindow.getColumns();
29 | }
30 |
31 | /**
32 | * Writes a WorldMap to the screen. This erases all the content currently on the screen.
33 | *
34 | * @param map a WorldMap, not null
35 | */
36 | private static void renderMap(@NotNull WorldMap map) {
37 | DungeonString string = new DungeonString();
38 | WorldMapSymbol[][] worldMapSymbolMatrix = map.getSymbolMatrix();
39 | for (int i = 1; i < worldMapSymbolMatrix.length - 1; i++) {
40 | for (WorldMapSymbol symbol : worldMapSymbolMatrix[i]) {
41 | // OK as setColor verifies if the color change is necessary (does not replace a color by itself).
42 | string.setColor(symbol.getColor());
43 | string.append(symbol.getCharacterAsString());
44 | }
45 | if (i < worldMapSymbolMatrix.length - 1) {
46 | string.append("\n");
47 | }
48 | }
49 | WorldMapLegend.renderLegend(worldMapSymbolMatrix, string);
50 | Writer.write(string);
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/JsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema;
2 |
3 | import com.eclipsesource.json.JsonValue;
4 |
5 | /**
6 | * Interface for JSON value validation rules.
7 | */
8 | public interface JsonRule {
9 |
10 | /**
11 | * Validates the provided JSON value.
12 | */
13 | void validate(JsonValue value);
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/ArrayJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.JsonValue;
6 |
7 | class ArrayJsonRule implements JsonRule {
8 |
9 | @Override
10 | public void validate(JsonValue value) {
11 | if (!value.isArray()) {
12 | throw new IllegalArgumentException(value + " is not an array.");
13 | }
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/ArraySizeJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import com.eclipsesource.json.JsonArray;
4 | import com.eclipsesource.json.JsonValue;
5 |
6 | class ArraySizeJsonRule extends ArrayJsonRule {
7 |
8 | private final int arraySize;
9 |
10 | ArraySizeJsonRule(int arraySize) {
11 | this.arraySize = arraySize;
12 | }
13 |
14 | @Override
15 | public void validate(JsonValue value) {
16 | super.validate(value);
17 | JsonArray jsonArray = value.asArray();
18 | if (jsonArray.size() != arraySize) {
19 | throw new IllegalArgumentException(jsonArray + " size is not valid.");
20 | }
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/BooleanJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.JsonValue;
6 |
7 | class BooleanJsonRule implements JsonRule {
8 |
9 | @Override
10 | public void validate(JsonValue value) {
11 | if (!value.isBoolean()) {
12 | throw new IllegalArgumentException(value + " is not a boolean.");
13 | }
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/BoundDoubleJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import com.eclipsesource.json.JsonValue;
4 |
5 | final class BoundDoubleJsonRule extends DoubleJsonRule {
6 |
7 | private final double minValue;
8 | private final double maxValue;
9 |
10 | BoundDoubleJsonRule(double minValue, double maxValue) {
11 | this.minValue = minValue;
12 | this.maxValue = maxValue;
13 | }
14 |
15 | @Override
16 | public void validate(JsonValue value) {
17 | super.validate(value);
18 | double doubleValue = value.asDouble();
19 | if (doubleValue < minValue) {
20 | throw new IllegalArgumentException(value + " is below the allowed minimum " + minValue + ".");
21 | }
22 | if (doubleValue > maxValue) {
23 | throw new IllegalArgumentException(value + " is above the allowed maximum " + maxValue + ".");
24 | }
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/BoundIntegerJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import com.eclipsesource.json.JsonValue;
4 |
5 | final class BoundIntegerJsonRule extends IntegerJsonRule {
6 |
7 | private final int minValue;
8 | private final int maxValue;
9 |
10 | BoundIntegerJsonRule(int minValue, int maxValue) {
11 | this.minValue = minValue;
12 | this.maxValue = maxValue;
13 | }
14 |
15 | @Override
16 | public void validate(JsonValue value) {
17 | super.validate(value);
18 | int intValue = value.asInt();
19 | if (intValue < minValue) {
20 | throw new IllegalArgumentException(value + " is below the allowed minimum of " + minValue);
21 | }
22 | if (intValue > maxValue) {
23 | throw new IllegalArgumentException(value + " is above the allowed maximum of " + maxValue);
24 | }
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/DoubleJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import com.eclipsesource.json.JsonValue;
4 |
5 | class DoubleJsonRule extends NumberJsonRule {
6 |
7 | @Override
8 | public void validate(JsonValue value) {
9 | super.validate(value);
10 | value.asDouble();
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/EmptyRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.JsonValue;
6 |
7 | final class EmptyRule implements JsonRule {
8 |
9 | @Override
10 | public void validate(JsonValue value) {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/EnumJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import com.eclipsesource.json.JsonValue;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | import java.util.HashSet;
7 | import java.util.Set;
8 |
9 | class EnumJsonRule> extends StringJsonRule {
10 |
11 | private final Set enumValues = new HashSet<>();
12 |
13 | EnumJsonRule(@NotNull Class enumClass) {
14 | if (!enumClass.isEnum()) {
15 | throw new IllegalArgumentException();
16 | }
17 | T[] enumConstants = enumClass.getEnumConstants();
18 | if (enumConstants == null) {
19 | throw new IllegalArgumentException();
20 | }
21 | for (Enum enumConstant : enumConstants) {
22 | enumValues.add(enumConstant.toString());
23 | }
24 | }
25 |
26 | @Override
27 | public void validate(JsonValue value) {
28 | super.validate(value);
29 | String valueAsString = value.asString();
30 | if (!enumValues.contains(valueAsString)) {
31 | throw new IllegalArgumentException(valueAsString + " is not a valid enum value.");
32 | }
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/FixedArrayJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.JsonArray;
6 | import com.eclipsesource.json.JsonValue;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | class FixedArrayJsonRule extends ArrayJsonRule {
12 |
13 | private final List rules;
14 |
15 | FixedArrayJsonRule(List rules) {
16 | this.rules = new ArrayList<>(rules);
17 | }
18 |
19 | @Override
20 | public void validate(JsonValue value) {
21 | super.validate(value);
22 | JsonArray array = value.asArray();
23 | if (rules.size() != array.size()) {
24 | throw new IllegalArgumentException("Array is not of the right size.");
25 | }
26 | for (int i = 0; i < rules.size(); i++) {
27 | rules.get(i).validate(array.values().get(i));
28 | }
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/GroupJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.JsonValue;
6 |
7 | import java.util.Arrays;
8 | import java.util.List;
9 |
10 | class GroupJsonRule implements JsonRule {
11 |
12 | private final List rules;
13 |
14 | GroupJsonRule(JsonRule... rules) {
15 | this.rules = Arrays.asList(rules);
16 | }
17 |
18 | @Override
19 | public void validate(JsonValue value) {
20 | for (JsonRule rule : rules) {
21 | rule.validate(value);
22 | }
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/IdJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.game.Id;
4 |
5 | import com.eclipsesource.json.JsonValue;
6 |
7 | class IdJsonRule extends StringJsonRule {
8 |
9 | @Override
10 | public void validate(JsonValue value) {
11 | super.validate(value);
12 | try {
13 | new Id(value.asString());
14 | } catch (IllegalArgumentException invalidValue) {
15 | throw new IllegalArgumentException(value + " is not a valid Dungeon id.");
16 | }
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/IdSetJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.game.Id;
4 |
5 | import com.eclipsesource.json.JsonValue;
6 | import org.jetbrains.annotations.NotNull;
7 |
8 | import java.util.Collection;
9 | import java.util.HashSet;
10 | import java.util.List;
11 | import java.util.Set;
12 |
13 | public class IdSetJsonRule extends StringJsonRule {
14 |
15 | private final Set idSet;
16 |
17 | IdSetJsonRule(@NotNull Collection ids) {
18 | idSet = new HashSet<>(ids);
19 | }
20 |
21 | @Override
22 | public void validate(JsonValue value) {
23 | super.validate(value);
24 | try {
25 | Id id = new Id(value.asString());
26 | if (!idSet.contains(id)) {
27 | throw new IllegalArgumentException(value + " is not in the set of valid ids.");
28 | }
29 | } catch (IllegalArgumentException invalidValue) {
30 | throw new IllegalArgumentException(value + " is not a valid Dungeon id.");
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/IntegerJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import com.eclipsesource.json.JsonValue;
4 |
5 | class IntegerJsonRule extends NumberJsonRule {
6 |
7 | @Override
8 | public void validate(JsonValue value) {
9 | super.validate(value);
10 | try {
11 | value.asInt();
12 | } catch (NumberFormatException exception) {
13 | throw new IllegalArgumentException(value + " is not an integer.");
14 | }
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/NumberJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.JsonValue;
6 |
7 | class NumberJsonRule implements JsonRule {
8 |
9 | @Override
10 | public void validate(JsonValue value) {
11 | if (!value.isNumber()) {
12 | throw new IllegalArgumentException(value + " is not a number.");
13 | }
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/ObjectJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.JsonObject;
6 | import com.eclipsesource.json.JsonValue;
7 |
8 | import java.util.HashSet;
9 | import java.util.Map;
10 | import java.util.Map.Entry;
11 | import java.util.Set;
12 |
13 | class ObjectJsonRule implements JsonRule {
14 |
15 | private final Map rules;
16 |
17 | ObjectJsonRule(Map rules) {
18 | this.rules = rules;
19 | }
20 |
21 | @Override
22 | public void validate(JsonValue value) {
23 | if (!value.isObject()) {
24 | throw new IllegalArgumentException(value + " is not an object.");
25 | }
26 | JsonObject object = value.asObject();
27 | Set names = new HashSet<>(object.names());
28 | for (Entry entry : rules.entrySet()) {
29 | entry.getValue().validate(object.get(entry.getKey()));
30 | names.remove(entry.getKey());
31 | }
32 | if (!names.isEmpty()) {
33 | throw new IllegalArgumentException(String.format("%s does not have a rule.", names.iterator().next()));
34 | }
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/OptionalJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.JsonValue;
6 |
7 | class OptionalJsonRule implements JsonRule {
8 |
9 | private final JsonRule rule;
10 |
11 | OptionalJsonRule(JsonRule rule) {
12 | this.rule = rule;
13 | }
14 |
15 | @Override
16 | public void validate(JsonValue value) {
17 | if (value != null) {
18 | rule.validate(value);
19 | }
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/PercentageJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.util.Percentage;
4 |
5 | import com.eclipsesource.json.JsonValue;
6 |
7 | class PercentageJsonRule extends StringJsonRule {
8 |
9 | @Override
10 | public void validate(JsonValue value) {
11 | super.validate(value);
12 | try {
13 | Percentage.fromString(value.asString());
14 | } catch (IllegalArgumentException invalidValue) {
15 | throw new IllegalArgumentException(value + " is not a valid Dungeon percentage.");
16 | }
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/PeriodJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.date.DungeonTimeParser;
4 |
5 | import com.eclipsesource.json.JsonValue;
6 |
7 | class PeriodJsonRule extends StringJsonRule {
8 |
9 | @Override
10 | public void validate(JsonValue value) {
11 | super.validate(value);
12 | try {
13 | DungeonTimeParser.parseDuration(value.asString());
14 | } catch (IllegalArgumentException invalidValue) {
15 | throw new IllegalArgumentException(value + " is not a valid Dungeon period.");
16 | }
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/StringJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.JsonValue;
6 |
7 | class StringJsonRule implements JsonRule {
8 |
9 | @Override
10 | public void validate(JsonValue value) {
11 | if (!value.isString()) {
12 | throw new IllegalArgumentException(value + " is not a string.");
13 | }
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/StringLengthJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import com.eclipsesource.json.JsonValue;
4 |
5 | class StringLengthJsonRule extends StringJsonRule {
6 |
7 | private final int stringLength;
8 |
9 | StringLengthJsonRule(int stringLength) {
10 | this.stringLength = stringLength;
11 | }
12 |
13 | @Override
14 | public void validate(JsonValue value) {
15 | super.validate(value);
16 | String stringValue = value.asString();
17 | if (stringValue.length() < stringLength) {
18 | throw new IllegalArgumentException(value + " is below the allowed minimum of " + stringLength);
19 | }
20 | if (stringValue.length() > stringLength) {
21 | throw new IllegalArgumentException(value + " is above the allowed maximum of " + stringLength);
22 | }
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/UppercaseStringJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import com.eclipsesource.json.JsonValue;
4 | import org.apache.commons.lang3.StringUtils;
5 |
6 | final class UppercaseStringJsonRule extends StringJsonRule {
7 |
8 | @Override
9 | public void validate(JsonValue value) {
10 | super.validate(value);
11 | if (!StringUtils.isAllUpperCase(value.asString())) {
12 | throw new IllegalArgumentException(value + " is not uppercase.");
13 | }
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/schema/rules/VariableArrayJsonRule.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.JsonArray;
6 | import com.eclipsesource.json.JsonValue;
7 |
8 | class VariableArrayJsonRule extends ArrayJsonRule {
9 |
10 | private final JsonRule rule;
11 |
12 | VariableArrayJsonRule(JsonRule rule) {
13 | this.rule = rule;
14 | }
15 |
16 | @Override
17 | public void validate(JsonValue value) {
18 | super.validate(value);
19 | JsonArray array = value.asArray();
20 | for (JsonValue arrayValue : array.values()) {
21 | rule.validate(arrayValue);
22 | }
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/spells/Spell.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.spells;
2 |
3 | import org.mafagafogigante.dungeon.entity.creatures.Hero;
4 | import org.mafagafogigante.dungeon.game.Id;
5 | import org.mafagafogigante.dungeon.game.Name;
6 | import org.mafagafogigante.dungeon.io.Version;
7 | import org.mafagafogigante.dungeon.util.Selectable;
8 |
9 | import java.io.Serializable;
10 |
11 | /**
12 | * The class that represents a spell.
13 | */
14 | public abstract class Spell implements Selectable, Serializable {
15 |
16 | private static final long serialVersionUID = Version.MAJOR;
17 | private final SpellDefinition definition;
18 |
19 | Spell(String id, String name) {
20 | this.definition = new SpellDefinition(id, name);
21 | }
22 |
23 | public abstract void operate(Hero hero, String[] targetMatcher);
24 |
25 | public Id getId() {
26 | return definition.id; // Delegate to SpellDefinition.
27 | }
28 |
29 | @Override
30 | public Name getName() {
31 | return definition.name; // Delegate to SpellDefinition.
32 | }
33 |
34 | @Override
35 | public boolean equals(Object object) {
36 | if (this == object) {
37 | return true;
38 | }
39 | if (object == null || getClass() != object.getClass()) {
40 | return false;
41 | }
42 | Spell spell = (Spell) object;
43 | return definition.equals(spell.definition);
44 | }
45 |
46 | @Override
47 | public int hashCode() {
48 | return definition.hashCode();
49 | }
50 |
51 | @Override
52 | public String toString() {
53 | return getName().getSingular();
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/spells/SpellDefinition.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.spells;
2 |
3 | import org.mafagafogigante.dungeon.game.Id;
4 | import org.mafagafogigante.dungeon.game.Name;
5 | import org.mafagafogigante.dungeon.game.NameFactory;
6 | import org.mafagafogigante.dungeon.io.Version;
7 |
8 | import java.io.Serializable;
9 |
10 | /**
11 | * SpellDefinition class that contains immutable data that may be shared by multiple Spell objects.
12 | *
13 | * Equality is tested based on the Id field.
14 | */
15 | final class SpellDefinition implements Serializable {
16 |
17 | private static final long serialVersionUID = Version.MAJOR;
18 | public final Id id;
19 | // Use a name because in the future we may want to write stuff like "you casted 10 fireballs so far."
20 | public final Name name;
21 |
22 | SpellDefinition(String id, String name) {
23 | this.id = new Id(id);
24 | this.name = NameFactory.newInstance(name);
25 | }
26 |
27 | @Override
28 | public boolean equals(Object object) {
29 | if (this == object) {
30 | return true;
31 | }
32 | if (object == null || getClass() != object.getClass()) {
33 | return false;
34 | }
35 | SpellDefinition that = (SpellDefinition) object;
36 | return id.equals(that.id);
37 | }
38 |
39 | @Override
40 | public int hashCode() {
41 | return id.hashCode();
42 | }
43 |
44 | @Override
45 | public String toString() {
46 | return "SpellDefinition{" + "id=" + id + ", name=" + name + '}';
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/stats/CommandStatistics.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.stats;
2 |
3 | import org.mafagafogigante.dungeon.commands.IssuedCommand;
4 | import org.mafagafogigante.dungeon.io.Version;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * CommandStatistics class that is a component of Statistics.
10 | */
11 | final class CommandStatistics implements Serializable {
12 |
13 | private static final long serialVersionUID = Version.MAJOR;
14 | private int commands;
15 | private int chars;
16 | private int words;
17 |
18 | /**
19 | * Adds an issued command to the statistics.
20 | *
21 | * @param issuedCommand the command to be added.
22 | */
23 | public void addCommand(IssuedCommand issuedCommand) {
24 | commands++;
25 | words += issuedCommand.getTokens().size();
26 | for (char c : issuedCommand.getStringRepresentation().toCharArray()) {
27 | if (!Character.isWhitespace(c)) {
28 | chars++;
29 | }
30 | }
31 | }
32 |
33 | /**
34 | * Returns how many commands the user has issued so far.
35 | *
36 | * @return the command count
37 | */
38 | public int getCommandCount() {
39 | return commands;
40 | }
41 |
42 | /**
43 | * Returns how many printable characters the user has entered so far.
44 | *
45 | * @return the character count
46 | */
47 | public int getChars() {
48 | return chars;
49 | }
50 |
51 | /**
52 | * Returns how many words the user has entered so far.
53 | *
54 | * @return the word count
55 | */
56 | public int getWords() {
57 | return words;
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/stats/ExplorationStatisticsEntry.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.stats;
2 |
3 | import org.mafagafogigante.dungeon.date.Date;
4 | import org.mafagafogigante.dungeon.game.Id;
5 | import org.mafagafogigante.dungeon.game.PartOfDay;
6 | import org.mafagafogigante.dungeon.io.Version;
7 |
8 | import java.io.Serializable;
9 |
10 | /**
11 | * An ExplorationLog entry that stores data relative to one Point.
12 | */
13 | class ExplorationStatisticsEntry implements Serializable {
14 |
15 | private static final long serialVersionUID = Version.MAJOR;
16 | private final Id locationId;
17 | private Date discoveredDate;
18 | private int visitCount;
19 | private int killCount;
20 |
21 | public ExplorationStatisticsEntry(Id locationId, Date discoveredDate) {
22 | this.locationId = locationId;
23 | this.discoveredDate = discoveredDate;
24 | }
25 |
26 | public Id getLocationId() {
27 | return locationId;
28 | }
29 |
30 | public Date getDiscoveredDate() {
31 | return discoveredDate;
32 | }
33 |
34 | /**
35 | * Returns how many times the Hero visited this Point.
36 | */
37 | public int getVisitCount() {
38 | return visitCount;
39 | }
40 |
41 | public void addVisit() {
42 | this.visitCount++;
43 | }
44 |
45 | /**
46 | * Returns how many times the Hero killed in this Point.
47 | */
48 | public int getKillCount() {
49 | return killCount;
50 | }
51 |
52 | public void addKill() {
53 | this.killCount++;
54 | }
55 |
56 | @Override
57 | public String toString() {
58 | String format = "ExplorationStatisticsEntry{locationId=%s, visitCount=%d, killCount=%d, discoveredDate=%s}";
59 | return String.format(format, locationId, visitCount, killCount, discoveredDate);
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/stats/HeroStatistics.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.stats;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | import java.io.Serializable;
6 |
7 | /**
8 | * HeroStatistics class that tracks the Hero's statistics.
9 | */
10 | public final class HeroStatistics implements Serializable {
11 |
12 | private static final long serialVersionUID = Version.MAJOR;
13 |
14 | private long healingThroughEating;
15 | private long damageInflicted;
16 | private long damageTaken;
17 | private long sleepingTime;
18 | private long restingTime;
19 |
20 | public void incrementHealingThroughEating(long healing) {
21 | healingThroughEating += healing;
22 | }
23 |
24 | public void incrementDamageInflicted(long damage) {
25 | damageInflicted += damage;
26 | }
27 |
28 | public void incrementDamageTaken(long damage) {
29 | damageTaken += damage;
30 | }
31 |
32 | public void incrementSleepingTime(long seconds) {
33 | sleepingTime += 1000L * seconds;
34 | }
35 |
36 | public void incrementRestingTime(long seconds) {
37 | restingTime += 1000L * seconds;
38 | }
39 |
40 | long getHealingThroughEating() {
41 | return healingThroughEating;
42 | }
43 |
44 | long getDamageInflicted() {
45 | return damageInflicted;
46 | }
47 |
48 | long getDamageTaken() {
49 | return damageTaken;
50 | }
51 |
52 | long getSleepingTime() {
53 | return sleepingTime;
54 | }
55 |
56 | long getRestingTime() {
57 | return restingTime;
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/stats/TypeOfCauseOfDeath.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.stats;
2 |
3 | /**
4 | * TypeOfCauseOfDeath enumerated type that defines the possible types of causes of death.
5 | */
6 | public enum TypeOfCauseOfDeath {
7 |
8 | UNARMED("Unarmed"), WEAPON("Weapon"), BROKEN_WEAPON("Broken Weapon"), SPELL("Spell");
9 |
10 | private final String stringRepresentation;
11 |
12 | TypeOfCauseOfDeath(String stringRepresentation) {
13 | this.stringRepresentation = stringRepresentation;
14 | }
15 |
16 | @Override
17 | public String toString() {
18 | return stringRepresentation;
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/stats/WorldStatistics.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.stats;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 | import org.mafagafogigante.dungeon.util.CounterMap;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * WorldStatistics class that tracks world statistics.
10 | */
11 | public final class WorldStatistics implements Serializable {
12 |
13 | private static final long serialVersionUID = Version.MAJOR;
14 | private final CounterMap spawnCounter = new CounterMap<>();
15 | private final CounterMap locationCounter = new CounterMap<>();
16 | private int spawnCount;
17 | private int locationCount;
18 |
19 | /**
20 | * Adds the spawn of a new Creature to the statistics.
21 | */
22 | public void addSpawn(String creature) {
23 | spawnCount++;
24 | spawnCounter.incrementCounter(creature);
25 | }
26 |
27 | /**
28 | * Adds the creation of a new Location to the statistics.
29 | */
30 | public void addLocation(String location) {
31 | locationCount++;
32 | locationCounter.incrementCounter(location);
33 | }
34 |
35 | /**
36 | * Returns the Creature count.
37 | *
38 | * @return the Creature count.
39 | */
40 | public int getSpawnCount() {
41 | return spawnCount;
42 | }
43 |
44 | /**
45 | * Returns the Location count.
46 | *
47 | * @return the Location count.
48 | */
49 | public int getLocationCount() {
50 | return locationCount;
51 | }
52 |
53 | /**
54 | * Returns the CounterMap that relate Creature name to spawn count.
55 | *
56 | * @return a CounterMap of String.
57 | */
58 | public CounterMap getSpawnCounter() {
59 | return spawnCounter;
60 | }
61 |
62 | public CounterMap getLocationCounter() {
63 | return locationCounter;
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/util/ColumnAlignment.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.util;
2 |
3 | public enum ColumnAlignment {
4 | LEFT, RIGHT
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/util/Messenger.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.util;
2 |
3 | import org.mafagafogigante.dungeon.io.Writer;
4 |
5 | /**
6 | * Messenger helper class that defines several static methods to print uniform warning messages.
7 | */
8 | public class Messenger {
9 |
10 | private Messenger() { // Ensure that this class cannot be instantiated.
11 | throw new AssertionError();
12 | }
13 |
14 | /**
15 | * Prints a warning that a command requires arguments.
16 | */
17 | public static void printMissingArgumentsMessage() {
18 | Writer.write("This command requires arguments.");
19 | }
20 |
21 | public static void printAmbiguousSelectionMessage() {
22 | Writer.write("Provided input is ambiguous.");
23 | }
24 |
25 | /**
26 | * Prints a warning that a directory creation failed.
27 | */
28 | public static void printFailedToCreateDirectoryMessage(String directory) {
29 | Writer.write("Failed to create the '" + directory + "' directory.");
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/util/NonNegativeInteger.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.util;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | /**
6 | * An Integer between 0 and 2 ^ 31 - 1, inclusive.
7 | */
8 | public class NonNegativeInteger {
9 |
10 | private final Integer integer;
11 |
12 | /**
13 | * Constructs a NonNegativeInteger from an integer. The integer must be nonnegative.
14 | */
15 | public NonNegativeInteger(@NotNull Integer integer) {
16 | if (integer < 0) {
17 | throw new IllegalArgumentException("integer must be nonnegative.");
18 | }
19 | this.integer = integer;
20 | }
21 |
22 | public Integer toInteger() {
23 | return integer;
24 | }
25 |
26 | @Override
27 | public String toString() {
28 | return integer.toString();
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/util/Selectable.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.util;
2 |
3 | import org.mafagafogigante.dungeon.game.Name;
4 |
5 | /**
6 | * Selectable interface that tags entities that are selectable through their name.
7 | */
8 | public interface Selectable {
9 |
10 | Name getName();
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/util/Tutorial.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.util;
2 |
3 | import org.mafagafogigante.dungeon.game.ColoredString;
4 | import org.mafagafogigante.dungeon.game.DungeonString;
5 | import org.mafagafogigante.dungeon.game.Writable;
6 | import org.mafagafogigante.dungeon.io.DungeonResource;
7 | import org.mafagafogigante.dungeon.io.JsonObjectFactory;
8 | import org.mafagafogigante.dungeon.io.ResourceNameResolver;
9 |
10 | import java.util.List;
11 |
12 | /**
13 | * Tutorial class that contains the game tutorial.
14 | */
15 | public class Tutorial extends Writable {
16 |
17 | private static final String FILENAME = ResourceNameResolver.resolveName(DungeonResource.TUTORIAL);
18 | private static final String text = JsonObjectFactory.makeJsonObject(FILENAME).get("tutorial").asString();
19 |
20 | @Override
21 | public List toColoredStringList() {
22 | return new DungeonString(text).toColoredStringList();
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/util/library/AutomaticShuffledRange.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.util.library;
2 |
3 | import org.mafagafogigante.dungeon.util.ShuffledRange;
4 |
5 | /**
6 | * An automated ShuffledRange.
7 | *
8 | * Objects of this class wrap a {@code ShuffledRange} and allow infinitely many calls to {@code getNext}. When the
9 | * end of the underlying {@code ShuffledRange} is reached, the index is reset and {@code shuffle} is called on the
10 | * {@code ShuffledRange}.
11 | */
12 | class AutomaticShuffledRange {
13 |
14 | private final ShuffledRange shuffledRange;
15 | private int index;
16 |
17 | /**
18 | * Constructs a new {@code AutomaticShuffledRange} of lower bound 0 given an upper bound.
19 | *
20 | * @param end the higher bound (exclusive)
21 | */
22 | AutomaticShuffledRange(int end) {
23 | shuffledRange = new ShuffledRange(0, end);
24 | }
25 |
26 | /**
27 | * Returns the next integer in the {@code ShuffledRange}.
28 | */
29 | public int getNext() {
30 | int value = shuffledRange.get(index);
31 | index++;
32 | if (index == shuffledRange.getSize()) {
33 | index = 0;
34 | shuffledRange.shuffle();
35 | }
36 | return value;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/util/library/AutomaticShuffledStringLibrary.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.util.library;
2 |
3 | import org.mafagafogigante.dungeon.io.JsonObjectFactory;
4 | import org.mafagafogigante.dungeon.logging.DungeonLogger;
5 |
6 | import com.eclipsesource.json.JsonObject;
7 | import com.eclipsesource.json.JsonValue;
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | /**
14 | * An automatically shuffled library of strings.
15 | */
16 | public class AutomaticShuffledStringLibrary {
17 |
18 | private final String filename;
19 | private final List strings = new ArrayList<>();
20 | private AutomaticShuffledRange automaticShuffledRange;
21 |
22 | public AutomaticShuffledStringLibrary(@NotNull String filename) {
23 | this.filename = filename;
24 | initialize();
25 | }
26 |
27 | private void initialize() {
28 | JsonObject jsonObject = JsonObjectFactory.makeJsonObject(filename);
29 | for (JsonValue value : jsonObject.get("strings").asArray()) {
30 | strings.add(value.asString());
31 | }
32 | if (strings.isEmpty()) {
33 | throw new IllegalStateException("no strings were loaded.");
34 | }
35 | automaticShuffledRange = new AutomaticShuffledRange(strings.size());
36 | DungeonLogger.info("Loaded " + strings.size() + " strings from " + filename + ".");
37 | }
38 |
39 | /**
40 | * Retrieves the next String in the library.
41 | */
42 | public String next() {
43 | return strings.get(automaticShuffledRange.getNext());
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/util/library/Libraries.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.util.library;
2 |
3 | import org.mafagafogigante.dungeon.io.DungeonResource;
4 | import org.mafagafogigante.dungeon.io.ResourceNameResolver;
5 |
6 | public final class Libraries {
7 |
8 | private static final String DREAMS_JSON = ResourceNameResolver.resolveName(DungeonResource.DREAMS);
9 | private static final String HINTS_JSON = ResourceNameResolver.resolveName(DungeonResource.HINTS);
10 | private static final AutomaticShuffledStringLibrary dreamLibrary = new AutomaticShuffledStringLibrary(DREAMS_JSON);
11 | private static final AutomaticShuffledStringLibrary hintLibrary = new AutomaticShuffledStringLibrary(HINTS_JSON);
12 | private static final PoetryLibrary poetryLibrary = new PoetryLibrary();
13 |
14 | private Libraries() {
15 | throw new AssertionError();
16 | }
17 |
18 | public static AutomaticShuffledStringLibrary getDreamLibrary() {
19 | return dreamLibrary;
20 | }
21 |
22 | public static AutomaticShuffledStringLibrary getHintLibrary() {
23 | return hintLibrary;
24 | }
25 |
26 | public static PoetryLibrary getPoetryLibrary() {
27 | return poetryLibrary;
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/util/library/Poem.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.util.library;
2 |
3 | import org.mafagafogigante.dungeon.game.ColoredString;
4 | import org.mafagafogigante.dungeon.game.DungeonString;
5 | import org.mafagafogigante.dungeon.game.Writable;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * Poem class that defines a poem storage data structure.
11 | */
12 | public final class Poem extends Writable {
13 |
14 | private final String title;
15 | private final String author;
16 | private final String content;
17 |
18 | Poem(String title, String author, String content) {
19 | this.title = title;
20 | this.author = author;
21 | this.content = content;
22 | }
23 |
24 | public List toColoredStringList() {
25 | DungeonString builder = new DungeonString(toString());
26 | return builder.toColoredStringList();
27 | }
28 |
29 | @Override
30 | public String toString() {
31 | return title + "\n\n" + content + "\n\n" + author;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/wiki/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Contains the classes related to the in-game wiki. Exposes only a WikiSearcher class that has a single public static
3 | * method search(IssuedCommand) that is used by the rest of the application to retrieve wiki articles.
4 | */
5 |
6 | package org.mafagafogigante.dungeon.wiki;
7 |
8 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/world/AstronomicalBody.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.world;
2 |
3 | import org.mafagafogigante.dungeon.entity.creatures.Observer;
4 |
5 | /**
6 | * An astronomical body that may be seen from a world.
7 | */
8 | interface AstronomicalBody {
9 |
10 | boolean isVisible(Observer observer);
11 |
12 | String describeYourself();
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/world/LuminosityVisibilityCriterion.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.world;
2 |
3 | import org.mafagafogigante.dungeon.entity.Luminosity;
4 | import org.mafagafogigante.dungeon.entity.creatures.Observer;
5 | import org.mafagafogigante.dungeon.io.Version;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | * A visibility criterion based on luminosity.
11 | */
12 | public class LuminosityVisibilityCriterion implements Serializable, VisibilityCriterion {
13 |
14 | private static final long serialVersionUID = Version.MAJOR;
15 | private final Luminosity minimumLuminosity;
16 |
17 | public LuminosityVisibilityCriterion(Luminosity minimumLuminosity) {
18 | this.minimumLuminosity = minimumLuminosity;
19 | }
20 |
21 | @Override
22 | public boolean isMetBy(Observer observer) {
23 | double observerLuminosity = observer.getObserverLocation().getLuminosity().toPercentage().toDouble();
24 | return Double.compare(observerLuminosity, minimumLuminosity.toPercentage().toDouble()) >= 0;
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/world/SimpleAstronomicalBody.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.world;
2 |
3 | import org.mafagafogigante.dungeon.entity.creatures.Observer;
4 | import org.mafagafogigante.dungeon.io.Version;
5 |
6 | import java.io.Serializable;
7 | import java.util.ArrayList;
8 | import java.util.Arrays;
9 | import java.util.Collection;
10 |
11 | class SimpleAstronomicalBody implements AstronomicalBody, Serializable {
12 |
13 | private static final long serialVersionUID = Version.MAJOR;
14 | private final String description;
15 | private final Collection visibilityCriteria;
16 |
17 | SimpleAstronomicalBody(String description, VisibilityCriterion... criteria) {
18 | this.description = description;
19 | this.visibilityCriteria = new ArrayList<>(Arrays.asList(criteria));
20 | }
21 |
22 | @Override
23 | public boolean isVisible(Observer observer) {
24 | for (VisibilityCriterion visibilityCriterion : visibilityCriteria) {
25 | if (!visibilityCriterion.isMetBy(observer)) {
26 | return false;
27 | }
28 | }
29 | return true;
30 | }
31 |
32 | @Override
33 | public String describeYourself() {
34 | return description;
35 | }
36 |
37 | @Override
38 | public String toString() {
39 | return description;
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/world/Sky.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.world;
2 |
3 | import org.mafagafogigante.dungeon.entity.creatures.Observer;
4 | import org.mafagafogigante.dungeon.io.Version;
5 | import org.mafagafogigante.dungeon.util.Utils;
6 |
7 | import java.io.Serializable;
8 | import java.util.ArrayList;
9 | import java.util.Collection;
10 | import java.util.List;
11 |
12 | /**
13 | * The sky of a world.
14 | */
15 | public class Sky implements Serializable {
16 |
17 | private static final long serialVersionUID = Version.MAJOR;
18 | private final Collection astronomicalBodies = new ArrayList<>();
19 |
20 | /**
21 | * Constructs an empty sky.
22 | */
23 | Sky() {
24 | }
25 |
26 | /**
27 | * Adds an astronomical body to the sky.
28 | */
29 | void addAstronomicalBody(AstronomicalBody astronomicalBody) {
30 | astronomicalBodies.add(astronomicalBody);
31 | }
32 |
33 | /**
34 | * Returns a description of the sky with all its visible features.
35 | */
36 | public String describeYourself(Observer observer) {
37 | List descriptions = new ArrayList<>();
38 | for (AstronomicalBody astronomicalBody : astronomicalBodies) {
39 | if (astronomicalBody.isVisible(observer)) {
40 | descriptions.add(astronomicalBody.describeYourself());
41 | }
42 | }
43 | return Utils.enumerate(descriptions);
44 | }
45 |
46 | @Override
47 | public String toString() {
48 | return "Sky{astronomicalBodies=" + astronomicalBodies + '}';
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/world/TimeVisibilityCriterion.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.world;
2 |
3 | import org.mafagafogigante.dungeon.entity.creatures.Observer;
4 | import org.mafagafogigante.dungeon.io.Version;
5 |
6 | import java.io.Serializable;
7 |
8 | public class TimeVisibilityCriterion implements Serializable, VisibilityCriterion {
9 |
10 | private static final long serialVersionUID = Version.MAJOR;
11 | private static final int HOURS_IN_DAY = 24;
12 |
13 | private final int begin;
14 | private final int duration;
15 |
16 | /**
17 | * Constructs a new TimeVisibilityCriterion that starts at begin and ends at end.
18 | *
19 | * @param begin the hour when it begins, nonnegative, smaller than the number of hours in the day
20 | * @param end the hour when it ends, nonnegative, smaller than the number of hours in the day, not equal to begin
21 | */
22 | public TimeVisibilityCriterion(final int begin, final int end) {
23 | if (end >= HOURS_IN_DAY) {
24 | throw new IllegalArgumentException("end should be a valid hour");
25 | }
26 | this.begin = begin;
27 | if (begin == end) {
28 | throw new IllegalArgumentException("begin should not be equal to end");
29 | } else if (begin < end) {
30 | this.duration = end - begin;
31 | } else {
32 | this.duration = HOURS_IN_DAY + end - begin;
33 | }
34 | }
35 |
36 | @Override
37 | public boolean isMetBy(Observer observer) {
38 | final long hour = observer.getObserverLocation().getWorld().getWorldDate().getHour();
39 | long delta = hour - begin;
40 | if (delta < 0) {
41 | delta += HOURS_IN_DAY;
42 | }
43 | return delta < duration;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/world/VisibilityCriteria.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.world;
2 |
3 | import org.mafagafogigante.dungeon.entity.creatures.Observer;
4 | import org.mafagafogigante.dungeon.io.Version;
5 |
6 | import java.io.Serializable;
7 | import java.util.Arrays;
8 | import java.util.List;
9 |
10 | /**
11 | * A collection of visibility criterion.
12 | */
13 | public class VisibilityCriteria implements Serializable {
14 |
15 | private static final long serialVersionUID = Version.MAJOR;
16 | private final List visibilityCriteria;
17 |
18 | public VisibilityCriteria(VisibilityCriterion... visibilityCriteria) {
19 | this.visibilityCriteria = Arrays.asList(visibilityCriteria);
20 | }
21 |
22 | /**
23 | * Evaluates whether or not these visibility criteria is met by an observer.
24 | */
25 | public boolean isMetBy(Observer observer) {
26 | for (VisibilityCriterion criterion : visibilityCriteria) {
27 | if (!criterion.isMetBy(observer)) {
28 | return false;
29 | }
30 | }
31 | return true;
32 | }
33 |
34 | @Override
35 | public String toString() {
36 | return "visibilityCriteria=VisibilityCriteria{" + visibilityCriteria + '}';
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/world/VisibilityCriterion.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.world;
2 |
3 | import org.mafagafogigante.dungeon.entity.creatures.Observer;
4 |
5 | /**
6 | * A criterion that describes whether or not something is visible.
7 | */
8 | public interface VisibilityCriterion {
9 |
10 | /**
11 | * Evaluates whether or not this criterion is met by the specified observer.
12 | */
13 | boolean isMetBy(Observer observer);
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/world/WeatherCondition.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.world;
2 |
3 | /**
4 | * WeatherCondition class that indicates a weather condition.
5 | */
6 | public enum WeatherCondition {
7 |
8 | CLEAR("the sky is clear"),
9 | CLOUDY("the sky is cloudy"),
10 | OVERCAST("the sky is overcast"),
11 | RAIN("it is raining"),
12 | STORM("it is storming");
13 |
14 | private final String descriptivePhrase;
15 |
16 | WeatherCondition(String descriptivePhrase) {
17 | this.descriptivePhrase = descriptivePhrase;
18 | }
19 |
20 | WeatherCondition getLighter() {
21 | return WeatherCondition.values()[Math.max(0, ordinal() - 1)];
22 | }
23 |
24 | boolean isLighterThan(WeatherCondition condition) {
25 | return ordinal() < condition.ordinal();
26 | }
27 |
28 | WeatherCondition getHeavier() {
29 | return WeatherCondition.values()[Math.min(WeatherCondition.values().length - 1, ordinal() + 1)];
30 | }
31 |
32 | boolean isHeavierThan(WeatherCondition condition) {
33 | return ordinal() > condition.ordinal();
34 | }
35 |
36 | public String toDescriptiveString() {
37 | return descriptivePhrase;
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/world/WeatherConditionVisibilityCriterion.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.world;
2 |
3 | import org.mafagafogigante.dungeon.entity.creatures.Observer;
4 | import org.mafagafogigante.dungeon.game.World;
5 | import org.mafagafogigante.dungeon.io.Version;
6 |
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | import java.io.Serializable;
10 |
11 | /**
12 | * A VisibilityCriterion based on the current weather condition.
13 | */
14 | public class WeatherConditionVisibilityCriterion implements Serializable, VisibilityCriterion {
15 |
16 | private static final long serialVersionUID = Version.MAJOR;
17 | private final WeatherCondition minimumCondition;
18 | private final WeatherCondition maximumCondition;
19 |
20 | /**
21 | * Creates a WeatherConditionVisibilityCriterion that will be met when the condition is heavier than or equal to
22 | * minimum and lighter than or equal to maximum.
23 | */
24 | public WeatherConditionVisibilityCriterion(@NotNull WeatherCondition minimum, @NotNull WeatherCondition maximum) {
25 | if (minimum.isHeavierThan(maximum)) {
26 | throw new IllegalArgumentException("minimum cannot be heavier than maximum");
27 | }
28 | this.minimumCondition = minimum;
29 | this.maximumCondition = maximum;
30 | }
31 |
32 | @Override
33 | public boolean isMetBy(Observer observer) {
34 | World world = observer.getObserverLocation().getWorld();
35 | WeatherCondition currentCondition = world.getWeather().getCurrentCondition(world.getWorldDate());
36 | boolean meetsMinimum = currentCondition == minimumCondition || currentCondition.isHeavierThan(minimumCondition);
37 | boolean meetsMaximum = currentCondition == maximumCondition || currentCondition.isLighterThan(maximumCondition);
38 | return meetsMinimum && meetsMaximum;
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/org/mafagafogigante/dungeon/world/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Groups together all the classes needed to build most of the environment.
3 | */
4 |
5 | package org.mafagafogigante.dungeon.world;
6 |
--------------------------------------------------------------------------------
/src/main/resources-filtered/project.properties:
--------------------------------------------------------------------------------
1 | version=${project.version}
2 |
--------------------------------------------------------------------------------
/src/main/resources/DroidSansMono.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bernardosulzbach/dungeon/3d372534e93defd0b71df3646e439fd18f99a24e/src/main/resources/DroidSansMono.ttf
--------------------------------------------------------------------------------
/src/main/resources/dreams.json:
--------------------------------------------------------------------------------
1 | {
2 | "strings": [
3 | "You dream of a river of snakes. The snakes fly into the air, away from you.",
4 | "You have dreams of power, flowing out from books, and flying into your head.",
5 | "You have a nightmare about a tower burning endlessly through the night while laughter rings out.",
6 | "In your dreams, you see an orc stomping on two small rabbits.",
7 | "You dream about a man stronger than you staring you from the other side of a circular table. His grin terrifies you.",
8 | "You have dreams of home, of your deceased father tanning hides to sell at his store.",
9 | "In your dreams, you remember how your benevolent mother would allow poor farmers to use the watermill for free."
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/resources/enchantments.json:
--------------------------------------------------------------------------------
1 | {
2 | "enchantments": [
3 | {
4 | "id": "CORROSIVE_LASH",
5 | "name": "Corrosive Lash",
6 | "damage": {
7 | "type": "ACID",
8 | "amount": 5
9 | }
10 | },
11 | {
12 | "id": "FREEZING_LASH",
13 | "name": "Freezing Lash",
14 | "damage": {
15 | "type": "COLD",
16 | "amount": 5
17 | }
18 | },
19 | {
20 | "id": "SHOCKING_LASH",
21 | "name": "Shocking Lash",
22 | "damage": {
23 | "type": "ELECTRICITY",
24 | "amount": 5
25 | }
26 | },
27 | {
28 | "id": "BURNING_LASH",
29 | "name": "Burning Lash",
30 | "damage": {
31 | "type": "FIRE",
32 | "amount": 5
33 | }
34 | },
35 | {
36 | "id": "POISONING_LASH",
37 | "name": "Poisoning Lash",
38 | "damage": {
39 | "type": "POISON",
40 | "amount": 5
41 | }
42 | },
43 | {
44 | "id": "THUNDERING_LASH",
45 | "name": "Thundering Lash",
46 | "damage": {
47 | "type": "SONIC",
48 | "amount": 5
49 | }
50 | }
51 | ]
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/resources/hints.json:
--------------------------------------------------------------------------------
1 | {
2 | "strings": [
3 | "The command 'achievements' also shows the total number of achievements.",
4 | "There is a 'poem' command that prints a poem to the screen.",
5 | "Use the 'wiki' command to browse the in-game wiki and to better understand the world of Dungeon.",
6 | "You can filter the output of the 'commands' command by typing the beginning of the command.",
7 | "Try to fight bats out in the open during daytime.",
8 | "Orcs become enraged when they are hurt and land several easy critical hits, kill them as fast as you can."
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/resources/preface.json:
--------------------------------------------------------------------------------
1 | {"format": "You wake up at %s. Your head hurts and you can't remember what happened to you. You were born in a city called Everdusk and raised by your parents: a man who worked as a trader and a woman who helped him with his business and owned the local watermill. Your instincts tell you to pick up something to hit your enemies with. As you are not physically strong, you don't think you would last very long unarmed."}
2 |
--------------------------------------------------------------------------------
/src/main/resources/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bernardosulzbach/dungeon/3d372534e93defd0b71df3646e439fd18f99a24e/src/main/resources/splash.png
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/achievements/AchievementStoreFactoryTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.achievements;
2 |
3 | import org.junit.Test;
4 |
5 | import java.util.Collections;
6 | import java.util.List;
7 |
8 | public class AchievementStoreFactoryTest {
9 |
10 | @Test(expected = IllegalStateException.class)
11 | public void testMakeAchievementStoreShouldReturnLockedStore() throws Exception {
12 | AchievementBuilder achievementBuilder = new AchievementBuilder();
13 | achievementBuilder.setId("ACHIEVEMENT");
14 | List emptyList = Collections.emptyList();
15 | AchievementStore achievementStore = AchievementStoreFactory.makeAchievementStore(emptyList);
16 | achievementStore.addAchievement(achievementBuilder.createAchievement());
17 | }
18 |
19 | @Test(expected = IllegalStateException.class)
20 | public void testDefaultStoreShouldBeLocked() throws Exception {
21 | AchievementBuilder achievementBuilder = new AchievementBuilder();
22 | achievementBuilder.setId("ACHIEVEMENT");
23 | AchievementStore defaultStore = AchievementStoreFactory.getDefaultStore();
24 | defaultStore.addAchievement(achievementBuilder.createAchievement());
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/achievements/AchievementStoreTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.achievements;
2 |
3 | import org.junit.Test;
4 |
5 | public class AchievementStoreTest {
6 |
7 | @Test(expected = IllegalStateException.class)
8 | public void testAddAchievementShouldFailIfLocked() throws Exception {
9 | // Not the right way to instantiate an AchievementStore outside the factory, used only for testing.
10 | AchievementBuilder achievementBuilder = new AchievementBuilder();
11 | achievementBuilder.setId("A");
12 | AchievementStore achievementStore = new AchievementStore();
13 | achievementStore.addAchievement(achievementBuilder.createAchievement());
14 | achievementStore.lock();
15 | achievementBuilder.setId("B");
16 | achievementStore.addAchievement(achievementBuilder.createAchievement());
17 | }
18 |
19 | @Test(expected = IllegalArgumentException.class)
20 | public void testAddAchievementShouldFailForRepeatedId() throws Exception {
21 | // Not the right way to instantiate an AchievementStore outside the factory, used only for testing.
22 | AchievementBuilder achievementBuilder = new AchievementBuilder();
23 | achievementBuilder.setId("A");
24 | AchievementStore achievementStore = new AchievementStore();
25 | achievementStore.addAchievement(achievementBuilder.createAchievement());
26 | achievementStore.addAchievement(achievementBuilder.createAchievement());
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/commands/CommandSetTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.commands;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 | import org.junit.Assert;
5 | import org.junit.Test;
6 |
7 | public class CommandSetTest {
8 |
9 | @Test
10 | public void shouldBeAbleToRetrieveAnAddedCommand() throws Exception {
11 | CommandSet commandSet = CommandSet.emptyCommandSet();
12 | Command command = new Command("go", "Go to the specified location.") {
13 | @Override
14 | public void execute(@NotNull String[] arguments) {
15 | }
16 | };
17 | commandSet.addCommand(command);
18 | Assert.assertEquals(command, commandSet.getCommand("go"));
19 | }
20 |
21 | @Test
22 | public void shouldGetNullWhenRetrievingANonexistentCommand() throws Exception {
23 | CommandSet commandSet = CommandSet.emptyCommandSet();
24 | Assert.assertNull(commandSet.getCommand("go"));
25 | }
26 |
27 | @Test
28 | public void shouldNotGetNullWhenRetrievingTheCommandsCommand() throws Exception {
29 | CommandSet commandSet = CommandSet.emptyCommandSet();
30 | Assert.assertNotNull(commandSet.getCommand("commands"));
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/commands/IssuedCommandTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.commands;
2 |
3 | import org.apache.commons.lang3.StringUtils;
4 | import org.junit.Test;
5 |
6 | public class IssuedCommandTest {
7 |
8 | @Test(expected = IllegalArgumentException.class)
9 | public void constructorShouldThrowExceptionOnInputTooBig() throws Exception {
10 | new IssuedCommand(StringUtils.repeat('A', 65536));
11 | }
12 |
13 | @Test(expected = IllegalArgumentException.class)
14 | public void constructorShouldThrowExceptionOnInputWithoutTokens() throws Exception {
15 | new IssuedCommand(StringUtils.repeat(' ', 128));
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/entity/creatures/DateOfBirthGeneratorTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import org.mafagafogigante.dungeon.date.Date;
4 | import org.mafagafogigante.dungeon.date.DungeonTimeUnit;
5 | import org.mafagafogigante.dungeon.date.Duration;
6 |
7 | import org.junit.Assert;
8 | import org.junit.Test;
9 |
10 | public class DateOfBirthGeneratorTest {
11 |
12 | @Test
13 | public void generateDateOfBirthShouldGenerateValidDates() throws Exception {
14 | Date now = new Date(1000, 1, 1);
15 | for (int age = 0; age < 100; age++) {
16 | DateOfBirthGenerator dateOfBirthGenerator = new DateOfBirthGenerator(now, age);
17 | for (int i = 0; i < 100; i++) {
18 | Date dateOfBirth = dateOfBirthGenerator.generateDateOfBirth();
19 | Duration duration = new Duration(dateOfBirth, now);
20 | long maximumSeconds = (age + 1) * DungeonTimeUnit.YEAR.as(DungeonTimeUnit.SECOND);
21 | Assert.assertTrue(duration.getSeconds() < maximumSeconds);
22 | }
23 | }
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/entity/creatures/SimpleBattleLogTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.entity.creatures;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class SimpleBattleLogTest {
7 |
8 | @Test
9 | public void testGetAndResetShouldResetCounters() {
10 | SimpleBattleLog simpleBattleLog = new SimpleBattleLog();
11 | long inflictedDamage = 1L;
12 | long receivedDamage = 2L;
13 | simpleBattleLog.incrementInflicted(inflictedDamage);
14 | simpleBattleLog.incrementTaken(receivedDamage);
15 | Assert.assertEquals(inflictedDamage, simpleBattleLog.getAndResetInflicted());
16 | Assert.assertEquals(0L, simpleBattleLog.getAndResetInflicted());
17 | Assert.assertEquals(receivedDamage, simpleBattleLog.getAndResetTaken());
18 | Assert.assertEquals(0L, simpleBattleLog.getAndResetTaken());
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/game/DirectionTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class DirectionTest {
7 |
8 | @Test
9 | public void invertShouldCorrectlyInvertTheDirection() throws Exception {
10 | Assert.assertEquals(Direction.UP, Direction.DOWN.invert());
11 | Assert.assertEquals(Direction.NORTH, Direction.SOUTH.invert());
12 | Assert.assertEquals(Direction.EAST, Direction.WEST.invert());
13 | Assert.assertEquals(Direction.DOWN, Direction.UP.invert());
14 | Assert.assertEquals(Direction.SOUTH, Direction.NORTH.invert());
15 | Assert.assertEquals(Direction.WEST, Direction.EAST.invert());
16 | }
17 |
18 | @Test
19 | public void invertTwiceShouldNotModifyTheDirection() throws Exception {
20 | for (Direction direction : Direction.values()) {
21 | Assert.assertEquals(direction, direction.invert().invert());
22 | }
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/game/DungeonStringTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | import java.awt.Color;
7 |
8 | public class DungeonStringTest {
9 |
10 | @Test
11 | public void testGetLengthShouldWorkWithDefaultColor() throws Exception {
12 | DungeonString dungeonString = new DungeonString();
13 | Assert.assertEquals(0, dungeonString.getLength());
14 | dungeonString.append("A");
15 | Assert.assertEquals(1, dungeonString.getLength());
16 | dungeonString.append("A");
17 | Assert.assertEquals(2, dungeonString.getLength());
18 | dungeonString.append("A");
19 | Assert.assertEquals(3, dungeonString.getLength());
20 | }
21 |
22 | @Test
23 | public void testGetLengthShouldWorkWithMultipleColors() throws Exception {
24 | DungeonString dungeonString = new DungeonString();
25 | Assert.assertEquals(0, dungeonString.getLength());
26 | dungeonString.append("A");
27 | Assert.assertEquals(1, dungeonString.getLength());
28 | dungeonString.setColor(Color.BLUE);
29 | Assert.assertEquals(1, dungeonString.getLength());
30 | dungeonString.append("A");
31 | Assert.assertEquals(2, dungeonString.getLength());
32 | dungeonString.setColor(Color.RED);
33 | Assert.assertEquals(2, dungeonString.getLength());
34 | dungeonString.append("A");
35 | Assert.assertEquals(3, dungeonString.getLength());
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/game/ExpandableIntegerSetTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.junit.Test;
4 |
5 | public class ExpandableIntegerSetTest {
6 |
7 | @Test(expected = IllegalArgumentException.class)
8 | public void testConstructorThrowsIllegalArgumentExceptionIfMinimumDifferenceIsNegative() {
9 | new ExpandableIntegerSet(-1, 1);
10 | }
11 |
12 | @Test(expected = IllegalArgumentException.class)
13 | public void testConstructorThrowsIllegalArgumentExceptionIfMinimumDifferenceIsZero() {
14 | new ExpandableIntegerSet(0, 1);
15 | }
16 |
17 | @Test(expected = IllegalArgumentException.class)
18 | public void testConstructorThrowsIllegalArgumentExceptionOnMaximumDifferenceNotBiggerThanMinimumDifference() {
19 | new ExpandableIntegerSet(1, 1);
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/game/IdTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.junit.Test;
4 |
5 | public class IdTest {
6 |
7 | @Test(expected = IllegalArgumentException.class)
8 | public void constructorShouldThrowExceptionOnNull() throws Exception {
9 | new Id(null);
10 | }
11 |
12 | @Test(expected = IllegalArgumentException.class)
13 | public void constructorShouldThrowExceptionOnEmptyString() throws Exception {
14 | new Id("");
15 | }
16 |
17 | @Test(expected = IllegalArgumentException.class)
18 | public void constructorShouldThrowExceptionOnStringWithSpaces() throws Exception {
19 | new Id(" ");
20 | }
21 |
22 | @Test
23 | public void constructorShouldWorkForValidStrings() throws Exception {
24 | new Id("403_ACCESS_FORBIDDEN");
25 | new Id("404_NOT_FOUND");
26 | new Id("VALID_ID");
27 | new Id("ID_WITH_NUMBER_255");
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/game/PointTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class PointTest {
7 |
8 | @Test
9 | public void equalsShouldReturnTrueToEqualPoints() throws Exception {
10 | Assert.assertTrue(new Point(0, 0, 0).equals(new Point(0, 0, 0)));
11 | Assert.assertTrue(new Point(1, 0, 0).equals(new Point(1, 0, 0)));
12 | Assert.assertTrue(new Point(0, 1, 0).equals(new Point(0, 1, 0)));
13 | Assert.assertTrue(new Point(0, 0, 1).equals(new Point(0, 0, 1)));
14 | }
15 |
16 | @Test
17 | public void equalsShouldReturnFalseToDifferentPoints() throws Exception {
18 | Assert.assertFalse(new Point(1, 0, 0).equals(new Point(0, 0, 0)));
19 | Assert.assertFalse(new Point(0, 1, 0).equals(new Point(0, 0, 0)));
20 | Assert.assertFalse(new Point(0, 0, 1).equals(new Point(0, 0, 0)));
21 | Assert.assertFalse(new Point(0, 0, 0).equals(new Point(1, 0, 0)));
22 | Assert.assertFalse(new Point(0, 0, 0).equals(new Point(0, 1, 0)));
23 | Assert.assertFalse(new Point(0, 0, 0).equals(new Point(0, 0, 1)));
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/game/RandomTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.mafagafogigante.dungeon.util.Percentage;
4 |
5 | import org.junit.Assert;
6 | import org.junit.Test;
7 |
8 | import java.util.ArrayList;
9 | import java.util.Collections;
10 | import java.util.List;
11 |
12 | public class RandomTest {
13 |
14 | @Test
15 | public void testRollWithDoubles() throws Exception {
16 | Assert.assertFalse(Random.roll(0.0));
17 | Assert.assertTrue(Random.roll(1.0));
18 | }
19 |
20 | @Test
21 | public void testRollWithPercentages() throws Exception {
22 | Assert.assertFalse(Random.roll(new Percentage(0.0)));
23 | Assert.assertTrue(Random.roll(new Percentage(1.0)));
24 | }
25 |
26 | @Test
27 | public void testSelect() throws Exception {
28 | try {
29 | Random.select(Collections.emptyList());
30 | Assert.fail("expected an exception.");
31 | } catch (IllegalArgumentException expected) {
32 | // Dungeon Code Style does not require a comment on exceptions named expected in tests.
33 | }
34 | List integerList = new ArrayList<>();
35 | integerList.add(0);
36 | Assert.assertTrue(Random.select(integerList).equals(0));
37 | }
38 |
39 | @Test
40 | public void testRandomIntegerRespectsMinimum() throws Exception {
41 | for (int i = 0; i < 1000; i++) {
42 | Assert.assertEquals(i, Random.nextInteger(i, i + 1));
43 | }
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/game/SpawnerPresetTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.junit.Test;
4 |
5 | public class SpawnerPresetTest {
6 |
7 | @Test(expected = IllegalArgumentException.class)
8 | public void testSpawnerPresetConstructorThrowsIllegalArgumentExceptionWhenMinimumIsNegative() {
9 | new SpawnerPreset("ID", -1, 2, 1);
10 | }
11 |
12 | @Test(expected = IllegalArgumentException.class)
13 | public void testSpawnerPresetConstructorThrowsIllegalArgumentExceptionWhenMinimumIsZero() {
14 | new SpawnerPreset("ID", 0, 2, 1);
15 | }
16 |
17 | @Test
18 | public void testSpawnerPresetConstructorShouldWorkWhenMinimumIsLessThanMaximum() {
19 | new SpawnerPreset("ID", 1, 2, 1);
20 | }
21 |
22 | @Test
23 | public void testSpawnerPresetConstructorShouldWorkWhenMinimumIsEqualToMaximum() {
24 | new SpawnerPreset("ID", 2, 2, 1);
25 | }
26 |
27 | @Test(expected = IllegalArgumentException.class)
28 | public void testSpawnerPresetConstructorThrowsIllegalArgumentExceptionWhenMinimumIsGreaterThanMaximum() {
29 | new SpawnerPreset("ID", 3, 2, 1);
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/game/VersionTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.game;
2 |
3 | import org.mafagafogigante.dungeon.io.Version;
4 |
5 | import org.hamcrest.Matchers;
6 | import org.hamcrest.core.IsNot;
7 | import org.hamcrest.text.IsEmptyString;
8 | import org.junit.Assert;
9 | import org.junit.Test;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | public class VersionTest {
15 |
16 | @Test
17 | public void versionStringShouldNotBeEmpty() {
18 | Assert.assertThat(Version.getCurrentVersion().toString(), new IsNot<>(new IsEmptyString()));
19 | }
20 |
21 | @Test
22 | public void versionOrderingShouldBeValid() {
23 | final int minimum = 1;
24 | final int maximum = 3;
25 | List versions = new ArrayList<>();
26 | for (int major = minimum; major <= maximum; major++) {
27 | for (int minor = minimum; minor <= maximum; minor++) {
28 | for (int patch = minimum; patch <= maximum; patch++) {
29 | versions.add(new Version(String.format("v%d.%d.%d", major, minor, patch)));
30 | }
31 | }
32 | }
33 | for (int i = 0; i < versions.size(); i++) {
34 | final Version left = versions.get(i);
35 | for (int j = 0; j < versions.size(); j++) {
36 | final Version right = versions.get(j);
37 | if (i < j) {
38 | Assert.assertThat(left, Matchers.lessThan(right));
39 | } else if (i == j) {
40 | Assert.assertThat(left, Matchers.equalTo(right));
41 | } else {
42 | Assert.assertThat(left, Matchers.greaterThan(right));
43 | }
44 | }
45 | }
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/gui/SwappingStyledDocumentTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.gui;
2 |
3 | import org.mafagafogigante.dungeon.game.DungeonString;
4 |
5 | import org.junit.Assert;
6 | import org.junit.Test;
7 |
8 | import javax.swing.JTextPane;
9 | import javax.swing.text.Document;
10 |
11 | public class SwappingStyledDocumentTest {
12 |
13 | @Test
14 | public void testWriteShouldSwapBetweenTwoDocuments() throws Exception {
15 | JTextPane jTextPane = new JTextPane();
16 | SwappingStyledDocument swappingStyledDocument = new SwappingStyledDocument(jTextPane);
17 | Document firstDocument = jTextPane.getStyledDocument();
18 | swappingStyledDocument.write(new DungeonString("A"), new WritingSpecifications(false, 0));
19 | Document secondDocument = jTextPane.getStyledDocument();
20 | swappingStyledDocument.write(new DungeonString("B"), new WritingSpecifications(false, 0));
21 | Document thirdDocument = jTextPane.getStyledDocument();
22 | Assert.assertNotEquals(firstDocument, secondDocument);
23 | Assert.assertEquals(firstDocument, thirdDocument);
24 | }
25 |
26 | @Test
27 | public void testClearShouldEraseEverythingInTheTextPane() throws Exception {
28 | JTextPane jTextPane = new JTextPane();
29 | SwappingStyledDocument swappingStyledDocument = new SwappingStyledDocument(jTextPane);
30 | swappingStyledDocument.write(new DungeonString("."), new WritingSpecifications(false, 0));
31 | Assert.assertNotEquals(jTextPane.getText().length(), 0);
32 | swappingStyledDocument.clear();
33 | Assert.assertEquals(jTextPane.getText().length(), 0);
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/io/ConverterTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class ConverterTest {
7 |
8 | @Test
9 | public void bytesToHuman() throws Exception {
10 | Assert.assertEquals("1 B", Converter.bytesToHuman(1));
11 | Assert.assertEquals("2 B", Converter.bytesToHuman(2));
12 | Assert.assertEquals("1023 B", Converter.bytesToHuman((1L << 10) - 1));
13 | Assert.assertEquals("1.0 KiB", Converter.bytesToHuman(1L << 10));
14 | Assert.assertEquals("1024.0 KiB", Converter.bytesToHuman((1L << 20) - 1));
15 | Assert.assertEquals("1.0 MiB", Converter.bytesToHuman(1L << 20));
16 | Assert.assertEquals("1024.0 MiB", Converter.bytesToHuman((1L << 30) - 1));
17 | Assert.assertEquals("1.0 GiB", Converter.bytesToHuman(1L << 30));
18 | Assert.assertEquals("1024.0 GiB", Converter.bytesToHuman((1L << 40) - 1));
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/io/DreamsJsonFileTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 | import org.mafagafogigante.dungeon.schema.rules.JsonRuleFactory;
5 |
6 | import com.eclipsesource.json.JsonObject;
7 | import org.junit.Test;
8 |
9 | import java.util.HashMap;
10 | import java.util.Map;
11 |
12 | public class DreamsJsonFileTest extends ResourcesTypeTest {
13 |
14 | private static final String STRINGS_FIELD = "strings";
15 |
16 | @Test
17 | public void testIsFileHasValidStructure() {
18 | JsonRule dreamsFileRuleObject = getDreamsFileRuleObject();
19 | String filename = ResourceNameResolver.resolveName(DungeonResource.DREAMS);
20 | JsonObject dreamsFileJsonObject = getJsonObjectByJsonFilename(filename);
21 | dreamsFileRuleObject.validate(dreamsFileJsonObject);
22 | }
23 |
24 | private JsonRule getDreamsFileRuleObject() {
25 | Map dreamsFileRules = new HashMap<>();
26 | JsonRule stringJsonRule = JsonRuleFactory.makeStringRule();
27 | dreamsFileRules.put(STRINGS_FIELD, JsonRuleFactory.makeVariableArrayRule(stringJsonRule));
28 | return JsonRuleFactory.makeObjectRule(dreamsFileRules);
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/io/HintsJsonFileTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 | import org.mafagafogigante.dungeon.schema.rules.JsonRuleFactory;
5 |
6 | import com.eclipsesource.json.JsonObject;
7 | import org.junit.Test;
8 |
9 | import java.util.HashMap;
10 | import java.util.Map;
11 |
12 | public class HintsJsonFileTest extends ResourcesTypeTest {
13 |
14 | private static final String STRINGS_FIELD = "strings";
15 |
16 | @Test
17 | public void testIsFileHasValidStructure() {
18 | final JsonRule hintsFileRuleObject = getHintsFileRuleObject();
19 | String filename = ResourceNameResolver.resolveName(DungeonResource.HINTS);
20 | JsonObject hitsFileJsonObject = getJsonObjectByJsonFilename(filename);
21 | hintsFileRuleObject.validate(hitsFileJsonObject);
22 | }
23 |
24 | private JsonRule getHintsFileRuleObject() {
25 | Map hintsFileRules = new HashMap<>();
26 | final JsonRule stringJsonRule = JsonRuleFactory.makeStringRule();
27 | hintsFileRules.put(STRINGS_FIELD, JsonRuleFactory.makeVariableArrayRule(stringJsonRule));
28 | return JsonRuleFactory.makeObjectRule(hintsFileRules);
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/io/PoemsJsonFileTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 | import org.mafagafogigante.dungeon.schema.rules.JsonRuleFactory;
5 |
6 | import com.eclipsesource.json.JsonObject;
7 | import org.junit.Test;
8 |
9 | import java.util.HashMap;
10 | import java.util.Map;
11 |
12 | public class PoemsJsonFileTest extends ResourcesTypeTest {
13 |
14 | private static final String POEMS_FIELD = "poems";
15 | private static final String TITLE_FIELD = "title";
16 | private static final String AUTHOR_FIELD = "author";
17 | private static final String CONTENT_FIELD = "content";
18 |
19 | @Test
20 | public void testIsFileHasValidStructure() {
21 | JsonRule poemsRuleObject = getPoemsRuleObject();
22 | JsonRule poemsFileJsonRule = getPoemsFileRuleObject(poemsRuleObject);
23 | String filename = ResourceNameResolver.resolveName(DungeonResource.POEMS);
24 | JsonObject poemsFileJsonObject = getJsonObjectByJsonFilename(filename);
25 | poemsFileJsonRule.validate(poemsFileJsonObject);
26 | }
27 |
28 | private JsonRule getPoemsFileRuleObject(JsonRule poemsRuleObject) {
29 | Map poemsFileRules = new HashMap<>();
30 | poemsFileRules.put(POEMS_FIELD, JsonRuleFactory.makeVariableArrayRule(poemsRuleObject));
31 | return JsonRuleFactory.makeObjectRule(poemsFileRules);
32 | }
33 |
34 | private JsonRule getPoemsRuleObject() {
35 | Map poemsRules = new HashMap<>();
36 | JsonRule stringRule = JsonRuleFactory.makeStringRule();
37 | poemsRules.put(TITLE_FIELD, stringRule);
38 | poemsRules.put(AUTHOR_FIELD, stringRule);
39 | poemsRules.put(CONTENT_FIELD, stringRule);
40 | return JsonRuleFactory.makeObjectRule(poemsRules);
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/io/PrefaceJsonFileTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 | import org.mafagafogigante.dungeon.schema.rules.JsonRuleFactory;
5 |
6 | import com.eclipsesource.json.JsonObject;
7 | import org.junit.Test;
8 |
9 | import java.util.HashMap;
10 | import java.util.Map;
11 |
12 | public class PrefaceJsonFileTest extends ResourcesTypeTest {
13 |
14 | private static final String FORMAT_FIELD = "format";
15 |
16 | @Test
17 | public void testIsFileHasValidStructure() {
18 | Map tutorialFileRules = new HashMap<>();
19 | tutorialFileRules.put(FORMAT_FIELD, JsonRuleFactory.makeStringRule());
20 | JsonRule tutorialJsonRule = JsonRuleFactory.makeObjectRule(tutorialFileRules);
21 | String filename = ResourceNameResolver.resolveName(DungeonResource.PREFACE);
22 | JsonObject prefaceFileJsonObject = getJsonObjectByJsonFilename(filename);
23 | tutorialJsonRule.validate(prefaceFileJsonObject);
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/io/ResourcesTypeTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | import com.eclipsesource.json.JsonObject;
4 |
5 | class ResourcesTypeTest {
6 |
7 | static JsonObject getJsonObjectByJsonFilename(String filename) {
8 | return JsonObjectFactory.makeJsonObject(filename);
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/io/TutorialJsonFileTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.io;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 | import org.mafagafogigante.dungeon.schema.rules.JsonRuleFactory;
5 |
6 | import com.eclipsesource.json.JsonObject;
7 | import org.junit.Test;
8 |
9 | import java.util.HashMap;
10 | import java.util.Map;
11 |
12 | public class TutorialJsonFileTest extends ResourcesTypeTest {
13 |
14 | private static final String TUTORIAL_FIELD = "tutorial";
15 |
16 | @Test
17 | public void testIsFileHasValidStructure() {
18 | Map tutorialFileRules = new HashMap<>();
19 | tutorialFileRules.put(TUTORIAL_FIELD, JsonRuleFactory.makeStringRule());
20 | JsonRule tutorialJsonRule = JsonRuleFactory.makeObjectRule(tutorialFileRules);
21 | String filename = ResourceNameResolver.resolveName(DungeonResource.TUTORIAL);
22 | JsonObject tutorialFileJsonObject = getJsonObjectByJsonFilename(filename);
23 | tutorialJsonRule.validate(tutorialFileJsonObject);
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/ArrayJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.Json;
6 | import com.eclipsesource.json.JsonArray;
7 | import com.eclipsesource.json.JsonValue;
8 | import org.junit.Test;
9 |
10 | public class ArrayJsonRuleTest {
11 |
12 | private static final JsonRule arrayJsonRule = new ArrayJsonRule();
13 |
14 | @Test(expected = IllegalArgumentException.class)
15 | public void arrayJsonRuleShouldFailNonArrayType() {
16 | JsonValue jsonValue = Json.value(true);
17 | arrayJsonRule.validate(jsonValue);
18 | }
19 |
20 | @Test
21 | public void arrayJsonRuleShouldPassArrayType() {
22 | JsonArray jsonArray = new JsonArray();
23 | arrayJsonRule.validate(jsonArray);
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/ArraySizeJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.Json;
6 | import com.eclipsesource.json.JsonArray;
7 | import com.eclipsesource.json.JsonValue;
8 | import org.junit.Test;
9 |
10 | public class ArraySizeJsonRuleTest {
11 |
12 | private static final int ARRAY_VALIDATION_SIZE = 2;
13 | private static final JsonRule arraySizeJsonRule = new ArraySizeJsonRule(ARRAY_VALIDATION_SIZE);
14 |
15 | @Test(expected = IllegalArgumentException.class)
16 | public void arrayJsonSizeRuleShouldFailNonArrayType() {
17 | JsonValue jsonValue = Json.value(true);
18 | arraySizeJsonRule.validate(jsonValue);
19 | }
20 |
21 | @Test(expected = IllegalArgumentException.class)
22 | public void arrayJsonSizeRuleShouldFailInvalidArraySize() {
23 | JsonArray jsonArray = new JsonArray();
24 | arraySizeJsonRule.validate(jsonArray);
25 | }
26 |
27 | @Test
28 | public void arrayJsonSizeRuleShouldPassValidArraySize() {
29 | JsonArray jsonArray = new JsonArray();
30 | jsonArray.add(Json.value(true));
31 | jsonArray.add(Json.value(true));
32 | arraySizeJsonRule.validate(jsonArray);
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/BooleanJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.Json;
6 | import com.eclipsesource.json.JsonValue;
7 | import org.junit.Test;
8 |
9 | public class BooleanJsonRuleTest {
10 |
11 | private static final JsonRule booleanJsonRule = new BooleanJsonRule();
12 |
13 | @Test(expected = IllegalArgumentException.class)
14 | public void booleanJsonRuleShouldFailNonBooleanType() {
15 | JsonValue jsonValue = Json.value("string");
16 | booleanJsonRule.validate(jsonValue);
17 | }
18 |
19 | @Test
20 | public void booleanJsonRuleShouldPassBooleanType() {
21 | JsonValue jsonValue = Json.value(false);
22 | booleanJsonRule.validate(jsonValue);
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/BoundDoubleJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.Json;
6 | import com.eclipsesource.json.JsonValue;
7 | import org.junit.Test;
8 |
9 | public class BoundDoubleJsonRuleTest {
10 |
11 | private static final double MIN_BOUND_VALUE = 1.5;
12 | private static final double MAX_BOUND_VALUE = 3.5;
13 | private static final JsonRule boundDoubleJsonRule = new BoundDoubleJsonRule(MIN_BOUND_VALUE, MAX_BOUND_VALUE);
14 |
15 | @Test(expected = IllegalArgumentException.class)
16 | public void boundDoubleJsonRuleShouldFailValueOutOfLowerBound() {
17 | final double lowerThanLowerBound = 1.0;
18 | JsonValue jsonValue = Json.value(lowerThanLowerBound);
19 | boundDoubleJsonRule.validate(jsonValue);
20 | }
21 |
22 | @Test(expected = IllegalArgumentException.class)
23 | public void boundDoubleJsonRuleShouldFailValueOutOfUpperBound() {
24 | final double greaterThanUpperBound = 5.0;
25 | JsonValue jsonValue = Json.value(greaterThanUpperBound);
26 | boundDoubleJsonRule.validate(jsonValue);
27 | }
28 |
29 | @Test
30 | public void boundDoubleJsonRuleShouldPassInBoundValue() {
31 | final double valid = 2.0;
32 | JsonValue jsonValue = Json.value(valid);
33 | boundDoubleJsonRule.validate(jsonValue);
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/BoundIntegerJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.Json;
6 | import com.eclipsesource.json.JsonValue;
7 | import org.junit.Test;
8 |
9 | public class BoundIntegerJsonRuleTest {
10 |
11 | private static final int MIN_BOUND_VALUE = 2;
12 | private static final int MAX_BOUND_VALUE = 5;
13 | private static final JsonRule boundIntegerJsonRule = new BoundIntegerJsonRule(MIN_BOUND_VALUE, MAX_BOUND_VALUE);
14 |
15 | @Test(expected = IllegalArgumentException.class)
16 | public void boundIntegerJsonRuleShouldFailWhenValueOutOfLowerBound() {
17 | final int lowerThanLowerBound = 1;
18 | JsonValue jsonValue = Json.value(lowerThanLowerBound);
19 | boundIntegerJsonRule.validate(jsonValue);
20 | }
21 |
22 | @Test(expected = IllegalArgumentException.class)
23 | public void boundIntegerJsonRuleShouldFailWhenValueOutOfUpperBound() {
24 | final int greaterThanUpperBound = 6;
25 | JsonValue jsonValue = Json.value(greaterThanUpperBound);
26 | boundIntegerJsonRule.validate(jsonValue);
27 | }
28 |
29 | @Test
30 | public void boundIntegerJsonRuleShouldPassWhenValueInBound() {
31 | final int valid = 3;
32 | JsonValue jsonValue = Json.value(valid);
33 | boundIntegerJsonRule.validate(jsonValue);
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/DoubleJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.Json;
6 | import com.eclipsesource.json.JsonValue;
7 | import org.junit.Test;
8 |
9 | public class DoubleJsonRuleTest {
10 |
11 | private static final JsonRule doubleJsonRule = new DoubleJsonRule();
12 |
13 | @Test(expected = IllegalArgumentException.class)
14 | public void doubleJsonRuleShouldFailNonDoubleType() {
15 | JsonValue jsonValue = Json.value("string");
16 | doubleJsonRule.validate(jsonValue);
17 | }
18 |
19 | @Test
20 | public void doubleJsonRuleShouldPassValidType() {
21 | JsonValue jsonValue = Json.value(1.0);
22 | doubleJsonRule.validate(jsonValue);
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/EnumJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.Json;
6 | import com.eclipsesource.json.JsonValue;
7 | import org.junit.Test;
8 |
9 | public class EnumJsonRuleTest {
10 |
11 | private static final String INVALID_ENUM_VALUE_UPPERCASE = "TWO";
12 | private static final String INVALID_ENUM_VALUE_LOWERCASE = "one";
13 | private static final JsonRule enumJsonRule = new EnumJsonRule<>(TestEnum.class);
14 |
15 | @Test
16 | public void enumJsonRuleShouldPassValidEnumValue() {
17 | JsonValue jsonValue = Json.value(TestEnum.ONE.toString());
18 | enumJsonRule.validate(jsonValue);
19 | }
20 |
21 | @Test(expected = IllegalArgumentException.class)
22 | public void enumJsonRuleShouldFailOnNonExistentEnumValue() {
23 | JsonValue jsonValue = Json.value(INVALID_ENUM_VALUE_UPPERCASE);
24 | enumJsonRule.validate(jsonValue);
25 | }
26 |
27 | @Test(expected = IllegalArgumentException.class)
28 | public void enumJsonRuleShouldFailOnNonStringValue() {
29 | JsonValue jsonValue = Json.value(true);
30 | enumJsonRule.validate(jsonValue);
31 | }
32 |
33 | @Test(expected = IllegalArgumentException.class)
34 | public void enumJsonRuleShouldFailOnLowercaseValue() {
35 | JsonValue jsonValue = Json.value(INVALID_ENUM_VALUE_LOWERCASE);
36 | enumJsonRule.validate(jsonValue);
37 | }
38 |
39 | @Test(expected = IllegalArgumentException.class)
40 | public void enumJsonRuleShouldFailOnEmptyValue() {
41 | JsonValue jsonValue = Json.value("");
42 | enumJsonRule.validate(jsonValue);
43 | }
44 |
45 | private enum TestEnum {
46 | ONE
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/GroupJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.JsonArray;
6 | import org.junit.Test;
7 |
8 | public class GroupJsonRuleTest {
9 |
10 | private static final int MIN_ELEMENT_VALUE = 0;
11 | private static final int MAX_ELEMENT_VALUE = 5;
12 | private static final int REQUIRED_ARRAY_SIZE = 2;
13 | private static final JsonRule groupRule = new GroupJsonRule(
14 | JsonRuleFactory.makeVariableArrayRule(JsonRuleFactory.makeBoundIntegerRule(MIN_ELEMENT_VALUE, MAX_ELEMENT_VALUE)),
15 | JsonRuleFactory.makeArraySizeRule(REQUIRED_ARRAY_SIZE));
16 |
17 | @Test(expected = IllegalArgumentException.class)
18 | public void groupRuleShouldFailOnBoundIntegerRule() {
19 | JsonArray jsonArray = new JsonArray();
20 | jsonArray.add(6);
21 | jsonArray.add(6);
22 | groupRule.validate(jsonArray);
23 | }
24 |
25 | @Test(expected = IllegalArgumentException.class)
26 | public void groupRuleShouldFailOnArraySizeRule() {
27 | JsonArray jsonArray = new JsonArray();
28 | jsonArray.add(1);
29 | jsonArray.add(2);
30 | jsonArray.add(3);
31 | groupRule.validate(jsonArray);
32 | }
33 |
34 | @Test
35 | public void groupRuleShouldPassOnValidObject() {
36 | JsonArray jsonArray = new JsonArray();
37 | jsonArray.add(1);
38 | jsonArray.add(2);
39 | groupRule.validate(jsonArray);
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/IdJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.Json;
6 | import com.eclipsesource.json.JsonValue;
7 | import org.junit.Test;
8 |
9 | public class IdJsonRuleTest {
10 |
11 | private static final JsonRule idJsonRule = new IdJsonRule();
12 |
13 | @Test(expected = IllegalArgumentException.class)
14 | public void idJsonRuleShouldFailNonStringType() {
15 | JsonValue jsonValue = Json.value(true);
16 | idJsonRule.validate(jsonValue);
17 | }
18 |
19 | @Test(expected = IllegalArgumentException.class)
20 | public void idJsonRuleShouldFailLowercaseChar() {
21 | JsonValue jsonValue = Json.value("mONSTER");
22 | idJsonRule.validate(jsonValue);
23 | }
24 |
25 | @Test
26 | public void idJsonRuleShouldPassNumberChar() {
27 | JsonValue jsonValue = Json.value("1");
28 | idJsonRule.validate(jsonValue);
29 | }
30 |
31 | @Test
32 | public void stringJsonRuleShouldPassUnderscoreChar() {
33 | JsonValue jsonValue = Json.value("MONSTER_A");
34 | idJsonRule.validate(jsonValue);
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/IntegerJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.Json;
6 | import com.eclipsesource.json.JsonValue;
7 | import org.junit.Test;
8 |
9 | public class IntegerJsonRuleTest {
10 |
11 | private static final JsonRule integerJsonRule = new IntegerJsonRule();
12 |
13 | @Test(expected = IllegalArgumentException.class)
14 | public void integerJsonRuleShouldFailNonIntegerType() {
15 | final double invalidValue = 2.5;
16 | JsonValue jsonValue = Json.value(invalidValue);
17 | integerJsonRule.validate(jsonValue);
18 | }
19 |
20 | @Test
21 | public void integerJsonRuleShouldPassValidType() {
22 | JsonValue jsonValue = Json.value(1);
23 | integerJsonRule.validate(jsonValue);
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/NumberJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.Json;
6 | import com.eclipsesource.json.JsonValue;
7 | import org.junit.Test;
8 |
9 | public class NumberJsonRuleTest {
10 |
11 | private static final JsonRule numberJsonRule = new NumberJsonRule();
12 |
13 | @Test(expected = IllegalArgumentException.class)
14 | public void numberJsonRuleShouldFailNonNumberType() {
15 | JsonValue jsonValue = Json.value("string");
16 | numberJsonRule.validate(jsonValue);
17 | }
18 |
19 | @Test
20 | public void numberJsonRuleShouldPassNumberType() {
21 | JsonValue jsonValue = Json.value(1);
22 | numberJsonRule.validate(jsonValue);
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/ObjectJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.Json;
6 | import com.eclipsesource.json.JsonObject;
7 | import com.eclipsesource.json.JsonValue;
8 | import org.junit.Test;
9 |
10 | import java.util.HashMap;
11 | import java.util.Map;
12 |
13 | public class ObjectJsonRuleTest {
14 |
15 | @Test
16 | public void shouldPassObjectWithValidAttributes() {
17 | JsonObject object = new JsonObject();
18 | object.add("favoriteInteger", 10);
19 | object.add("count", 1000);
20 | object.add("optionalInteger", 10);
21 | Map rules = new HashMap<>();
22 | rules.put("favoriteInteger", new IntegerJsonRule());
23 | rules.put("count", new BoundIntegerJsonRule(0, 1000));
24 | rules.put("optionalInteger", new OptionalJsonRule(new IntegerJsonRule()));
25 | JsonRule rule = new ObjectJsonRule(rules);
26 | rule.validate(object);
27 | }
28 |
29 | @Test(expected = IllegalArgumentException.class)
30 | public void shouldFailOnNonObjectValue() {
31 | JsonValue value = Json.value(true);
32 | Map rules = new HashMap<>();
33 | JsonRule rule = new ObjectJsonRule(rules);
34 | rule.validate(value);
35 | }
36 |
37 | @Test(expected = IllegalArgumentException.class)
38 | public void shouldFailOnObjectWithInvalidAttributes() {
39 | JsonObject object = new JsonObject();
40 | object.add("id", "john");
41 | Map rules = new HashMap<>();
42 | rules.put("id", new UppercaseStringJsonRule());
43 | JsonRule rule = new ObjectJsonRule(rules);
44 | rule.validate(object);
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/OptionalJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import static org.mockito.Mockito.never;
4 | import static org.mockito.Mockito.only;
5 |
6 | import org.mafagafogigante.dungeon.schema.JsonRule;
7 |
8 | import com.eclipsesource.json.Json;
9 | import com.eclipsesource.json.JsonValue;
10 | import org.junit.Test;
11 | import org.mockito.Mockito;
12 |
13 | public class OptionalJsonRuleTest {
14 |
15 | private static final JsonRule jsonRuleStub = Mockito.mock(JsonRule.class);
16 | private static final JsonRule optionalJsonRule = new OptionalJsonRule(jsonRuleStub);
17 |
18 | @Test
19 | public void optionalJsonRuleShouldIgnoreNullValue() {
20 | optionalJsonRule.validate(null);
21 | Mockito.verify(jsonRuleStub, never()).validate(null);
22 | }
23 |
24 | @Test
25 | public void optionalJsonRuleShouldValidateNonNullValue() {
26 | JsonValue jsonValue = Json.value(1);
27 | optionalJsonRule.validate(jsonValue);
28 | Mockito.verify(jsonRuleStub, only()).validate(jsonValue);
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/PercentageJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.Json;
6 | import com.eclipsesource.json.JsonValue;
7 | import org.junit.Test;
8 |
9 | public class PercentageJsonRuleTest {
10 |
11 | private static final JsonRule percentJsonRule = new PercentageJsonRule();
12 |
13 | @Test(expected = IllegalArgumentException.class)
14 | public void percentageJsonRuleShouldFailOnInvalidPercentageFormat() {
15 | JsonValue jsonValue = Json.value("A%");
16 | percentJsonRule.validate(jsonValue);
17 | }
18 |
19 | @Test(expected = IllegalArgumentException.class)
20 | public void percentageJsonRuleShouldFailOnValueBelowValidRange() {
21 | JsonValue jsonValue = Json.value("-1.0%");
22 | percentJsonRule.validate(jsonValue);
23 | }
24 |
25 | @Test(expected = IllegalArgumentException.class)
26 | public void percentageJsonRuleShouldFailOnValueAboveValidRange() {
27 | JsonValue jsonValue = Json.value("101.0%");
28 | percentJsonRule.validate(jsonValue);
29 | }
30 |
31 | @Test
32 | public void percentageJsonRuleShouldPassOnValidFormatAndRange() {
33 | JsonValue jsonValue = Json.value("2%");
34 | percentJsonRule.validate(jsonValue);
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/PeriodJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.Json;
6 | import com.eclipsesource.json.JsonValue;
7 | import org.junit.Test;
8 |
9 | public class PeriodJsonRuleTest {
10 |
11 | private static final JsonRule periodJsonRule = new PeriodJsonRule();
12 |
13 | @Test(expected = IllegalArgumentException.class)
14 | public void periodJsonRuleShouldFailOnInvalidPeriodFormat() {
15 | JsonValue jsonValue = Json.value("1 monthss");
16 | periodJsonRule.validate(jsonValue);
17 | }
18 |
19 | @Test
20 | public void percentageJsonRuleShouldPassOnValidDaysPeriod() {
21 | JsonValue oneDay = Json.value("1 day");
22 | JsonValue twoDays = Json.value("2 days");
23 | periodJsonRule.validate(oneDay);
24 | periodJsonRule.validate(twoDays);
25 | }
26 |
27 | @Test
28 | public void percentageJsonRuleShouldPassOnValidMonthPeriod() {
29 | JsonValue oneMonth = Json.value("1 month");
30 | JsonValue twoMonths = Json.value("2 months");
31 | periodJsonRule.validate(oneMonth);
32 | periodJsonRule.validate(twoMonths);
33 | }
34 |
35 | @Test
36 | public void percentageJsonRuleShouldPassOnValidYearPeriod() {
37 | JsonValue oneYear = Json.value("1 year");
38 | JsonValue twoYears = Json.value("2 years");
39 | periodJsonRule.validate(oneYear);
40 | periodJsonRule.validate(twoYears);
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/StringJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.Json;
6 | import com.eclipsesource.json.JsonValue;
7 | import org.junit.Test;
8 |
9 | public class StringJsonRuleTest {
10 |
11 | private static final JsonRule stringJsonRule = new StringJsonRule();
12 |
13 | @Test(expected = IllegalArgumentException.class)
14 | public void stringJsonRuleShouldFailNonStringType() {
15 | JsonValue jsonValue = Json.value(true);
16 | stringJsonRule.validate(jsonValue);
17 | }
18 |
19 | @Test
20 | public void stringJsonRuleShouldPassStringType() {
21 | JsonValue jsonValue = Json.value("string");
22 | stringJsonRule.validate(jsonValue);
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/StringLengthJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.Json;
6 | import com.eclipsesource.json.JsonValue;
7 | import org.junit.Test;
8 |
9 | public class StringLengthJsonRuleTest {
10 |
11 | private static final int VALIDATION_STRING_LENGTH = 2;
12 | private static final JsonRule stringLengthJsonRule = new StringLengthJsonRule(VALIDATION_STRING_LENGTH);
13 |
14 | @Test(expected = IllegalArgumentException.class)
15 | public void stringLengthJsonRuleShouldFailLowerLength() {
16 | String ltRequired = "a";
17 | JsonValue jsonValue = Json.value(ltRequired);
18 | stringLengthJsonRule.validate(jsonValue);
19 | }
20 |
21 | @Test(expected = IllegalArgumentException.class)
22 | public void stringLengthJsonRuleShouldFailUpperLength() {
23 | String gtRequired = "abc";
24 | JsonValue jsonValue = Json.value(gtRequired);
25 | stringLengthJsonRule.validate(jsonValue);
26 | }
27 |
28 | @Test
29 | public void stringLengthJsonRuleShouldPassValidLength() {
30 | String eqRequired = "ab";
31 | JsonValue jsonValue = Json.value(eqRequired);
32 | stringLengthJsonRule.validate(jsonValue);
33 | }
34 |
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/schema/rules/StringUppercaseJsonRuleTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.schema.rules;
2 |
3 | import org.mafagafogigante.dungeon.schema.JsonRule;
4 |
5 | import com.eclipsesource.json.Json;
6 | import com.eclipsesource.json.JsonValue;
7 | import org.junit.Test;
8 |
9 | public class StringUppercaseJsonRuleTest {
10 |
11 | private static final JsonRule uppercaseStringJsonRule = new UppercaseStringJsonRule();
12 |
13 | @Test(expected = IllegalArgumentException.class)
14 | public void uppercaseStringJsonRuleShouldFailLowercase() {
15 | String lowercase = "a";
16 | JsonValue jsonValue = Json.value(lowercase);
17 | uppercaseStringJsonRule.validate(jsonValue);
18 | }
19 |
20 | @Test
21 | public void uppercaseStringJsonRuleShouldPassUppercase() {
22 | String uppercase = "A";
23 | JsonValue jsonValue = Json.value(uppercase);
24 | uppercaseStringJsonRule.validate(jsonValue);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/stats/RecordTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.stats;
2 |
3 | import org.mafagafogigante.dungeon.stats.Record.Type;
4 |
5 | import org.junit.Assert;
6 | import org.junit.Test;
7 |
8 | public class RecordTest {
9 |
10 | @Test
11 | public void testUpdate() throws Exception {
12 | Record maximumRecord = new Record(Type.MAXIMUM);
13 | Assert.assertNull(maximumRecord.getValue());
14 | Assert.assertEquals("N/A", maximumRecord.toString());
15 | maximumRecord.update(1);
16 | Assert.assertTrue(maximumRecord.getValue().equals(1));
17 | Assert.assertEquals("1", maximumRecord.toString());
18 | maximumRecord.update(0); // An update that does not change the Record.
19 | Assert.assertTrue(maximumRecord.getValue().equals(1));
20 | Assert.assertEquals("1", maximumRecord.toString());
21 | maximumRecord.update(2); // An update that changes the Record.
22 | Assert.assertTrue(maximumRecord.getValue().equals(2));
23 | Assert.assertEquals("2", maximumRecord.toString());
24 |
25 | Record minimumRecord = new Record(Type.MINIMUM);
26 | Assert.assertNull(minimumRecord.getValue());
27 | Assert.assertEquals("N/A", minimumRecord.toString());
28 | minimumRecord.update(1);
29 | Assert.assertTrue(minimumRecord.getValue().equals(1));
30 | Assert.assertEquals("1", minimumRecord.toString());
31 | minimumRecord.update(0); // An update that changes the Record.
32 | Assert.assertTrue(minimumRecord.getValue().equals(0));
33 | Assert.assertEquals("0", minimumRecord.toString());
34 | minimumRecord.update(2); // An update that does not change the Record.
35 | Assert.assertTrue(minimumRecord.getValue().equals(0));
36 | Assert.assertEquals("0", minimumRecord.toString());
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/util/ShuffledRangeTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.util;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class ShuffledRangeTest {
7 |
8 | @Test
9 | public void testShuffle() throws Exception {
10 | // The special case of a ShuffledRange of a single element.
11 | ShuffledRange shuffledRange = new ShuffledRange(1, 2);
12 | int oldLast = shuffledRange.get(shuffledRange.getSize() - 1);
13 | shuffledRange.shuffle();
14 | int newFirst = shuffledRange.get(0);
15 | Assert.assertEquals(oldLast, newFirst);
16 | // ShuffledRanges of different lengths, checking one of the properties of the shuffle method a few times.
17 | for (int rangeEnd = 3; rangeEnd <= 5; rangeEnd++) {
18 | shuffledRange = new ShuffledRange(1, rangeEnd);
19 | for (int i = 0; i < 100; i++) {
20 | oldLast = shuffledRange.get(shuffledRange.getSize() - 1);
21 | shuffledRange.shuffle();
22 | newFirst = shuffledRange.get(0);
23 | Assert.assertNotEquals(oldLast, newFirst);
24 | }
25 | }
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/util/StopWatchTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.util;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | import java.util.concurrent.TimeUnit;
7 |
8 | public class StopWatchTest {
9 |
10 | @Test
11 | public void testToString() throws Exception {
12 | StopWatch stopWatch = new StopWatch();
13 | Assert.assertTrue(stopWatch.toString(TimeUnit.NANOSECONDS).endsWith("ns"));
14 | Assert.assertTrue(stopWatch.toString(TimeUnit.MICROSECONDS).endsWith("μs"));
15 | Assert.assertTrue(stopWatch.toString(TimeUnit.MILLISECONDS).endsWith("ms"));
16 | Assert.assertTrue(stopWatch.toString(TimeUnit.SECONDS).endsWith("s"));
17 | Assert.assertTrue(stopWatch.toString().endsWith("ms"));
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/util/SystemInformationTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.util;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class SystemInformationTest {
7 |
8 | @Test
9 | public void testToColoredStringListShouldHaveTheExpectedFormat() throws Exception {
10 | SystemInformation systemInformation = new SystemInformation();
11 | String string = systemInformation.toString();
12 | String expectedRegexp = "User: .*\nTime: .*\nDate: .*\nJava: .*\nHeap: .*\nOS: .*";
13 | Assert.assertTrue("SystemInformation string does not match the expected format", string.matches(expectedRegexp));
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/java/org/mafagafogigante/dungeon/util/TableTest.java:
--------------------------------------------------------------------------------
1 | package org.mafagafogigante.dungeon.util;
2 |
3 | import org.junit.Test;
4 |
5 | public class TableTest {
6 |
7 | @Test
8 | public void insertRowShouldWorkWithTheCorrectAmountOfArguments() throws Exception {
9 | Table table = new Table("A", "B");
10 | for (int i = 0; i < 100; i++) {
11 | table.insertRow("1", "2");
12 | }
13 | }
14 |
15 | @Test(expected = IllegalArgumentException.class)
16 | public void constructorShouldThrowAnExceptionIfThereAreNoArguments() throws Exception {
17 | new Table();
18 | }
19 |
20 | @Test(expected = IllegalArgumentException.class)
21 | public void constructorShouldThrowAnExceptionIfThereAreTooManyArguments() throws Exception {
22 | new Table("A", "B", "C", "D", "E", "F", "G");
23 | }
24 |
25 | @Test(expected = IllegalArgumentException.class)
26 | public void insertRowShouldThrowAnExceptionWithTooFewArguments() throws Exception {
27 | Table table = new Table("A", "B");
28 | table.insertRow("1");
29 | }
30 |
31 | @Test(expected = IllegalArgumentException.class)
32 | public void insertRowShouldThrowAnExceptionWithTooManyArguments() throws Exception {
33 | Table table = new Table("A", "B");
34 | table.insertRow("1", "2", "3");
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/stats/cloc.txt:
--------------------------------------------------------------------------------
1 | 3a944d539b896eeb389f83b53d8d7c4e591790c3
2 | -------------------------------------------------------------------------------
3 | Language files blank comment code
4 | -------------------------------------------------------------------------------
5 | Java 214 2474 6322 10438
6 | JSON 10 0 0 3476
7 | -------------------------------------------------------------------------------
8 | SUM: 224 2474 6322 13914
9 | -------------------------------------------------------------------------------
10 |
11 | 1e4f4106887d93474117630584b58f1763c19944
12 | -------------------------------------------------------------------------------
13 | Language files blank comment code
14 | -------------------------------------------------------------------------------
15 | Java 237 2503 2954 11336
16 | JSON 10 0 0 3847
17 | -------------------------------------------------------------------------------
18 | SUM: 247 2503 2954 15183
19 | -------------------------------------------------------------------------------
20 |
--------------------------------------------------------------------------------
/wiki/README.md:
--------------------------------------------------------------------------------
1 | # Updating the wiki
2 |
3 | Only [mafagafogigante](https://github.com/mafagafogigante/) or users with push
4 | rights to [dungeon](https://github.com/mafagafogigante/dungeon/) can do this.
5 |
6 | In order to update the GitHub wiki from the in-game wiki, run `wiki.sh` from
7 | the root directory of the project.
8 |
9 | The `wiki.sh` script simply runs `clone.sh`, `update.sh`, and `push.sh`, in
10 | this order.
11 |
--------------------------------------------------------------------------------
/wiki/clone.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Delete the wiki clone if it is there (shouldn't be)
4 | rm -rf dungeon.wiki
5 |
6 | # Clone the wiki
7 | git clone git@github.com:mafagafogigante/dungeon.wiki.git
8 |
--------------------------------------------------------------------------------
/wiki/push.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Commit changes and update remote
4 | cd dungeon.wiki
5 | git add *.md
6 | git commit -am "Regenerated the Wiki"
7 | git push origin
8 |
9 | # Self-destruct
10 | cd ..
11 | rm -rf dungeon.wiki
12 |
--------------------------------------------------------------------------------
/wiki/update.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Run the converter
4 | python3 wiki/wiki.py
5 |
--------------------------------------------------------------------------------
/wiki/wiki.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | bash wiki/clone.sh
4 | bash wiki/update.sh
5 | bash wiki/push.sh
6 |
--------------------------------------------------------------------------------