Landing : Athabascau University
  • Wikis
  • Zachary Kernick
  • Assignment 4 reflection (plus some of non research things supposed to be in the research document)

Assignment 4 reflection (plus some of non research things supposed to be in the research document)

Last updated December 7, 2024 - 1:04pm by Zachary Kernick

Personal Notebook Reflection: Wonderland Game Assignment

 


 

Initial Thoughts and Approach

The Wonderland game assignment was, without a doubt, the most ambitious project I’ve undertaken in this course. At the outset, I was equal parts excited and intimidated. The idea of building a fully functional text-based adventure game, complete with combat mechanics, inventory management felt like a huge leap forward from previous assignments. The Wonderland theme, inspired by Lewis Carroll’s iconic tale, offered some interesting ideas, which made me eager to dive into the project.

Looking back on my previous assignments, I realized how much they had prepared me for this challenge. From managing file I/O operations and implementing OOP principles to debugging nested loops and writing modular code, the skills I’d honed throughout the course laid a solid foundation. However, I also knew that this assignment would push me to apply those skills on a much larger scale and tackle new complexities, especially with JSON files and dynamic game mechanics.

 


 

How I Arrived at the Final Design

The journey to the final design of my game was one of constant iteration, reflection, and problem-solving. At its core, the project evolved as I balanced my creative vision with the time I was given, often refining and expanding ideas based on challenges I encountered and lessons learned. This section explores how the design came together, focusing on key elements and decisions that shaped the game.

Combat System Evolution

The combat system was one of the most dynamic features of the game, and its final design emerged through a mix of experimentation and incremental improvements. Initially, I planned for a simple combat system where the player could attack enemies using either unarmed strikes or weapons. However, as I developed the game, I realized the potential for more engaging combat mechanics by incorporating items with diverse effects.

Key Changes and Additions:
  1. Item Effects and Types:

  2. I introduced different item types (weapon, throwable, consumable) to diversify combat interactions. Each item type had unique attributes:

  3. Weapons dealt consistent damage.

  4. Consumables provided temporary buffs, healing, or defensive boosts.

  5. Throwables inflicted status effects, such as confusing enemies or weakening their attacks.

  6. These distinctions created opportunities for strategic gameplay. For instance, a player could use a "Trip-up Potion" to weaken an enemy's attack before finishing them off with a weapon.

  7. Effect Implementation:

  8. Adding effects like "sleep," "weaken," and "confuse" required significant changes to the combat logic. I created a structure within the Item and Action classes to handle these effects dynamically. This allowed me to reuse the framework for future items, making the system modular and extensible.

  9. Debugging these effects revealed edge cases, such as ensuring sleeping enemies dropped items and couldn’t attack. Resolving these issues helped refine the combat flow.

  10. Balancing (not the most indepth balancing) and Randomness

  11. The randomness in combat—such as the 60% chance for enemies to hit or miss—was added to create tension and unpredictability. This required careful balancing to ensure that the randomness felt fair rather than frustrating.

Transition to JSON Files

Early in the project, I used simple text files to define game data, such as characters and rooms. However, as the game grew in complexity, I recognized the limitations of this approach. Text files offered minimal structure, making it difficult to manage additional parameters like attackDmg, spawnChance, or effect.

Why JSON?
          Support for Nested and Structured Data:
  1. JSON's ability to represent nested data allowed me to define detailed relationships between objects. For example, in the rooms.json file, I could specify connected rooms, their keywords, and descriptions in a single structure. This level of organization was impossible with plain text files.

    Parameter Expansion:

  2. With JSON, I could easily add parameters like dialogueKeywords for characters, effect for items, or connectedRoomDescriptions for rooms. This flexibility allowed the game to evolve organically without requiring a complete overhaul of the data management system.

  3. For example, adding the "effectDescription" parameter to throwable items enhanced the narrative by providing flavorful text whenever an effect was triggered.

    Improved Readability and Maintenance:

  4. JSON files were easier to read and update. Instead of managing long strings of text, I could clearly see how data was organized. This made it easier to debug and expand the game’s content.

