Back
PROGRAMMING FUNDAMENTALS

Two Assignments, One Rollercoaster

GDEV40024 Programming Fundamentals was completed across two assignments. Assignment 1 required ten C++ coding challenges covering core language concepts: ASCII art output, user I/O, a multi-function calculator, text box generation, text casing transformations, a number guessing game, party selection with a shop system, a dynamic inventory manager, a Vector2 math class, and a 16-bit bitwise controller input manipulator.

Assignment 2 required a complete C++ console game. The original concept — a narrative horror RPG titled The Forbidden Hell, inspired by Blair Witch Project, FINAL FANTASY XIII, Silent Hill Homecoming, Slender: The Arrival, Resident Evil 3: Nemesis, and The Evil Within — was scrapped four weeks before the deadline due to over-ambition and time constraints. The battle system alone had grown to 2,300 lines of unfinished code out of approximately 9,000 total. The game was redesigned as an endless dungeon: infinite floors of randomised enemies with dynamically increasing difficulty, a full turn-based battle system, player stats and roles, Windows API integrations, and a console UI library for the main menu.

The thread described the challenges as "a rollercoaster ride — they start nice and slow but become terrifyingly and quickly difficult to manage without trying to research more about C++ using 100+ Google Chrome tabs."

  • Two assignments completed across the module
  • Ten C++ coding challenges — ASCII art, calculators, OOP, bitwise
  • C++ console horror RPG as Assignment 2 (The Forbidden Hell)
  • Pivoted to endless dungeon after scope overrun at 4 weeks to deadline
  • Full turn-based battle system with ailments and resistances
  • Solo throughout — Staffordshire University, October–December 2024

All 10 Challenges

Ten challenges increasing in complexity — from declarative ASCII output to a full bitwise controller manipulator. Each one introduced new C++ concepts and was later refactored for consistent code style.

Challenge 1
ASCII Boat
Print an ASCII boat in the console precisely as the brief outlined. The immediate obstacle: C++ treats \ as an escape character, breaking ASCII art strings entirely. The fix was raw string literals (R"(...)"), which allow multi-line strings without escape sequences or repeated std::cout calls. No variables required — purely declarative output.
Challenge 2
Player Details
Prompt user for name, in-game username, clan tag, and experience — then print them back. Considered the easiest challenge. Notable firsts: a string array for multiple values, an unsigned integer for experience (never negative), and first use of Windows.h to clear the console.
Challenge 3
Calculator
A multi-operation calculator: square root, floor, ceiling, rounding, negation, cubed, and custom error codes. Slightly tricky due to rounding to a specific decimal place matching the brief's example output. Required researching cmath and iomanip headers. Implementing custom error codes in C++ for the first time.
Challenge 4
Text Boxes
Generate ASCII text boxes around user input — each character in its own individual box. Validation required no special characters or numbers. Used isalpha() and isspace() from ctype.h. Concept worked correctly on first attempt — minor tweaks for accuracy. Refactored out of main() into boolean helper functions.
Challenge 5
Text Casing
Four transformations: lower case, upper case, sentence case, alternating/sarcastic case. First three completed quickly. Sentence case was deeply problematic — two to three consecutive broken implementations before the bug was traced to using .Size() on a string instead of correct index-based iteration. Fixed after returning to the problem with fresh perspective after illness.
Bugfor (int i = 0; i < inputString.Size(); i++).Size() is not the correct method for iterating string characters in C++. Failure to plan before writing led to three consecutive broken implementations.
Challenge 6
Number Guessing Game
Generate a random number, prompt the user to guess, calculate the difference, apply error handling for values outside 0–100. Described as "pretty simple" but the brief's use of the word "furthermore" kept revealing additional requirements — described in the thread as "gaslighting." Required careful attention to comparative operators in nested conditionals.
Challenge 7
Party Selection
A party of three members and a shop where each member buys a weapon that determines their role. Boolean array to track purchases. A bug appeared post-submission: on shop reset, the second member was queried first instead of iterating from the start. Hours of debugging led nowhere — the code was scrapped and reimplemented using a Shop class with an ID field, resolving the ordering bug cleanly.
BugAfter shop reset, party member iteration started from the second member. Root cause: poor structural coupling between shop state and party member identity. Fix: Shop class with ID-based resetShop(id) function.
Challenge 8
Dynamic Inventory
Full dynamic inventory supporting: assign slots, add items, remove items, view inventory, view a specific slot, search, view assignable items, restart, help prompt, clear, and exit. First implementation used vectors, two arrays, and a list. Fully rewritten using classes, structs, and unordered_map STL. Each item became a struct with ID and name. Search function made case-insensitive. Final code was described as "presentable and neat."
Challenge 9
Vector2 Class
A C++ class storing X/Y float coordinates with operator overloads, copy constructor, copy-assignment, and static/instance methods: Dot product, Magnitude, Normalize, Normalized, Distance. Also evaluated whether one vector was within another's field-of-view cone. Described as "overwhelming" — simultaneously learning pointers, class construction, operator overloading, and header declarations.
Reflection"The amount of code required was less than expected — the challenge was psychologically overwhelming but technically achievable once broken down." Cognitive overload is a genuine barrier to retention.
Challenge 10
Bitwise Controller Input
The most demanding challenge. Manipulate a 16-bit bitfield (uint16_t) representing controller input for up to 4 players. Lower 12 bits encode button states (DPad, face buttons, shoulder/trigger); upper 4 bits store player index. Four typedef structs in structure.h. Functions included: SetBitAtPosition, SetData, SetPlayers, GetPlayers, GetData, TransformInputByPlayer (D-pad rotated per player), and bitfield conversion utilities.
On Challenge 10"One of the toughest yet most annoying challenges." Extended focus caused common English words to look wrong — a Stroop-effect-like cognitive fatigue. Unlike Challenge 9, no satisfaction or fun factor — purely a headache.

