Quests ~ Globalization - uchicago-cs/chiventure GitHub Wiki

Overview

The Problem

Previously, we intended to add quests to the player struct by simply adding a quest_hash_t typed variable into the struct and calling it a day. This turns out to cause many, many problems, primarily because it creates a circular dependency. The quest module includes many functions that depend on the player and adding this quest hash-table to the player class would make the player module also rely on the quest module. When we tried this, it gave numerous errors in a bunch of different files (including many that aren't related to quests at all other than include statements), all pertaining to different types not being declared. After some testing, it was clear these strange bugs were caused by the circular dependency.

The Solution

Much of the quest module relies on the player module, so removing that functionality is near-impossible. That means the best solution is to remove quests from the player module and find some other way of including quests without referencing quest_state.h. From a conceptual standpoint, this means we need to globalize quests, making it so the only instance of each quest is in game_state and all of the duplicate instances like the ones we were going to put into player will be removed. That way, the player can communicate with quests indirectly by storing ids that the quests can manage through game_state.

Note that quests are already getting stored in game_state, so this rework is not introducing any additional global scope to muck up game_state. If anything, this change actually cleans up the code by no longer requiring multiple duplicates of every quest for each player.

Struct Changes

The easiest way of accomplishing this design change is by replacing the quest_hash_t we were going to add to the player module with a hash table of player_quest_t structs and a hash table of player_task_t structs as defined below:

typedef struct player_quest {
    UI_hash_handle hh;
    char *quest_id;
    int completion;
} player_quest_t;

typedef struct player_task {
    UT_hash_handle hh;
    char *task_id;
    bool completed;
} player_task_t;

This change should come along with removing int status from the quest struct and removing bool completed from the task struct.

By defining these structs in the player struct and using these over the regular quest_hash_t tables, the player module can take advantage of quest ids being strings to remove the circular dependency.

Function Changes

Moving int status and bool completed from the quest and task structs is going to require small reworks to many of the functions in the quest module. Here is a list of all of the functions that need to be changed:

  • quest_new(): Currently calls quest_init()with the final parameter, int status, set to 0. This parameter is getting removed, so it should be removed from here as well.
  • quest_init(): Currently sets quest->status to its int status parameter which is no longer relevant. This functionality needs to be removed.
  • start_quest() and fail_quest(): Currently only sets quest->status which is no longer relevant. Needs to be reworked to update a specific player's quest status instead. Also, these functions could be consolidated into a single update_quest_status() function since they both contain the same logic with the only difference being the new quest status value.
  • is_quest_completed() When this function determines that a quest is completed, it sets the quest's completion status, which now needs to be reworked with this new quest completion design.
  • get_quest_status(): This function no longer applies at all and barely served a purpose before this redesign. Realistically, it should be removed entirely.
  • task_init(): Currently sets task->completed to false which is no longer relevant. This functionality needs to be removed.
  • find_task(): Currently checks if a given task is in the current path of a given tree and relies on completion to make the search more efficient. Needs to be reworked to take the completion status from a given player's player_task hash table.
  • complete_task(): Currently sets completion for the task. Needs to set completion in the player's player_task hash table.