-
Notifications
You must be signed in to change notification settings - Fork 13
Custom Actions ~ Design Document
User will be able to:
- Define an action
- Construct its effects and requirements from:
- Pre-existing actions
- Supplied keywords
- We supply/implement these
- Examples: set, say
- Other actions defined in the WDL document
They will do so by:
- Constructing an action block from CCCs and parameters
a. Represents a single step the program will take
b. Format: {"block": “CCC”, "params": "param1 param2 … “}
c. Example: {"block": "set", "params": "obj_CHAIR upright flipped"}
- action block: {"block": "set", "params": "obj_CHAIR upright flipped"}
- CCC: set
- parameters: obj_CHAIR upright flipped
- Chaining those action blocks together into an action sequence
- Supplying a context a. i.e. item, location b. Will expand later
- Linking this sequence to our defined action
{
"action": "act_PUSH",
"context": "item",
"item": "obj_CHAIR",
"sequence": [
{"block": "if", "params": "inventory has item_SPINACH"},
{"block": "set", "params": "arg1 flipped"},
{"block": "say", "params": "'You pushed the chair. It flipped!'"},
{"block": "else", "params": ""},
{"block": "say", "params": "'Couldn't push the chair. Spinach needed.''"},
{"block": "endif", "params": ""},
{"block": "say", "params": "'This is printed regardless of push success.'"},
{"block": "lua", "params": "'path/to/example.lua' arg0 arg1 arg2 arg3"}
]
}
Action: act_PUSH
Context: item
Action sequence: all of the blocks
Action blocks: each { … }
CCCs: if, set, say, else, say, endif, say, lua
These are the planned atomic blocks and a description of what each one is.
Note: The functions that execute the following atomic blocks are currently not intended to be exposed to the interface. They are simply listed here to indicate what the user is able to write in their WDL++ file.
- IF/ELSE
- WHILE/ENDWHILE
- FOR/ENDFOR
- Determine whether an attribute is equal to another
- Results:
- Returns an int status code (TRUE/FALSE)
- Returns failure status code if attributes are invalid
- Arguments:
- Two attributes
- Attributes must be compatible (int and double, or string, bool, char only)
- Supports all attribute types
- Notes:
- Runs strcmp for strings and == for other types
- double types are checked for similarity within small epsilon distance of each other (handle rounding errors)
- Determine whether an attribute is less than or greater than another
- Results:
- Returns an int status code (TRUE/FALSE)
- Returns failure status code if attributes are invalid
- Arguments:
- Two attributes
- Supports int and double attribute types only
- Determine whether the first attribute is less than or greater than or equal to the second attribute
- Results:
- Returns an int status code (TRUE/FALSE)
- Returns failure status code if attributes are invalid
- Arguments:
- Two attributes
- Supports int and double attribute types only
- Return a boolean determining whether the attribute (object) is in the container
- Attribute must be string only (search by name)
- Set the first attribute’s value to be that of the second attribute.
- Notes:
- If an attribute is variable, use the value stored in that attribute. If it is a constant string, then it is considered a call to look up a temporary attribute with the same name as the value.
- Attribute types must match
- Print the phrase for the player to read
- Phrase must be an attribute with the string type. Can be constant or variable.
- Move the player to the specified room
- Room must be valid
- Perform the specified arithmetic operation on the first and second attribute with the following logic (attribute_1 (OP) attribute_2) then store in the third attribute
- Notes:
- Attributes must be of matching types and valid for arithmetic (i.e. int/double). They can be variable or constant.
- 3rd attribute can be a constant string--will be considered a call to store in a temporary variable with name as 3rd attribute’s value.
- Generate a random number between min and max
- Notes:
- Type determines whether an integer or double is generated. Must be an attribute encoding either double or int in its attribute field.
- Min/Max must be attributed with the same type as type attribute--they can, however, be constant or variable.
- Attribute can be a constant string--will be considered a call to store in temporary variable with same name as attribute’s value
- Execute a specified lua script
- Notes:
- The arguments passed after lua_script are simply listed in the order they are passed to the lua script
- Do the existing action with the following arguments passed to it
- Notes:
- Action must exist as a hardcoded action (functioning effectively as a synonym)
The motivating structure behind the design for storing custom actions in memory is an Abstract Syntax Tree (AST), essentially a multiway tree (i.e. a tree whose nodes have arbitrary numbers of children) whose root represents the “first” action and the children are followed for subsequent actions. The sequence of action blocks is wrapped in a struct called “Action Sequence” which also contains temporary variable storage, action execution context, etc. and serves as the main object to be passed through and outside of the interface.
Motivation:
- Essentially a wrapper for the whole tree
- Provides flexibility to accommodate future updates in functionality for different contexts
- e.g. battle, player, and item contexts
Contents:
- Pointer to the first block to be executed
- What context the action should be executed in
- E.g. On an item, between two items, in battle, not on a item, etc.
- Necessary to determine validity of arguments passed in during runtime
- Pointers to data for use in the context of executing the action
- e.g. a pointer to an item to be acted upon, a pointer to the player object
- Sequence-specific attributes
- Limited to use within sequence itself, serving as temporary variables for modification and retrieval within sequence
- Can be created and deleted as necessary
Current Contexts:
- Player
- Battle
- Item
- Item-item
typedef struct custom_action
{
char *action_name;
char *context;
char *item;
char *type;
AST_block_t *head;
UT_hash_handle hh;
} custom_action_t;
Structs
- block_t
- a union which may represent any of the four types of blocks (see Control, Branch, Action, Conditional)
- control block
- branch block
- action block
- conditional block
- a union which may represent any of the four types of blocks (see Control, Branch, Action, Conditional)
- AST_block_t
- block_t block - (see above)
- enum block_type - shows which type of block is contained within the block_t struct Usage
- An abstraction of all the different block objects. Serves to make code cleaner and simplify execution logic.
typedef union block {
control_block_t control_block;
branch_block_t branch_block;
action_block_t action_block;
conditional_block_t conditional_block;
} block_t;
typedef struct AST_block {
block_t block;
enum block_type block_type;
struct AST_block *next;
struct AST_block *prev;
} AST_block_t;
Control Block: block to introduce a single action
- Introduce a new sequence of logic for execution
- Pointed to by Branch blocks (see next section)
- Contain a single pointer to the first action in the structure
- Created to exist in the Branch block struct
typedef struct control_block {
enum control_type control_type;
AST_block* next
} control_block_t;
Branch Block: holds pointers to the 1+ Control block and 1+ Conditional block
- Purpose: Essential element of control structure
- Simplifies checking for correctness (all control structures will have conditionals)
- Enables us to have just one pointer to the next AST block for Action and Control blocks
- Reduces complexity and errors Initially, a branch block will support a simple AND/OR for all its Conditional blocks.
typedef struct branch_block {
int num_conditionals;
conditional_block_t** conditionals;
int num_controls;
control_block_t** controls;
} branch_block_t;
Contents:
- Action - data structure indicating an action from “Atomic Effects” section
- Action arguments - list of attributes
- Number of action arguments
- Pointer to next block
Classes of actions - classifying atomic effects
- Modifying existing attribute
- Creating temporary attribute
- Generating random numbers
- Storing temporary values
A helpful way to think of actions would be as a function and its arguments.
typedef struct action_block {
enum action_type action_type;
int num_args;
attribute_t** args;
AST_block* next;
} action_block_t;
Returns true or false Contains an operator and two attributes:
- Binary comparison operator (represented as an enum) - see Atomic Conditionals.
- Two attributes (represented as attribute_t structs - see Attributes). Types of attributes:
- existing attributes (i.e. player’s gold)
- temporary attributes (i.e. generated number, later deleted)
- fixed values (i.e. 5) Process:
- Performs a typecheck on the attributes (to determine if their types can be logically compared).
- Compares the attributes using the operator. Always placed under a Branch block (see Branch).
typedef struct conditional_block {
enum conditional_type conditional_type;
attribute_t* left;
attribute_t* right;
} conditional_block_t;
Attribute Block: wrapper for a single primitive value
- Has the feature of being able to store different types of primitive values
- Helps to “enable” actions and conditionals
- Types of Attributes:
- Constants:
- Value not tied to an object or field
- Shouldn’t be tied to a persistent pointer outside the Action Sequence
- Named “NULL”
- Variables
- Value tied to an object or field
- Can exist in the Action Sequence (when tied to an object/field)
- Have some definitive name
- Constants:
- Types do need to be matched and checked for attributes since different types of primitive values are supported, which is something to not overlook during implementation
typedef union attribute_value {
double double_val;
char char_val;
bool bool_val;
char* str_val;
int int_val;
} attribute_value_t;
typedef struct attribute {
attribute_value_t value;
attribute_type attribute_type;
char* name;
} attribute_t;
custom_action_t* search_for_custom_action(char* action_name, game* game)
Arguments:
- action_name: The name of the custom action to be searched for
- game: The current game chiventure is running, and the custom action is contained in Return:
- custom_action_t* Pointer to the custom action with the same name as action_name if it exists
- NULL if no such action_name custom action exists in game
int do_custom_action(custom_action_t* action, char** args, int num_args)
Arguments:
- action: A pointer to the custom action to be executed (most likely acquired from search_for_custom_action)
- args: An array of strings of the arguments passed to the action (i.e. the words succeeding the action written in the command line)
- num_args: The number of arguments being passed in Return:
- SUCCESS on successful execution
- FAILURE/TBD on specific types of failure
custom_action_t* compile_custom_action(json_dict_obj* json, game* game)
Build a custom action object and add it to the game’s dictionary of custom actions. Also associates custom actions with objects and attributes if necessary.
NOTE: Any objects or attributes the action is associated with need to be initialized before the action is compiled.
Arguments:
- json: A dictionary(?) object containing the basic parsed json from a WDL++ file. See example below in Sample Parse and Data Structure. TBD, need to coordinate with WDL++ team.
- game: The game the custom action should be associated with Return:
- custom_action_t* A pointer to the compiled custom action if successful
- NULL if there was an error parsing the json
int free_custom_action(custom_action_t* action)
Free a custom action and all its associated structs
Arguments:
- action: The custom action to be freed Return
- SUCCESS
- FAILURE
char* get_custom_action_name(custom_action_t* action)
Arguments:
- action: The custom action to be queried Return
- char* A string containing the name of the custom action
- NULL if the action passed in was invalid
{
"action": "act_PUSH",
"context": "item",
"item": "obj_CHAIR",
"sequence": [
{"block": "if", "params": "inventory has item_SPINACH"},
{"block": "set", "params": "obj_CHAIR status flipped"},
{"block": "say", "params": "'You pushed the chair. It flipped!'"},
{"block": "else", "params": ""},
{"block": "say", "params": "'Couldn't push the chair. Spinach needed.''"},
{"block": "endif", "params": ""},
{"block": "say", "params": "'This is printed regardless of push success.'"}
]
}
-
Action Management
-
Battles
- Design Document
- Text Based Combat in Other Games
- User Stories
- Wishlist
- Battle Planning 2022
- Battle User Stories Review 2022
- Structs in Other Modules Related to Battles 2022
- Stat Changes Design Document
- Run Function Design Document
- CLI Integration Design Document
- Move Changes Design Document
- Unstubbing Stubs Design Document
- Battle Items and Equipment Design Document
- Battle Item Stats
- Battles Demo Design Document
- Battles Testing Moves, Items, and Equipment Design Document
- Sound integration with battle (design document)
-
Custom Actions
-
Custom Scripts
-
DSL
-
CLI
-
Enhanced CLI
-
Game-State
-
Graphics
- Design Plan
- Design document for integrating split screen graphics with chiventure
- GDL (Graphical Description Language)
- Graphics Sandbox
- Design Document for NPC Graphics and Dialogue
- Feature Wishlist (Spring 2021)
- Installing and Building raylib on a VM
- LibSDL Research
- Module Interactions
- Working with Raylib and SSH
- raylib
- GDL
-
Linking the Libzip and Json C to chiventure on CSIL machines
-
Lua
-
NPC
- Dependencies: Player class, Open world, Battle
- Action Documentation
- Design Document for NPC Generation in Openworld
- Design and Planning
- Establishing Dependencies
- Implementation of Custom Scripts
- Independent Feature: NPC Movement Design Document
- Player Interaction Design and Planning
- Dialogue
- Design Document for NPC Dialogue and Action Implementation
- Loading NPCs from WDL Files
- NPC Battle Integration Design Document
- NPC Battle Integration Changes Design Document
-
Open World
- Autogeneration and Game State
- Deciding an integration approach
- Designing approach for static integration into chiventure
- Feature Wishlist
- Generation Module Design layout
- Potential connections to the rest of chiventure
- Single Room Generation Module Design
- Source Document
- User Stories
- World Generation Algorithm Plan
- Loading OpenWorld Attribute from WDL
-
Player Class
-
Player
-
Quests
-
Rooms
-
Skill Trees
- Avoiding soft locks in skill tree integration
- Components of Exemplary Skill Trees
- Design Document and Interface Guide
- Environment interactions based on skill characteristics
- Integrating complex skill (combined, random, sequential, etc.) implementation
- Integration of a Leveling System
- Potential Integration with existing WDL
- Research on game balancing in regards to skill trees
- Research on skill tree support in modern day game engines
- SkillTree Wiki Summary
- Skilltree "effect" implementation and roadmap
- Summary of md doc file for skilltrees
- Design ideas in connection to other features
- Summary of Skill Tree Integration 2022
- The Difficulty of the Reading the World
- Complex Skills Summary
-
Sound
-
Stats
-
WDL