2 Commits
56 changed files with 955 additions and 24 deletions
+10
View File
@@ -0,0 +1,10 @@
# Default ignored files
/shelf/
/workspace.xml
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="Java-Knight" />
</profile>
</annotationProcessing>
</component>
</project>
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://maven.devneeds.ir/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="25" project-jdk-type="JavaSDK" />
</project>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>
@@ -4,12 +4,46 @@ import org.project.location.Location;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.project.entity.enemies.Enemy;
import org.project.utils.ConsoleColors;
public class Main { public class Main {
public static void main(String[] args) { public static void main(String[] args) {
// TODO: ADD LOCATIONS TO YOUR GAME // TODO: ADD LOCATIONS TO YOUR GAME
List<Location> locations = new ArrayList<>(); List<Location> locations = new ArrayList<>();
Location village = new Location("Village", new ArrayList<>(), new ArrayList<Enemy>());
Location forest = new Location("Forest", new ArrayList<>(), new ArrayList<Enemy>());
Location cave = new Location("Cave", new ArrayList<>(), new ArrayList<Enemy>());
Location dungeon = new Location("Dungeon", new ArrayList<>(), new ArrayList<Enemy>());
Location castle = new Location("Castle", new ArrayList<>(), new ArrayList<Enemy>());
// TODO: IMPLEMENT GAMEPLAY // TODO: IMPLEMENT GAMEPLAY
//The movement paths between locations
village.getLocations().add(forest);
forest.getLocations().add(village);
forest.getLocations().add(cave);
cave.getLocations().add(forest);
cave.getLocations().add(dungeon);
dungeon.getLocations().add(cave);
dungeon.getLocations().add(castle);
castle.getLocations().add(dungeon);
locations.add(village);
locations.add(forest);
locations.add(cave);
locations.add(dungeon);
locations.add(castle);
//THe first location in the world map
Location currentLocation = locations.get(0);
System.out.println(ConsoleColors.BRIGHT_GREEN + "Welcome to the adventure!" + ConsoleColors.RESET);
System.out.println(ConsoleColors.BRIGHT_CYAN + "You are currently in: " + currentLocation.getName() + ConsoleColors.RESET);
System.out.println(ConsoleColors.BRIGHT_YELLOW + "The world is ready. Gameplay will continue from here." + ConsoleColors.RESET);
} }
} }
@@ -18,4 +18,12 @@ public interface Entity {
/* /*
TODO: ADD OTHER REQUIRED AND BONUS METHODS TODO: ADD OTHER REQUIRED AND BONUS METHODS
*/ */
/*
Added common entity state accessors so all entities expose their current HP and MP.
This allows combat systems and game logic to interact with Player and Enemy
through the same polymorphic interface.
*/
int getHp();
int getMp();
} }
@@ -0,0 +1,38 @@
package org.project.entity.enemies;
import org.project.entity.Entity;
import org.project.item.weapons.Weapon;
import java.util.Random;
public class Dragon extends Enemy{
// Reduces incoming damage by 10 points.
private final int armorDefense = 10;
private final Random random = new Random();
public Dragon(Weapon weapon) {
//Massive HP and MP pool to suit its Boss role.
super(350, 100, weapon);
}
@Override
public void attack(Entity target) {
int baseDamage = weapon.getDamage();
//25% chance to perform "Fire Breath" which deals double damage
if (random.nextInt(100) < 25) {
System.out.println("Dragon uses Fire Breath!"); // Visual feedback for boss ability
target.takeDamage(baseDamage * 2);
} else {
target.takeDamage(baseDamage);
}
}
@Override
public void takeDamage(int damage) {
// Minimum damage received is always 1 unless damage is 0.
int effectiveDamage = Math.max(1, damage - armorDefense);
if (damage <= 0) effectiveDamage = 0;
super.takeDamage(effectiveDamage);
}
}
@@ -1,17 +1,21 @@
package org.project.entity.enemies; package org.project.entity.enemies;
import org.project.item.weapons.Weapon; import org.project.item.weapons.Weapon;
import org.project.entity.Entity;
// TODO: UPDATE IMPLEMENTATION // TODO: UPDATE IMPLEMENTATION
public abstract class Enemy { public abstract class Enemy implements Entity{
Weapon weapon; protected Weapon weapon;
private int hp; protected int hp;
private int mp; protected int mp;
protected int maxHp;
protected int maxMp;
public Enemy(int hp, int mp, Weapon weapon) { public Enemy(int hp, int mp, Weapon weapon) {
this.hp = hp; this.hp = hp;
this.mp = mp; this.mp = mp;
this.maxHp = hp;
this.maxMp = mp;
this.weapon = weapon; this.weapon = weapon;
} }
@@ -20,6 +24,18 @@ public abstract class Enemy {
hp -= damage; hp -= damage;
} }
@Override
public void attack(Entity target) {
// English comment: Default enemy attack uses weapon damage.
if (weapon != null) {
target.takeDamage(weapon.getDamage());
}
}
protected void setHp(int hp) {
this.hp = hp;
}
public int getHp() { public int getHp() {
return hp; return hp;
} }
@@ -31,4 +47,31 @@ public abstract class Enemy {
public Weapon getWeapon() { public Weapon getWeapon() {
return weapon; return weapon;
} }
@Override
public void defend() {
// English comment: Default enemy defense does nothing special.
}
@Override
public void heal(int health) {
// English comment: Clamp HP so it never exceeds maximum HP.
hp = Math.min(maxHp, hp + health);
}
@Override
public void fillMana(int mana) {
// English comment: Clamp MP so it never exceeds maximum MP.
mp = Math.min(maxMp, mp + mana);
}
@Override
public int getMaxHP() {
return maxHp;
}
@Override
public int getMaxMP() {
return maxMp;
}
} }
@@ -0,0 +1,27 @@
package org.project.entity.enemies;
import org.project.entity.Entity;
import org.project.item.weapons.Weapon;
import java.util.Random;
public class Goblin extends Enemy {
private final Random random = new Random();
public Goblin(Weapon weapon) {
//Lower health but higher burst damage potential
super(50, 15, weapon);
}
@Override
public void attack(Entity target) {
int damage = weapon.getDamage();
//Has a 35% chance to deal double damage.
if (random.nextInt(100) < 35) {
damage *= 2;
}
target.takeDamage(damage);
}
}
@@ -1,6 +1,25 @@
package org.project.entity.enemies; package org.project.entity.enemies;
import org.project.item.weapons.Weapon;
// TODO: UPDATE IMPLEMENTATION // TODO: UPDATE IMPLEMENTATION
public class Skeleton { public class Skeleton extends Enemy{
// TODO: DESIGN ENEMY AND IMPLEMENT THE CONSTRUCTOR // TODO: DESIGN ENEMY AND IMPLEMENT THE CONSTRUCTOR
private boolean resurrected = false;
public Skeleton(Weapon weapon) {
//A low-tier enemy with moderate HP and low mana.
super(80, 20, weapon);
}
@Override
public void takeDamage(int damage) {
//Apply damage
super.takeDamage(damage);
//If dies for the first time, resurrect with 50% HP.
if (hp <= 0 && !resurrected) {
resurrected = true;
hp = maxHp / 2;
}
}
} }
@@ -0,0 +1,26 @@
package org.project.entity.enemies;
import org.project.entity.Entity;
import org.project.item.weapons.Weapon;
public class Vampire extends Enemy {
public Vampire(Weapon weapon) {
//Has balanced stats with sustain ability.
super(90, 30, weapon);
}
@Override
public void attack(Entity target) {
int damage = weapon.getDamage();
target.takeDamage(damage);
//Heals for 50% of the damage dealt.
this.hp += damage / 2;
//Ensure HP does not exceed maximum.
if (this.hp > this.maxHp) {
this.hp = this.maxHp;
}
}
}
@@ -0,0 +1,11 @@
package org.project.entity.players;
import org.project.item.armors.AssassinLeatherArmor;
import org.project.item.weapons.Dagger;
public class Assassin extends Player{
//The highest max mana/stamina
public Assassin(String name) {
//The highest max mana/stamina and agile equipment.
super(name, 100, 100, new Dagger(), new AssassinLeatherArmor());
}
}
@@ -1,6 +1,14 @@
package org.project.entity.players; package org.project.entity.players;
import org.project.item.armors.KnightArmor;
import org.project.item.weapons.Sword;
// TODO: UPDATE IMPLEMENTATION // TODO: UPDATE IMPLEMENTATION
public class Knight { public class Knight extends Player{
// TODO: DESIGN KNIGHT'S WEAPON AND ARMOR AND IMPLEMENT THE CONSTRUCTOR // TODO: DESIGN KNIGHT'S WEAPON AND ARMOR AND IMPLEMENT THE CONSTRUCTOR
// Knight-specific constructor with higher damage-oriented equipment.
public Knight(String name) {
// Base stats are selected according to README priorities:
// Knight should have the strongest base damage and solid survivability.
super(name, 120, 30, new Sword(), new KnightArmor());
}
} }
@@ -5,7 +5,7 @@ import org.project.item.armors.Armor;
import org.project.item.weapons.Weapon; import org.project.item.weapons.Weapon;
// TODO: UPDATE IMPLEMENTATION // TODO: UPDATE IMPLEMENTATION
public abstract class Player { public abstract class Player implements Entity {
protected String name; protected String name;
Weapon weapon; Weapon weapon;
Armor armor; Armor armor;
@@ -18,6 +18,8 @@ public abstract class Player {
this.name = name; this.name = name;
this.hp = hp; this.hp = hp;
this.mp = mp; this.mp = mp;
this.maxHP = hp;
this.maxMP = mp;
this.weapon = weapon; this.weapon = weapon;
this.armor = armor; this.armor = armor;
@@ -31,6 +33,10 @@ public abstract class Player {
@Override @Override
public void defend() { public void defend() {
// TODO // TODO
// If armor is broken, defend action repairs it
if (armor != null && armor.getIsBrocke()) {
armor.repair();
}
} }
@@ -0,0 +1,11 @@
package org.project.entity.players;
import org.project.item.armors.WizardRobe;
import org.project.item.weapons.Staff;
public class Wizard extends Player {
// Wizard is the class with the highest max HP according to the README.
public Wizard(String name) {
//The highest max HP and enough mana for spell usage.
super(name, 150, 80, new Staff(), new WizardRobe());
}
}
@@ -8,4 +8,14 @@ public interface Item {
/* /*
TODO: ADD OTHER REQUIRED AND BONUS METHODS TODO: ADD OTHER REQUIRED AND BONUS METHODS
*/ */
/*
Added shared item inspection and identification methods.
These methods allow unified access to item information in inventories and UI,
keeping all items (Weapon, Armor, Consumable) consistent under the same contract.
*/
String getName(); // Returns the name of the item.
String getDescription(); // Returns a brief description of the item.
int getValue(); // Represents shop or trade value of item.
} }
@@ -1,7 +1,9 @@
package org.project.item.armors; package org.project.item.armors;
import org.project.item.Item;
// TODO: UPDATE IMPLEMENTATION // TODO: UPDATE IMPLEMENTATION
public abstract class Armor { public abstract class Armor implements Item {
private int defense; private int defense;
private int maxDefense; private int maxDefense;
private int durability; private int durability;
@@ -16,27 +18,47 @@ public abstract class Armor {
public void checkBreak() { public void checkBreak() {
if (durability <= 0) { if (durability <= 0) {
isBroke = true;
defense = 0; defense = 0;
isBroke = true;
} }
} }
// TODO: (BONUS) UPDATE THE REPAIR METHOD // TODO: (BONUS) UPDATE THE REPAIR METHOD
/*
Repair weapon durability.
*/
public void repair() { public void repair() {
isBroke = false;
defense = maxDefense;
durability = maxDurability; durability = maxDurability;
} }
public int getDefense() { /*
return defense; Inspection methods required by Item interface.
} These are left abstract so each concrete weapon
can define its own identity and value.
*/
@Override
public abstract String getName();
@Override
public abstract String getDescription();
@Override
public abstract int getValue();
/*
BONUS: durability getters.
*/
public int getDurability() { public int getDurability() {
return durability; return durability;
} }
public boolean isBroke() { public int getMaxDurability() {
return maxDurability;
}
public int getDefense(){
return defense;
}
public boolean getIsBrocke(){
return isBroke; return isBroke;
} }
} }
@@ -0,0 +1,31 @@
package org.project.item.armors;
import org.project.entity.Entity;
public class AssassinLeatherArmor extends Armor {
//offering medium protection (2/3 of Knight)
public AssassinLeatherArmor() {
super(8, 60);
}
// Added item identity methods required by the Item contract.
@Override
public String getName() {
return "Assassin Leather Armor";
}
@Override
public String getDescription() {
return "Reinforced leather armor providing a balance between protection and speed.";
}
@Override
public int getValue() {
return 100;
}
@Override
public void use(Entity target) {
}
}
@@ -1,6 +1,33 @@
package org.project.item.armors; package org.project.item.armors;
import org.project.entity.Entity;
// TODO: UPDATE IMPLEMENTATION // TODO: UPDATE IMPLEMENTATION
public class KnightArmor { public class KnightArmor extends Armor {
// TODO: DESIGN ARMOR'S ATTRIBUTES IMPLEMENT THE CONSTRUCTOR // TODO: DESIGN ARMOR'S ATTRIBUTES IMPLEMENT THE CONSTRUCTOR
// Added default knight armor stats for the combat and durability systems.
public KnightArmor() {
super(12, 120);
}
// Added item identity methods required by the Item contract.
@Override
public String getName() {
return "Knight Armor";
}
@Override
public String getDescription() {
return "Heavy armor designed for frontline combat and high durability.";
}
@Override
public int getValue() {
return 140;
}
@Override
public void use(Entity target) {
}
} }
@@ -0,0 +1,30 @@
package org.project.item.armors;
import org.project.entity.Entity;
public class WizardRobe extends Armor{
public WizardRobe() {
// Lower defense but reasonable durability for magic users.
super(4, 80);
}
// Added item identity methods required by the Item contract.
@Override
public String getName() {
return "Wizard Robe";
}
@Override
public String getDescription() {
return "Light magical robe providing minimal protection but high mobility for casters.";
}
@Override
public int getValue() {
return 60;
}
@Override
public void use(Entity target) {
}
}
@@ -1,8 +1,35 @@
package org.project.item.consumables; package org.project.item.consumables;
import org.project.entity.Entity;
import org.project.item.Item;
// TODO: UPDATE IMPLEMENTATION // TODO: UPDATE IMPLEMENTATION
public abstract class Consumable { public abstract class Consumable implements Item {
/* /*
TODO: ADD OTHER REQUIRED AND BONUS METHODS TODO: ADD OTHER REQUIRED AND BONUS METHODS
*/ */
// Base economic value for all consumables
protected int value;
//To initialize consumable value
public Consumable(int value) {
this.value = value;
}
// Shared implementation of getValue for all consumables
@Override
public int getValue() {
return value;
}
/*
* Abstract methods force subclasses to define their own identity and behavior.
*/
@Override
public abstract String getName();
@Override
public abstract String getDescription();
@Override
public abstract void use(Entity target);
} }
@@ -3,14 +3,30 @@ package org.project.item.consumables;
import org.project.entity.Entity; import org.project.entity.Entity;
// TODO: UPDATE IMPLEMENTATION // TODO: UPDATE IMPLEMENTATION
public class Flask { public class Flask extends Consumable{
/* /*
THIS IS AN EXAMPLE OF A CONSUMABLE DESIGN. THIS IS AN EXAMPLE OF A CONSUMABLE DESIGN.
*/ */
public Flask() {
super(50);
}
// TODO: UPDATE USE METHOD // TODO: UPDATE USE METHOD
@Override @Override
public void use(Entity target) { public void use(Entity target) {
target.heal(target.getMaxHP() / 10); target.heal(target.getMaxHP() / 10);
} }
// Defines the display name
@Override
public String getName() {
return "Healing Flask";
}
//The effect of the flask
@Override
public String getDescription() {
return "A small flask that restores a portion of the user's health.";
}
} }
@@ -0,0 +1,36 @@
package org.project.item.weapons;
import org.project.entity.Entity;
public class Dagger extends Weapon{
private double criticalChance;
public Dagger() {
// Dagger is meant to be quick and efficient, not the highest raw damage weapon.
super(12, 2);
this.criticalChance = 0.30;
}
// Critical damage supports a high-risk, high-reward playstyle.
public void criticalStrike(Entity target) {
if (Math.random() < criticalChance) {
target.takeDamage(getDamage() * 2);
} else {
target.takeDamage(getDamage());
}
}
@Override
public String getName() {
return "Dagger";
}
@Override
public String getDescription() {
return "A light and deadly blade designed for quick strikes and critical hits.";
}
@Override
public int getValue() {
return 90;
}
}
@@ -0,0 +1,40 @@
package org.project.item.weapons;
import org.project.entity.Entity;
import java.util.ArrayList;
public class Staff extends Weapon{
private int spellCharge;
public Staff() {
// Staff is designed around magic damage and higher mana dependency.
super(10, 8);
this.spellCharge = 0;
}
// This ability is intended to be stronger than a normal attack and to consume buildup.
public void magicBurst(ArrayList<Entity> targets) {
spellCharge++;
if (spellCharge >= 2) {
for (Entity target : targets) {
target.takeDamage(getDamage() + 6);
}
spellCharge = 0;
}
}
@Override
public String getName() {
return "Staff";
}
@Override
public String getDescription() {
return "A rune-carved staff that channels arcane energy for powerful spells.";
}
@Override
public int getValue() {
return 120;
}
}
@@ -5,7 +5,7 @@ import org.project.entity.Entity;
import java.util.ArrayList; import java.util.ArrayList;
// TODO: UPDATE IMPLEMENTATION // TODO: UPDATE IMPLEMENTATION
public class Sword { public class Sword extends Weapon {
/* /*
THIS IS AN EXAMPLE OF A WEAPON DESIGN. THIS IS AN EXAMPLE OF A WEAPON DESIGN.
*/ */
@@ -14,13 +14,35 @@ public class Sword {
public Sword() { public Sword() {
// TODO: DESIGN SWORD'S ATTRIBUTES IMPLEMENT THE CONSTRUCTOR // TODO: DESIGN SWORD'S ATTRIBUTES IMPLEMENT THE CONSTRUCTOR
// Added default sword stats based on the combat system requirements.
super(15, 5);
// Initialize ability charge for gameplay progression.
this.abilityCharge = 0;
} }
// TODO: (BONUS) UPDATE THE UNIQUE ABILITY // TODO: (BONUS) UPDATE THE UNIQUE ABILITY
// Added a sword-specific multi-target attack ability.
// The ability gains charge after each use and damages all enemies in range.
public void uniqueAbility(ArrayList<Entity> targets) { public void uniqueAbility(ArrayList<Entity> targets) {
abilityCharge += 2; abilityCharge++;
for (Entity target : targets) { for (Entity target : targets) {
target.takeDamage(getDamage()); target.takeDamage(getDamage());
} }
} }
// Added item identity methods required by the Item contract.
@Override
public String getName() {
return "Sword";
}
@Override
public String getDescription() {
return "A balanced melee weapon used by knights.";
}
@Override
public int getValue() {
return 100;
}
} }
@@ -1,15 +1,29 @@
package org.project.item.weapons; package org.project.item.weapons;
import org.project.entity.Entity; import org.project.entity.Entity;
import org.project.item.Item;
// TODO: UPDATE IMPLEMENTATION // TODO: UPDATE IMPLEMENTATION
public abstract class Weapon { public abstract class Weapon implements Item {
private int damage; private int damage;
private int manaCost; private int manaCost;
/* /*
TODO: ADD OTHER REQUIRED AND BONUS ATTRIBUTES TODO: ADD OTHER REQUIRED AND BONUS ATTRIBUTES
*/ */
/*
Added shared item attributes for inspection and inventory usage.
Subclasses will define the concrete values (name, description, value).
*/
private String name;
private String description;
private int value;
/*
Added durability system so weapons can degrade through combat usage.
*/
private int durability = 100;
private int maxDurability = 100;
public Weapon(int damage, int manaCost) { public Weapon(int damage, int manaCost) {
this.damage = damage; this.damage = damage;
@@ -19,6 +33,7 @@ public abstract class Weapon {
@Override @Override
public void use(Entity target) { public void use(Entity target) {
target.takeDamage(damage); target.takeDamage(damage);
reduceDurability();
} }
public int getDamage() { public int getDamage() {
@@ -28,8 +43,52 @@ public abstract class Weapon {
public int getManaCost() { public int getManaCost() {
return manaCost; return manaCost;
} }
/*
Reduces durability whenever the weapon is used.
*/
private void reduceDurability() {
durability--;
if (durability < 0) {
durability = 0;
}
}
/* /*
TODO: ADD OTHER REQUIRED AND BONUS METHODS TODO: ADD OTHER REQUIRED AND BONUS METHODS
*/ */
/*
Repair weapon durability.
*/
public void repair() {
durability = maxDurability;
}
/*
Implemented inspection methods required by Item interface.
*/
@Override
public String getName() {
return name;
}
@Override
public String getDescription() {
return description;
}
@Override
public int getValue() {
return value;
}
/*
Durability getters.
*/
public int getDurability() {
return durability;
}
public int getMaxDurability() {
return maxDurability;
}
} }
@@ -6,10 +6,11 @@ import java.util.ArrayList;
public class Location { public class Location {
private String name; private String name;
private ArrayList<Location> locations;
private ArrayList<Enemy> enemies; private ArrayList<Enemy> enemies;
public Location(ArrayList<Location> locations, ArrayList<Enemy> enemies) { public Location(String name, ArrayList<Location> locations, ArrayList<Enemy> enemies) {
this.name = name;
this.locations = locations; this.locations = locations;
this.enemies = enemies; this.enemies = enemies;
} }
@@ -25,4 +26,44 @@ public class Location {
public ArrayList<Enemy> getEnemies() { public ArrayList<Enemy> getEnemies() {
return enemies; return enemies;
} }
/**
*This method initializes the game world by creating locations
* and establishing their connections.
* @return The starting location.
*/
public static Location generateMap() {
// Create individual locations
Location village = new Location("Village", new ArrayList<>(), new ArrayList<>());
Location forest = new Location("Forest", new ArrayList<>(), new ArrayList<>());
Location cave = new Location("Cave", new ArrayList<>(), new ArrayList<>());
Location dungeon = new Location("Dungeon", new ArrayList<>(), new ArrayList<>());
Location castle = new Location("Castle", new ArrayList<>(), new ArrayList<>());
// Establishing connections between locations
// Village <-> Forest
village.addConnection(forest);
forest.addConnection(village);
// Forest <-> Cave
forest.addConnection(cave);
cave.addConnection(forest);
// Cave <-> Dungeon
cave.addConnection(dungeon);
dungeon.addConnection(cave);
// Dungeon <-> Castle
dungeon.addConnection(castle);
castle.addConnection(dungeon);
return village; // Start of the journey
}
//Helper method to add a connection to avoid direct list manipulation from outside.
public void addConnection(Location location) {
if (!this.locations.contains(location)) {
this.locations.add(location);
}
}
} }
@@ -0,0 +1,23 @@
package org.project.utils;
public class ConsoleColors {
public static final String RESET = "\u001B[0m";
public static final String BLACK = "\u001B[30m";
public static final String RED = "\u001B[31m";
public static final String GREEN = "\u001B[32m";
public static final String YELLOW = "\u001B[33m";
public static final String BLUE = "\u001B[34m";
public static final String PURPLE = "\u001B[35m";
public static final String CYAN = "\u001B[36m";
public static final String WHITE = "\u001B[37m";
// Bold or bright variants
public static final String BRIGHT_RED = "\u001B[91m";
public static final String BRIGHT_GREEN = "\u001B[92m";
public static final String BRIGHT_YELLOW = "\u001B[93m";
public static final String BRIGHT_BLUE = "\u001B[94m";
public static final String BRIGHT_PURPLE = "\u001B[95m";
public static final String BRIGHT_CYAN = "\u001B[96m";
public static final String BRIGHT_WHITE = "\u001B[97m";
}
Binary file not shown.
+248
View File
@@ -0,0 +1,248 @@
:::writing
# Javanest Adventure
## Overview
**Javanest Adventure** is a turnbased console RPG written in Java.
The player explores different locations, fights monsters, collects keys, and eventually unlocks the castle to confront the final enemy.
The game is inspired by classic textbased RPGs and demonstrates core **objectoriented programming (OOP)** concepts such as inheritance, abstraction, interfaces, and polymorphism.
---
# Story
The peaceful land of **Javanest** has fallen under a terrible curse.
A powerful **Dragon** has taken control of the kingdom and unleashed monsters across the land. Villages are abandoned, forests are haunted, and caves are filled with undead creatures.
The dragon locked itself inside the **Castle**, and the only way to enter is by collecting **three hidden keys** scattered among the monsters.
Your mission is simple:
- Explore the world
- Defeat monsters
- Collect the keys
- Enter the castle
- Defeat the dragon and free Javanest
---
# Game Features
## Turn-Based Combat
Combat is **turn-based**.
Each round consists of:
1. Player turn
2. Enemy turn
The battle continues until either the player or the enemy dies.
---
## Player Actions
During each turn the player can choose one of the following actions:
1. **Attack** perform a normal attack with the equipped weapon
2. **Use Skill** perform a stronger ability depending on the player class
3. **Use Item** consume a healing or utility item
4. **Defend** reduce incoming damage
5. **Run** attempt to escape the battle
---
## Exploration
The world contains several locations:
- Village (starting area)
- Forest
- Cave
- Dungeon
- Castle (final area)
Players can move between connected locations and may encounter enemies in dangerous areas.
---
## Keys and Progression
The **Castle is locked**.
To unlock it the player must collect **3 keys**.
Keys are obtained by **defeating enemies**.
Once all keys are collected, the player can enter the **Castle** and fight the final boss.
---
# Enemies
Enemies are represented by the abstract class `Enemy`.
Possible enemy types include:
- Skeleton
- Goblin
- Vampire
- Dragon (final boss)
Each enemy has different stats such as:
- Health
- Attack power
- Defense
---
# Player Classes
The player is represented by the abstract class `Player`, which implements the `Entity` interface.
Possible subclasses include:
- **Knight** high defense and balanced attack
- **Wizard** strong magic attacks and mana usage
- **Assassin** fast and high critical damage
Each class has different abilities and combat strategies.
---
# Items
Items help the player survive and improve combat performance.
Types of items include:
- **Weapon** increases attack damage
- **Armor** increases defense
- **Consumable** restores health or provides temporary effects
---
# Project Structure
Example structure of the project:
```
src/
├── Main.java
├── Entity.java
├── Player.java
├── Enemy.java
├── Location.java
├── players/
│ ├── Knight.java
│ ├── Wizard.java
│ └── Assassin.java
├── enemies/
│ ├── Skeleton.java
│ ├── Goblin.java
│ ├── Vampire.java
│ └── Dragon.java
├── items/
│ ├── Item.java
│ ├── Weapon.java
│ ├── Armor.java
│ └── Consumable.java
└── utils/
└── ConsoleColors.java
```
---
# Console Colors
The game uses ANSI colors to improve readability.
| Color | Usage |
| ------ | ------------------- |
| Red | Damage messages |
| Blue | Mana or defense |
| Green | Healing and success |
| Yellow | Warnings and keys |
| Cyan | UI information |
Example:
```
System.out.println(ConsoleColors.RED + "You took 10 damage!" + ConsoleColors.RESET);
```
---
# How to Run the Game
### Compile
```
javac *.java
```
### Run
```
java Main
```
The game will start in the **Village** and the player can begin exploring.
---
# Gameplay Loop
Typical gameplay flow:
1. Player starts in Village
2. Moves to a new location
3. Random enemy appears
4. Combat begins
5. Enemy defeated → possible key drop
6. Repeat exploration
7. Collect 3 keys
8. Enter Castle
9. Fight the Dragon
10. Win the game
---
# OOP Concepts Used
This project demonstrates several core Java concepts:
- **Abstraction**
- **Inheritance**
- **Interfaces**
- **Polymorphism**
- **Encapsulation**
---
# Future Improvements
Possible future features:
- Inventory system
- Equipment upgrades
- Experience and leveling
- More enemy types
- More locations
- Boss mechanics
- Save/load system
---
# Author
Developed as a Java OOP project for practicing game architecture and objectoriented design.
:::
BIN
View File
Binary file not shown.