develop #1

Merged
peyman merged 2 commits from develop into main 2026-07-18 17:32:28 +00:00
31 changed files with 661 additions and 201 deletions
Showing only changes of commit 1f16d21aa6 - Show all commits
+221 -5
View File
@@ -1,15 +1,231 @@
package org.project;
import org.project.location.Location;
import org.project.entity.Entity;
import org.project.entity.enemies.*;
import org.project.entity.players.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO: ADD LOCATIONS TO YOUR GAME
List<Location> locations = new ArrayList<>();
private static Scanner scanner = new Scanner(System.in);
private static Player player;
private static boolean hasGoblinKey = false;
private static boolean hasSkeletonKey = false;
private static boolean hasVampireKey = false;
private static int currentLocationIndex = 0;
private static List<Location> locations = new ArrayList<>();
private static String[] locationNames = {"Forest", "Cemetery", "Crypt", "Ruins"};
// TODO: IMPLEMENT GAMEPLAY
public static void main(String[] args) {
for (int i = 0; i < locationNames.length; i++) {
locations.add(new Location(new ArrayList<>(), new ArrayList<>()));
}
System.out.println("Welcome to Java Knight");
System.out.println("Choose your class:");
System.out.println("1. Knight");
System.out.println("2. Assassin");
System.out.println("3. Wizard");
int choice = readInt("Choice: ", 1, 3);
switch (choice) {
case 1:
player = new Knight("Arthur", 60, 40, 60, 40,
12, 24, 8, 20, 10);
break;
case 2:
player = new Assassin("Layla", 45, 55, 45, 55,
8, 18, 8, 15, 10);
break;
case 3:
player = new Wizard("Merlin", 70, 50, 70, 50,
6, 14, 8, 25, 10);
break;
}
System.out.println(player.getName() + " starts the journey.");
System.out.println("Collect three keys (Goblin, Skeleton, Vampire) then face the Dragon.\n");
while (player.isAlive()) {
System.out.println("\nYou are in " + locationNames[currentLocationIndex] + ".");
Enemy currentEnemy = spawnRandomEnemyForLocation();
System.out.println("A " + currentEnemy.getClass().getSimpleName() + " appears!");
// Menu for the location
boolean actionDone = false;
while (!actionDone && player.isAlive()) {
System.out.println("\nWhat do you want to do?");
System.out.println("1. Fight the enemy");
System.out.println("2. Move to another location");
if (hasGoblinKey && hasSkeletonKey && hasVampireKey) {
System.out.println("3. Go to the Castle to fight the Dragon");
}
int action = readInt("Choose: ", 1, (hasGoblinKey && hasSkeletonKey && hasVampireKey) ? 3 : 2);
if (action == 1) {
// Fight
boolean enemyDefeated = false;
while (!enemyDefeated && player.isAlive()) {
printStatus(currentEnemy);
int combatAction = showCombatMenu();
executePlayerAction(combatAction, currentEnemy);
if (!currentEnemy.isAlive()) {
enemyDefeated = true;
break;
}
if (!player.isAlive()) break;
enemyTurn(currentEnemy);
}
if (!player.isAlive()) {
System.out.println("You died. Game over.");
return;
}
// Victory handling
handleVictory(currentEnemy);
actionDone = true;
// Full restore after fight
player.fillMana(player.getMaxMP());
player.heal(player.getMaxHP() - player.getHp());
System.out.println("Your health and mana are fully restored.");
} else if (action == 2) {
// Move to random different location
int newIndex = currentLocationIndex;
while (newIndex == currentLocationIndex) {
newIndex = new Random().nextInt(locations.size());
}
currentLocationIndex = newIndex;
System.out.println("You move to " + locationNames[currentLocationIndex] + ".");
actionDone = true; // enemy respawns in new location automatically in next loop iteration
} else if (action == 3) {
// Go to castle
fightDragon();
if (!player.isAlive()) {
System.out.println("You died. Game over.");
return;
}
System.out.println("You defeated the Dragon! The curse is lifted. Victory!");
return;
}
}
}
}
private static Enemy spawnRandomEnemyForLocation() {
Random rand = new Random();
int type = rand.nextInt(3);
switch (type) {
case 0: return new Goblin(40, 20, 14);
case 1: return new Skeleton(50, 20, 12);
default: return new Vampire(55, 25, 16);
}
}
private static void printStatus(Enemy enemy) {
System.out.println("\n" + player.getName() + ": " + player.getHp() + "/" + player.getMaxHP() +
" HP, " + player.getMp() + "/" + player.getMaxMP() + " Mana");
System.out.println(enemy.getClass().getSimpleName() + ": " + enemy.getHp() + " HP");
}
private static int showCombatMenu() {
System.out.println("\nYour turn:");
System.out.println("1. Light Attack (0 mana)");
System.out.println("2. Heavy Attack (8 mana)");
System.out.println("3. Defend (6 mana)");
System.out.println("4. Heal (10 mana)");
System.out.println("5. Special Ability (15 mana)");
return readInt("Choose: ", 1, 5);
}
private static void executePlayerAction(int action, Entity target) {
switch (action) {
case 1:
player.LightAttack(target, 0);
System.out.println("Light attack performed.");
break;
case 2:
player.HeavyAttack(target, 0);
System.out.println("Heavy attack performed.");
break;
case 3:
System.out.println(player.defend());
break;
case 4:
player.heal(0);
System.out.println("Heal attempted.");
break;
case 5:
player.SpecialAbility(target);
System.out.println("Special ability used.");
break;
}
}
private static void enemyTurn(Enemy enemy) {
System.out.println(enemy.getClass().getSimpleName() + "'s turn:");
Random rand = new Random();
int dmg = 0;
if (enemy instanceof Goblin) dmg = ((Goblin) enemy).getAttackDamage();
else if (enemy instanceof Skeleton) dmg = ((Skeleton) enemy).getAttackDamage();
else if (enemy instanceof Vampire) dmg = ((Vampire) enemy).getAttackDamage();
if (rand.nextDouble() < 0.7) {
enemy.LightAttack(player, dmg);
System.out.println(enemy.getClass().getSimpleName() + " attacks!");
} else {
enemy.SpecialAbility(player);
System.out.println(enemy.getClass().getSimpleName() + " uses special ability!");
}
}
private static void handleVictory(Enemy enemy) {
System.out.println(enemy.getClass().getSimpleName() + " defeated!");
Random rand = new Random();
int chance = rand.nextInt(100);
if (enemy instanceof Goblin && !hasGoblinKey && chance < 20) {
hasGoblinKey = true;
System.out.println("You obtained the Goblin Key!");
} else if (enemy instanceof Skeleton && !hasSkeletonKey && chance < 20) {
hasSkeletonKey = true;
System.out.println("You obtained the Skeleton Key!");
} else if (enemy instanceof Vampire && !hasVampireKey && chance < 20) {
hasVampireKey = true;
System.out.println("You obtained the Vampire Key!");
}
System.out.println("Keys status: Goblin=" + hasGoblinKey + " Skeleton=" + hasSkeletonKey + " Vampire=" + hasVampireKey);
}
private static void fightDragon() {
Dragon dragon = new Dragon(180, 100, 45);
System.out.println("Dragon appears! Final battle begins.");
while (player.isAlive() && dragon.isAlive()) {
printStatus(dragon);
int action = showCombatMenu();
executePlayerAction(action, dragon);
if (!dragon.isAlive()) break;
if (!player.isAlive()) break;
System.out.println("Dragon uses fiery breath!");
dragon.SpecialAbility(player);
System.out.println("Dragon deals " + dragon.getAttackDamage() * 2 + " damage ignoring defense.");
}
}
private static int readInt(String prompt, int min, int max) {
int value;
while (true) {
System.out.print(prompt);
if (scanner.hasNextInt()) {
value = scanner.nextInt();
if (value >= min && value <= max) return value;
else System.out.println("Enter number between " + min + " and " + max);
} else {
System.out.println("Invalid input. Enter a number.");
scanner.next();
}
}
}
}
}
@@ -1,9 +1,8 @@
package org.project.entity;
public interface Entity {
void attack(Entity target);
void defend();
String defend();
void heal(int health);
@@ -15,7 +14,11 @@ public interface Entity {
int getMaxMP();
/*
TODO: ADD OTHER REQUIRED AND BONUS METHODS
*/
void LightAttack(Entity target, int damage);
void HeavyAttack(Entity target, int damage);
boolean isAlive();
int getHp();
int getMp();
}
@@ -0,0 +1,26 @@
package org.project.entity.enemies;
import org.project.entity.Entity;
public class Dragon extends Enemy{
private final int attackDamage;
public Dragon(int hp, int mp, int attackDamage){
super(hp, mp);
this.attackDamage = attackDamage;
}
public int getAttackDamage(){
return attackDamage;
}
@Override
public void SpecialAbility(Entity target) {
target.takeDamage(attackDamage*2);
}
@Override
public String defend() {
return "dragon ignores defense";
}
}
@@ -1,23 +1,59 @@
package org.project.entity.enemies;
import org.project.item.weapons.Weapon;
import org.project.entity.Entity;
// TODO: UPDATE IMPLEMENTATION
public abstract class Enemy {
Weapon weapon;
private int hp;
private int mp;
public Enemy(int hp, int mp, Weapon weapon) {
public abstract class Enemy implements Entity {
protected int hp;
protected int mp;
protected int maxHp;
protected int maxMp;
public Enemy(int hp, int mp) {
this.hp = hp;
this.mp = mp;
this.maxHp = hp;
this.maxMp = mp;
this.weapon = weapon;
}
@Override
public void takeDamage(int damage) {
hp -= damage;
if (hp < 0) hp = 0;
}
@Override
public void LightAttack(Entity target, int damage) {
target.takeDamage(damage);
}
@Override
public void HeavyAttack(Entity target, int damage) {
target.takeDamage(damage);
}
public abstract void SpecialAbility(Entity target);
@Override
public void heal(int health) {
hp += health;
}
@Override
public void fillMana(int mana) {
mp += mana;
}
@Override
public String defend() {
return "enemy defends";
}
@Override
public boolean isAlive() {
return hp > 0;
}
public int getHp() {
@@ -28,7 +64,16 @@ public abstract class Enemy {
return mp;
}
public Weapon getWeapon() {
return weapon;
@Override
public int getMaxHP() {
return maxHp;
}
@Override
public int getMaxMP() {
return maxMp;
}
}
@@ -0,0 +1,37 @@
package org.project.entity.enemies;
import org.project.entity.Entity;
import java.util.Random;
public class Goblin extends Enemy {
private final int attackDamage;
private Random random;
public Goblin(int hp, int mp, int attackDamage) {
super(hp, mp);
this.attackDamage = attackDamage;
this.random = new Random();
}
public int getAttackDamage() {
return attackDamage;
}
@Override
public void LightAttack(Entity target, int damage) {
int chance = random.nextInt(10) + 1;
if (chance <= 3) {
target.takeDamage(2 * attackDamage);
} else {
target.takeDamage(attackDamage);
}
}
@Override
public void SpecialAbility(Entity target) {
}
}
@@ -1,6 +1,39 @@
package org.project.entity.enemies;
// TODO: UPDATE IMPLEMENTATION
public class Skeleton {
// TODO: DESIGN ENEMY AND IMPLEMENT THE CONSTRUCTOR
import org.project.entity.Entity;
public class Skeleton extends Enemy {
private final int attackDamage;
private boolean hasRevived;
public Skeleton(int hp, int mp, int attackDamage) {
super(hp, mp);
this.attackDamage = attackDamage;
this.hasRevived = false;
}
public int getAttackDamage() {
return attackDamage;
}
@Override
public void takeDamage(int damage) {
super.takeDamage(damage);
if (!hasRevived && hp <= 0) {
hp = maxHp / 2;
hasRevived = true;
}
}
@Override
public void SpecialAbility(Entity target) {
// Skeleton's revive is handled in takeDamage
}
@Override
public boolean isAlive() {
return hp > 0;
}
}
@@ -0,0 +1,23 @@
package org.project.entity.enemies;
import org.project.entity.Entity;
public class Vampire extends Enemy {
private final int attackDamage;
public Vampire(int hp, int mp, int attackDamage) {
super(hp, mp);
this.attackDamage = attackDamage;
}
public int getAttackDamage() {
return attackDamage;
}
@Override
public void SpecialAbility(Entity target) {
int healAmount = (int)(0.3 * attackDamage);
heal(healAmount);
target.takeDamage(attackDamage);
}
}
@@ -0,0 +1,74 @@
package org.project.entity.players;
import org.project.entity.Entity;
public class Assassin extends Player{
private final int lightAttackDamage;
private final int heavyAttackDamage;
private final int heavyAttackMana;
private final int healNumber;
private final int healMana;
private boolean invisible;
public Assassin(String name, int hp, int mp,int maxHP,int maxMP, int lightAttackDamage, int heavyAttackDamage, int heavyAttackMana, int healNumber, int healMana){
super(name, hp, mp, maxHP,maxMP);
this.lightAttackDamage = lightAttackDamage ;
this.heavyAttackDamage = heavyAttackDamage;
this.heavyAttackMana=heavyAttackMana ;
this.healNumber =healNumber ;
this.healMana=healMana ;
this.invisible = false;
}
@Override
public void SpecialAbility(Entity target) {
if (mp >= heavyAttackMana + 10) {
invisible = true;
mp -= (heavyAttackMana + 10);
}
}
@Override
public void LightAttack(Entity target, int damage) {
int dmg = invisible ? lightAttackDamage * 2 : lightAttackDamage;
target.takeDamage(dmg);
invisible = false;
}
@Override
public void HeavyAttack(Entity target, int damage) {
if (mp >= heavyAttackMana) {
int dmg = invisible ? heavyAttackDamage * 2 : heavyAttackDamage;
target.takeDamage(dmg);
mp -= heavyAttackMana;
invisible = false;
}
}
@Override
public void heal(int health) {
if (mp >= healMana) {
super.heal(healNumber);
mp -= healMana;
}
}
public int getLightAttackDamage(){
return lightAttackDamage;
}
public int getHeavyAttackDamage(){
return heavyAttackDamage;
}
public int getHeavyAttackMana(){
return heavyAttackMana;
}
public int getHealNumber(){
return healNumber;
}
public int getHealMana(){
return healMana;
}
}
@@ -1,6 +1,69 @@
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;
public class Knight extends Player {
private final int lightAttackDamage;
private final int heavyAttackDamage;
private final int heavyAttackMana;
private final int healNumber;
private final int healMana;
public Knight(String name, int hp, int mp ,int maxHP,int maxMP,int lightAttackDamage,int heavyAttackDamage,int haeavyAttackMana,int healNumber,int healMana){
super(name, hp, mp, maxHP,maxMP);
this.lightAttackDamage = lightAttackDamage ;
this.heavyAttackDamage = heavyAttackDamage;
this.heavyAttackMana=haeavyAttackMana ;
this.healNumber =healNumber ;
this.healMana=healMana ;
}
@Override
public void SpecialAbility(Entity target) {
if (mp >= heavyAttackMana + 10) {
target.takeDamage(heavyAttackDamage);
mp -= (heavyAttackMana + 10);
}
}
@Override
public void LightAttack(Entity target, int damage) {
target.takeDamage(lightAttackDamage);
}
@Override
public void HeavyAttack(Entity target, int damage) {
if (mp >= heavyAttackMana) {
target.takeDamage(heavyAttackDamage);
mp -= heavyAttackMana;
}
}
@Override
public void heal(int health) {
if (mp >= healMana) {
super.heal(healNumber);
mp -= healMana;
}
}
public int getLightAttackDamage(){
return lightAttackDamage;
}
public int getHeavyAttackDamage(){
return heavyAttackDamage;
}
public int getHeavyAttackMana(){
return heavyAttackMana;
}
public int getHealNumber(){
return healNumber;
}
public int getHealMana(){
return healMana;
}
}
@@ -1,42 +1,43 @@
package org.project.entity.players;
import org.project.entity.Entity;
import org.project.item.armors.Armor;
import org.project.item.weapons.Weapon;
// TODO: UPDATE IMPLEMENTATION
public abstract class Player {
public abstract class Player implements Entity {
protected String name;
Weapon weapon;
Armor armor;
private int hp;
private int maxHP;
private int mp;
private int maxMP;
protected int hp;
protected int maxHP;
protected int mp;
protected int maxMP;
protected boolean isDefending;
public Player(String name, int hp, int mp, Weapon weapon, Armor armor) {
public Player(String name, int hp, int mp, int maxHP,int maxMP) {
this.name = name;
this.hp = hp;
this.mp = mp;
this.weapon = weapon;
this.armor = armor;
this.maxMP = maxMP;
this.maxHP = maxHP;
this.isDefending = false;
}
@Override
public void attack(Entity target) {
target.takeDamage(weapon.getDamage());
public String defend() {
if (mp >= 6) {
mp -= 6;
isDefending = true;
return name + " assumes defensive stance";
}
return "not enough mana to defend";
}
@Override
public void defend() {
// TODO
}
@Override
public void takeDamage(int damage) {
hp -= damage - armor.getDefense();
if (isDefending) {
damage = damage / 2;
isDefending = false;
}
hp -= damage;
if (hp < 0) hp = 0;
}
@Override
@@ -55,6 +56,27 @@ public abstract class Player {
}
}
@Override
public void LightAttack(Entity target, int damage) {
target.takeDamage(damage);
}
@Override
public void HeavyAttack(Entity target, int damage) {
if (mp >= 8) {
target.takeDamage(damage);
mp -= 8;
}
}
public abstract void SpecialAbility(Entity target);
@Override
public boolean isAlive() {
return hp > 0;
}
public String getName() {
return name;
@@ -78,12 +100,4 @@ public abstract class Player {
return maxMP;
}
public Weapon getWeapon() {
return weapon;
}
public Armor getArmor() {
return armor;
}
}
@@ -0,0 +1,69 @@
package org.project.entity.players;
import org.project.entity.Entity;
public class Wizard extends Player {
private final int lightAttackDamage;
private final int heavyAttackDamage;
private final int heavyAttackMana;
private final int healNumber;
private final int healMana;
public Wizard(String name, int hp, int mp,int maxHP,int maxMP, int lightAttackDamage, int heavyAttackDamage, int heavyAttackMana, int healNumber, int healMana){
super(name, hp, mp, maxHP,maxMP);
this.lightAttackDamage = lightAttackDamage ;
this.heavyAttackDamage = heavyAttackDamage;
this.heavyAttackMana=heavyAttackMana ;
this.healNumber =healNumber ;
this.healMana=healMana ;
}
@Override
public void SpecialAbility(Entity target) {
if (mp >= heavyAttackMana + 10) {
target.takeDamage(heavyAttackDamage + 10);
heal(healNumber);
mp -= (heavyAttackMana + 10);
}
}
@Override
public void LightAttack(Entity target, int damage) {
target.takeDamage(lightAttackDamage);
}
@Override
public void HeavyAttack(Entity target, int damage) {
if (mp >= heavyAttackMana) {
target.takeDamage(heavyAttackDamage);
mp -= heavyAttackMana;
}
}
@Override
public void heal(int health) {
if (mp >= healMana) {
super.heal(healNumber);
mp -= healMana;
}
}
public int getLightAttackDamage(){
return lightAttackDamage;
}
public int getHeavyAttackDamage(){
return heavyAttackDamage;
}
public int getHeavyAttackMana(){
return heavyAttackMana;
}
public int getHealNumber(){
return healNumber;
}
public int getHealMana(){
return healMana;
}
}
@@ -1,11 +0,0 @@
package org.project.item;
import org.project.entity.Entity;
public interface Item {
void use(Entity target);
/*
TODO: ADD OTHER REQUIRED AND BONUS METHODS
*/
}
@@ -1,42 +0,0 @@
package org.project.item.armors;
// TODO: UPDATE IMPLEMENTATION
public abstract class Armor {
private int defense;
private int maxDefense;
private int durability;
private int maxDurability;
private boolean isBroke;
public Armor(int defense, int durability) {
this.defense = defense;
this.durability = durability;
}
public void checkBreak() {
if (durability <= 0) {
isBroke = true;
defense = 0;
}
}
// TODO: (BONUS) UPDATE THE REPAIR METHOD
public void repair() {
isBroke = false;
defense = maxDefense;
durability = maxDurability;
}
public int getDefense() {
return defense;
}
public int getDurability() {
return durability;
}
public boolean isBroke() {
return isBroke;
}
}
@@ -1,6 +0,0 @@
package org.project.item.armors;
// TODO: UPDATE IMPLEMENTATION
public class KnightArmor {
// TODO: DESIGN ARMOR'S ATTRIBUTES IMPLEMENT THE CONSTRUCTOR
}
@@ -1,8 +0,0 @@
package org.project.item.consumables;
// TODO: UPDATE IMPLEMENTATION
public abstract class Consumable {
/*
TODO: ADD OTHER REQUIRED AND BONUS METHODS
*/
}
@@ -1,16 +0,0 @@
package org.project.item.consumables;
import org.project.entity.Entity;
// TODO: UPDATE IMPLEMENTATION
public class Flask {
/*
THIS IS AN EXAMPLE OF A CONSUMABLE DESIGN.
*/
// TODO: UPDATE USE METHOD
@Override
public void use(Entity target) {
target.heal(target.getMaxHP() / 10);
}
}
@@ -1,26 +0,0 @@
package org.project.item.weapons;
import org.project.entity.Entity;
import java.util.ArrayList;
// TODO: UPDATE IMPLEMENTATION
public class Sword {
/*
THIS IS AN EXAMPLE OF A WEAPON DESIGN.
*/
int abilityCharge;
public Sword() {
// TODO: DESIGN SWORD'S ATTRIBUTES IMPLEMENT THE CONSTRUCTOR
}
// TODO: (BONUS) UPDATE THE UNIQUE ABILITY
public void uniqueAbility(ArrayList<Entity> targets) {
abilityCharge += 2;
for (Entity target : targets) {
target.takeDamage(getDamage());
}
}
}
@@ -1,35 +0,0 @@
package org.project.item.weapons;
import org.project.entity.Entity;
// TODO: UPDATE IMPLEMENTATION
public abstract class Weapon {
private int damage;
private int manaCost;
/*
TODO: ADD OTHER REQUIRED AND BONUS ATTRIBUTES
*/
public Weapon(int damage, int manaCost) {
this.damage = damage;
this.manaCost = manaCost;
}
@Override
public void use(Entity target) {
target.takeDamage(damage);
}
public int getDamage() {
return damage;
}
public int getManaCost() {
return manaCost;
}
/*
TODO: ADD OTHER REQUIRED AND BONUS METHODS
*/
}
@@ -6,6 +6,7 @@ import java.util.ArrayList;
public class Location {
private String name;
private ArrayList<Location> locations;
private ArrayList<Enemy> enemies;
Binary file not shown.