Files
2026-05-12 00:44:44 +04:30
..
2026-05-12 00:44:44 +04:30
2026-04-30 20:00:29 +03:30
2026-05-12 00:44:44 +04:30

⚔️ Java RPG Game

A text-based roleplaying game built in Java, demonstrating core ObjectOriented Programming principles such as inheritance, polymorphism, interfaces, abstraction, and encapsulation.

The player chooses a hero (Knight, Wizard, or Assassin), equips weapons and armour, and battles various enemies (Skeleton, Vampire, Goblin) in a simple turnbased loop. Locations and consumable items are also partially implemented.


📁 Project Structure


🎮 Gameplay Overview

  1. Character Selection Enter your name, pick a class (Assassin, Wizard, Knight), choose a weapon and armour.
  2. Combat Loop You face random enemies from a list. Each turn you can:
    • Light Attack
    • Heavy Attack (normal attack)
    • Defend
    • Heal
    • Use Special Ability
  3. Enemy AI Enemies randomly choose between light and heavy attacks. Some enemies (e.g. Goblin) have special behaviours.
  4. Progression After defeating an enemy, the player's maximum HP and MP increase, and both player and enemy stats are refreshed.
  5. Relocation You can choose to move to another location (currently selecting a random enemy from the list).

🧱 Class Hierarchy & Interfaces

Interface Entity

Defines the contract for all living beings in the game.

Method Description
void attack(Entity target) Basic attack on a target.
void LightAttack(Entity target, int base_damage) A weaker attack with fixed damage.
void defend(Entity me, int damage) Defensive action (confusing signature, see Player).
String getName() Returns the entity's name.
void heal(int health) Restores health points.
void fillMana(int mana) Restores mana points.
void takeDamage(int damage) Applies damage after armour reduction.
int getMaxHP() Returns maximum health.
int getMaxMP() Returns maximum mana.
boolean ISLive() Checks if the entity is alive (HP > 0).

Interface Item

Defines usable items.

Method Description
void use(Entity target) Apply the item's effect to the target.
String getName() Returns the item's name.

🧙 Abstract Classes

Player (extends Entity)

Common base for all player characters.

Fields:

  • name, weapon, armor, hp, maxHP, mp, maxMP, baseDamage (unused)

Constructors:

  • Player(String name, int hp, int mp, Weapon weapon, Armor armor, int baseDamage)
  • Player(String name, int hp, int mp, Weapon weapon, Armor armor) sets maxHP/maxMP equal to initial hp/mp.

Methods:

  • void attack(Entity target) Deals weapon damage.
  • void defend(Entity me, int damage) Heals the entity itself (unusual).
  • void takeDamage(int damage) Reduces damage by armour defence.
  • void heal(int health) Adds health, capped at maxHP.
  • void fillMana(int mana) Adds mana, capped at maxMP.
  • abstract void specialAttack(Entity target) Each subclass defines its own special move.
  • boolean IsLive() Returns true if HP > 0.
  • void LightAttack(Entity target, int base_damage) Deals flat damage.
  • void UpGradeMaxHP() / UpGradeMaxMP() Increases max stats by 20% (used after battle).
  • void freshFactors() Fully restores HP and MP.

Enemy (extends Entity)

Base for all enemy types.

Fields:

  • weapon, hp, mp, maxHp, maxMp

Constructor:

  • Enemy(int hp, int mp, Weapon weapon) Initialises stats and weapon.

Methods:

  • int getHp(), int getMp(), Weapon getWeapon(), void setNewHp(int newhp)
  • void takeDamage(int damage) Direct HP reduction.
  • abstract void attack(Entity target)
  • abstract void check_hp() Intended for death/recovery checks.
  • abstract void defend() Normal defend.
  • abstract String getName()
  • void heal(int health), void fillMana(int mana) Standard recovery.
  • boolean IsLive() HP > 0.
  • void LightAttack(Entity target, int base_damage) Flat damage.
  • int getMaxHP(), int getMaxMp()
  • void freshFactors() Resets HP/MP to max.

Consumable (implements Item)

Base for consumable items.

  • Consumable(String name) Sets the item name.
  • String getName()

Weapon (abstract)

Base for all weapons.

Fields:

  • int damage, int manaCost

Constructor: Weapon(int damage, int manaCost)

Methods:

  • int getDamage(), int getManaCost()
  • (No use method not implementing Item)

Armor (abstract)

Base for all armour pieces. Fields:

  • defense, maxDefense, durability, maxDurability, isBroke (private)

Constructors:

  • Armor(int defense, int durability) Main constructor (does not initialise max values correctly).
  • Armor(int maxDefense, int maxDurability, boolean isBroke) Unused overload.

