Skip to content

Instantly share code, notes, and snippets.

@fergcb
Last active August 21, 2021 17:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fergcb/a02760c460def3904358cbdfea9312c6 to your computer and use it in GitHub Desktop.
Save fergcb/a02760c460def3904358cbdfea9312c6 to your computer and use it in GitHub Desktop.
Proposed reform to Choice structure in TypeScript syntax, with JSON examples for StartingEquipment and a Multiattack action.
interface Choice {
desc: string
choose: number
type: string
from: OptionSet
}
type OptionSet = {
option_set_type: 'resource_list' | 'equipment_category' | 'options_array'
} & (ResourceListOptionSet | EquipmentCategoryOptionSet | ArrayOptionSet)
/* Choose from a ResourceList by it's URL */
interface ResourceListOptionSet {
option_set_type: 'resource_list'
resource_list_url: string // url of the resource list endpoint
}
/* Choose an Equipment item from an EquipmentCategory */
interface EquipmentCategoryOptionSet {
option_set_type: 'equipment_category'
equipment_category: APIReference
}
/* Choose from an array of complex Options */
interface ArrayOptionSet {
option_set_type: 'options_array'
options: Option[]
}
type Option = {
option_type: 'reference' | 'action' | 'multiple' | 'choice'
desc?: string
prerequisites?: Prerequisite[]
} & (ReferenceOption | ActionOption | MultipleOption | ChoiceOption)
/* A single kind of object of the `type` defined in the root Choice */
interface ReferenceOption {
option_type: 'reference'
item: CountedReference
}
/* A named action, for Multiattack actions */
interface ActionOption {
option_type: 'action'
action_name: string
count: number
type: "melee" | "ranged"
}
/* An array of options. The "chooser" gets all of these. */
interface MultipleOption {
option_type: 'multiple'
items: Option[]
}
/* A nested choice. The `choice.type` should equal the root `type`. */
interface ChoiceOption {
option_type: 'choice'
choice: Choice
}
/* Some auxilliary structures */
interface CountedReference {
count: number
of: APIReference
}
interface APIReference {
index: string,
name: string,
url: string
}
interface Prerequisite {
type: "proficiency" | "feature" | "spell" | "level"
}
interface ProficiencyPrerequisite extends Prerequisite {
type: "proficiency"
proficiency: APIReference
}
/* <other proficiency types here> */
{
"name": "Multiattack",
"desc": "The captain makes three melee attacks: two with its scimitar and one with its dagger. Or the captain makes two ranged attacks with its daggers.",
"options": {
"desc": "(a) two with its scimitar and one with its dagger or (b) two ranged attacks with its daggers.",
"choose": 1,
"type": "action",
"from": {
"option_set_type": "options_array",
"options": [
{
"desc": "two with its scimitar and one with its dagger",
"option_type": "multiple",
"items": [
{
"option_type": "action",
"action_name": "Scimitar",
"count": 2,
"type": "melee"
},
{
"option_type": "action",
"action_name": "Dagger",
"count": 1,
"type": "melee"
}
]
},
{
"desc": "two ranged attacks with its daggers",
"option_type": "action",
"action_name": "Dagger",
"count": 2,
"type": "ranged"
}
]
}
}
}
[
{
"desc": "(a) chain mail or (b) leather armor, longbow, and 20 arrows",
"type": "equipment",
"choose": 1,
"from": {
"option_set_type": "options_array",
"options": [
{
"option_type": "reference",
"item": {
"count": 1,
"of": {
"name": "Chain Mail",
"index": "chain-mail",
"url": "/api/equipment/chain-mail"
}
}
},
{
"option_type": "multiple",
"items": [
{
"option_type": "reference",
"item": {
"count": 1,
"of": {
"name": "Leather",
"index": "leather",
"url": "/api/equipment/leather"
}
}
},
{
"option_type": "reference",
"item": {
"count": 1,
"of": {
"name": "Longbow",
"index": "longbow",
"url": "/api/equipment/longbow"
}
}
},
{
"option_type": "reference",
"item": {
"count": 20,
"of": {
"name": "Arrow",
"index": "arrow",
"url": "/api/equipment/arrow"
}
}
}
]
}
]
}
},
{
"desc": "(a) a martial weapon and a shield or (b) two martial weapons",
"type": "equipment",
"choose": 1,
"from": {
"option_set_type": "options_array",
"options": [
{
"option_type": "multiple",
"items": [
{
"option_type": "choice",
"choice": {
"desc": "a martial weapon",
"type": "equipment",
"choose": 1,
"from": {
"option_set_type": "equipment_category",
"equipment_category": {
"index": "martial-weapons",
"name": "Martial Weapons",
"url": "/api/equipment-categories/martial-weapons"
}
}
}
},
{
"option_type": "reference",
"item": {
"count": 1,
"of": {
"name": "Shield",
"index": "shield",
"url": "/api/equipment/shield"
}
}
}
]
},
{
"option_type": "choice",
"choice": {
"desc": "a martial weapon",
"type": "equipment",
"choose": 2,
"from": {
"option_set_type": "equipment_category",
"equipment_category": {
"index": "martial-weapons",
"name": "Martial Weapons",
"url": "/api/equipment-categories/martial-weapons"
}
}
}
}
]
}
},
{
"desc": "(a) a light crossbow and 20 bolts or (b) two handaxes",
"type": "equipment",
"choose": 1,
"from": {
"option_set_type": "options_array",
"options": [
{
"option_type": "multiple",
"items": [
{
"option_type": "reference",
"item": {
"count": 1,
"of": {
"name": "Crossbow, Light",
"index": "crossbow-light",
"url": "/api/equipment/crossbow-light"
}
}
},
{
"option_type": "reference",
"item": {
"count": 20,
"of": {
"name": "Crossbow bolt",
"index": "crossbow-bolt",
"url": "/api/equipment/crossbow-bolt"
}
}
}
]
},
{
"option_type": "reference",
"item": {
"count": 2,
"of": {
"name": "Handaxe",
"index": "handaxe",
"url": "/api/equipment/handaxe"
}
}
}
]
}
},
{
"desc": "(a) a dungeoneer's pack or (b) an explorer's pack",
"type": "equipment",
"choose": 1,
"from": {
"option_set_type": "options_array",
"options": [
{
"option_type": "reference",
"item": {
"count": 1,
"of": {
"name": "Dungeoneer's Pack",
"index": "dungeoneers-pack",
"url": "/api/equipment/dungeoneers-pack"
}
}
},
{
"option_type": "reference",
"item": {
"count": 1,
"of": {
"name": "Explorer's Pack",
"index": "explorers-pack",
"url": "/api/equipment/explorers-pack"
}
}
}
]
}
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment