Files
HW-04-JAVA-KNIGHT/README.md
T
2026-07-12 19:20:33 +03:30

8.3 KiB
Raw Blame History

Java Knight ⚔️

A turn-based, roguelike-inspired RPG that runs entirely in the terminal, written in Java for the fourth Advanced Programming assignment.

For centuries, the land of Javanest lived in peace, until a magical Dragon plunged it into darkness, cursing its people into monsters and scattering the three keys to its lair among them. Battle the cursed creatures, recover the Goblin, Skeleton and Vampire keys, grow strong, and slay the Dragon to break the curse and restore peace to Javanest!


Table of Contents

  1. How to Compile & Run
  2. How to Play
  3. Classes, Enemies & Stats
  4. Project Structure
  5. OOP Principles Used
  6. Bonus Features

How to Compile & Run

The project is a standard Maven project. You need JDK 21+ installed.

cd Java-Knight
mvn compile
mvn exec:java -Dexec.mainClass=org.project.Main

Using plain javac / java

cd Java-Knight
# compile every source file into the target/classes folder
find src/main/java -name "*.java" > sources.txt
javac -d target/classes @sources.txt

# run it
java -cp target/classes org.project.Main

The game uses ANSI colour codes, so run it in a real terminal (macOS Terminal, Linux shell, Windows Terminal) for the intended colourful output.


How to Play

  1. Name your hero and pick a class (Knight, Wizard, or Assassin).

  2. You wander into a random location and a random standard enemy appears. For each encounter you choose:

    • 1. Fight enter turn-based combat.
    • 2. Move skip this enemy and travel somewhere new.
    • 3. Visit the Merchant spend coins on potions, a weapon, or repairs.
    • 4. Go to the Castle only appears once you hold all 3 keys fight the Dragon.
  3. Combat is turn-based. On your turn you pick one of five actions. Only Light Attack is free; the rest cost Mana/Stamina, and the class Special costs the most. If you run out of Mana, you can still Light Attack.

    # Action Cost Effect
    1 Light Attack 0 Moderate damage
    2 Heavy Attack 8 Double damage
    3 Defend 6 Blocks ~75% of the next hit
    4 Heal 12 Restores 40% of max HP
    5 Special 15 Unique class ultimate
    6 Use Item Drink a potion from your inventory
  4. Winning a fight grants XP (scaled to the enemy's power), coins, and a chance to drop that species' key. Your HP and Mana are then fully restored.

  5. Leveling up automatically raises your Max HP, Max Mana and base damage.

  6. Collect all 3 keys, go to the Castle, and defeat the Dragon to win. Dying at any point is Game Over.


Classes, Enemies & Stats

Player Classes

Each class has deliberately different starting stats, so they play differently.

Class HP Mana Base Dmg Weapon Special ability
Knight ⚔️ 50 40 8 (highest) Iron Sword Shield Bash heavy damage + stuns the enemy (skips its next turn)
Wizard 🧙 65 (highest) 45 5 Oak Staff Arcane Blast heavy damage AND heals the caster
Assassin 🗡️ 45 55 (highest) 6 Twin Dagger Vanish dodges the next attack + guarantees a crit on the next strike

Enemies

Enemy HP Ability Key
Goblin 👹 30 40% chance to land a critical hit (double damage) Goblin Key
Skeleton ☠️ 40 Resurrects once per battle at 50% HP Skeleton Key
Vampire 🦇 48 Lifesteal heals for 50% of the damage it deals Vampire Key
Dragon 🐉 160 True damage fiery breath ignores armor and the Defend stance

Standard enemies each have a 25% chance to drop their key, and only one key per species can ever drop (once you have the Goblin Key, no other Goblin will drop one).


Project Structure

org.project
├── Main.java                 // entry point  builds the world, starts the game
├── Game.java                 // the game controller / main loop
├── Merchant.java             // bonus shop system
├── entity
│   ├── Entity.java           // interface every combatant implements
│   ├── players
│   │   ├── ICombatActions.java   // interface: the 5 required actions
│   │   ├── Player.java           // abstract base for all heroes
│   │   ├── Knight.java / Wizard.java / Assassin.java
│   └── enemies
│       ├── Enemy.java            // abstract base for all monsters
│       ├── KeyType.java          // enum of the three keys
│       ├── Goblin.java / Skeleton.java / Vampire.java / Dragon.java
├── item
│   ├── Item.java             // interface for anything ownable/sellable
│   ├── weapons  (Weapon abstract → Sword, Dagger, Staff, GreatAxe)
│   ├── armors   (Armor abstract  → KnightArmor, LeatherArmor, Robe)
│   └── consumables (Consumable abstract → Flask, ManaPotion)
├── location
│   └── Location.java         // a place that spawns random enemies
└── util
    ├── ConsoleColors.java    // ANSI colour helpers
    └── Dice.java             // random-number helpers

OOP Principles Used

This project was designed around the seven principles the assignment asks for:

  • Encapsulation all fields are private/protected with getters. HP, Mana and XP can only be changed through methods like takeDamage, heal and gainXP, which enforce their own rules (clamping to max, capping at zero, leveling up).

  • Inheritance shared logic lives in abstract base classes so it isn't duplicated. Player holds the HP/Mana bars, leveling, inventory and four of the five actions; Knight, Wizard and Assassin only add what's unique. Same idea for Enemy → its four monster subclasses, and for Weapon/Armor/Consumable → their concrete items.

  • Interfaces Entity is the contract every combatant obeys, which is what lets the combat loop treat a Knight and a Dragon identically. ICombatActions guarantees every player class implements exactly the five required actions. Item unifies weapons, armor and consumables so the merchant can sell any of them.

  • Abstract classes Player, Enemy, Weapon, Armor and Consumable are all abstract: they provide shared state/behaviour but can't be instantiated on their own, forcing subclasses to fill in the specifics (e.g. Player.specialAbility is abstract).

  • Polymorphism the whole game loop is polymorphic. Game only ever calls Player/Enemy/Entity methods; the correct specialAbility, attack or takeDamage runs depending on the real object. Each enemy overrides attack to add its signature move.

  • Overriding subclasses override base behaviour, e.g. Skeleton overrides takeDamage to resurrect, Vampire/Goblin/Dragon override attack, and every player class overrides specialAbility.

  • Overloading takeDamage(int) vs takeDamage(int, boolean) in Player. The second, overloaded version ignores defenses and is how the Dragon's breath bypasses armor and shields. The Sword also overloads its constructor.


Bonus Features

  • Coins & Merchant system enemies drop coins; the Merchant sells Health Flasks, Mana Potions, a stronger Great Axe, and can repair armor.
  • Inventory & consumables potions can be bought, stored and used mid-combat (action 6).
  • Durable armor armor loses durability as it absorbs hits and eventually breaks, until repaired at the merchant.
  • Colourful narrative console ANSI colours (red for damage, blue for mana, green for healing) make the combat log easy to read.

Born of God and Void. You shall seal the blinding light that plagues their dreams. You are the Vessel. You are the Java Knight.