196 lines
8.3 KiB
Markdown
196 lines
8.3 KiB
Markdown
# 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](#how-to-compile--run)
|
||
2. [How to Play](#how-to-play)
|
||
3. [Classes, Enemies & Stats](#classes-enemies--stats)
|
||
4. [Project Structure](#project-structure)
|
||
5. [OOP Principles Used](#oop-principles-used)
|
||
6. [Bonus Features](#bonus-features)
|
||
|
||
---
|
||
|
||
## How to Compile & Run
|
||
|
||
The project is a standard Maven project. You need **JDK 21+** installed.
|
||
|
||
### Using Maven (recommended)
|
||
```bash
|
||
cd Java-Knight
|
||
mvn compile
|
||
mvn exec:java -Dexec.mainClass=org.project.Main
|
||
```
|
||
|
||
### Using plain `javac` / `java`
|
||
```bash
|
||
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.*
|