[go: up one dir, main page]

0% found this document useful (0 votes)
9 views17 pages

Week 5 - S5 - Core OOP - Encapsulation - Lab Problem

The document outlines the design and implementation of a professional virtual pet evolution system in Java, focusing on access control, encapsulation, and JavaBean standards. It details the creation of a VirtualPet class with various access levels, immutable configuration objects, and specialized pet classes like DragonPet and RobotPet. Additionally, it includes a medieval kingdom management system with immutable objects and a KingdomManager class for structure interaction and power calculation.

Uploaded by

sm9395
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views17 pages

Week 5 - S5 - Core OOP - Encapsulation - Lab Problem

The document outlines the design and implementation of a professional virtual pet evolution system in Java, focusing on access control, encapsulation, and JavaBean standards. It details the creation of a VirtualPet class with various access levels, immutable configuration objects, and specialized pet classes like DragonPet and RobotPet. Additionally, it includes a medieval kingdom management system with immutable objects and a KingdomManager class for structure interaction and power calculation.

Uploaded by

sm9395
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 17

Practice Problem 1: 🎮 Professional Virtual Pet Evolution

System with Access Control


Topics Covered: Access Modifiers, Encapsulation, JavaBean Standards, Constructor
Chaining, final Keyword
Requirements: Design a VirtualPet class system that demonstrates professional Java
development standards with proper access control, data hiding, and immutable configuration
objects.
Core Tasks:
a. Create VirtualPet class with four access levels:
● private final String petId, PetSpecies species, long
birthTimestamp (Immutable core)
● private String petName, int age, happiness, health (Controlled mutable
state)
● protected static final String[] DEFAULT_EVOLUTION_STAGES (Package
accessible)
● static final int MAX_HAPPINESS = 100, MAX_HEALTH = 100
(Package-private constants)
● public static final String PET_SYSTEM_VERSION = "2.0" (Global access)
b. Implement immutable PetSpecies class:
● final class that cannot be extended
● All fields must be final: speciesName, evolutionStages[], maxLifespan,
habitat
● Only getters (no setters) - defensive copying for arrays
● Constructor validation with IllegalArgumentException for invalid data
c. Constructor chaining with validation:
● Default constructor: Creates random pet with default species
● Constructor with name only: Uses default species and moderate stats
● Constructor with name and species: Uses default moderate stats
● Main constructor: Full parameter validation, all others chain to this
d. JavaBean compliance:
● Proper getter/setter naming conventions
● Validated setters with range checking (0-100 for stats)
● toString(), equals(), hashCode() implementations
● Private helper methods: validateStat(), generatePetId(), checkEvolution()
e. Access-controlled methods:
● public feedPet(String foodType), playWithPet(String gameType) - main
interface
● protected calculateFoodBonus(), calculateGameEffect() - internal
calculations
● private modifyHappiness(), modifyHealth(), updateEvolutionStage() -
internal logic
● Package-private getInternalState() for debugging within package
f. Create separate specialized pet classes (no inheritance):
● DragonPet class with private final String dragonType, breathWeapon
● RobotPet class with private boolean needsCharging, batteryLevel
● Each class follows same access patterns and JavaBean standards
● Use composition with VirtualPet reference if needed for shared functionality

Program:
import java.util.*;

// 🔹 Immutable PetSpecies
final class PetSpecies {
private final String speciesName;
private final String[] evolutionStages;
private final int maxLifespan;
private final String habitat;

public PetSpecies(String speciesName, String[] evolutionStages, int maxLifespan, String


habitat) {
if (speciesName == null || speciesName.isBlank()) {
throw new IllegalArgumentException("Species name cannot be null/blank");
}
if (evolutionStages == null || evolutionStages.length == 0) {
throw new IllegalArgumentException("Evolution stages cannot be empty");
}
if (maxLifespan <= 0) {
throw new IllegalArgumentException("Max lifespan must be positive");
}
if (habitat == null || habitat.isBlank()) {
throw new IllegalArgumentException("Habitat cannot be null/blank");
}
this.speciesName = speciesName;
this.evolutionStages = Arrays.copyOf(evolutionStages, evolutionStages.length);
this.maxLifespan = maxLifespan;
this.habitat = habitat;
}

public String getSpeciesName() { return speciesName; }


public String[] getEvolutionStages() { return Arrays.copyOf(evolutionStages,
evolutionStages.length); }
public int getMaxLifespan() { return maxLifespan; }
public String getHabitat() { return habitat; }

@Override
public String toString() {
return "PetSpecies{" +
"speciesName='" + speciesName + '\'' +
", maxLifespan=" + maxLifespan +
", habitat='" + habitat + '\'' +
'}';
}

@Override
public boolean equals(Object o) {
if (!(o instanceof PetSpecies)) return false;
PetSpecies other = (PetSpecies) o;
return maxLifespan == other.maxLifespan &&
Objects.equals(speciesName, other.speciesName) &&
Arrays.equals(evolutionStages, other.evolutionStages) &&
Objects.equals(habitat, other.habitat);
}

@Override
public int hashCode() {
return Objects.hash(speciesName, maxLifespan, habitat) +
Arrays.hashCode(evolutionStages);
}
}