Dynamic Room Descriptions

From the beginning, I wanted Wonderland to feel alive and responsive to the player’s actions. The Room class became the foundation for this, and its design evolved to support dynamic updates based on gameplay events. For example:

  • Connected Room Descriptions: Each room’s description included detailed transitions to its connected rooms, adding to the immersion.

  • Dynamic Updates: Rooms like the Queen’s Throne Room changed their description after the Queen’s defeat, reflecting the player’s impact on the world.

Implementing Text Wrapping:
  • The wrapText() method was introduced to improve the readability of room descriptions, ensuring that text was displayed like a cohesive paragraph. Iterating on this feature revealed subtle formatting issues, such as spacing around punctuation, which were addressed to achieve the final design.

Character Design and Interaction

Characters were initially envisioned as static elements—either friendly or hostile—with predefined behaviors. However, as the game took shape, I saw the potential for more nuanced interactions:

          Dynamic States:

  1. Characters could shift between friendly and hostile based on player actions, such as attacking a friendly NPC. This added moral complexity to the game and reinforced the theme of choice.

    Expanded Dialogue:

  2. Dialogue systems incorporated keywords that triggered specific responses. This required additional parameters in characters.json, such as dialogueKeywords and dialogueText.

  3. Testing revealed edge cases, such as players entering invalid keywords, which led to the implementation of fallback responses.

Item Integration

Items became a cornerstone of the gameplay, and their design expanded significantly over time:

          Custom Attributes:

  1. Weapons included attackDmg to define their damage output.

  2. Consumables had effect parameters specifying their type (heal, buff, etc.) and magnitude (amount).

  3. Throwables featured effectDescription, adding flavor text to their effects.

    Room-Based Item Placement:

  4. Items were assigned to specific rooms or dropped by defeated enemies. This created opportunities for exploration and resource management, encouraging players to think strategically about their inventory.

    Breaking and Removing Items:

  5. To balance powerful items like keys and consumables, I implemented logic to break and remove them after use. This ensured that players couldn’t rely too heavily on a single resource.

Iterative Development

Each feature went through multiple iterations, guided by testing and feedback:

  • Initial Prototypes:

  • Early versions of the game focused on basic mechanics, such as moving between rooms and interacting with NPCs. These prototypes served as a foundation for more complex systems.

Feature Expansion:

  • As the game grew, I added layers of complexity, such as combat effects, dynamic room descriptions, and branching character interactions. Each addition required careful integration to avoid breaking existing functionality.

Final Polishing:

  • The final phase focused on refining the user experience, addressing edge cases, and ensuring that all features worked together seamlessly.

 


 

Challenges and How I Overcame Them

Throughout the assignment, I encountered numerous challenges, many of which required revisiting concepts from previous assignments or learning new techniques and code from stack overflow or video tutorials. Below, I’ve documented these challenges and how I resolved them.

1. Handling JSON Files for Dynamic Content

Challenge: One of the first hurdles was working with JSON files to load rooms, characters, items, and actions. Each file had unique parameters, and I needed to ensure they were correctly parsed and integrated into the game. Additionally, items and characters had optional attributes, like effect for consumables or spawnChance for characters, which added complexity. I leaned on tutorials and help from online to figure out how to parse the files and carefully handled optional parameters with checks like containsKey() to avoid null pointer exceptions. This iterative approach ensured that every game element was loaded correctly, and debugging print statements helped identify issues early on when they came up.

2. Wrapping Text for Room Descriptions

Challenge: Displaying room descriptions in a readable paragraph format was more difficult than I expected. Initially, descriptions were split awkwardly or didn’t align with connected room or item descriptions. I created a wrapText() method to dynamically format text, ensuring lines didn’t exceed a specific width. This involved carefully tracking where one description ended and the next began, testing with various text lengths to achieve the desired flow. While I ran into issues with duplicated text and missing spaces, iterative debugging and small adjustments to the logic resolved these problems.

