Repository navigation
Win System
The game is won by defeating Zeus in Level 3. That is the only way to win. How well the player won is then graded into three tiers, with one extra honour:
| Tier | Level | How it is earned |
|---|---|---|
| Victory | 1 | Zeus in Level 3 is defeated |
| Glory | 2 | Victory, and the guardian of each of the eight side rooms is also defeated |
| Legend | 3 | Glory, and at least 3 quests have been completed |
| Tortoise Champion | honour | every hidden tortoise has been found; independent of the tier |
Each tier includes the one below it. Quests alone never lift a Victory to Legend.
Making "kill every mini boss" a second route to the ending would make the final fight skippable and the side rooms compulsory for that route, even though nothing gates a side-room door. As a scale, the side rooms and quests stay optional, they pay off, and the game keeps one clear ending.
Zeus (Level 3) dies
| BossDefeatedWinComponent hears his "death" event and announces "finalBossDefeated"
| on a listener entity owned by the LevelGameArea
v
LevelGameArea.isFinalBossDefeated() becomes true
v
MainGameScreen, each frame: WinCountdown.update(defeated, frame time)
| waits 2.5 seconds so the death is seen
v
WinEvaluator.evaluateNow(true)
| reads EnemyRegistry (kills), QuestLedger (quests), TortoiseLedger (tortoises)
v
WinResult (tier, counts, what is missing)
v
WinScreenDisplay.showWinScreen(result)
The announcement goes to an entity owned by the area, not to the boss and not to the player. The boss is disposed the moment it dies, and reviving the player creates a new player entity, so neither outlives the moment reliably.
| Class | Kind | Responsibility |
|---|---|---|
WinTier |
enum | the four values with a level, a title and a subtitle |
BossRoster |
static data | which enemy is the final boss, and which mini bosses count |
QuestLedger |
static state | how many quests have been completed, by kind |
TortoiseLedger |
static state | which hidden tortoises have been found, and how many exist |
WinEvaluator |
static logic | turns kills, quests and tortoises into a WinResult
|
WinResult |
immutable value | the tier and the numbers behind it |
BossDefeatedWinComponent |
component | on the final boss; announces his death once |
WinCountdown |
timer | the wait between the death and the win screen |
| Class | Change |
|---|---|
LevelGameArea |
owns the listener and the finalBossDefeated flag; armWinTrigger gives the final boss its component; noteAlreadyKilled handles a save made after the win |
MainGameScreen |
runs the WinCountdown each frame and shows the win screen; loads and resets the two ledgers |
WinScreenDisplay |
showWinScreen(WinResult) and five small methods that build the text |
QuestGiverComponent |
records a quest in the QuestLedger when it is turned in at 100 percent |
GameSaveData, PauseMenuActions
|
save the completed quests and found tortoises |
A kill is already saved under an id of the form <map name>:<x>,<y> (EnemyId, EnemyRegistry). The roster uses those ids, so no enemy needs a new component to be counted, and kills survive a save and a load.
Final boss: Zeus, Level 3 - Zeus's Palace:26,4.
| Room | Required guardian | Kill id |
|---|---|---|
| Hound's Den | Cerberus | Hound's Den:48,2 |
| Gorgon's Gallery | Medusa | Gorgon's Gallery:37,11 |
| Minotaur's Labyrinth | Minotaur | Minotaur's Labyrinth:24,35 |
| Shades' Barracks | Minotaur | Shades' Barracks:40,17 |
| Cyclops Forge | Cyclops | Cyclops Forge:30,15 |
| Centaur Pavilion | Centaur (upper) | Centaur Pavilion:44,12 |
| Zeus's Outer Guard | Medusa | Zeus's Outer Guard:24,16 |
| Zeus's Thunder Hall | Medusa | Zeus's Thunder Hall:26,12 |
The required guardian is the boss on the room's highest storey, beside the exit. Three other boss-type enemies (a Centaur in the Labyrinth, the lower Centaur in the Pavilion, the Cyclops in the Outer Guard) are listed as escorts and are not required.
There is only one Zeus in the game, in Level 3. The Thunder Hall and Level 2 bosses that used to be Zeus are now Medusa, so no other enemy can end the game.
The roster is tied to the maps. Moving a boss marker or renaming a map breaks its id. BossRosterMapsTest reads the real map files and fails as soon as they disagree.
The screen shows, top to bottom:
- the tier's title in capitals, its subtitle, and "Rank n of 3"
- "Guardians defeated: x of 8"
- "Quests completed: x of 3"
- "Tortoises found: x of y", with "- Tortoise Champion" when all were found
- what is still missing: up to four guardians by name, then "and n more", then the quests still needed
- the Play Again and Main Menu buttons (unchanged, including keyboard navigation)
The win terminal command shows the screen for the current game without killing Zeus.
-
Quests.
QuestGiverComponentrecords a completion when a quest is turned in with a progress of 100 or more. A quest cleared below 100 is abandoned and is not counted. NPCs hand out jump, enemies killed and shields collected quests throughDialogueComponent. -
Tortoises.
MainGameScreencallsTortoiseLedger.setTotal(n)with how many tortoises the game hides (theTORTOISES_HIDDENconstant, currently 1), andTortoiseComponentcallsrecordFound(id)when the player touches one. Raise the constant when more tortoises are placed.
| To change | Edit |
|---|---|
| which bosses count for Glory | the table in BossRoster
|
| how many quests Legend needs | WinEvaluator.QUESTS_REQUIRED_FOR_LEGEND |
| the wait before the win screen |
WIN_SCREEN_DELAY in MainGameScreen
|
| the titles and subtitles | WinTier |
Class diagram of the win package.