// 🔹 VirtualPet Core Class


class VirtualPet {
// Immutable core
private final String petId;
private final PetSpecies species;
private final long birthTimestamp;

// Mutable state
private String petName;
private int age;
private int happiness;
private int health;

// Protected default stages


protected static final String[] DEFAULT_EVOLUTION_STAGES = {"Egg", "Child", "Adult"};

// Package-private constants
static final int MAX_HAPPINESS = 100;
static final int MAX_HEALTH = 100;

// Public constant
public static final String PET_SYSTEM_VERSION = "2.0";

// 🔹 Constructor chaining
public VirtualPet() {
this("Defaulty", new PetSpecies("DefaultSpecies", DEFAULT_EVOLUTION_STAGES, 100,
"VirtualWorld"), 1, 50, 50);
}

public VirtualPet(String petName) {


this(petName, new PetSpecies("DefaultSpecies", DEFAULT_EVOLUTION_STAGES, 100,
"VirtualWorld"));
}

public VirtualPet(String petName, PetSpecies species) {


this(petName, species, 1, 50, 50);
}

public VirtualPet(String petName, PetSpecies species, int age, int happiness, int health) {
this.petId = generatePetId();
this.species = Objects.requireNonNull(species);
this.birthTimestamp = System.currentTimeMillis();
this.petName = Objects.requireNonNull(petName);
setAge(age);
setHappiness(happiness);
setHealth(health);
}

// 🔹 Getters/Setters
public String getPetId() { return petId; }
public PetSpecies getSpecies() { return species; }
public long getBirthTimestamp() { return birthTimestamp; }
public String getPetName() { return petName; }
public void setPetName(String petName) { this.petName = petName; }
public int getAge() { return age; }
public void setAge(int age) { this.age = Math.max(0, age); }
public int getHappiness() { return happiness; }
public void setHappiness(int happiness) { this.happiness = validateStat(happiness); }
public int getHealth() { return health; }
public void setHealth(int health) { this.health = validateStat(health); }

// 🔹 Access-controlled methods
public void feedPet(String foodType) {
int bonus = calculateFoodBonus(foodType);
modifyHealth(bonus);
}

public void playWithPet(String gameType) {


int bonus = calculateGameEffect(gameType);
modifyHappiness(bonus);
}

protected int calculateFoodBonus(String foodType) {


return foodType.equalsIgnoreCase("fruit") ? 10 : 5;
}

protected int calculateGameEffect(String gameType) {


return gameType.equalsIgnoreCase("fetch") ? 15 : 8;
}

private void modifyHappiness(int delta) {


happiness = Math.min(MAX_HAPPINESS, happiness + delta);
updateEvolutionStage();
}

private void modifyHealth(int delta) {


health = Math.min(MAX_HEALTH, health + delta);
updateEvolutionStage();
}

private void updateEvolutionStage() {


// Placeholder for evolution logic
}

// Package-private for debugging


String getInternalState() {
return "Pet{" + petName + ", age=" + age + ", health=" + health + ", happiness=" +
happiness + "}";
}

// Helpers
private int validateStat(int value) {
if (value < 0 || value > 100) return 50;
return value;
}

private String generatePetId() {


return UUID.randomUUID().toString();
}
@Override
public String toString() {
return "VirtualPet{" +
"petId='" + petId + '\'' +
", petName='" + petName + '\'' +
", species=" + species +
", age=" + age +
", happiness=" + happiness +
", health=" + health +
'}';
}

@Override
public boolean equals(Object o) {
if (!(o instanceof VirtualPet)) return false;
VirtualPet other = (VirtualPet) o;
return Objects.equals(petId, other.petId);
}

@Override
public int hashCode() {
return Objects.hash(petId);
}
}

