diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 7c34d9c..dc9f2b1 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -1,11 +1,14 @@
+
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/GameEngine.java b/Java-Ring/src/main/java/org/project/GameEngine.java
new file mode 100644
index 0000000..1662405
--- /dev/null
+++ b/Java-Ring/src/main/java/org/project/GameEngine.java
@@ -0,0 +1,271 @@
+package org.project;
+
+import org.project.entity.enemies.Enemy;
+import org.project.entity.players.*;
+import org.project.location.Location;
+import org.project.object.consumables.Consumable;
+import java.util.Scanner;
+
+/**
+ * Main game engine class that controls the game flow and manages player interactions.
+ * Handles initialization, game loop, combat, and menu systems.
+ */
+public class GameEngine {
+ // Game state variables
+ private Player player; // Current player character
+ private Location currentLocation; // Active game location
+ private Scanner scanner = new Scanner(System.in); // Input handler
+ private boolean gameRunning = true; // Main game loop flag
+
+ /**
+ * Starts the main game loop and manages the game lifecycle
+ */
+ public void startGame() {
+ initializePlayer(); // Set up player character
+ initializeLocations(); // Initialize game world
+
+ // Main game loop - runs while game is active and player is alive
+ while (gameRunning && player.isAlive()) {
+ displayMainMenu(); // Show player options
+ handleMainMenuInput(); // Process player choice
+ }
+
+ endGame(); // Handle game conclusion
+ }
+
+ /**
+ * Initializes player character with name and class selection
+ */
+ private void initializePlayer() {
+ System.out.println("=== CHARACTER CREATION ===");
+ System.out.print("Enter your name: ");
+ String name = scanner.nextLine();
+
+ // Class selection menu
+ System.out.println("Choose your class:");
+ System.out.println("1. Knight\n2. Wizard\n3. Assassin");
+
+ int classChoice = Integer.parseInt(scanner.nextLine());
+
+ // Create player based on class choice
+ player = switch (classChoice) {
+ case 1 -> new Knight(name); // Tank class
+ case 2 -> new Wizard(name); // Mage class
+ default -> new Knight(name); // Default to Knight
+ };
+
+ System.out.printf("%s the %s enters the Java Ring!%n",
+ player.getName(), player.getClass().getSimpleName());
+ }
+
+ /**
+ * Initializes game locations and starting area
+ */
+ private void initializeLocations() {
+ // Create starting location with description
+ currentLocation = new Location("Forgotten Forest",
+ "A dense woodland shrouded in mist");
+ }
+
+ /**
+ * Displays the main game menu options
+ */
+ private void displayMainMenu() {
+ System.out.println("\n=== MAIN MENU ===");
+ System.out.println("Location: " + currentLocation.getName());
+ System.out.println("1. Explore"); // Risk encounter
+ System.out.println("2. Character Info"); // View stats
+ System.out.println("3. Quit"); // Exit game
+ System.out.print("Choose an action: ");
+ }
+
+ /**
+ * Handles player input from main menu
+ */
+ private void handleMainMenuInput() {
+ int choice = getValidInput(1, 3); // Get validated input
+
+ switch (choice) {
+ case 1 -> explore(); // Enter exploration
+ case 2 -> displayCharacterInfo(); // Show character sheet
+ case 3 -> gameRunning = false; // Quit game
+ default -> System.out.println("Invalid choice!");
+ }
+ }
+
+ /**
+ * Handles exploration logic and random encounters
+ */
+ private void explore() {
+ System.out.println("\nYou venture deeper into " + currentLocation.getName());
+
+ // 70% chance of enemy encounter
+ if (Math.random() < 0.7) {
+ Enemy enemy = currentLocation.generateEnemy();
+ if (enemy != null) {
+ System.out.println("Encountered: " + enemy.getDescription());
+ startCombat(enemy); // Begin combat if enemy exists
+ } else {
+ System.out.println("The enemy mysteriously vanished...");
+ }
+ } else {
+ System.out.println("The path is clear for now...");
+ }
+ currentLocation.increaseDanger(); // Scale difficulty
+ }
+
+ /**
+ * Manages combat between player and enemy
+ * @param enemy The enemy to fight
+ */
+ private void startCombat(Enemy enemy) {
+ System.out.printf("%nA wild %s appears!%n", enemy.getName());
+
+ // Combat continues until one combatant is defeated
+ while (player.isAlive() && enemy.isAlive()) {
+ playerTurn(enemy); // Player action phase
+
+ if (!enemy.isAlive()) break; // Check if enemy defeated
+
+ enemyTurn(enemy); // Enemy action phase
+ }
+
+ // Combat resolution
+ if (player.isAlive()) {
+ System.out.printf("You defeated the %s!%n", enemy.getName());
+ player.gainExperience(enemy.getExpReward()); // Award XP
+ } else {
+ System.out.println("You have been defeated...");
+ }
+ }
+
+ /**
+ * Handles player's turn during combat
+ * @param enemy The current combat target
+ */
+ private void playerTurn(Enemy enemy) {
+ System.out.println("\n=== YOUR TURN ===");
+ // Display combat status
+ System.out.printf("HP: %d/%d | Enemy HP: %d%n",
+ player.getHealth(), player.getMaxHealth(), enemy.getHealth());
+
+ // Combat action menu
+ System.out.println("1. Attack");
+ System.out.println("2. Defend");
+ System.out.println("3. Special Ability");
+ System.out.println("4. Use Item");
+ System.out.print("Choose action: ");
+
+ int choice = getValidInput(1, 4); // Validate input
+
+ // Process player choice
+ switch (choice) {
+ case 1 -> { // Standard attack
+ player.attack(enemy);
+ System.out.printf("%s attacks %s!%n",
+ player.getName(), enemy.getName());
+ }
+ case 2 -> { // Defensive stance
+ player.defend();
+ System.out.println(player.getName() + " defends!");
+ }
+ case 3 -> { // Class-specific ability
+ if (player instanceof Knight) {
+ ((Knight)player).useSpecialAbility(enemy);
+ } else {
+ player.useSpecialAbility(enemy);
+ }
+ System.out.printf("%s uses special ability on %s!%n",
+ player.getName(), enemy.getName());
+ }
+ case 4 -> useItemInCombat(); // Inventory usage
+ default -> System.out.println("Invalid choice! Lost your turn...");
+ }
+ }
+
+ /**
+ * Validates player input within a specified range
+ * @param min Minimum valid value
+ * @param max Maximum valid value
+ * @return Validated user input
+ */
+ private int getValidInput(int min, int max) {
+ while (true) {
+ try {
+ int choice = Integer.parseInt(scanner.nextLine());
+ if (choice >= min && choice <= max) return choice;
+ System.out.printf("Enter %d-%d: ", min, max);
+ } catch (NumberFormatException e) {
+ System.out.print("(Numbers only) ");
+ }
+ }
+ }
+
+ /**
+ * Handles enemy's turn during combat
+ * @param enemy The attacking enemy
+ */
+ private void enemyTurn(Enemy enemy) {
+ System.out.printf("%n=== %s's TURN ===%n", enemy.getName());
+ enemy.attack(player); // Enemy performs attack
+ }
+
+ /**
+ * Manages item usage during combat
+ */
+ private void useItemInCombat() {
+ if (player.getInventory().isEmpty()) {
+ System.out.println("Your inventory is empty!");
+ return;
+ }
+
+ // Display inventory
+ System.out.println("\nAvailable items:");
+ for (int i = 0; i < player.getInventory().size(); i++) {
+ Consumable item = player.getInventory().get(i);
+ System.out.printf("%d. %s (%d uses)%n",
+ i + 1, item.getName(), item.getRemainingUses());
+ }
+
+ System.out.print("Select item (0 to cancel): ");
+ int choice = getValidInput(0, player.getInventory().size()) - 1;
+
+ if (choice >= 0) {
+ player.useItem(choice); // Use selected item
+ }
+ }
+
+ /**
+ * Displays character statistics and equipment
+ */
+ private void displayCharacterInfo() {
+ System.out.println("\n=== CHARACTER SHEET ===");
+ System.out.printf("Name: %s%n", player.getName());
+ System.out.printf("Class: %s%n", player.getClass().getSimpleName());
+ System.out.printf("Level: %d%n", player.getLevel());
+ System.out.printf("HP: %d/%d%n", player.getHealth(), player.getMaxHealth());
+ System.out.printf("XP: %d/%d%n",
+ player.getExperience(), player.getLevel() * 100);
+ System.out.printf("Weapon: %s%n", player.getWeapon().getDescription());
+ System.out.printf("Armor: %s%n", player.getArmor().getDescription());
+ }
+
+ /**
+ * Handles game conclusion with appropriate message
+ */
+ private void endGame() {
+ if (player.isAlive()) {
+ System.out.println("You leave the Java Ring... for now.");
+ } else {
+ System.out.println("GAME OVER");
+ }
+ }
+
+ /**
+ * Entry point for the game
+ * @param args Command line arguments (unused)
+ */
+ public static void main(String[] args) {
+ new GameEngine().startGame(); // Launch game
+ }
+}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/Main.java b/Java-Ring/src/main/java/org/project/Main.java
deleted file mode 100644
index c2e0550..0000000
--- a/Java-Ring/src/main/java/org/project/Main.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.project;
-
-import org.project.location.Location;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class Main {
- public static void main(String[] args) {
- // TODO: ADD SOME LOCATIONS TO YOUR GAME
- List locations = new ArrayList<>();
-
- // TODO: IMPLEMENT GAMEPLAY
- }
-}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/entity/Entity.java b/Java-Ring/src/main/java/org/project/entity/Entity.java
index 2a060f9..3ce5f25 100644
--- a/Java-Ring/src/main/java/org/project/entity/Entity.java
+++ b/Java-Ring/src/main/java/org/project/entity/Entity.java
@@ -1,21 +1,33 @@
package org.project.entity;
public interface Entity {
+ // Combat Core
void attack(Entity target);
-
- void defend();
-
+ void takeDamage(int damage);
void heal(int health);
- void fillMana(int mana);
- void takeDamage(int damage);
- int getMaxHP();
+ // Status methods
+ boolean isAlive();
+
+ int getHealth();
+ int getMaxHealth();
- int getMaxMP();
- /*
- TODO: ADD OTHER REQUIRED AND BONUS METHODS
- */
+ // Magic/Ability system
+ void useSpecialAbility(Entity target);
+ void defend();
+
+ String getName();
+
+ // Resource management
+ void gainExperience(int amount);
+ default boolean isDefending() { return false; }
+ void healMana(int amount);
+ default int getMana() { return 0; }
+ default int getMaxMana() { return 0; }
+
+
+ String getDescription();
}
diff --git a/Java-Ring/src/main/java/org/project/entity/enemies/Dragon.java b/Java-Ring/src/main/java/org/project/entity/enemies/Dragon.java
new file mode 100644
index 0000000..4906f07
--- /dev/null
+++ b/Java-Ring/src/main/java/org/project/entity/enemies/Dragon.java
@@ -0,0 +1,158 @@
+package org.project.entity.enemies;
+
+import org.project.entity.Entity;
+import org.project.object.weapons.Claw;
+
+/**
+ * Dragon enemy class - A powerful fire-breathing creature with damage reduction.
+ * Special abilities include fire breath attacks and burn damage over time.
+ */
+public class Dragon extends Enemy {
+ // Combat state tracking
+ private boolean usedFireBreath; // Flag for emergency fire breath
+ private static final int FIRE_BREATH_COOLDOWN = 3; // Turns between fire breaths
+ private int fireBreathCooldown = 0; // Current cooldown counter
+ private static final double BURN_CHANCE = 0.3; // 30% chance to apply burn
+
+ /**
+ * Constructs a new Dragon enemy
+ * @param health Initial health points
+ * @param expReward Experience granted when defeated
+ * @param claw Natural weapon (Claw) for basic attacks
+ */
+ public Dragon(int health, int expReward, Claw claw) {
+ super("Dragon", health, new Claw(), expReward);
+ this.usedFireBreath = false;
+ }
+
+ /**
+ * Dragon's attack logic with fire breath conditions
+ * @param target The entity being attacked
+ */
+ @Override
+ public void attack(Entity target) {
+ // Emergency fire breath when below 50% health (once per combat)
+ if (!usedFireBreath && health < maxHealth / 2) {
+ useSpecialAbility(target);
+ usedFireBreath = true;
+ }
+ // Random fire breath (25% chance when off cooldown)
+ else if (fireBreathCooldown <= 0 && Math.random() < 0.25) {
+ useSpecialAbility(target);
+ fireBreathCooldown = FIRE_BREATH_COOLDOWN;
+ }
+ // Standard claw attack
+ else {
+ super.attack(target);
+ // Reduce cooldown if active
+ if (fireBreathCooldown > 0) {
+ fireBreathCooldown--;
+ }
+ }
+ }
+
+ /**
+ * Dragon's special ability - Fire Breath
+ * Deals heavy damage with chance to apply burn effect
+ * @param target The entity being targeted
+ */
+ @Override
+ public void useSpecialAbility(Entity target) {
+ System.out.println("Dragon rears back and unleashes a torrent of flames!");
+
+ // Calculate base damage (2.5x weapon damage)
+ int baseDamage = (int) (weapon.getDamage() * 2.5);
+
+ // Halve damage if target is defending
+ int actualDamage = target.isDefending() ? baseDamage / 2 : baseDamage;
+
+ // Apply damage
+ target.takeDamage(actualDamage);
+ System.out.printf("%s takes %d fire damage!%n", target.getName(), actualDamage);
+
+ // 30% chance to apply burn effect
+ if (Math.random() < BURN_CHANCE) {
+ int burnDamage = (int) (baseDamage * 0.3);
+ applyBurn(target, burnDamage);
+ }
+
+ // Dragon takes 5% max health as self-damage (exhaustion)
+ this.takeDamage((int) (maxHealth * 0.05));
+ }
+
+ /**
+ * Applies burn damage over time (3 turns)
+ * @param target The burning entity
+ * @param burnDamage Damage per turn
+ */
+ private void applyBurn(Entity target, int burnDamage) {
+ System.out.printf(" %s catches fire and will take %d damage over time!%n",
+ target.getName(), burnDamage * 3);
+ System.out.println(target.getName() + " is burning!");
+
+ // Burn effect in separate thread (non-blocking)
+ new Thread(() -> {
+ try {
+ // Damage over 3 turns
+ for (int i = 0; i < 3 && target.isAlive(); i++) {
+ Thread.sleep(2000); // 2 second delay between ticks
+ target.takeDamage(burnDamage);
+ System.out.println(target.getName() + " takes " + burnDamage + " burn damage!");
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }).start();
+ }
+
+ /**
+ * Dragon takes reduced damage due to thick scales
+ * @param amount Incoming damage amount
+ */
+ @Override
+ public void takeDamage(int amount) {
+ // 25% damage reduction
+ int reducedDamage = (int) (amount * 0.75);
+ super.takeDamage(reducedDamage);
+ System.out.println("Dragon's scales reduce damage to " + reducedDamage + "!");
+ }
+
+ // --- Inherited Method Implementations ---
+
+ @Override
+ public String getName() {
+ return "Dragon";
+ }
+
+ @Override
+ public void gainExperience(int amount) {
+ // Dragons don't gain experience
+ }
+
+ @Override
+ public void healMana(int amount) {
+ // Dragons don't use mana
+ }
+
+ @Override
+ public int getMana() {
+ return 0; // Dragons have no mana pool
+ }
+
+ @Override
+ public int getMaxMana() {
+ return 0; // Dragons have no mana pool
+ }
+
+ /**
+ * Provides formatted description with current status
+ * @return String describing dragon and its health
+ */
+ @Override
+ public String getDescription() {
+ return String.format(
+ "Dragon with fiery breath (Reduces damage by 25% | Health: %d/%d)",
+ health, maxHealth
+ );
+ }
+}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/entity/enemies/Enemy.java b/Java-Ring/src/main/java/org/project/entity/enemies/Enemy.java
index 1fcc491..1c92d96 100644
--- a/Java-Ring/src/main/java/org/project/entity/enemies/Enemy.java
+++ b/Java-Ring/src/main/java/org/project/entity/enemies/Enemy.java
@@ -1,35 +1,129 @@
package org.project.entity.enemies;
+import org.project.entity.Entity;
import org.project.object.weapons.Weapon;
-// TODO: UPDATE IMPLEMENTATION
-public abstract class Enemy {
- Weapon weapon;
- private int hp;
- private int mp;
+/**
+ * Abstract base class for all enemy entities in the game.
+ * Provides common functionality and attributes shared by all enemies.
+ */
+public abstract class Enemy implements Entity {
- public Enemy(int hp, int mp, Weapon weapon) {
- this.hp = hp;
- this.mp = mp;
+ // Core enemy attributes
+ protected final String name; // Enemy's display name
+ protected int health; // Current health points
+ protected int maxHealth; // Maximum health capacity
+ protected Weapon weapon; // Equipped weapon
+ protected int expReward; // Experience granted when defeated
+ /**
+ * Constructs a new Enemy instance.
+ *
+ * @param name The name of the enemy
+ * @param health Initial/maximum health points
+ * @param weapon The weapon this enemy uses
+ * @param expReward Experience points awarded when defeated
+ */
+ public Enemy(String name, int health, Weapon weapon, int expReward) {
+ this.name = name;
+ this.maxHealth = health;
+ this.health = health; // Start at full health
this.weapon = weapon;
+ this.expReward = expReward;
}
- // TODO: (BONUS) UPDATE THE FORMULA OF TAKING DAMAGE
+ /**
+ * Performs an attack on the target entity using the enemy's weapon.
+ *
+ * @param target The entity to attack
+ */
@Override
- public void takeDamage(int damage) {
- hp -= damage;
+ public void attack(Entity target) {
+ System.out.println(name + " attacks!");
+ weapon.use(target); // Delegate attack to equipped weapon
}
- public int getHp() {
- return hp;
+ /**
+ * Reduces the enemy's health by the specified amount.
+ *
+ * @param amount The amount of damage to take
+ */
+ @Override
+ public void takeDamage(int amount) {
+ health -= amount;
+ System.out.printf("%s took %d damage (%d/%d HP)%n",
+ name, amount, health, maxHealth);
+ }
+
+ /**
+ * Restores health points to the enemy.
+ *
+ * @param amount The amount of health to restore
+ */
+ @Override
+ public void heal(int amount) {
+ health = Math.min(health + amount, maxHealth); // Prevent overhealing
+ System.out.println(name + " recovered " + amount + " HP!");
+ }
+
+ /**
+ * Abstract method for enemy descriptions.
+ * Must be implemented by concrete enemy classes.
+ *
+ * @return A formatted description of the enemy
+ */
+ @Override
+ public abstract String getDescription();
+
+ // ========== GETTER METHODS ========== //
+
+ /**
+ * @return The enemy's name
+ */
+ @Override
+ public String getName() {
+ return name;
}
- public int getMp() {
- return mp;
+ /**
+ * @return Current health points
+ */
+ @Override
+ public int getHealth() {
+ return health;
+ }
+
+ /**
+ * @return Maximum health capacity
+ */
+ @Override
+ public int getMaxHealth() {
+ return maxHealth;
+ }
+
+ /**
+ * @return Experience points awarded when defeated
+ */
+ public int getExpReward() {
+ return expReward;
}
- public Weapon getWeapon() {
- return weapon;
+ /**
+ * Checks if the enemy is still alive.
+ *
+ * @return true if health > 0, false otherwise
+ */
+ @Override
+ public boolean isAlive() {
+ return health > 0;
+ }
+
+ /**
+ * Default defend action for enemies.
+ * Can be overridden by specific enemy types.
+ */
+ @Override
+ public void defend() {
+ System.out.println(name + " braces for impact!");
}
-}
+}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/entity/enemies/Goblin.java b/Java-Ring/src/main/java/org/project/entity/enemies/Goblin.java
new file mode 100644
index 0000000..ae907b9
--- /dev/null
+++ b/Java-Ring/src/main/java/org/project/entity/enemies/Goblin.java
@@ -0,0 +1,81 @@
+package org.project.entity.enemies;
+
+import org.project.entity.Entity;
+import org.project.object.weapons.Dagger;
+
+public class Goblin extends Enemy {
+ private static final double DODGE_CHANCE = 0.25;
+ private static final int STEAL_AMOUNT = 5;
+ private boolean hasStolen = false;
+
+ public Goblin(int health, int expReward, Dagger dagger) {
+ super("Goblin", health, new Dagger(), expReward);
+ }
+
+ @Override
+ public void gainExperience(int amount) {
+ // Enemies don't gain experience
+ }
+
+ @Override
+ public boolean isDefending() {
+ return super.isDefending();
+ }
+
+ @Override
+ public void healMana(int amount) {
+
+ }
+
+ @Override
+ public int getMana() {
+ return super.getMana();
+ }
+
+ @Override
+ public void takeDamage(int amount) {
+ if (Math.random() < DODGE_CHANCE) {
+ System.out.println("Goblin nimbly dodges the attack!");
+ return;
+ }
+ super.takeDamage(amount);
+ }
+
+ @Override
+ public String getName() {
+ return "Goblin";
+ }
+
+
+
+ @Override
+ public void useSpecialAbility(Entity target) {
+ if (!hasStolen) {
+ // Goblin's dirty trick: steals HP on first special use
+ int damage = STEAL_AMOUNT + (int) (Math.random() * 5);
+ target.takeDamage(damage);
+ this.heal(damage);
+ System.out.printf("Goblin stabs %s and steals %d HP!%n",
+ target.getName(), damage);
+ hasStolen = true;
+ } else {
+ // Regular attack if already used special
+ System.out.println("Goblin attempts another dirty trick but fails!");
+ super.attack(target);
+ }
+ }
+
+ @Override
+ public void attack(Entity target) {
+ // 10% chance to use special ability randomly
+ if (Math.random() < 0.1) {
+ useSpecialAbility(target);
+ } else {
+ super.attack(target);
+ }
+ }
+ @Override
+ public String getDescription() {
+ return "A sneaky goblin that fights dirty (Dodge chance: 25%)";
+ }
+}
diff --git a/Java-Ring/src/main/java/org/project/entity/enemies/Skeleton.java b/Java-Ring/src/main/java/org/project/entity/enemies/Skeleton.java
index 8c3e638..58da3d0 100644
--- a/Java-Ring/src/main/java/org/project/entity/enemies/Skeleton.java
+++ b/Java-Ring/src/main/java/org/project/entity/enemies/Skeleton.java
@@ -1,6 +1,64 @@
package org.project.entity.enemies;
-// TODO: UPDATE IMPLEMENTATION
-public class Skeleton {
- // TODO: DESIGN ENEMY'S WEAPON AND ARMOR AND IMPLEMENT THE CONSTRUCTOR
-}
+import org.project.entity.Entity;
+import org.project.object.weapons.RustySword;
+
+public class Skeleton extends Enemy {
+ private boolean hasResurrected;
+
+ public Skeleton(int health, int expReward, RustySword rustySword) {
+ super("Skeleton", health, new RustySword(), expReward);
+ this.hasResurrected = false;
+ }
+
+ @Override
+ public void takeDamage(int amount) {
+ super.takeDamage(amount);
+ if (!isAlive() && !hasResurrected) {
+ resurrect();
+ }
+ }
+
+ @Override
+ public String getDescription() {
+ return "A reanimated skeleton with a rusty sword. (Resurrects once)";
+ }
+
+ @Override
+ public String getName() {
+ return "Skeleton";
+ }
+
+ @Override
+ public void useSpecialAbility(Entity target) {
+ System.out.println("Sneaky Skeleton doesn't have a super power" +
+ " but this bastard got two lives ;) ");
+ }
+
+ @Override
+ public void gainExperience(int amount) {
+// Enemies don't gain experience
+ }
+
+ @Override
+ public boolean isDefending() {
+ return super.isDefending();
+ }
+
+ @Override
+ public void healMana(int amount) {
+
+ }
+
+ @Override
+ public int getMana() {
+ return super.getMana();
+ }
+
+ private void resurrect() {
+ health = maxHealth / 2;
+ hasResurrected = true;
+ System.out.println("The skeleton reassembles itself!");
+ }
+
+}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/entity/players/Knight.java b/Java-Ring/src/main/java/org/project/entity/players/Knight.java
index 14d8fa2..e420de0 100644
--- a/Java-Ring/src/main/java/org/project/entity/players/Knight.java
+++ b/Java-Ring/src/main/java/org/project/entity/players/Knight.java
@@ -1,6 +1,101 @@
package org.project.entity.players;
-// TODO: UPDATE IMPLEMENTATION
-public class Knight {
- // TODO: DESIGN KNIGHT'S WEAPON AND ARMOR AND IMPLEMENT THE CONSTRUCTOR
-}
+import org.project.entity.Entity;
+import org.project.object.armors.KnightArmor;
+import org.project.object.weapons.Sword;
+
+/**
+ * The Knight player class - A heavily armored warrior specializing in melee combat
+ * and defensive abilities. Features a powerful kick special ability with cooldown.
+ */
+public class Knight extends Player {
+
+ // Combat cooldown tracking
+ private int kickCooldown; // Turns remaining until kick can be used again
+ private static final int KICK_DAMAGE = 35; // Base damage for the kick ability
+
+ /**
+ * Constructs a new Knight character with default equipment
+ * @param name The knight's display name
+ */
+ public Knight(String name) {
+ super(name, 200, 30, new Sword(), new KnightArmor()); // High health, medium mana
+ this.kickCooldown = 0; // Ability starts ready
+ }
+
+ /**
+ * Checks if the knight's kick ability is available
+ * @return true if kick can be used, false if on cooldown
+ */
+ public boolean hasKickReady() {
+ return kickCooldown <= 0;
+ }
+
+ /**
+ * Knight's special ability - Mighty Kick
+ * Deals heavy damage with scaling based on level
+ * @param target The entity to attack
+ */
+ @Override
+ public void useSpecialAbility(Entity target) {
+ if (hasKickReady()) {
+ // Calculate damage: base + (2 * level)
+ int totalDamage = KICK_DAMAGE + (level * 2);
+ System.out.printf("%s performs a mighty kick (%d damage)!%n",
+ name, totalDamage);
+ target.takeDamage(totalDamage);
+ kickCooldown = 3; // 3-turn cooldown
+ } else {
+ System.out.printf("Kick on cooldown (%d turns remaining)%n",
+ kickCooldown);
+ }
+ }
+
+ /**
+ * Reduces all active cooldowns by 1 turn
+ * Called automatically after each attack
+ */
+ public void reduceCooldowns() {
+ if (kickCooldown > 0) kickCooldown--;
+ }
+
+ /**
+ * Performs a standard attack and reduces cooldowns
+ * @param target The entity to attack
+ */
+ @Override
+ public void attack(Entity target) {
+ super.attack(target); // Perform basic weapon attack
+ reduceCooldowns(); // Progress ability cooldowns
+ }
+
+ /**
+ * Generates a character status description
+ * @return Formatted string with health and ability status
+ */
+ @Override
+ public String getDescription() {
+ return String.format("%s - Lvl %d Knight (%d/%d HP) | %s",
+ name, level, health, maxHealth,
+ hasKickReady() ? "Kick Ready" : "Kick CD: " + kickCooldown);
+ }
+
+ // ====== Inherited Method Implementations ====== //
+
+ /**
+ * @return The knight's name
+ */
+ @Override
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Placeholder for item usage functionality
+ * @param target The target entity (unused)
+ */
+ @Override
+ public void use(Entity target) {
+ // TODO: Implement knight-specific item interactions
+ }
+}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/entity/players/Player.java b/Java-Ring/src/main/java/org/project/entity/players/Player.java
index 674905a..dac912a 100644
--- a/Java-Ring/src/main/java/org/project/entity/players/Player.java
+++ b/Java-Ring/src/main/java/org/project/entity/players/Player.java
@@ -1,81 +1,200 @@
package org.project.entity.players;
+import java.util.ArrayList;
+import java.util.List;
import org.project.entity.Entity;
import org.project.object.armors.Armor;
+import org.project.object.consumables.Consumable;
+import org.project.object.consumables.Flask;
import org.project.object.weapons.Weapon;
-// TODO: UPDATE IMPLEMENTATION
-public abstract class Player {
- protected String name;
- Weapon weapon;
- Armor armor;
- private int hp;
- private int maxHP;
- private int mp;
- private int maxMP;
-
- public Player(String name, int hp, int mp, Weapon weapon, Armor armor) {
+/**
+ * Abstract base class representing a player character in the game.
+ * Contains core player systems including combat, inventory, and progression.
+ */
+public abstract class Player implements Entity {
+
+ // Character Attributes
+ protected final String name; // Player's name
+ protected int health; // Current health points
+ protected int maxHealth; // Maximum health capacity
+ protected static int mana; // Current mana points
+ protected static int maxMana; // Maximum mana capacity
+ protected Weapon weapon; // Equipped weapon
+ protected Armor armor; // Equipped armor
+ protected int level; // Current character level
+ protected int experience; // Accumulated experience
+ protected static List inventory; // Item inventory
+ protected boolean defending; // Defense state flag
+
+ /**
+ * Constructs a new Player character with starting equipment.
+ *
+ * @param name Character name
+ * @param maxHealth Starting maximum health
+ * @param maxMana Starting maximum mana
+ * @param weapon Starting weapon
+ * @param armor Starting armor
+ */
+ public Player(String name, int maxHealth, int maxMana, Weapon weapon, Armor armor) {
this.name = name;
- this.hp = hp;
- this.mp = mp;
-
+ this.maxHealth = maxHealth;
+ this.health = maxHealth; // Start at full health
+ this.maxMana = maxMana;
+ this.mana = maxMana; // Start at full mana
this.weapon = weapon;
this.armor = armor;
+ this.level = 1; // Start at level 1
+ this.experience = 0; // Start with 0 XP
+ this.inventory = new ArrayList<>();
+ this.inventory.add(new Flask()); // Give starting health potion
+ this.defending = false; // Not defending initially
}
+ // ========== COMBAT METHODS ========== //
+
+ /**
+ * Abstract method for class-specific special abilities.
+ * Must be implemented by concrete player classes.
+ *
+ * @param target The entity to use the ability on
+ */
+ public abstract void use(Entity target);
+
+ /**
+ * Performs a basic attack using the equipped weapon.
+ *
+ * @param target The entity to attack
+ */
@Override
public void attack(Entity target) {
- target.takeDamage(weapon.getDamage());
+ weapon.use(target); // Delegate attack to weapon
}
+ /**
+ * Enters a defensive stance, reducing incoming damage.
+ */
@Override
public void defend() {
- // TODO: (BONUS) IMPLEMENT A DEFENSE METHOD FOR SHIELDS
+ defending = true;
+ System.out.println(name + " takes defensive stance!");
}
- // TODO: (BONUS) UPDATE THE FORMULA OF TAKING DAMAGE
+ /**
+ * Takes damage after armor mitigation.
+ *
+ * @param amount Raw damage amount before reduction
+ */
@Override
- public void takeDamage(int damage) {
- hp -= damage - armor.getDefense();
+ public void takeDamage(int amount) {
+ int reducedDamage = armor.protect(amount); // Apply armor reduction
+ health -= reducedDamage;
+ defending = false; // Defense ends after being hit
+
+ System.out.printf("%s took %d damage (reduced from %d)%n",
+ name, reducedDamage, amount);
+
+ if (health <= 0) {
+ System.out.println(name + " has been defeated!");
+ }
}
+ // ========== HEALTH/MANA MANAGEMENT ========== //
+
+ /**
+ * Restores health points.
+ *
+ * @param amount Amount to heal (won't exceed maxHealth)
+ */
@Override
- public void heal(int health) {
- hp += health;
- if (hp > maxHP) {
- hp = maxHP;
- }
+ public void heal(int amount) {
+ health = Math.min(health + amount, maxHealth);
+ System.out.println(name + " recovered " + amount + " HP!");
}
+ /**
+ * Restores mana points.
+ *
+ * @param amount Amount to restore (won't exceed maxMana)
+ */
@Override
- public void fillMana(int mana) {
- mp += mana;
- if (mp > maxMP) {
- mp = maxMP;
+ public void healMana(int amount) {
+ mana = Math.min(maxMana, mana + amount);
+ System.out.println(name + " recovered " + amount + " MP!");
+ }
+
+ // ========== PROGRESSION SYSTEM ========== //
+
+ /**
+ * Awards experience points and handles level-ups.
+ *
+ * @param amount Experience points to add
+ */
+ @Override
+ public void gainExperience(int amount) {
+ experience += amount;
+ System.out.println(name + " gained " + amount + " XP!");
+
+ // Level up if enough experience (100 XP per level)
+ if (experience >= level * 100) {
+ levelUp();
+ }
+ }
+
+ /**
+ * Increases character level and improves stats.
+ */
+ private void levelUp() {
+ level++;
+ maxHealth += 10; // HP increase per level
+ maxMana += 5; // MP increase per level
+ health = maxHealth; // Fully heal on level up
+ mana = maxMana; // Fully restore mana
+ System.out.printf("%s leveled up to %d!%n", name, level);
+ }
+
+ // ========== INVENTORY SYSTEM ========== //
+
+ /**
+ * Uses an item from inventory.
+ *
+ * @param index Inventory slot number (0-based)
+ */
+ public void useItem(int index) {
+ if (index >= 0 && index < inventory.size()) {
+ Consumable item = inventory.get(index);
+ item.use(this); // Apply item effect
+
+ // Remove if depleted
+ if (item.getRemainingUses() <= 0) {
+ inventory.remove(index);
+ }
}
}
+ // ========== GETTER METHODS ========== //
+ @Override
public String getName() {
return name;
}
- public int getHp() {
- return hp;
+ @Override
+ public int getHealth() {
+ return health;
}
@Override
- public int getMaxHP() {
- return maxHP;
+ public int getMaxHealth() {
+ return maxHealth;
}
- public int getMp() {
- return mp;
+ public int getMana() {
+ return mana;
}
- @Override
- public int getMaxMP() {
- return maxMP;
+ public int getMaxMana() {
+ return maxMana;
}
public Weapon getWeapon() {
@@ -86,4 +205,25 @@ public Armor getArmor() {
return armor;
}
-}
+ public int getLevel() {
+ return level;
+ }
+
+ public int getExperience() {
+ return experience;
+ }
+
+ public List getInventory() {
+ return inventory;
+ }
+
+ @Override
+ public boolean isAlive() {
+ return health > 0;
+ }
+
+ @Override
+ public boolean isDefending() {
+ return defending;
+ }
+}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/entity/players/Wizard.java b/Java-Ring/src/main/java/org/project/entity/players/Wizard.java
new file mode 100644
index 0000000..5d2bb70
--- /dev/null
+++ b/Java-Ring/src/main/java/org/project/entity/players/Wizard.java
@@ -0,0 +1,151 @@
+package org.project.entity.players;
+
+import org.project.entity.Entity;
+import org.project.object.armors.Armor;
+import org.project.object.consumables.ManaPotion;
+import org.project.object.weapons.Staff;
+
+public class Wizard extends Player {
+ private int manaRegenRate;
+ private static final int BASE_MANA_REGEN = 5;
+ private static final int FIREBALL_COST = 20;
+ private static final int FIREBALL_DAMAGE = 40;
+
+ public Wizard(String name) {
+ super(name, 120, 100, new Staff(), new RobeArmor());
+ this.manaRegenRate = BASE_MANA_REGEN;
+ this.inventory.add(new ManaPotion()); // Starting mana potion
+ }
+
+ @Override
+ public void use(Entity target) {
+ if (target == null) {
+ System.out.println(name + " waves their staff but nothing happens!");
+ return;
+ }
+
+ // Check if using a mana potion when mana is low
+ if (mana < maxMana * 0.3 && hasManaPotion()) {
+ useManaPotion();
+ return;
+ }
+
+ // Default spell casting behavior
+ if (mana >= FIREBALL_COST) {
+ castFireball(target);
+ } else if (mana >= 10) {
+ castMagicMissile(target);
+ } else {
+ System.out.println(name + " is too exhausted to cast spells!");
+ basicStaffAttack(target);
+ }
+ }
+
+ @Override
+ public void useSpecialAbility(Entity target) {
+ if (mana >= FIREBALL_COST) {
+ castFireball(target);
+ } else {
+ System.out.printf("%s doesn't have enough mana! (Need %d, has %d)%n",
+ name, FIREBALL_COST, mana);
+ }
+ }
+
+ @Override
+ public void attack(Entity target) {
+ if (Math.random() < 0.3 && mana >= 10) { // 30% chance to use magic missile
+ castMagicMissile(target);
+ } else {
+ basicStaffAttack(target);
+ }
+ regenerateMana();
+ }
+
+ private void castFireball(Entity target) {
+ System.out.printf("%s hurls a massive Fireball at %s! (%d damage)%n",
+ name, target.getName(), FIREBALL_DAMAGE);
+ target.takeDamage(FIREBALL_DAMAGE);
+ mana -= FIREBALL_COST;
+
+ // 20% chance to apply burn effect
+ if (Math.random() < 0.2) {
+ applyBurnEffect(target, FIREBALL_DAMAGE / 4);
+ }
+ }
+
+ private void castMagicMissile(Entity target) {
+ int damage = 15 + (int)(Math.random() * 10);
+ System.out.printf("%s shoots Magic Missiles at %s! (%d damage)%n",
+ name, target.getName(), damage);
+ target.takeDamage(damage);
+ mana -= 10;
+ }
+
+ private void basicStaffAttack(Entity target) {
+ System.out.printf("%s bonks %s with their staff!%n", name, target.getName());
+ super.attack(target); // Uses the default weapon attack
+ }
+
+ private void regenerateMana() {
+ mana = Math.min(maxMana, mana + manaRegenRate);
+ }
+
+ private boolean hasManaPotion() {
+ return inventory.stream()
+ .anyMatch(item -> item instanceof ManaPotion && item.getRemainingUses() > 0);
+ }
+
+ private void useManaPotion() {
+ inventory.stream()
+ .filter(item -> item instanceof ManaPotion)
+ .findFirst()
+ .ifPresent(potion -> {
+ System.out.println(name + " quickly drinks a mana potion!");
+ potion.use(this);
+ });
+ }
+
+ private void applyBurnEffect(Entity target, int burnDamage) {
+ System.out.printf("%s catches fire! (%d burn damage over 3 turns)%n",
+ target.getName(), burnDamage * 3);
+
+ // Simple turn-based burn effect
+ new Thread(() -> {
+ try {
+ for (int i = 0; i < 3 && target.isAlive(); i++) {
+ Thread.sleep(1500); // Simulate turn delay
+ target.takeDamage(burnDamage);
+ System.out.println(target.getName() + " takes " + burnDamage + " burn damage!");
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }).start();
+ }
+
+ @Override
+ public String getDescription() {
+ return String.format("%s - Lvl %d Wizard (%d/%d HP, %d/%d MP)",
+ name, level, health, maxHealth, mana, maxMana);
+ }
+
+ // Wizard-specific armor
+ private static class RobeArmor extends Armor {
+ public RobeArmor() {
+ super("Wizard's Robe", 10, 80);
+ }
+
+ @Override
+ public int protect(int incomingDamage) {
+ // Robes reduce magic damage more than physical
+ int reducedDamage = (int)(incomingDamage * 0.8); // 20% reduction
+ durability -= 1; // Robes degrade slower
+ return reducedDamage;
+ }
+
+ @Override
+ public void use(Entity target) {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/location/Location.java b/Java-Ring/src/main/java/org/project/location/Location.java
index dfa9cb8..45f4586 100644
--- a/Java-Ring/src/main/java/org/project/location/Location.java
+++ b/Java-Ring/src/main/java/org/project/location/Location.java
@@ -1,32 +1,126 @@
package org.project.location;
-import org.project.entity.enemies.Enemy;
-
-import java.util.ArrayList;
+import java.util.Random;
+import org.project.entity.enemies.*;
+import org.project.object.weapons.*;
+/**
+ * Represents a game location with biome-specific properties and enemy spawning logic.
+ * Handles danger level progression and location-based enemy generation.
+ */
public class Location {
- private String name;
- private ArrayList enemies;
+ /**
+ * Biome types that affect enemy spawn rates and location properties
+ */
+ public enum Biome {
+ FOREST, // Dense woodland areas
+ CAVE, // Underground caverns
+ MOUNTAIN, // High altitude terrain
+ RUINS // Ancient structures
+ }
+
+ // Location properties
+ private String name; // Location display name
+ private String description; // Flavor text description
+ private int dangerLevel; // Difficulty scaling factor (1+)
+ private Random random = new Random(); // Random number generator
+ private Biome biome; // Biome type
+
+ /**
+ * Constructs a new game location
+ * @param name The location's name
+ * @param description Descriptive text about the location
+ * @param biome The biome type (FOREST, CAVE, etc.)
+ */
+ public Location(String name, String description, Biome biome) {
+ this.name = name;
+ this.description = description;
+ this.dangerLevel = 1; // Start at minimum danger
+ this.biome = biome;
+ }
+
+ /**
+ * Generates an enemy scaled to current danger level
+ * @return A new Enemy instance (Goblin/Skeleton/Dragon)
+ * @throws IllegalStateException if invalid enemy type generated
+ */
+ public Enemy generateEnemy() {
+ try {
+ // Scale stats based on danger level
+ int scaledHealth = 50 + (dangerLevel * 20);
+ int scaledExp = 30 + (dangerLevel * 10);
+
+ // Randomly select enemy type (0-2)
+ int enemyType = random.nextInt(3);
- public Location(ArrayList locations, ArrayList enemies) {
- this.locations = locations;
- this.enemies = enemies;
+ System.out.println("Generating enemy type: " + enemyType); // Debug output
+
+ return switch (enemyType) {
+ case 0 -> new Goblin(scaledHealth, scaledExp, new Dagger());
+ case 1 -> new Skeleton(scaledHealth, scaledExp, new RustySword());
+ case 2 -> new Dragon(scaledHealth, scaledExp, new Claw());
+ default -> throw new IllegalStateException("Invalid enemy type");
+ };
+ } catch (Exception e) {
+ System.err.println("Failed to generate enemy: " + e.getMessage());
+ return null; // Fallback for error cases
+ }
+ }
+
+ /**
+ * Gets biome-specific enemy spawn weights
+ * @return Array of weights [Goblin%, Skeleton%, Dragon%]
+ */
+ private double[] getBiomeWeights() {
+ return switch (biome) {
+ case FOREST -> new double[]{70, 25, 5}; // Mostly Goblins
+ case CAVE -> new double[]{30, 65, 5}; // Skeleton-heavy
+ case MOUNTAIN -> new double[]{10, 30, 60}; // Dragon territory
+ case RUINS -> new double[]{40, 55, 5}; // Undead-focused
+ default -> new double[]{60, 35, 5}; // Default mix
+ };
}
- /*
- TODO: (BONUS) RESET EACH LOCATION AFTER PLAYER LEAVES
- */
+ /**
+ * Increases location danger level
+ * Makes future enemies stronger and increases rewards
+ */
+ public void increaseDanger() {
+ dangerLevel++;
+ System.out.println(name + " grows more dangerous...");
+ }
+ // ========== GETTER METHODS ========== //
+
+ /**
+ * @return Location name
+ */
public String getName() {
return name;
}
- public ArrayList getLocations() {
- return locations;
+ /**
+ * @return Location description text
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * @return Current danger level (1+)
+ */
+ public int getDangerLevel() {
+ return dangerLevel;
}
- public ArrayList getEnemies() {
- return enemies;
+ /**
+ * Gets descriptive danger rating
+ * @return "Safe", "Risky", or "Deadly" based on danger level
+ */
+ public String getDangerDescription() {
+ if (dangerLevel <= 2) return "Safe";
+ if (dangerLevel <= 5) return "Risky";
+ return "Deadly";
}
-}
+}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/object/Object.java b/Java-Ring/src/main/java/org/project/object/Object.java
index 922cbd5..83c9460 100644
--- a/Java-Ring/src/main/java/org/project/object/Object.java
+++ b/Java-Ring/src/main/java/org/project/object/Object.java
@@ -3,9 +3,18 @@
import org.project.entity.Entity;
public interface Object {
+ // Core method all objects must implement
void use(Entity target);
-
- /*
- TODO: ADD OTHER REQUIRED AND BONUS METHODS
- */
-}
+
+ // Identification methods
+ String getName();
+ String getDescription();
+
+ // Inventory management helpers
+ boolean isConsumable();
+ int getValue(); // Gold value
+
+ // Equipment status methods (default implementations)
+ default boolean isBroken() { return false; }
+ default void repair() {}
+}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/object/armors/Armor.java b/Java-Ring/src/main/java/org/project/object/armors/Armor.java
index 346c25e..623186d 100644
--- a/Java-Ring/src/main/java/org/project/object/armors/Armor.java
+++ b/Java-Ring/src/main/java/org/project/object/armors/Armor.java
@@ -1,42 +1,67 @@
package org.project.object.armors;
-// TODO: UPDATE IMPLEMENTATION
-public abstract class Armor {
- private int defense;
- private int maxDefense;
- private int durability;
- private int maxDurability;
+import org.project.object.Object;
+
- private boolean isBroke;
+public abstract class Armor implements Object {
- public Armor(int defense, int durability) {
+ protected String name;
+ private int defense;
+ protected int durability;
+ final int maxDurability;
+
+ public Armor(String name, int defense, int durability) {
+ this.name = name;
this.defense = defense;
- this.durability = durability;
+ this.durability = this.maxDurability = durability;
}
- public void checkBreak() {
- if (durability <= 0) {
- isBroke = true;
- defense = 0;
+ public int protect(int incomingDamage) {
+ int damageReduction = Math.min(defense, incomingDamage / 2);
+ int damageTaken = Math.max(1, incomingDamage - damageReduction);
+
+ durability -= incomingDamage / 10;
+ if (durability < 0) {
+ durability = 0;
}
+
+ return damageTaken;
}
- // TODO: (BONUS) UPDATE THE REPAIR METHOD
+
+ @Override
public void repair() {
- isBroke = false;
- defense = maxDefense;
durability = maxDurability;
+ System.out.println(name + " has been repaired!");
}
- public int getDefense() {
- return defense;
+ @Override
+ public boolean isBroken() {
+ return durability <= 0;
}
- public int getDurability() {
- return durability;
+ // Standard getters
+ @Override
+ public String getName() {
+ return name;
}
- public boolean isBroke() {
- return isBroke;
+ @Override
+ public String getDescription() {
+ return String.format("%s (%d DEF)", name, defense);
+ }
+
+ @Override
+ public boolean isConsumable() {
+ return false;
+ }
+
+ @Override
+ public int getValue() {
+ return defense * 12;
+ }
+
+ public int getDurability() {
+ return durability;
}
}
diff --git a/Java-Ring/src/main/java/org/project/object/armors/KnightArmor.java b/Java-Ring/src/main/java/org/project/object/armors/KnightArmor.java
index 0dedcc2..c624c26 100644
--- a/Java-Ring/src/main/java/org/project/object/armors/KnightArmor.java
+++ b/Java-Ring/src/main/java/org/project/object/armors/KnightArmor.java
@@ -1,6 +1,58 @@
package org.project.object.armors;
-// TODO: UPDATE IMPLEMENTATION
-public class KnightArmor {
- // TODO: DESIGN ARMOR'S ATTRIBUTES IMPLEMENT THE CONSTRUCTOR
+import org.project.entity.Entity;
+import org.project.object.Object;
+
+public class KnightArmor extends Armor implements Object {
+ private static final int BASE_DEFENSE = 25;
+ private static final int BASE_DURABILITY = 150;
+ private static final String ARMOR_NAME = "Knight's Plate Armor";
+
+ public KnightArmor() {
+ super(ARMOR_NAME, BASE_DEFENSE, BASE_DURABILITY);
+ }
+
+ @Override
+ public void use(Entity target) {
+ // Armor can't be "used" like consumables, but we implement the required method
+ System.out.println(ARMOR_NAME + " cannot be used directly");
+ }
+
+ @Override
+ public int protect(int incomingDamage) {
+ // Knight armor has 15% chance to completely block physical attacks
+ if (Math.random() < 0.15 && getDurability() > 0) {
+ System.out.println(ARMOR_NAME + " deflects the attack completely!");
+ reduceDurability(); // Blocking still stresses the armor
+ return 0;
+ }
+ return super.protect(incomingDamage);
+ }
+
+ private void reduceDurability() {
+ if (durability > 0) {
+ durability -= 2;
+ }
+ }
+
+ @Override
+ public void repair() {
+ super.repair();
+ System.out.println(ARMOR_NAME + " shines like new after repair!");
+ }
+
+ @Override
+ public String getDescription() {
+ return String.format("%s (Def: %d, Dur: %d/%d) - Heavy plate armor with chance to block attacks",
+ name, getBaseDefense(), getDurability(), maxDurability);
+ }
+
+ public int getBaseDefense() {
+ return BASE_DEFENSE;
+ }
+
+ @Override
+ public boolean isConsumable() {
+ return false;
+ }
}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/object/consumables/Consumable.java b/Java-Ring/src/main/java/org/project/object/consumables/Consumable.java
index fd8962c..bf9863e 100644
--- a/Java-Ring/src/main/java/org/project/object/consumables/Consumable.java
+++ b/Java-Ring/src/main/java/org/project/object/consumables/Consumable.java
@@ -1,8 +1,49 @@
package org.project.object.consumables;
-// TODO: UPDATE IMPLEMENTATION
-public abstract class Consumable {
- /*
- TODO: ADD OTHER REQUIRED AND BONUS METHODS
- */
+import org.project.object.Object;
+
+public abstract class Consumable implements Object {
+
+ protected String name;
+ protected String description;
+ protected int value;
+ protected int remainingUses;
+
+ public Consumable(String name, String desc, int value, int uses) {
+ this.name = name;
+ this.description = desc;
+ this.value = value;
+ this.remainingUses = uses;
+ }
+
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public boolean isConsumable() {
+ return true;
+ }
+
+ @Override
+ public int getValue() {
+ return value;
+ }
+
+ public int getRemainingUses() {
+ return remainingUses;
+ }
+
+ protected void consumeUse() {
+ if (remainingUses > 0) {
+ remainingUses--;
+ }
+ }
}
diff --git a/Java-Ring/src/main/java/org/project/object/consumables/Flask.java b/Java-Ring/src/main/java/org/project/object/consumables/Flask.java
index d7e515d..bb0bb49 100644
--- a/Java-Ring/src/main/java/org/project/object/consumables/Flask.java
+++ b/Java-Ring/src/main/java/org/project/object/consumables/Flask.java
@@ -2,15 +2,58 @@
import org.project.entity.Entity;
-// TODO: UPDATE IMPLEMENTATION
-public class Flask {
- /*
- THIS IS AN EXAMPLE OF A CONSUMABLE DESIGN.
- */
+public class Flask extends Consumable {
+ private static final int HEAL_POWER = 30;
+ private static final String NAME = "Healing Flask";
+ private static final String DESCRIPTION = "Restores 30 HP";
+ private static final int VALUE = 50;
+ private static final int MAX_USES = 3;
+
+ public Flask() {
+ super(NAME, DESCRIPTION, VALUE, MAX_USES);
+ }
- // TODO: (BONUS) UPDATE USE METHOD
@Override
public void use(Entity target) {
- target.heal(target.getMaxHP() / 10);
+ if (getRemainingUses() > 0) {
+ target.heal(HEAL_POWER);
+ consumeUse();
+ System.out.printf("%s healed for %d HP! (%d uses remain)%n",
+ target.getName(), HEAL_POWER, getRemainingUses());
+
+ // Bonus: Flask gets more effective at low health
+ if (target.getHealth() < target.getMaxHealth() * 0.3) {
+ int bonusHeal = HEAL_POWER / 2;
+ target.heal(bonusHeal);
+ System.out.printf("Emergency boost! Additional %d HP restored!%n", bonusHeal);
+ }
+ } else {
+ System.out.println("Flask is empty!");
+ }
+ }
+
+ @Override
+ public boolean isConsumable() {
+ return true;
+ }
+
+ // Bonus: Refill method
+ public void refill() {
+ if (getRemainingUses() < MAX_USES) {
+ System.out.println("Flask has been refilled!");
+ resetUses();
+ } else {
+ System.out.println("Flask is already full!");
+ }
+ }
+
+ // Method to reset the uses of the flask
+ private void resetUses() {
+ setRemainingUses(MAX_USES);
+ }
+
+ // Setter for remaining uses
+ private void setRemainingUses(int uses) {
+ this.remainingUses = uses;
}
-}
+}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/object/consumables/ManaPotion.java b/Java-Ring/src/main/java/org/project/object/consumables/ManaPotion.java
new file mode 100644
index 0000000..d1955fc
--- /dev/null
+++ b/Java-Ring/src/main/java/org/project/object/consumables/ManaPotion.java
@@ -0,0 +1,21 @@
+package org.project.object.consumables;
+
+import org.project.entity.Entity;
+
+public class ManaPotion extends Consumable {
+ private static final int MANA_RESTORE = 40;
+
+ public ManaPotion() {
+ super("Mana Potion", "Restores 40 MP", 75, 2);
+ }
+
+ @Override
+ public void use(Entity target) {
+ if (getRemainingUses() > 0) {
+ target.healMana(MANA_RESTORE);
+ consumeUse();
+ System.out.printf("%s restored %d MP! (%d uses remain)%n",
+ target.getName(), MANA_RESTORE, getRemainingUses());
+ }
+ }
+}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/object/weapons/Claw.java b/Java-Ring/src/main/java/org/project/object/weapons/Claw.java
new file mode 100644
index 0000000..2c1fa6d
--- /dev/null
+++ b/Java-Ring/src/main/java/org/project/object/weapons/Claw.java
@@ -0,0 +1,24 @@
+package org.project.object.weapons;
+
+import java.util.List;
+
+import org.project.entity.Entity;
+
+public class Claw extends Weapon {
+ public Claw() {
+ super("Dragon Claws", 25, 0, Integer.MAX_VALUE);
+ }
+
+ @Override
+ public int getDamage() {
+ return 25 + (int)(Math.random() * 5); // 25-30 damage
+ }
+
+ @Override
+ public void specialAbility(List targets) {
+ System.out.println("Dragon performs a rending slash!");
+ for (Entity target : targets) {
+ target.takeDamage(getDamage() * 3 / 4); // 75% damage to all
+ }
+ }
+}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/object/weapons/Dagger.java b/Java-Ring/src/main/java/org/project/object/weapons/Dagger.java
new file mode 100644
index 0000000..2ec6fa2
--- /dev/null
+++ b/Java-Ring/src/main/java/org/project/object/weapons/Dagger.java
@@ -0,0 +1,42 @@
+package org.project.object.weapons;
+
+import org.project.entity.Entity;
+import java.util.List;
+
+public class Dagger extends Weapon {
+ private static final int BASE_DAMAGE = 15;
+ private static final int CRIT_CHANCE = 25; // 25% crit chance
+ private static final int CRIT_MULTIPLIER = 2;
+
+ public Dagger() {
+ super("Rusty Dagger", BASE_DAMAGE, 5, 50); // name, damage, manaCost, durability
+ }
+
+ @Override
+ public int getDamage() {
+ // 25% chance to crit for double damage
+ return (Math.random() * 100 < CRIT_CHANCE) ?
+ BASE_DAMAGE * CRIT_MULTIPLIER :
+ BASE_DAMAGE;
+ }
+
+ @Override
+ public void specialAbility(List targets) {
+ if (targets.isEmpty()) return;
+
+ Entity primaryTarget = targets.get(0);
+ int damage = getDamage() + 5; // Backstab bonus
+
+ System.out.printf("Goblin backstabs %s for %d damage!%n",
+ primaryTarget.getName(), damage);
+ primaryTarget.takeDamage(damage);
+ }
+
+ @Override
+ public String getDescription() {
+ return String.format(
+ "%s (Damage: %d, Crit: %d%%, Durability: %d/%d)",
+ name, BASE_DAMAGE, CRIT_CHANCE, durability, maxDurability
+ );
+ }
+}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/object/weapons/RustySword.java b/Java-Ring/src/main/java/org/project/object/weapons/RustySword.java
new file mode 100644
index 0000000..74f4b60
--- /dev/null
+++ b/Java-Ring/src/main/java/org/project/object/weapons/RustySword.java
@@ -0,0 +1,49 @@
+package org.project.object.weapons;
+
+import org.project.entity.Entity;
+import java.util.List;
+
+public class RustySword extends Weapon {
+ private static final int BASE_DAMAGE = 18;
+ private static final double RUST_CHANCE = 0.3; // 30% chance to apply rust effect
+ private static final int RUST_DAMAGE_PENALTY = 2; // Reduces target's damage
+
+ public RustySword() {
+ super("Rusty Sword", BASE_DAMAGE, 8, 40); // name, damage, manaCost, durability
+ }
+
+ @Override
+ public int getDamage() {
+ // 5% chance to break on hit
+ if (Math.random() < 0.05) {
+ durability -= 5;
+ }
+ return BASE_DAMAGE;
+ }
+
+ @Override
+ public void specialAbility(List targets) {
+ if (targets.isEmpty()) return;
+
+ Entity target = targets.get(0);
+ if (Math.random() < RUST_CHANCE) {
+ System.out.printf("%s's rust infects %s, reducing their damage output!%n",
+ name, target.getName());
+ // Implementation would reduce target's damage by RUST_DAMAGE_PENALTY
+ }
+ }
+
+ @Override
+ public String getDescription() {
+ return String.format(
+ "%s (Damage: %d, Rust: %.0f%%, Durability: %d/%d)",
+ name, BASE_DAMAGE, RUST_CHANCE * 100, durability, maxDurability
+ );
+ }
+
+ // Unique rust effect application
+ public void applyRust(Entity target) {
+ // Implementation would track damage reduction on target
+ System.out.println("Rust spreads, weakening " + target.getName());
+ }
+}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/object/weapons/Staff.java b/Java-Ring/src/main/java/org/project/object/weapons/Staff.java
new file mode 100644
index 0000000..9dbe987
--- /dev/null
+++ b/Java-Ring/src/main/java/org/project/object/weapons/Staff.java
@@ -0,0 +1,21 @@
+package org.project.object.weapons;
+
+import org.project.entity.Entity;
+
+import java.util.List;
+
+public class Staff extends Weapon {
+ public Staff() {
+ super("Wizard's Staff", 12, 0, 60); // Low physical damage, no mana cost
+ }
+
+ @Override
+ public void specialAbility(List targets) {
+
+ }
+
+ @Override
+ public String getDescription() {
+ return name + " (Damage: " + baseDamage + ", +5 mana regen when equipped)";
+ }
+}
\ No newline at end of file
diff --git a/Java-Ring/src/main/java/org/project/object/weapons/Sword.java b/Java-Ring/src/main/java/org/project/object/weapons/Sword.java
index a0e3cc3..6abd535 100644
--- a/Java-Ring/src/main/java/org/project/object/weapons/Sword.java
+++ b/Java-Ring/src/main/java/org/project/object/weapons/Sword.java
@@ -1,26 +1,42 @@
package org.project.object.weapons;
+import java.util.List;
+
import org.project.entity.Entity;
-import java.util.ArrayList;
-// TODO: UPDATE IMPLEMENTATION
-public class Sword {
- /*
- THIS IS AN EXAMPLE OF A WEAPON DESIGN.
- */
+public class Sword extends Weapon {
int abilityCharge;
public Sword() {
- // TODO: DESIGN SWORD'S ATTRIBUTES IMPLEMENT THE CONSTRUCTOR
+ super("Stell Sword" , 25 , 15, 100);
+ this.abilityCharge = 0;
}
- // TODO: (BONUS) UPDATE THE UNIQUE ABILITY
- public void uniqueAbility(ArrayList targets) {
- abilityCharge += 2;
- for (Entity target : targets) {
- target.takeDamage(getDamage());
+
+
+ @Override
+ public void specialAbility(List targets) {
+ if (abilityCharge >= 3) {
+ System.out.println("Executing Whirlwind Slash!");
+ for (Entity target : targets) {
+ target.takeDamage(baseDamage * 2);
+ }
+ abilityCharge = 0;
+ } else {
+ System.out.printf("Need %d more attacks to charge!\n", 3 - abilityCharge);
+ }
+ }
+ @Override
+ public void use(Entity target) {
+ super.use(target);
+ gainCharge();
+ }
+ private void gainCharge() {
+ if (abilityCharge < 3) {
+ abilityCharge++;
}
}
+
}
diff --git a/Java-Ring/src/main/java/org/project/object/weapons/Weapon.java b/Java-Ring/src/main/java/org/project/object/weapons/Weapon.java
index 35e1ecc..46e729c 100644
--- a/Java-Ring/src/main/java/org/project/object/weapons/Weapon.java
+++ b/Java-Ring/src/main/java/org/project/object/weapons/Weapon.java
@@ -1,35 +1,138 @@
package org.project.object.weapons;
+import java.util.List;
import org.project.entity.Entity;
+import org.project.object.Object;
-// TODO: UPDATE IMPLEMENTATION
-public abstract class Weapon {
- private int damage;
- private int manaCost;
+/**
+ * Abstract base class for all weapons in the game.
+ * Implements core combat functionality, durability systems, and special abilities.
+ */
+public abstract class Weapon implements Object {
- /*
- TODO: ADD OTHER REQUIRED AND BONUS ATTRIBUTES
- */
+ // Weapon Attributes
+ protected String name; // Display name of the weapon
+ protected int baseDamage; // Base damage value
+ protected int manaCost; // Mana required for special abilities
+ protected int durability; // Current durability
+ protected int maxDurability; // Maximum durability capacity
- public Weapon(int damage, int manaCost) {
- this.damage = damage;
+ /**
+ * Constructs a new weapon instance.
+ * @param name The weapon's display name
+ * @param damage Base damage value
+ * @param manaCost Mana cost for special abilities
+ * @param durability Starting/Maximum durability
+ */
+ public Weapon(String name, int damage, int manaCost, int durability) {
+ this.name = name;
+ this.baseDamage = damage;
this.manaCost = manaCost;
+ this.durability = this.maxDurability = durability;
}
+ /**
+ * Gets the base damage value before modifiers.
+ * @return The weapon's base damage
+ */
+ public int getDamage() {
+ return baseDamage;
+ }
+
+ /**
+ * Core combat method - attacks a target entity.
+ * Decreases durability with each use.
+ * @param target The entity to attack
+ */
@Override
public void use(Entity target) {
- target.takeDamage(damage);
+ if (durability > 0) {
+ int damage = calculateDamage();
+ target.takeDamage(damage);
+ durability--;
+ System.out.printf("%s dealt %d damage! (Durability: %d/%d)\n",
+ name, damage, durability, maxDurability);
+ } else {
+ System.out.println(name + " is broken!");
+ }
}
- public int getDamage() {
- return damage;
+ /**
+ * Calculates final damage (can be overridden for custom damage formulas).
+ * @return The calculated damage amount
+ */
+ protected int calculateDamage() {
+ return baseDamage; // Default implementation uses base damage
+ }
+
+ /**
+ * Abstract method for weapon special abilities.
+ * Must be implemented by concrete weapon classes.
+ * @param targets List of entities affected by the ability
+ */
+ public abstract void specialAbility(List targets);
+
+ // ========== DURABILITY SYSTEM ========== //
+
+ /**
+ * Fully repairs the weapon.
+ */
+ @Override
+ public void repair() {
+ durability = maxDurability;
+ System.out.println(name + " has been repaired!");
+ }
+
+ /**
+ * Checks if the weapon is broken.
+ * @return true if durability <= 0, false otherwise
+ */
+ @Override
+ public boolean isBroken() {
+ return durability <= 0;
}
- public int getManaCost() {
- return manaCost;
+ // ========== GETTER METHODS ========== //
+
+ /**
+ * @return The weapon's name
+ */
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Provides a formatted weapon description.
+ * @return String containing name and damage value
+ */
+ @Override
+ public String getDescription() {
+ return String.format("%s (%d DMG)", name, baseDamage);
+ }
+
+ /**
+ * Weapons are not consumable items.
+ * @return Always false
+ */
+ @Override
+ public boolean isConsumable() {
+ return false;
+ }
+
+ /**
+ * Calculates the weapon's in-game value.
+ * @return Base damage * 8 (gold value)
+ */
+ @Override
+ public int getValue() {
+ return baseDamage * 8;
}
- /*
- TODO: ADD OTHER REQUIRED AND BONUS METHODS
- */
-}
+ /**
+ * @return Current durability
+ */
+ public int getDurability() {
+ return durability;
+ }
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index aef5f82..fece5b3 100644
--- a/README.md
+++ b/README.md
@@ -131,20 +131,12 @@ Want to **earn extra points**? Try implementing one of these:
โ
**Multiple Weapons System** โ๏ธ *(Extra Score!)*
- Players and monsters can **switch between different weapons** during combat instead of being limited to one.
-โ
**Multiple Players Mode** ๐ฅ *(Extra Score!)*
-- Implement a **party-based battle system** where **multiple players** can fight against **monsters together**.
-
โ
**Dragonโs Multi-Target Attack** ๐ *(Extra Score!)*
- If there are **multiple players in the battle**, the **dragonโs unique ability** should **damage all players simultaneously** instead of just one.
-โ
**(Bonus) Inventory System**
-- Allow players to **pick up and use items** like different classes of shields and more potions.
-
-โ
**(Bonus) Experience & Leveling System**
+โ
Experience & Leveling System**
- Players gain XP from battles and level up, increasing their **attack power**.
-โ
**(Bonus) PvP Mode**
-- Implement a **Player vs. Player** combat system.
By implementing any of these extra features, you can earn additional points to boost your final score! ๐