Every class in the win package has its own JUnit test class in com.csse3200.game.win, and each changed class outside the package has a test beside it. The ledgers are static, so every test resets them before and after it runs.
Tests were used to ensure the following situations were working:
- There are exactly four tiers, in ascending order of level
- Each tier has the level its name implies and its own non-blank title
-
isAtLeastcompares tiers by level - A tier can be found by its level, and a level outside 0 to 3 is rejected
Tests were used to ensure the following situations were working:
- The roster holds eight required guardians and three escorts, with the required ones first
- The final boss is not in the list of mini bosses, and only its id is the final boss
- A mini boss with a blank id, label, room or type is rejected
- The lists handed out cannot be changed by the caller
- Every id in the roster matches a boss marker in the real map files, and there is only one Zeus
Tests were used to ensure the following situations were working:
- A completed quest is counted under its kind, and an unknown kind is rejected
- The ledger can be reset, saved and loaded, ignoring unknown kinds and counts of zero or below
- Each of the four quest kinds reaches the ledger when it is turned in at 100 percent
- A quest cleared below 100 percent is not counted
Tests were used to ensure the following situations were working:
- A found tortoise is counted once, however many times it is recorded
- The honour is earned only when every hidden tortoise is found, and never when none are hidden
- The ledger can be reset, saved and loaded
- The honour is independent of the tier
Tests were used to ensure the following situations were working:
- A result stores its tier and its counts
- A negative count is rejected
- The list of missing guardians cannot be changed by the caller
-
isFullyCompleteandisTortoiseChampionreport correctly
Tests were used to ensure the following situations were working:
- No tier is given while the final boss is alive, whatever else is done
- Victory, Glory and Legend are each given at exactly their rule
- Escorts, unknown ids, duplicate ids and a null collection do not change the tier
- The guardians still standing are listed in roster order
-
evaluateNowreads the kills, quests and tortoises from the live registries
Tests were used to ensure the following situations were working:
- The final boss's death is announced on the listener entity, not on the boss
- It is announced once, even if the death is reported again
- Only the final boss is given the component; any other enemy is left alone
- The area is won when the armed boss dies, stays won, and a save with the boss already dead loads as won
- Two areas keep their own flags
Tests were used to ensure the following situations were working:
- Nothing happens until the final boss is defeated
- The countdown finishes exactly once, after the delay, frame by frame
- A negative, infinite or not-a-number delay is rejected
Tests were used to ensure the following situations were working:
- The rank, guardians, quests and tortoises lines have the right wording
- At most four missing guardians are named, with the rest summed up
- The screen is hidden until a result is shown, and shows the tier's title
Tests were used to ensure the following situations were working:
- Completed quests and found tortoises are written into the save
- A fresh game saves none
- Both ledgers are restored from what was saved
- Everything that was saved before is still saved
Tests were used to ensure the following situations were working:
- The static holder classes cannot be instantiated
The lines in MainGameScreen that connect the countdown to the screen, and the two calls inside LevelGameArea.spawnEnemies(), need a running game. To check them:
- Kill Zeus in Level 3 and the win screen appears after about 2.5 seconds.
- Kill the Thunder Hall Medusa and the game does not end.
- Save after a win, reload, and the guardian, quest and tortoise counts are kept.