// 🔹 Specialized Pets via Composition


class DragonPet {
private final String dragonType;
private final String breathWeapon;
private final VirtualPet corePet;

public DragonPet(String petName, String dragonType, String breathWeapon) {


this.dragonType = dragonType;
this.breathWeapon = breathWeapon;
this.corePet = new VirtualPet(
petName,
new PetSpecies("Dragon", new String[]{"Egg", "Wyrmling", "Adult Dragon"}, 500,
"Cave")
);
}

public VirtualPet getCorePet() { return corePet; }


public String getDragonType() { return dragonType; }
public String getBreathWeapon() { return breathWeapon; }
}

class RobotPet {
private boolean needsCharging;
private int batteryLevel;
private final VirtualPet corePet;

public RobotPet(String petName) {


this.needsCharging = false;
this.batteryLevel = 100;
this.corePet = new VirtualPet(
petName,
new PetSpecies("Robot", new String[]{"Prototype", "AdvancedBot", "AI Overlord"},
1000, "Lab")
);
}

public VirtualPet getCorePet() { return corePet; }


public boolean isNeedsCharging() { return needsCharging; }
public void setNeedsCharging(boolean needsCharging) { this.needsCharging =
needsCharging; }
public int getBatteryLevel() { return batteryLevel; }
public void setBatteryLevel(int batteryLevel) {
this.batteryLevel = Math.max(0, Math.min(100, batteryLevel));
}
}

// 🔹 Demo
public class Main {
public static void main(String[] args) {
VirtualPet pet = new VirtualPet("Buddy");
System.out.println(pet);

pet.feedPet("fruit");
pet.playWithPet("fetch");
System.out.println("After activities: " + pet.getInternalState());

DragonPet draco = new DragonPet("Smaug", "Fire", "Flame Breath");


System.out.println("DragonPet core: " + draco.getCorePet());

RobotPet robo = new RobotPet("R2D2");


robo.setBatteryLevel(80);
System.out.println("RobotPet core: " + robo.getCorePet() + ", battery=" +
robo.getBatteryLevel());
}
}

Output:
VirtualPet{petId='a6e2c52e-7d8c-4c1a-bc4e-8fa3e3b3c1d1', petName='Buddy',
species=PetSpecies{speciesName='DefaultSpecies', maxLifespan=100, habitat='VirtualWorld'},
age=1, happiness=50, health=50}
After activities: Pet{Buddy, age=1, health=60, happiness=65}
DragonPet core: VirtualPet{petId='4b3912b7-bad5-44e1-92a5-7f25bb2cf2ab',
petName='Smaug', species=PetSpecies{speciesName='Dragon', maxLifespan=500,
habitat='Cave'}, age=1, happiness=50, health=50}
RobotPet core: VirtualPet{petId='dc2213a2-62b4-4af6-9ed2-3f42acaa73a9', petName='R2D2',
species=PetSpecies{speciesName='Robot', maxLifespan=1000, habitat='Lab'}, age=1,
happiness=50, health=50}, battery=80

Practice Problem 2: 🏰 Medieval Kingdom Management