3. Combat Mechanics

Challenge: Implementing combat was one of the most complex parts of the assignment. I wanted to include unarmed attacks, item-based attacks, and random outcomes like missed hits. Adding throwable and consumable items with unique effects (e.g., weakening enemies or healing the player) added another layer of complexity.

I broke the problem into smaller tasks:

  • First, I implemented a basic attack system and tested it with mock data.

  • Next, I added support for item-based actions, referencing the actions.json file for outcomes.

  • Finally, I integrated special effects for consumables and throwables, using a combination of parameters like effectType and amount. Debugging was key here—initially, some items didn’t apply their effects correctly, but detailed logging helped pinpoint and fix these issues.

4. Dynamic Room Descriptions

Challenge: Creating room descriptions that updated based on player actions (e.g., defeating the Queen of Hearts) required careful management of state. I used flags in the Room and Game classes to track changes. For example, after defeating an enemy, the room’s description was updated with setDescription(). This approach ensured that the game world felt responsive without overcomplicating the code.

5. Player Input Handling

Challenge: Ensuring smooth user input handling, especially for commands like move to, attack, and use, required a flexible parser. Early on, the game struggled to interpret variations in input (e.g., "move to mushroom" vs. "go to mushroom"). The Control class was pivotal in parsing and standardizing input. I implemented methods to match input keywords with room or item names, allowing for intuitive commands. Testing with various inputs helped refine this system.

Testing and Debugging

Testing and debugging were fundamental to the development of my game. The interconnected nature of its mechanics meant that issues in one part of the code could ripple across the entire system. A methodical and iterative approach to testing and debugging ensured the game achieved its desired functionality while providing a smooth user experience. This section outlines the key challenges encountered during testing, the debugging strategies employed, and the lessons learned from resolving various issues.

Initial Testing: Core Mechanics

Testing began with the core functionality of the game—room navigation, character interaction, and item handling. Each feature was tested independently before being integrated into the larger system. For example:

  • Room Navigation: The movePlayer() method was tested with valid and invalid commands. Early issues included allowing movement to non-connected rooms or incorrectly handling case sensitivity in room names. Implementing case-insensitive keyword matching and refining the findRoomByKeyword() method resolved these issues.

  • Character Spawning: Testing the logic for character spawning revealed edge cases where characters were either not appearing or spawning in unintended locations. Debugging this required tracing the flow of the loadCharacters() method and ensuring the spawnChance parameter worked as intended. Adjustments were made to the randomization logic to respect both spawn probabilities and room restrictions.

Combat System Testing

The combat system was one of the most intricate parts of the game, requiring extensive testing to ensure a balanced and functional experience. Several challenges emerged during testing:

  • Unarmed Attacks: Initial testing showed that the system incorrectly displayed "Item not found in inventory" when performing unarmed attacks. This was traced to the handleCombatAction() method, where the program attempted to retrieve an item even when none was specified. The fix involved adding a separate condition to handle unarmed attacks, bypassing the inventory check.

  • Enemy Behavior: Testing enemy attacks revealed inconsistencies in damage calculation and attack text. For example, enemies would occasionally deal negative damage due to incorrect handling of temporary defense buffs. Debugging involved verifying the calculations in the enemyAttack() method and ensuring temporary defense values were reset after use.

  • Throwable Items: Items like the "Hooka" and "Trip-up Potion" had unique effects, such as confusing enemies or weakening their attacks. Early testing showed that these effects were not consistently applied due to missing logic in the handleCombatAction() method. Adding a dedicated switch case for each effect type and ensuring the effect parameter was correctly parsed resolved this issue.

Room Description and Text Wrapping