Code Rewrite

After completing all ten challenges, all code was rewritten for consistent naming conventions and readability. The changes were lost once and had to be completed a second time. Three major systematic changes applied across all challenges:

  • Removed using namespace std; — identified as bad practice. When multiple namespaces are in use, functions can silently collide with std equivalents. Explicit std:: prefixing applied throughout.
  • Introduced while(true) loops — continuously accepting user input without requiring the application to restart between tests, saving significant debugging and recompilation time.
  • Fragmented main() — split monolithic main functions into appropriately named sub-functions for readability, maintainability, and isolation of bugs.

Final naming convention pass: camelCase for variables and functions, PascalCase for classes and structs, SNAKE_CASE for #define and constant definitions.

The Forbidden Hell → Endless Dungeon

Original Concept: The Forbidden Hell

The original game concept was a narrative horror RPG titled The Forbidden Hell. Genre: Action, Adventure, Horror, Sci-Fi, Fantasy. Inspirations: Blair Witch Project, FINAL FANTASY XIII, Silent Hill Homecoming, Slender: The Arrival, Resident Evil 3: Nemesis, and The Evil Within. Planned mechanics included turn-based combat, player roles, an RPG levelling system, narrative story, varied randomised enemies, puzzles, player inventory/skills/abilities, save and load, RNG-based decision making, and BGM/SFX.

The plot: the player is knocked unconscious and wakes in a rural, isolated forest known as "The Forbidden Hell" — a location notorious for unexplained kidnappings and consistent murders. The player discovers they can cast healing magic when nursing a leg injury. The player's name was dynamically inserted into the narration via game_introduction().

Change of Plans — October 28, 2024 With four weeks until the deadline, the original game was scrapped. The battle system alone had grown to 2,300 lines of unfinished code; the total codebase was approximately 9,000 lines. Genre changed from narrative horror RPG to endless dungeon — infinite floors of randomised enemies with dynamically increasing difficulty and no fixed floor limit.

Endless Dungeon — Development

The redesigned game retained the battle system architecture but scrapped the narrative. Key systems built or extended:

  • Story / Introduction: Narrative scrapped, introduction revised to fit the dungeon genre. Boss room function added. Debug functions for skipping to specific game states.
  • External Functions: clear_console() extended with loading screen message parameters. Float variant of randomise_number() added.
  • Windows API: sleep_game(int sleep_time) with customisable duration. disable_console_resize() — thread implementation caused OS hang before process termination; resolved by using MessageBoxA() to warn the user. change_console_title() added. WIN32_LEAN_AND_MEAN defined for additional libraries.
  • Player: Global variables for weaknesses, resistances, immunities, abilities, and roles. Classes created. Battle-related functions: is_dead(), is_poisoned(), is_cursed(), is_player_turn(), assign_abilities(), output_roles(), switch_roles().
  • Enemies: Global variables for HP, immunities, and XP yield. Classes and string vectors to return ability lists per encounter type.

Battle System

The centrepiece of Assignment 2. Key functions: Battle_Setup() — configures enemy stats and assigns the player's role; Battle_Start(); Battle_End(); Battle_Cleanup() — deletes pointers and resets all variables; Game_Over(). Player logic: Battle_Player_Turn(), Battle_Player_Attack(), Battle_Player_Inflict_Bleed(). Ailment boolean functions for both player and enemy perform specific actions per active ailment — poison, curse, bleed, etc. Damage calculations factor in weakness, resistance, and immunity. The system uses inheritance.

Named Bugs — Battle System

  • Trillion-HP Enemy: Enemy HP multiplied by approximately 2 trillion when the player changed roles — game-breaking and critical.
  • Wrong Role Assignment: Incorrect role assigned to the player under certain conditions.
  • Wrong Battle Log: Damage log displayed when the player cast the Regenerate buff.
  • No Log on Self-Cure: No battle log printed when the player chose to cure themselves.
  • HP Exceeding Maximum: Player HP exceeded max HP after Regenerate was applied.
  • Negative Damage: Negative damage values not clamped — the enemy could effectively heal the player unintentionally.
  • Protection Duration Not Tracked: The Protection buff duration was not decremented each turn.

Final Build — December 9, 2024

Acknowledged getting "carried away" with original plans. The final build was disappointing — unable to implement everything intended. Code was written unnecessarily sophisticatedly, causing mental burnout. Boss BGM sourced from FINAL FANTASY XIII-2; voiceovers from South Park (both credited). Thread archived December 9, 2024.

Reflection "Being over-ambitious is a recurring personal pattern." The final build suffered from over-complex architecture — hundreds of unnecessary subfunctions created via "over-functioning" where single code blocks were broken into far too many sub-calls. Simpler, more pragmatic architecture is preferable under time pressure.

Foundational C++ Explorations

Tutorial 1 — Basic Output

Task 1: The \t escape sequence inserts a tab space; multiple \t characters insert multiple tabs. Task 2: 5+5 written directly within a cout statement performs the calculation dynamically without pre-assigning a variable — the result is printed directly.

Tutorial 2 — Arithmetic

Confirmed that arithmetic expressions within cout statements are evaluated at runtime. Task 2 was screenshot-based with no additional written content captured.

Tutorial 3 — Conditions Part 1

Covered conditional/relational operators and how they use booleans under the hood. Task 1 involved five explicit comparisons with predictions confirmed before running:

  • (5 < 1)0 / false
  • (5 > 1)1 / true
  • (5 == 1)0 / false
  • (90 != 90)0 / false
  • (-5*2)==(5*2)0 / false (−10 ≠ 10)

Task 2 built progressively: a pass/fail grade calculator expanded with 2:2, 2:1, and 1st class thresholds; a name-equality check for "Bob"; ASCII-value string comparison ('Bob' > 'Car' is false because b = 98 < c = 99); and relational operator examples with int player_ammo, const int MAX_AMMO, and bool isPlayerOutOfAmmo.

Key Lessons

Naming Conventions

Inconsistent naming was a recurring problem across all challenges — fluctuating between PascalCase, camelCase, snake_case, and kebab-case within the same codebase. The final naming convention target: camelCase for variables and functions, PascalCase for classes and structs, SNAKE_CASE for #define and constant definitions.

Namespace Hygiene

Removing using namespace std; improves readability and prevents namespace collisions. If multiple namespaces are in use, functions can silently conflict with std equivalents. Explicit std:: prefixing makes the origin of every function call unambiguous.

Rule adopted Never use using namespace std; — always prefix with std:: explicitly.

Cognitive Overload and Retention

Challenge 9 and Challenge 10 both demonstrated that cognitive overload is a real barrier to knowledge retention. Challenge 9's scope was psychologically overwhelming despite being technically achievable once broken down. Challenge 10 induced a Stroop-effect-like fatigue where common English words began to look wrong after hours of focus on bitwise logic. Concepts learned under this kind of overload risk being lost immediately after the task ends.

Over-Functioning

A pattern of "over-functioning" — breaking every small block of logic into its own function — created branching trees of hundreds of unnecessary subfunctions where a single function would have sufficed. This was identified in the final challenge review and corrected. Functions should be extracted only when genuinely warranted: for reuse, readability, or isolation of complexity.

Over-Ambition

Assignment 2's original game concept was too ambitious given the time available and the level of C++ experience at the time. The same pattern had occurred the prior year. The redesign to an endless dungeon was necessary but left the final build feeling incomplete. Writing unnecessarily sophisticated code under time pressure causes mental burnout and produces worse output than simpler, more pragmatic architecture would have.

Iterative Rewrites

Implementing suboptimal solutions first and returning to rewrite them slowed overall progress and introduced new bugs — but ultimately refined programming skills through the revision process. Significant confidence was gained in C++ by the end of the module, particularly around structs, classes, namespaces, and header files.