Skip to content

Latest commit

Β 

History

35 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Patient Zero

A text-based console RPG demonstrating Object-Oriented Programming principles through a complex game engine with branching narratives, resource management, and multiple endings.


πŸ“‹ Description/Overview

Patient Zero is a choice-driven narrative game where players navigate a post-apocalyptic world ravaged by plague. You arrive at Havenβ€”a hidden sanctuaryβ€”and must uncover the truth about your immunity while managing resources, navigating political factions, and making critical decisions that determine humanity's fate.

The game demonstrates advanced Object-Oriented Programming principles through a sophisticated engine featuring:

  • 11 distinct endings based on player stats, relationships, and choices
  • 13 branching decision points with random and deterministic outcomes
  • Resource management (health, energy, knowledge, suspicion, morale)
  • Dynamic relationships affecting story outcomes
  • Zone progression (Wasteland β†’ Haven β†’ Research Hub)
  • Interrupt system with 6 global conditions that override normal gameplay flow
  • Rumor collection system with persistent knowledge tracking

Game Premise

You are Patient Zero. In a world ravaged by plague, you arrive at Havenβ€”a hidden sanctuary. Uncover the truth about your immunity, navigate political factions, and decide humanity's fate. Will you expose the secret, seize power, find comfort, or escape?


🎯 OOP Concepts Applied

Patient Zero demonstrates all core Object-Oriented Programming principles:

1. Encapsulation

Player Model:

  • Private fields (health, energy, knowledge, suspicion, morale, day, zone, havenDays, etc.) protect game state
  • Public getter/setter methods provide controlled access
  • Validation enforced in methods (e.g., changeEnergy() enforces 0-5 cap)
  • Example:
    private int energy;
    
    public void changeEnergy(int delta) {
        this.energy += delta;
        if (this.energy > 5) this.energy = 5;  // Cap at max
        if (this.energy < 0) this.energy = 0;  // Cap at min
    }

Data Separation:

  • StoryData.RUMORS (static String array) contains narrative content
  • Player.heardRumors (boolean array) tracks which rumors player discovered
  • Clear separation between content and state

2. Abstraction

Effect System:

  • Abstract Effect class defines apply(Player) method
  • GameEngine applies effects without knowing concrete types
  • Hides complexity of stat modifications
  • Example:
    for (Effect effect : node.getEffects()) {
        effect.apply(player);  // Don't need to know if it's Health, Energy, etc.
    }

GameEngine:

  • Hides complexity of 13 branching points, 6 interrupts, 11-step game loop
  • Main.java only calls: new GameEngine().startGame()
  • Internal logic completely abstracted away

TextRenderer:

  • Abstracts all console formatting and display logic
  • GameEngine only calls printGameScreen() and clearScreen()

3. Inheritance

Effect Hierarchy:

        Effect (abstract class)
           ↑
    β”Œβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚      β”‚      β”‚         β”‚          β”‚        β”‚
Health  Energy  Knowledge  Suspicion  Morale  Day
Effect  Effect   Effect     Effect    Effect  Effect
  • All effects inherit protected int amount field
  • Each implements apply(Player) method
  • Enables code reuse and consistent interface

Condition Hierarchy:

      Condition (interface)
           ↑
    β”Œβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚      β”‚      β”‚          β”‚
Energy  Knowledge  Suspicion  Flag
Condition Condition Condition Condition
  • All implement isMet(Player) method
  • Uniform interface for choice gating

4. Polymorphism

Runtime Polymorphism with Effects:

// Node can have any mix of effect types
node.addEffect(new HealthEffect(-2));
node.addEffect(new EnergyEffect(-1));
node.addEffect(new KnowledgeEffect(1));

// Applied polymorphically - actual type determined at runtime
for (Effect effect : node.getEffects()) {
    effect.apply(player);  // Calls correct subclass method
}

Polymorphism with Conditions:

// Choices can have multiple condition types
choice.addCondition(new EnergyCondition(3));
choice.addCondition(new KnowledgeCondition(5));

// Checked polymorphically
for (Condition condition : conditions) {
    if (!condition.isMet(player)) return false;
}

5. Arrays

Boolean Array - Rumor Tracking:

// Player class
private boolean[] heardRumors = new boolean[7];