Displaying room descriptions with proper text wrapping was another area that required careful testing and debugging. Initially, descriptions appeared as fragmented or duplicated text due to issues with the wrapText() method. Debugging revealed:

  • Spacing Issues: The lack of spacing between sentences occurred because the method concatenated strings without accounting for punctuation marks. Adjusting the logic to add a single space after periods resolved this issue.

  • Text Duplication: Room descriptions were printed multiple times due to redundant calls to the displayRoomInfo() method within the game loop. Consolidating these calls eliminated the duplication.

Item Interactions

Items played a critical role in the game, and their functionality required rigorous testing:

  • Consumables: Items like the "Rabbit's Foot" and "Tweedledum's Cap" had healing or buffing effects defined by their effect parameter. Early tests revealed that invalid or missing effect types caused the program to crash. Debugging involved adding error handling to validate the effect parameter and ensure only recognized effects were applied.

  • Weapons: Testing weapon durability (initially planned but not implemented) highlighted the importance of ensuring consistent updates to item attributes. Although durability was omitted due to time constraints, debugging this feature provided insights into managing mutable item attributes.

  • Keys: Locked rooms such as the "Large Mushroom House" required keys for entry. Testing revealed issues where used keys remained in the player's inventory or failed to unlock the room. The fix involved updating the movePlayer() method to remove keys upon use and change the room's lock status dynamically.

Character Interaction and Dialogue

Interacting with NPCs presented its own set of challenges:

  • Dialogue Handling: Early tests showed that the game did not respond appropriately to player inputs during dialogue with characters. This was traced to a lack of validation in the input loop. Adding checks for valid keywords and providing default responses for unrecognized input improved the dialogue system.

  • Dynamic States: Characters could transition between friendly and hostile states based on player actions, such as attacking a friendly NPC. Testing this transition revealed inconsistencies in how characters responded post-transition. Debugging involved ensuring state changes were reflected in both the Character object and the room description.

JSON Integration and Data Validation

The use of JSON files for game data added flexibility but also introduced potential errors:

  • Missing or Mismatched Keys: Early attempts to load data occasionally failed due to missing keys in the JSON files. For example, omitting the effect parameter for an item caused null pointer exceptions. Debugging involved adding default values and error messages to handle incomplete data gracefully.

  • Inconsistent Parameters: Some characters or items lacked attributes present in others, such as health for non-combat NPCs or effects for non-consumable items. Adding conditional checks in the loading methods ensured that the absence of certain parameters did not break the game.

Combat Edge Cases

Combat testing revealed several edge cases that required additional debugging:

  • Enemy Defeat: Initially, defeated enemies were not removed from the room, allowing players to interact with "dead" characters. Adding a condition to remove defeated enemies from the characters map resolved this issue.

  • Player Health Display: Testing showed that player health was not consistently displayed after using consumable items or during combat. Debugging involved updating the health display logic in both the enterCombat() and inventory management methods.

 

 


 

Learning Outcomes

The Use of Knowledge in Object-Oriented Programming, Arrays, and ArrayLists:

  • The principles and techniques of object-oriented programming (OOP) covered in the textbook were invaluable throughout this project. The modular design of the game, with separate classes for Room, Character, Item, and others, adhered to OOP principles like encapsulation and abstraction. These principles ensured that each class had a clear responsibility, making the codebase manageable and extensible. For example, the Item class was the foundation for all items in the game, with attributes like itemType and methods like useEffect(), which varied depending on whether the item was a weapon, consumable, or throwable.

Arrays and ArrayLists, as emphasized in the textbook, were particularly helpful in managing collections of data. ArrayLists were used extensively for storing and dynamically managing items, characters, and connected room keywords. For example, the player's inventory was implemented as an ArrayList, allowing for seamless addition, removal, and iteration through items. Similarly, ArrayLists were essential for handling multiple spawn locations for characters and the keywords associated with connected rooms. 