Methods:

  • void checkBreak() If durability ≤ 0, sets isBroke = true and defense = 0.
  • void repair() Restores defence/durability to max values.
  • int getDefense(), int getDurability(), boolean isBroke()
  • void setMaxDefense(int max)
  • void newDurability() Decrements durability (does not autocall checkBreak).

🧝‍♂️ Concrete Player Classes

Knight

  • Base stats: HP=40, MP=20
  • specialAttack(Entity target) Deals 5 damage.

Wizard

  • Base stats: HP=40, MP=20
  • specialAttack(Entity target) Deals 5 damage and heals self for 10 HP (capped at max).

Assassin

  • Base stats: HP=20, MP=40
  • specialAttack(Entity target) Deals weapon damage.

All three override ISLive() to always return false (bug should use IsLive() from Player).


👹 Concrete Enemy Classes

Skeleton

  • HP=10, MP=2
  • attack(Entity target) Weapon damage.
  • check_hp() If HP ≤ 0 and not yet revived, sets HP to Max_hp/2 (5). (Bug: ISLive() returns false, so this may not work as intended.)
  • getName() returns "Skeleton".

Vampire

  • HP=12, MP=5
  • attack(Entity target) Weapon damage, heals self by damage/3, capped at Max_hp.
  • getName() returns "Vampire".

Goblin

  • HP=6, MP=18
  • attack(Entity target) Weapon damage.
  • getName() returns "Gobblin".

Dragon

  • Extends Enemy but currently all methods are empty/return default values not fully implemented.

⚔️ Weapons

Sword

  • damage=3, manaCost=4 (constants, but constructor accepts parameters that are ignored)
  • Copy constructor: Sword(Weapon other) copies damage and manaCost from another weapon.
  • uniqueAbility(ArrayList targets) deals weapon damage to all targets.

SwordPro

  • damage=4, manaCost=3
  • Same copy constructor and unique ability.

SwordProMax

  • damage=5, manaCost=2
  • Same pattern.

🛡️ Armors

KnightArmor

  • defense=3, durability=2 (constructor ignores parameters, always uses static constants)
  • No copy constructor.

ArmorNormal

  • defense=1, durability=2

ArmorPro

  • defense=2, durability=2

ArmorProMax

  • defense=1, durability=5

All armours use the same pattern: a static final value passed to super().


🧪 Consumables

Flask (extends Consumable)

  • Flask(String name) calls super.
  • use(Entity target) Heals target by 10% of its max HP.

Currently unused in gameplay; the Main loop does not reference flasks.


📍 Location

  • Fields: name, enemies (ArrayList), locations (ArrayList)
  • Constructor takes locations and enemies, but does not assign name (remains null).
  • Not integrated into the main game loop yet.

🎯 Main Class (Game Loop)

The main method contains:

  1. Setup: Creates weapon instances, enemy list (Skeleton, Vampire, Goblin), scanner, random.
  2. Player creation: Asks for name, class (13), weapon (13), armour (14). Uses copy constructors for weapons.
  3. Game loop: While player is alive (checks player.ISLive() currently buggy, always false so loop never enters). Inside:
    • Displays current enemy name.
    • Offers two options: Fight (1) or Move (2). Moving picks a random enemy from the list.
    • When fight is selected, calls playerMove() (player attacks), then if enemy lives, enemyMove() (enemy attacks).
    • After enemy dies, players max HP/MP increase, both are refreshed.
  4. Helper methods:
  • playerMove(Player, Enemy) Displays a menu of actions (Light Attack, Heavy Attack, Defend, Heal, Special) and calls the corresponding method.
    • enemyMove(Player, Enemy, int) Randomly chooses Light Attack or normal Attack for the enemy.
    • showDetails(Player, Enemy) Prints current stats.
    • pause(double seconds) Sleeps the program for a given time.

🐞 Known Issues / Quirks

  • Player.ISLive() always returns false because overridden incorrectly in subclasses; the loop condition is never satisfied.
  • Armor constructors do not properly initialise maxDefense/maxDurability.
  • Entity interface contains defend(Entity me, int damage) which doesnt match the usual defend() signature.
  • Many ISLive() overrides just return false, while the correct logic is in IsLive() (noninterface method). The game uses ISLive() (interface method) which clashes with the intended behaviour.
  • Location is not used; its name field is never set.

🚀 How to Run

  1. Compile all .java files inside the org/project package.
  2. Run org.project.Main.
  3. Follow the console prompts to play.

📚 OOP Concepts Demonstrated

  • Inheritance: Player and Enemy extend Entity; weapons extend Weapon; armours extend Armor.
  • Polymorphism: Entity references used for both players and enemies in combat.
  • Encapsulation: Private fields with getters/setters (though some fields could be better protected).
  • Abstraction: Abstract classes Player, Enemy, Weapon, Armor define common behaviour; subclasses fill in specifics.

Enjoy the game! Contributions and fixes are welcome.