Menu
Coddy logo textTech

Game Character Development

Part of the Object Oriented Programming section of Coddy's PHP journey — lesson 90 of 91.

challenge icon

Challenge

Easy

Let's build a Game Character Development system where different character classes battle using unique abilities. You'll create a hierarchy of characters with an experience and leveling system, demonstrating how inheritance, interfaces, traits, and encapsulation work together in a game context.

You'll organize your code across six files:

  • Ability.php — Define an Ability interface with two methods: getName(): string and use(Character $target): string. This contract ensures all abilities can be used consistently regardless of their specific effects.
  • CombatLogger.php — Create a CombatLogger trait that provides a logAction(string $action): string method. This method should return the action string prefixed with "[COMBAT] ". Characters will use this trait to format their combat messages consistently.
  • Character.php — Include the Ability and CombatLogger files. Create an abstract Character class that uses the CombatLogger trait. Use constructor promotion for name (string, public readonly). Include private properties for health (int, starting at 100), level (int, starting at 1), and experience (int, starting at 0). Implement:
    • getHealth(): int and getLevel(): int — getters for the private properties
    • takeDamage(int $amount): void — reduces health but never below 0
    • heal(int $amount): void — increases health but never above 100
    • gainExperience(int $xp): string — adds XP; if experience reaches 100 or more, level up (reset XP to 0, increase level, heal 20 HP), return "[name] leveled up to [level]!"; otherwise return "[name] gained [xp] XP"
    • isAlive(): bool — returns true if health is greater than 0
    • abstract getSpecialAbility(): Ability — each character type provides their unique ability
    • attack(Character $target): string — deals 10 damage to target, uses logAction() to return "[COMBAT] [name] attacks [target name] for 10 damage"
  • Warrior.php — Include the Character file. Create a Warrior class extending Character. Implement getSpecialAbility() to return an anonymous class implementing Ability:
    • getName() returns "Shield Bash"
    • use() deals 25 damage and returns "[COMBAT] Shield Bash hits [target name] for 25 damage!" (use the trait's logAction())
  • Mage.php — Include the Character file. Create a Mage class extending Character. Implement getSpecialAbility() to return an anonymous class implementing Ability:
    • getName() returns "Fireball"
    • use() deals 35 damage and returns "[COMBAT] Fireball engulfs [target name] for 35 damage!"
  • main.php — Include the Warrior and Mage files. You'll receive two inputs: character data (JSON) and a sequence of combat actions (JSON).

    Characters JSON format:

    [{"type": "warrior", "name": "Thorin"}, {"type": "mage", "name": "Gandalf"}]

    Actions JSON format:

    [{"action": "attack", "attacker": 0, "target": 1}, {"action": "special", "attacker": 1, "target": 0}, {"action": "xp", "character": 0, "amount": 100}, {"action": "status", "character": 0}]

    Create all characters and store them in an array (index 0, 1, etc.). Process each action:

    • "attack" — Character at attacker index attacks target; print the result
    • "special" — Character uses their special ability on target; print the result
    • "xp" — Character gains experience; print the result
    • "heal" — Character heals by the given amount; print "[name] healed to [health] HP"
    • "status" — Print "[name] - Level [level], HP: [health], Alive: [Yes/No]"

    Print each result on a new line.

This system demonstrates how abstract classes define shared character behavior, interfaces ensure abilities follow a consistent contract, traits provide reusable logging functionality, and anonymous classes create unique ability implementations without cluttering your codebase with single-use classes.

Try it yourself

<?php
require_once 'Warrior.php';
require_once 'Mage.php';

// Read input
$charactersJson = trim(fgets(STDIN));
$actionsJson = trim(fgets(STDIN));

// Parse JSON inputs
$charactersData = (array)json_decode($charactersJson, true);
$actionsData = (array)json_decode($actionsJson, true);

// TODO: Create an array to store character objects
$characters = [];

// TODO: Loop through $charactersData and create Warrior or Mage objects
// based on the "type" field, store them in $characters array

// TODO: Process each action in $actionsData
// Handle these action types:
// - "attack": Character at attacker index attacks target; print result
// - "special": Character uses getSpecialAbility()->use() on target; print result
// - "xp": Character gains experience; print result
// - "heal": Character heals; print "[name] healed to [health] HP"
// - "status": Print "[name] - Level [level], HP: [health], Alive: [Yes/No]"

?>

All lessons in Object Oriented Programming