Problem Solving and Debugging headaches:

  • This assignment provided numerous opportunities to sharpen problem-solving and debugging skills. The complexity of integrating multiple mechanics, such as combat, item interactions, and room transitions, meant encountering a wide range of challenges. For example, debugging the issue where unarmed attacks displayed the message "Item not found in inventory" required a methodical approach to isolate the problem in the combat handling logic. Through careful testing and detailed examination of the handleCombatAction() method, I identified and resolved the issue by ensuring that unarmed attacks bypassed inventory checks.
    Additionally, handling locked rooms and ensuring items like keys functioned as intended involved careful planning and iteration. Debugging these issues required writing test cases for various scenarios, such as attempting to unlock a door without the required key or using a key that had already been consumed. The experience of identifying edge cases, replicating bugs, and implementing fixes reinforced my understanding of debugging as a systematic process rather than mere trial and error.

Designing and Implementing Algorithms:

  • Creating algorithms that governed the behavior of NPCs, items, and game mechanics was a significant aspect of this project. One example was designing the logic for randomly spawning characters in specific or multiple rooms based on predefined probabilities. Implementing this required understanding and applying algorithms to handle randomness while ensuring consistency in game mechanics. The use of Java's Random class, combined with weighted probabilities, allowed for dynamic gameplay while maintaining a balance in difficulty and unpredictability.
    Similarly, implementing the wrapText() method for displaying room descriptions and other text required careful thought about string manipulation algorithms. I had to iterate over the string, insert line breaks at appropriate places, and ensure continuity between text elements like room descriptions, item details, and character presence. This process highlighted the importance of designing algorithms that were not only functional but also enhanced the user experience.

Using External Files for Data Management:

  • The integration of JSON files for managing game data, such as rooms.json, characters.json, items.json, and actions.json, was a major learning outcome. Understanding how to parse and utilize external data files added a layer of complexity to the project but also made it highly modular and extensible. For instance, the loadRooms(), loadCharacters(), and loadItems() methods demonstrated how to efficiently read and store structured data from JSON files into corresponding objects.
    A deeper understanding of JSON structures allowed me to design flexible files that supported varied parameters for different entities. For example:

  • Rooms: Parameters like locked and unlockItem added dynamic gameplay elements.

  • Characters: Attributes such as spawnChance, possibleRooms, and dialogueKeywords allowed for complex NPC behaviors.

  • Items: Differentiating between weapons, consumables, and throwables by including attributes like attackDmg, effect, and effectDescription ensured diverse interactions.
    Debugging issues with missing or mismatched JSON keys reinforced the importance of validating external data and handling exceptions gracefully. This experience deepened my understanding of managing external resources and their integration into a program.

User Experience Design and Interaction:

  • Designing the game’s interface and user interactions was a critical learning outcome. The use of commands like "move to," "go to," "talk to," and "use" required thoughtful design to make the game intuitive while accommodating various inputs. A significant aspect of this was implementing the Control class to handle user input effectively and map it to appropriate game actions.
    Another example was the text wrapping feature in the wrapText() method, which ensured room descriptions and other outputs were displayed as clean, readable paragraphs. This enhancement improved immersion and readability, especially for longer descriptions or when multiple entities were present in a room.
    Balancing the game’s difficulty and ensuring a smooth user experience during combat were additional challenges. For instance, displaying player and enemy health after every combat action provided clear feedback, while designing enemy attack behaviors (with a 60% hit chance) added an element of unpredictability. These considerations emphasized the importance of user-focused design in game development.

Testing and Debugging Complex Systems:

  • The iterative process of testing and debugging this project mirrored real-world development cycles. From the initial mechanics of room transitions to advanced features like combat and item effects, each feature underwent rigorous testing to ensure functionality. For example:

  • Testing locked rooms revealed edge cases where the game did not correctly handle reused keys. This led to refining the logic to consume keys upon use and update room states dynamically.

  • Debugging the combat system involved extensive testing of different item interactions, such as throwable effects and consumable buffs, to ensure each action performed as intended.
    Through systematic testing, I learned to isolate and resolve issues, often relying on detailed debugging output to pinpoint the root cause. This process underscored the importance of testing every feature in multiple scenarios to achieve a robust and reliable system.