public void markRumorHeard(int index) {
    if (index >= 0 && index < 7) {
        heardRumors[index] = true;
    }
}

public boolean hasHeardRumor(int index) {
    return index >= 0 && index < 7 && heardRumors[index];
}
  • O(1) lookup for rumor availability
  • Persistent knowledge tracking throughout game

String Array - Story Content:

// StoryData class
public static final String[] RUMORS = {
    "A woman whispers that her husband went to the medical wing...",
    "Two janitors argue about the 'incinerator schedule'...",
    // ... 7 total rumors
};
  • Immutable story content
  • Accessed by index during Mingle branching

πŸ—οΈ Program Structure

The project follows a clean three-layer architecture separating concerns:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   PRESENTATION LAYER                β”‚
β”‚   (TextRenderer, Main)              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   BUSINESS LOGIC LAYER              β”‚
β”‚   (GameEngine, Branching, Interrupts)
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   DATA LAYER                        β”‚
β”‚   (Player, StoryNode, StoryData)    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   RULE LAYER                        β”‚
β”‚   (Effects, Conditions)             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

File Structure

πŸ“‚ Patient Zero/
β”œβ”€β”€ πŸ“‚ src/
β”‚   β”œβ”€β”€ Main.java                    # Game entry point
β”‚   β”œβ”€β”€ πŸ“‚ model/
β”‚   β”‚   β”œβ”€β”€ Player.java              # Game state: 19 fields, 40+ methods
β”‚   β”‚   β”œβ”€β”€ StoryNode.java           # Story content with effect list & dynamic story updates
β”‚   β”‚   └── Choice.java              # Player choices with condition list & inverted conditions
β”‚   β”œβ”€β”€ πŸ“‚ engine/
β”‚   β”‚   β”œβ”€β”€ GameEngine.java          # Core game loop: 11 steps, 6 interrupts, 13 branching IDs
β”‚   β”‚   └── StoryData.java           # 71 story nodes, 7 rumors, effect wiring
β”‚   β”œβ”€β”€ πŸ“‚ effect/
β”‚   β”‚   β”œβ”€β”€ Effect.java              # Abstract class
β”‚   β”‚   β”œβ”€β”€ HealthEffect.java        # -/+ health
β”‚   β”‚   β”œβ”€β”€ EnergyEffect.java        # -/+ energy (capped 0-5)
β”‚   β”‚   β”œβ”€β”€ KnowledgeEffect.java     # -/+ knowledge
β”‚   β”‚   β”œβ”€β”€ SuspicionEffect.java     # -/+ suspicion
β”‚   β”‚   β”œβ”€β”€ MoraleEffect.java        # -/+ morale
β”‚   β”‚   └── DayEffect.java           # Increment day counter
β”‚   β”œβ”€β”€ πŸ“‚ condition/
β”‚   β”‚   β”œβ”€β”€ Condition.java           # Interface
β”‚   β”‚   β”œβ”€β”€ EnergyCondition.java     # Requires minimum energy
β”‚   β”‚   β”œβ”€β”€ KnowledgeCondition.java  # Requires minimum knowledge
β”‚   β”‚   β”œβ”€β”€ SuspicionCondition.java  # Requires suspicion < limit
β”‚   β”‚   └── FlagCondition.java       # Checks player flags
β”‚   └── πŸ“‚ ui/
β”‚       └── TextRenderer.java        # Formatted console display
β”œβ”€β”€ πŸ“„ README.md                     # This file
└── πŸ“„ CHANGELOG.md                  # Version history

Main Classes and Their Roles

1. Main.java

  • Role: Entry point for the application
  • Responsibilities: Display welcome screen, initialize GameEngine, start game

2. Player.java (Model Layer)

  • Role: Game state management
  • Responsibilities:
    • Store 19 player stats (health, energy, knowledge, suspicion, morale, day, zone, havenDays, purgeCountdown, etc.)
    • Provide validated getters/setters
    • Enforce energy capping (0-5)
    • Track rumor knowledge with boolean array
    • Manage relationship scores

3. StoryNode.java (Model Layer)

  • Role: Story content container
  • Responsibilities:
    • Store narrative text
    • Hold list of effects to apply
    • Contain available choices
    • Support dynamic story updates (for rumor text)

4. Choice.java (Model Layer)

  • Role: Player decision representation
  • Responsibilities:
    • Display choice text and subtext
    • Track conditions that gate availability
    • Point to next story node ID
    • Support inverted conditions (show when NOT met)

5. GameEngine.java (Logic Layer)

  • Role: Core game loop orchestration
  • Responsibilities:
    • Execute 11-step main game loop
    • Check 6 global interrupt conditions
    • Filter choices by conditions
    • Apply effects polymorphically
    • Handle 13 branching decision points
    • Validate player input
    • Manage zone transitions and special effects

6. StoryData.java (Data Layer)

  • Role: Story content repository
  • Responsibilities:
    • Initialize all 61 story nodes
    • Store 7 rumors as static String array
    • Wire effects to nodes
    • Provide node lookup via HashMap

7. Effect.java & Implementations (Rule Layer)

  • Role: Game stat modification
  • Implementations: HealthEffect, EnergyEffect, KnowledgeEffect, SuspicionEffect, MoraleEffect, DayEffect
  • Responsibilities:
    • Apply stat changes polymorphically
    • Enforce game rules (energy cap, etc.)

8. Condition.java & Implementations (Rule Layer)

  • Role: Choice gating logic
  • Implementations: EnergyCondition, KnowledgeCondition, SuspicionCondition, FlagCondition
  • Responsibilities:
    • Check if player meets requirements
    • Enable conditional choice availability

9. TextRenderer.java (Presentation Layer)

  • Role: Console UI formatting
  • Responsibilities:
    • Display formatted game screen
    • Show player stats with borders
    • Print story sections with word wrap
    • List numbered choices
    • Clear console screen

πŸš€ How to Run the Program

Prerequisites

  • Java Development Kit (JDK) 11 or higher
  • Command line terminal (bash, cmd, or PowerShell)

Step 1: Navigate to Project Directory

cd "/home/user/Documents/School Projects/Patient Zero"

(Adjust path based on your actual project location)

Step 2: Compile All Java Files

javac -cp src src/*.java src/**/*.java

This compiles all Java files in the src directory and its subdirectories.

Step 3: Run the Game

java -cp src Main

Step 4: Play the Game

  1. Read the story text presented on screen
  2. View your current stats (Health, Energy, Knowledge, Suspicion, Morale, Day)
  3. Review available choices (numbered 1, 2, 3, etc.)
  4. Enter the number of your choice and press Enter
  5. Continue making decisions to progress through the story

Alternative: Using an IDE

If using an IDE like IntelliJ IDEA, Eclipse, or VS Code:

  1. Open the project folder
  2. Set src as the source root
  3. Run Main.java directly from the IDE

πŸ“Έ Sample Output

Game Start Screen

===========================================================================


                                @@@@@@@@@@               
                              @@@@@@@@@@@@@@             
                            : + + @@@@@@ *:: .           
                           @       @@@@       @          
                                   @@@@                  
                           #      @*@@#@      *          
                            @  : @@@@@@@@.:  @           
                            @@@@@@@@@*@@@@@@@@           
                          .  @@@@%      %@@@@  .         
                     -@@@-@  @@@@ @:-.+- :@@@  @:@@@-    
                   @@@@@@@-@%@@@: @-@@*@ :@@@%@-@@@@@@@  
                    =@@@@@@*@@@@@  @@%@  @@@@@*@@@@@@=   
                    @@@@@@@@-@  @@+.   +@@  @=@@@@@@@@   
                    +@@@@@@@@@*  #@@@@@@#  *@@@@@@@@@+   
                      =@@@@@@                @@@@@@=     
                       -@-                      -@-      


                               PATIENT ZERO
                                Press Enter


===========================================================================

Gameplay Example

===========================================================================
STATS:
===========================================================================
|  Health: 10  |  Energy: 3  | Knowledge: 0 | Suspicion: 0 |  Morale: 10  |
===========================================================================
DAY: 2
DAYS IN HAVEN: 1
===========================================================================
You are in the refugees' quarters, a converted gymnasium filled with
cots.
People keep to themselves, avoiding eye contact. Something's not
right here.
===========================================================================
ACTIONS: 
===========================================================================
[1] "I should listen to what people are saying."
    └─ Maybe I can learn something useful... (-1 Energy)