with Security Architecture
Topics Covered: Access Modifiers, Immutable Objects, instanceof, Constructor
Overloading
Requirements: Build a magical kingdom system with proper access control and immutable
configuration management using separate classes for different structure types.
Core Tasks:
a. Create immutable KingdomConfig class:
● final class with all final fields: kingdomName, foundingYear,
allowedStructureTypes[], resourceLimits Map
● Constructor with full validation and defensive copying
● Only getters, no setters - return clones for mutable references
● Factory methods: createDefaultKingdom(), createFromTemplate(String
type)
b. Base MagicalStructure class (no inheritance hierarchy):
● private final String structureId, long constructionTimestamp
(Immutable identity)
● private final String structureName, location (Immutable properties)
● private int magicPower, boolean isActive, String
currentMaintainer (Controlled state)
● static final int MIN_MAGIC_POWER = 0, MAX_MAGIC_POWER = 1000
(Package constants)
● public static final String MAGIC_SYSTEM_VERSION = "3.0" (Global
constant)
c. Constructor chaining in base class:
● public MagicalStructure(String name, String location) - basic
constructor
● public MagicalStructure(String name, String location, int power) -
with power
● Main constructor: public MagicalStructure(String name, String
location, int power, boolean active)
● All constructors validate inputs and chain to main constructor
d. Four separate specialized structure classes:
● WizardTower: private final int maxSpellCapacity, private
List<String> knownSpells, private String currentWizard
● EnchantedCastle: private final String castleType, private int
defenseRating, private boolean hasDrawbridge
● MysticLibrary: private final Map<String, String> bookCollection,
private int knowledgeLevel
● DragonLair: private final String dragonType, private long
treasureValue, private int territorialRadius
e. Each structure class with unique constructor patterns:
● WizardTower: Empty tower, basic spells, fully equipped options
● Castle: Simple fort, royal castle, impregnable fortress variations
● Library: Few books, moderate collection, ancient archives options
● DragonLair: Different dragon types with specific lair requirements
f. KingdomManager class with instanceof usage:
● private final List<Object> structures (stores different structure types)
● private final KingdomConfig config
● public static boolean canStructuresInteract(Object s1, Object s2)
- use instanceof for type checking
● public static String performMagicBattle(Object attacker, Object
defender)
● public static int calculateKingdomPower(Object[] structures)
● private String determineStructureCategory(Object structure) - type
identification
g. JavaBean compliance for all classes:
● Proper getter/setter patterns where appropriate
● Immutable classes with only getters
● Standard toString(), equals(), hashCode() methods

Program:
import java.util.*;

// 🔹 Immutable KingdomConfig
final class KingdomConfig {
private final String kingdomName;
private final int foundingYear;
private final String[] allowedStructureTypes;
private final Map<String, Integer> resourceLimits;

public KingdomConfig(String kingdomName, int foundingYear, String[]


allowedStructureTypes, Map<String, Integer> resourceLimits) {
if (kingdomName == null || kingdomName.isBlank())
throw new IllegalArgumentException("Kingdom name cannot be empty");
if (foundingYear <= 0)
throw new IllegalArgumentException("Invalid founding year");
if (allowedStructureTypes == null || allowedStructureTypes.length == 0)
throw new IllegalArgumentException("Must allow at least one structure type");
if (resourceLimits == null || resourceLimits.isEmpty())
throw new IllegalArgumentException("Resource limits must be provided");

this.kingdomName = kingdomName;
this.foundingYear = foundingYear;
this.allowedStructureTypes = Arrays.copyOf(allowedStructureTypes,
allowedStructureTypes.length);
this.resourceLimits = new HashMap<>(resourceLimits); // defensive copy
}

public String getKingdomName() { return kingdomName; }


public int getFoundingYear() { return foundingYear; }
public String[] getAllowedStructureTypes() { return Arrays.copyOf(allowedStructureTypes,
allowedStructureTypes.length); }
public Map<String, Integer> getResourceLimits() { return new HashMap<>(resourceLimits); }

// Factory Methods
public static KingdomConfig createDefaultKingdom() {
return new KingdomConfig("Avaloria", 1024, new String[]{"Tower", "Castle", "Library",
"Lair"},
Map.of("Gold", 10000, "Mana", 5000));
}

public static KingdomConfig createFromTemplate(String type) {


switch (type.toLowerCase()) {
case "military":
return new KingdomConfig("Ironhold", 1200, new String[]{"Castle", "Lair"},
Map.of("Gold", 20000, "Mana", 2000));
case "magical":
return new KingdomConfig("Mystica", 800, new String[]{"Tower", "Library"},
Map.of("Gold", 5000, "Mana", 10000));
default:
return createDefaultKingdom();
}
}

@Override
public String toString() {
return "KingdomConfig{" + "kingdomName='" + kingdomName + '\'' +
", foundingYear=" + foundingYear +
", resources=" + resourceLimits + '}';
}

@Override
public boolean equals(Object o) {
if (!(o instanceof KingdomConfig)) return false;
KingdomConfig other = (KingdomConfig) o;
return foundingYear == other.foundingYear &&
Objects.equals(kingdomName, other.kingdomName) &&
Arrays.equals(allowedStructureTypes, other.allowedStructureTypes) &&
Objects.equals(resourceLimits, other.resourceLimits);
}

@Override
public int hashCode() {
return Objects.hash(kingdomName, foundingYear, resourceLimits) +
Arrays.hashCode(allowedStructureTypes);
}
}

// 🔹 Base MagicalStructure (no inheritance hierarchy, but shared logic)


class MagicalStructure {
private final String structureId;
private final long constructionTimestamp;
private final String structureName;
private final String location;

private int magicPower;


private boolean isActive;
private String currentMaintainer;
static final int MIN_MAGIC_POWER = 0;
static final int MAX_MAGIC_POWER = 1000;
public static final String MAGIC_SYSTEM_VERSION = "3.0";

// Constructor chaining
public MagicalStructure(String name, String location) {
this(name, location, 100, true);
}

public MagicalStructure(String name, String location, int power) {


this(name, location, power, true);
}

public MagicalStructure(String name, String location, int power, boolean active) {


if (name == null || name.isBlank()) throw new IllegalArgumentException("Invalid structure
name");
if (location == null || location.isBlank()) throw new IllegalArgumentException("Invalid
location");
if (power < MIN_MAGIC_POWER || power > MAX_MAGIC_POWER)
throw new IllegalArgumentException("Invalid power");

this.structureId = UUID.randomUUID().toString();
this.constructionTimestamp = System.currentTimeMillis();
this.structureName = name;
this.location = location;
this.magicPower = power;
this.isActive = active;
this.currentMaintainer = "Unknown";
}

// Getters/Setters
public String getStructureId() { return structureId; }
public long getConstructionTimestamp() { return constructionTimestamp; }
public String getStructureName() { return structureName; }
public String getLocation() { return location; }
public int getMagicPower() { return magicPower; }
public void setMagicPower(int magicPower) {
this.magicPower = Math.max(MIN_MAGIC_POWER, Math.min(MAX_MAGIC_POWER,
magicPower));
}
public boolean isActive() { return isActive; }
public void setActive(boolean active) { isActive = active; }
public String getCurrentMaintainer() { return currentMaintainer; }
public void setCurrentMaintainer(String currentMaintainer) { this.currentMaintainer =
currentMaintainer; }

@Override
public String toString() {
return structureName + " at " + location + " (Power=" + magicPower + ")";
}

@Override
public boolean equals(Object o) {
if (!(o instanceof MagicalStructure)) return false;
return Objects.equals(structureId, ((MagicalStructure) o).structureId);
}

@Override
public int hashCode() {
return Objects.hash(structureId);
}
}

// 🔹 Specialized Structures
class WizardTower {
private final int maxSpellCapacity;
private List<String> knownSpells;
private String currentWizard;
private final MagicalStructure core;

// Constructor variations
public WizardTower(String name, String location) {
this(name, location, 100, new ArrayList<>(), "No wizard");
}
public WizardTower(String name, String location, int maxCapacity, List<String> spells, String
wizard) {
this.core = new MagicalStructure(name, location);
this.maxSpellCapacity = maxCapacity;
this.knownSpells = new ArrayList<>(spells);
this.currentWizard = wizard;
}
public MagicalStructure getCore() { return core; }
public List<String> getKnownSpells() { return new ArrayList<>(knownSpells); }
public void addSpell(String spell) { if (knownSpells.size() < maxSpellCapacity)
knownSpells.add(spell); }
@Override public String toString() { return "WizardTower{" + core + ", wizard=" +
currentWizard + "}"; }
}

class EnchantedCastle {
private final String castleType;
private int defenseRating;
private boolean hasDrawbridge;
private final MagicalStructure core;

public EnchantedCastle(String name, String location, String type) {


this(name, location, type, 100, true);
}
public EnchantedCastle(String name, String location, String type, int defense, boolean
drawbridge) {
this.core = new MagicalStructure(name, location);
this.castleType = type;
this.defenseRating = defense;
this.hasDrawbridge = drawbridge;
}
public MagicalStructure getCore() { return core; }
@Override public String toString() { return "EnchantedCastle{" + core + ", type=" + castleType
+ "}"; }
}

class MysticLibrary {
private final Map<String, String> bookCollection;
private int knowledgeLevel;
private final MagicalStructure core;

public MysticLibrary(String name, String location) {


this(name, location, Map.of("Basics", "Magic 101"), 50);
}
public MysticLibrary(String name, String location, Map<String, String> collection, int
knowledge) {
this.core = new MagicalStructure(name, location);
this.bookCollection = new HashMap<>(collection);
this.knowledgeLevel = knowledge;
}
public MagicalStructure getCore() { return core; }
@Override public String toString() { return "MysticLibrary{" + core + ", knowledge=" +
knowledgeLevel + "}"; }
}

class DragonLair {
private final String dragonType;
private long treasureValue;
private int territorialRadius;
private final MagicalStructure core;

public DragonLair(String name, String location, String type) {


this(name, location, type, 1000, 50);
}
public DragonLair(String name, String location, String type, long treasure, int radius) {
this.core = new MagicalStructure(name, location);
this.dragonType = type;
this.treasureValue = treasure;
this.territorialRadius = radius;
}
public MagicalStructure getCore() { return core; }
@Override public String toString() { return "DragonLair{" + core + ", dragon=" + dragonType +
"}"; }
}

// 🔹 KingdomManager
class KingdomManager {
private final List<Object> structures;
private final KingdomConfig config;

public KingdomManager(KingdomConfig config) {


this.config = config;
this.structures = new ArrayList<>();
}

public void addStructure(Object structure) { structures.add(structure); }

public static boolean canStructuresInteract(Object s1, Object s2) {


return s1.getClass() == s2.getClass(); // only same type interact
}

public static String performMagicBattle(Object attacker, Object defender) {


if (attacker instanceof WizardTower && defender instanceof DragonLair) {
return "Wizard casts spells at the dragon!";
} else if (attacker instanceof DragonLair && defender instanceof EnchantedCastle) {
return "Dragon breathes fire on the castle!";
} else if (attacker instanceof MysticLibrary && defender instanceof WizardTower) {
return "Library knowledge empowers the tower!";
}
return "No significant battle.";
}
public static int calculateKingdomPower(Object[] structures) {
int total = 0;
for (Object s : structures) {
if (s instanceof WizardTower) total += ((WizardTower) s).getCore().getMagicPower();
else if (s instanceof EnchantedCastle) total += ((EnchantedCastle)
s).getCore().getMagicPower();
else if (s instanceof MysticLibrary) total += ((MysticLibrary)
s).getCore().getMagicPower();
else if (s instanceof DragonLair) total += ((DragonLair) s).getCore().getMagicPower();
}
return total;
}

private String determineStructureCategory(Object structure) {


if (structure instanceof WizardTower) return "Tower";
if (structure instanceof EnchantedCastle) return "Castle";
if (structure instanceof MysticLibrary) return "Library";
if (structure instanceof DragonLair) return "Lair";
return "Unknown";
}

@Override
public String toString() { return "KingdomManager{" + "config=" + config + ", structures=" +
structures + "}"; }
}

// 🔹 Demo
public class Main {
public static void main(String[] args) {
KingdomConfig config = KingdomConfig.createDefaultKingdom();
KingdomManager manager = new KingdomManager(config);

WizardTower tower = new WizardTower("Arcane Spire", "North Hill");


EnchantedCastle castle = new EnchantedCastle("Iron Keep", "Central Plains", "Royal");
MysticLibrary library = new MysticLibrary("Grand Archives", "East Grove");
DragonLair lair = new DragonLair("Smaug's Den", "Mountain Peak", "Fire Dragon");

manager.addStructure(tower);
manager.addStructure(castle);
manager.addStructure(library);
manager.addStructure(lair);

System.out.println(config);
System.out.println(tower);
System.out.println(castle);
System.out.println(library);
System.out.println(lair);

System.out.println("Can Tower & Lair interact? " +


KingdomManager.canStructuresInteract(tower, lair));
System.out.println("Battle: " + KingdomManager.performMagicBattle(tower, lair));

Object[] structures = {tower, castle, library, lair};


System.out.println("Total Kingdom Power: " +
KingdomManager.calculateKingdomPower(structures));
}
}

Output:
KingdomConfig{kingdomName='Avaloria', foundingYear=1024, resources={Mana=5000,
Gold=10000}}
WizardTower{Arcane Spire at North Hill (Power=100), wizard=No wizard}
EnchantedCastle{Iron Keep at Central Plains (Power=100), type=Royal}
MysticLibrary{Grand Archives at East Grove (Power=100), knowledge=50}
DragonLair{Smaug's Den at Mountain Peak (Power=100), dragon=Fire Dragon}
Can Tower & Lair interact? false
Battle: Wizard casts spells at the dragon!
Total Kingdom Power: 400

You might also like