Balancing Creativity and Technical Constraints:

  • Developing "Wonderland: Cheshire’s Folly" highlighted the interplay between creative storytelling and technical implementation. Designing a narrative that blended exploration, combat, and decision-making required balancing the complexity of mechanics with the need for engaging gameplay. For example, incorporating two distinct endings (peaceful and violent) enriched the story but added complexity to the game logic.
    Time constraints necessitated compromises, such as leaving certain item attributes like durability unused in the final implementation. Despite these limitations, the project demonstrated how to creatively adapt technical skills to realize a compelling vision. This balance between creativity and practicality was one of the most rewarding aspects of the project.

 

 


 

Final Reflections

Building the Wonderland game was a rewarding challenge. It combined creativity with technical problem-solving, allowing me to apply everything I’ve learned in this course and push my skills further. While there were moments of frustration—like debugging combat logic or fixing text wrapping—the satisfaction of seeing the final game come together made it all worthwhile.

This assignment not only deepened my understanding of Java but also gave me confidence in tackling larger projects. The ability to create a dynamic, modular system using JSON files and OOP principles is something I’m particularly proud of. Moving forward, I’m excited to explore even more complex projects and continue refining my programming skills.

Overall, the Wonderland game felt like the culmination of all the smaller lessons from previous assignments, and I am proud with how it turned out in the end. 

Sources used throughout the project:

For loading json and figuring out how to use it:
https://www.youtube.com/watch?v=wDVH3qnXv74&t=67s

https://www.centron.de/en/tutorial/json-simple-example/

https://stackoverflow.com/questions/8997598/importing-json-into-an-eclipse-project

https://www.youtube.com/watch?v=U-5VHRvOFpA

https://stackoverflow.com/questions/10926353/how-to-read-json-file-into-java-with-simple-json-library

https://stackoverflow.com/questions/39979837/reading-in-json-files-using-eclipse-do-i-need-a-library-or-not

Help with combat logic and misc things related to rpg design:

https://stackoverflow.com/questions/57127560/how-to-create-a-loop-that-will-attack-an-enemy-until-the-enemy-is-dead

https://stackoverflow.com/questions/31525207/methods-for-a-text-adventure-game-battle-system

https://stackoverflow.com/questions/33754830/java-access-objects

https://stackoverflow.com/questions/37033361/how-can-dynamic-behaviors-change-state-in-java

https://stackoverflow.com/questions/45002521/using-a-players-stats-in-multiple-different-classes

Video series- https://www.youtube.com/watch?v=8SvjF0ZhMes

https://www.reddit.com/r/javahelp/comments/kwql74/how_should_i_go_about_writing_an_attack_method/

Object oriented programming and arrays help

Used the textbook mainly 

https://comp.athabascau.ca/268/r12/c6/index.html

https://comp.athabascau.ca/268/r12/c5/index.html

https://comp.athabascau.ca/268/r12/c7/index.html

Wrapping text into a paragraph-like format

https://stackoverflow.com/questions/4055430/java-code-for-wrapping-text-lines-to-a-max-line-width

Java.util stuff (hashmaps, lists, arraylists, map, random)

https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html

https://docs.oracle.com/javase/7/docs/api/java/util/Random.html

https://docs.oracle.com/javase/7/docs/api/java/util/Map.html

https://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html

java.oi stuff (inputstream, reader, file not found exception)

https://docs.oracle.com/javase/8/docs/api/index.html?java/io/FileNotFoundException.html

Text based games research

https://en.wikipedia.org/wiki/Colossal_Cave_Adventure#:~:text=In%20the%20game%2C%20the%20player,game's%20natural%20language%20input%20system.

https://zarfhome.com/dreamhold/

https://classicreload.com/zork-i.html#

https://eblong.com/zarf/zweb/tangle/