Battles ~ Run Function Design Document - uchicago-cs/chiventure GitHub Wiki
This function runs a battle from start to finish, calling battle setup functions under start_battle(). It accepts a linked list of turn_components (which is already decided by the developer) from the battle_cxt_t struct that is passed in, then runs a loop that executes the specified turn-phase order for each player in turn, calling battle_flow_move(), battle_flow_item(), and enemy_make_move() as well as a yet to be implemented function called apply_status_effects() to add support for status effects. The function checks for a winner at every step until one team wins. Then it cleans up the battle and returns to the world context. This design allows for more flexible battles, allowing the game designer to specify a turn structure that makes sense for their specific game. While the CLI team has some run battle functions, we feel it is best for our team to handle the implementation.
Already Implemented Structs to include (may need some modification):
/* see battle_flow_structs.h */
typedef struct battle_player {
// Other fields: hash handle, inventory, other stats
char *player_id;
class_t *class_type;
stat_t *stats;
move_t *moves;
battle_item_t *items;
} battle_player_t;
/* see battle_flow_structs.h */
typedef struct battle_game {
// Would have other fields (eg hash tables for players, rooms, battle_items)
battle_player_t *player;
battle_t *battle;
} battle_game_t;
/* see battle_common.h */
typedef enum battle_status {
BATTLE_IN_PROGRESS,
BATTLE_VICTOR_PLAYER,
BATTLE_VICTOR_ENEMY,
NO_BATTLE
} battle_status_t;
Structs We Need to Implement:
/* Determined by the game creator, allows for players to either use an item or make a move in a turn or do both */
typedef struct turn_component {
bool item;
bool move;
turn_component *next;
} turn_component_t;
/* A linked list of turn_components, used if a player can use multiple items in one turn or make multiple moves
* Will most likely be included in the battle_cxt_t
*/
typedef struct turn_component_list {
bool item;
bool move;
turn_component *next;
} turn_component_list_t;
New Helper Functions:
/* Will apply the effect of the status of a player or NPC to their stats
*
* Parameters:
* -combatant: the current battle player before status effects
*
*Return:
*/ -returns a battle_player_t with status effects applied.
battle_player_t *apply_status_effects(battle_player_t *combatant);
/* Will apply the effect of the turn
*
* Parameters:
* -ctx: the current battle status
*
*Return:
*/ -returns the new battle status after the turn
battle_status_t *run_turn(battle_ctx_t *ctx);
Main Run Battle Funtion:
/* sets up, runs, and ends a rpg battle
* runs each turn by carrying out the phases specified by a given linked list in battle context
*
* parameters:
* - battle_ctx_t *ctx; // the context struct that holds info about the battle
* - npc_t *npc_enemy; // the enemy
* - environment_t env; // the environment that the battle takes place in
*
* returns:
* - the result of the battle.
*
*/
battle_status_t *run_battle(battle_ctx_t *ctx, npc_t *npc_enemy, environment_t env);
Example:
The game developer wants to have a turn-based battle system in their game where in a turn, a combatant can use an item, then use another item or use an ability, then use another item. They would specify this in the WDL and it would be converted into this linked list of turn components:
(item=true, move=false) -> (item=true, move=true) -> (item=true, move=false) -> NULL
Then, when a battle is loaded, each player turn would work like this:
A loop in run_turn() would point at the first item in the linked list (item=true, move=false in this case) and call the battle_flow_item() function, prompting the user to select an item to use. After the user uses an item or decides not to, the loop would run again, this time pointing at the second item of the linked list (item=true, move=true). The CLI would prompt the user to either use a move or an item. Then the loop would iterate again, pointing to (item=true, move=false) and prompting the user to choose an item to use. Then the loop would iterate again, pointing to NULL. This signals the end of the turn. run_turn() returns, and run_battle flips the turn in the battle_ctx and calls run_turn() for the enemy with a fresh pointer pointing to the beginning of the linked list again. run_turn() would then do a similar thing, this time calling the enemy’s ai rather than prompting the user for each turn component. At the end of the enemy’s turn, run_battle() would flip the turn again and call run_turn() for the user again This loop would continue until one combatant or the other wins the fight, at which point run_battle() will call battle_over() and return to the larger game.
Here is an example of what we would like the player to see when running a battle:
Turn starts with a numbered menu of possible actions as determined by the current turn component, e.g.
Select an action: M1 - Fireball I1 - Potion of Healing P - Do nothing (pass) M2 - Magic Missile I2 - Lucky Dice M3 - Healing pool
Running INFO [key] brings up an info blurb about the given menu item, e.g.
> INFO M3
Healing pool
Type: magic (defensive)
Targets: none (area)
Uses: 1
B - Back
Selecting a number corresponding to an action (M1, I2, etc.) will lead to a targeting page e.g.,
> M1
Select a target:
1 - Goblin Bodyguard soldier 70 hp
2 - Goblin Bodyguard soldier 70 hp
3 - Warlock mage 150 hp
4 - Back
entering the key for a valid target completes the action- the move is executed and the CLI prints the result, e.g.
> 1
You hurl a ball of arcane fire at Goblin Bodyguard. It does 42 dmg. Goblin Bodyguard has 28 hp remaining.
The turn then progresses to the next phase, either prompting the user for another action or continuing to the enemies’ turn.
Overall, here is the list of commands that will need to be supported by the CLI in battle mode:
-
[key]
: selects a menu item labeled as the given key -
INFO [key]
: works on a menu item that is an item, move, or combatant. Also works with the arguments PLAYER or SELF which bring up information about the player -
OVERVIEW
,SUMMARY
: lists all combatants in a numeric menu with their class and hp -
RUN
,FLEE
: attempt to leave the battle -
INVENTORY
: lists items in the player’s inventory
New function documentation:
In battle_flow module:
/* Finds the possible targets for a move
*
* Parameters:
* - move: the move that was chosen by the player. Should have information about what targets
* it can be used on.
*
* Returns:
* - return a linked list of possible targets
*/
combatant_t get_possible_move_targets(move_t move);
/ * Parameters:
* - b: pointer to a battle
* - input: string that identifies the move or item the user will use
* - e.g. M1, I3.
* - rc: return code
* - game: the Chiventure game being run
*
* Returns:
* - A string confirming the selection and a prompt for the next action
* printed by the CLI.
* - An RC of: 1 if the battle has ended, 0 if the battle is still ongoing,
* and -1 if an error occured.
*/
run_turn_component(battle_t *b, int input, int *rc, game_t *game);
We will need to update print_moves and print_battle_items to include the key that each move/item corresponds to.