[2] "The medical wing seems important..."
    └─ What are they really doing in there? (-1 Energy)
[3] "Maybe I can find something useful in the dorms."
    └─ People must leave clues behind... (-1 Energy)
[4] "Help in the kitchen."
    └─ Blend in with workers (-1 Energy)
[5] "Do cleaning duty."
    └─ Appear harmless (-1 Energy)
[6] "I should share my rations with that family."
    └─ They look like they need it more than me (-1 Energy)
[7] "I'll just rest and watch the courtyard."
    └─ Maybe I'm overthinking this... (-1 Energy)
[8] "I'm going for the main office. No more playing safe."
    └─ Time for desperate measures (High suspicion only, -2 Energy)
[9] "I need to rest for tomorrow."
    └─ Tomorrow will be another day
===========================================================================
Enter Action Number: 9

After Making a Choice

===========================================================================
STATS:
===========================================================================
|  Health: 10  |  Energy: 5  | Knowledge: 0 | Suspicion: 0 |  Morale: 11  |
===========================================================================
DAY: 3
DAYS IN HAVEN: 1
===========================================================================
You collapse onto your cot, surrounded by the sounds of sleeping
refugees.

"Just a few hours of peace," you think before drifting off.

(A
new day begins - Energy fully restored, +1 day, Haven day counter +1)
===========================================================================
ACTIONS: 
===========================================================================
[1] Continue to Next Day
===========================================================================
Enter Action Number: 1

Stat Changes Example (Energy Depletion)

===========================================================================
STATS:
===========================================================================
|  Health: 10  |  Energy: 0  | Knowledge: 4 | Suspicion: 0 |  Morale: 7  |
===========================================================================
DAY: 3
DAYS IN HAVEN: 2
===========================================================================
Your body finally gives out. You collapse, unable to take another step.

As
consciousness fades, you find yourself in a bunk, recovering.

(Energy
fully restored, +1 day)
===========================================================================
ACTIONS: 
===========================================================================
[1] (Continue)
===========================================================================
Enter Action Number: 1

Game Ending Example

===========================================================================
STATS:
===========================================================================
|  Health: 11  |  Energy: 3  | Knowledge: 7 | Suspicion: 3 |  Morale: 6  |
===========================================================================
DAY: 9
Purge Countdown: 0
===========================================================================
ENDING: CLEANSED

The gas floods the vents exactly on schedule. You take
your final breath surrounded by the evidence that could have saved
everyone.

The Haven reports another 'successful containment operation.'
The world never learns the truth.

GAME OVER
===========================================================================
ACTIONS: 
===========================================================================
===========================================================================
Enter Action Number: 
[END OF GAME]

πŸ‘₯ Authors and Acknowledgement

Development Team

Name Role Contributions
Bueno, Sebastian Miguel A. Lead Developer Story writing, game engine architecture, effect system, branching logic, bug fixes
Canalita, Harry D. Developer Game engine architecture, Story nodes, condition system, documentaion, bug fixes
Manalo, Cris Julian V. Developer Player model, UI rendering, documentation, testing & bug fixes

Acknowledgements

  • Professor: For guidance on Object-Oriented Programming principles
  • Course: CS/IT Object-Oriented Programming Course
  • Inspiration: Text-based adventure games and narrative-driven RPGs
  • Java Documentation: Oracle Java SE Documentation for reference

Special Thanks

Special appreciation to all teammates for their dedication, collaborative problem-solving, and commitment to demonstrating OOP principles through this project.


πŸ“ Other Sections

Game Features

  • 11 Distinct Endings: Different outcomes based on stats, relationships, and choices
  • 13 Branching Decision Points: Random and deterministic outcomes affecting story progression
  • 7 Collectable Rumors: Story elements with persistent player knowledge tracking via boolean arrays
  • Resource Management: Health, Energy, Knowledge, Suspicion, Morale dynamically affect gameplay
  • Zone Progression: Travel from Wasteland β†’ Haven β†’ Research Hub with zone-specific mechanics
  • Relationship Dynamics: Cris relationship determines escape ending variant
  • Global Interrupts: 6 interrupt conditions override normal flow (health, suspicion, morale, energy, haven days, purge countdown)
  • Conditional Choices: Choices become available/unavailable based on player stats
  • Inverted Conditions: Choices can be shown only when conditions are NOT met (e.g., rest option appears only when energy is low)
  • Purge System: 7-day countdown creates time pressure for critical decisions
  • Haven Days Tracking: Day counter specifically for time spent in Haven (increments only on sleep/rest)

How to Play

  1. Start the game by running Main
  2. Make choices by entering the choice number (1-9 typically)
  3. Manage stats:
    • Health: Drop to ≀0 = BadEnd
    • Energy: Required for most activities (0-5 capped). When energy = 0, most exploration choices disappear and only rest options remain. When energy hits 0, triggers ForcedRest interrupt.
    • Knowledge: Unlock choices at 5+ and 7+ thresholds
    • Suspicion: Hit 10 = ArrestedEnd
    • Morale: Drop to ≀0 = DespairEvent
    • Days in Haven: Track time spent resting in Haven (increments only on sleep/rest actions)
  4. Collect Rumors: Encounter story elements that add to your knowledge (max 4 knowledge from rumors)
  5. Build Relationships: Interacting with Cris affects escape ending outcome
  6. Reach Endings: Decisions and stats determine which of 11 endings you get

Rest System

The game has three rest nodes:

  • LeisurelyRest: Casual resting in Haven (restores morale, increments haven days)
  • RestInDorm: Intentional sleep in Haven dorm (advances day, restores energy, increments haven days)
  • ForcedRest: Automatic rest when energy hits 0 (emergency collapse, advances day, restores energy, increments haven days)

Important: Haven days counter only increments on actual sleep/rest actions, not on regular explorations. Regular actions (Mingle, ObserveClinic, SearchDorms) do NOT count as days passing.

Game Endings (11 Total)

  1. BadEnd: Health ≀ 0 (starvation/exhaustion)
  2. ArrestedEnd: Suspicion β‰₯ 10 (discovered by authorities)
  3. HavenPanicEnd: Haven Days β‰₯ 20 without purge (confinement madness)
  4. PurgeEnd: Purge countdown ≀ 0 (military execution)
  5. DespairEvent: Morale ≀ 0 (temporary event, leads to HavenIntro or ResearchHub)
  6. ComfortBadEnd: Choosing comfort and stability
  7. Collapse: Authority system fails
  8. EscapeEnd_Alliance: Cris relationship β‰₯ 6 (united escape with scientist)
  9. EscapeEnd_Savior: Cris relationship 3-5 (escape with medium relationship)
  10. EscapeEnd_Fugitive: Cris relationship ≀ 2 (solo escape)
  11. ExposeEnd: Reveal truth to humanity

Code Metrics

  • Total Files: 18 Java files
  • Total Lines of Code: ~2,000+ LOC
  • Game Nodes: 61 unique story nodes
  • Branching Points: 13 decision branches
  • Global Interrupts: 6 interrupt conditions
  • Effects: 6 effect types (polymorphic)
  • Conditions: 4 condition types (polymorphic)

Game Loop Architecture

The GameEngine follows an 11-step main loop:

  1. Check global interrupts (health, suspicion, morale, energy, haven days, purge countdown)
  2. Get available choices (filtered by conditions)
  3. Display game screen (stats, story, choices)
  4. Get player input (validated choice number)
  5. Get chosen choice (from available list)
  6. Apply effects from current node (polymorphic)
  7. Handle special node effects (zone changes, flag updates, haven day increments on rest)
  8. Get next node ID (handles 13 branching points)
  9. Move to next node (null check)
  10. Decrement purge countdown if active
  11. Loop continues or game ends

πŸ“„ License & Disclaimer

Educational Use Only

This project was created for educational purposes as part of an Object-Oriented Programming course. Students may use this as a reference for understanding OOP concepts, but should not copy it verbatim for their own assignments.

Version Information

  • Current Version: 2.3
  • Last Updated: December 2, 2025
  • Java Version: Java 11+

For detailed technical documentation, see:

  • developer guides/README_DEVELOPERS.md - Architecture and design patterns
  • CHANGELOG.md - Version history
  • PROJECT_COMPLETION_SUMMARY.md - Completion metrics

Β© 2025 Patient Zero Development Team. All Rights Reserved.

About

A text-based RPG

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages