Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions data/story/wire-conformance.json
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,50 @@
"value": {"map": "M", "certainty": "unknown", "where": {"kind": "gps"}}
},
"expectation": {"rejected": true}
},
{
"input": {
"name": "args",
"record": "step",
"value": {
"id": "buy",
"kind": "game_action",
"variant": "mart",
"args": {"map": "CeruleanCity_Mart", "budget": 3000, "if_present": true}
}
},
"expectation": {
"canonical": {
"id": "buy",
"kind": "game_action",
"variant": "mart",
"args": {"map": "CeruleanCity_Mart", "budget": 3000, "if_present": true}
}
}
},
{
"input": {
"name": "fractional arg",
"record": "step",
"value": {"id": "a", "kind": "game_action", "variant": "mart", "args": {"budget": 1.5}}
},
"expectation": {"rejected": true}
},
{
"input": {
"name": "nested arg",
"record": "step",
"value": {"id": "a", "kind": "game_action", "variant": "mart", "args": {"items": [1]}}
},
"expectation": {"rejected": true}
},
{
"input": {
"name": "args not an object",
"record": "step",
"value": {"id": "a", "kind": "game_action", "variant": "mart", "args": ["map"]}
},
"expectation": {"rejected": true}
}
]
}
1 change: 1 addition & 0 deletions schemas/story-checkpoint.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
}
},
"variant": {"type": "string"},
"args": {"type": "object", "additionalProperties": {"type": ["boolean", "integer", "string"]}},
"skip_if": {"type": "array", "items": {"type": "string"}},
"once_per_save": {"type": "boolean"},
"notes": {"$ref": "#/$defs/notes"}
Expand Down
21 changes: 20 additions & 1 deletion src/pokesim/story/checkpoint_wire.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,22 @@ def array(value):
return value


def read_args(value):
"""A step's args: flags, whole numbers and words by name, as the step's
action declares them in the game's C++ (StoryArgSpec); this reader checks
only the value types."""
if not isinstance(value, dict):
raise ValueError('expected args object')
result = {}
for key, item in value.items():
if type(item) is int:
integer(item, -9223372036854775808, 9223372036854775807)
elif type(item) is not bool and not isinstance(item, str):
raise ValueError('arg is not a flag, whole number or word: ' + key)
result[key] = item
return result


def read_notes(root, result):
"""Copy non-empty `notes` paragraphs; no executor reads them."""
notes = [text(v) for v in array(root.get('notes', []))]
Expand Down Expand Up @@ -79,7 +95,7 @@ def read_pose(value):

def read_step(value):
root = fields(value, ('id', 'kind', 'why', 'target', 'direction', 'legs', 'fight_wild',
'yes', 'may_lose', 'battles', 'items', 'variant', 'skip_if', 'declared_after',
'yes', 'may_lose', 'battles', 'items', 'variant', 'args', 'skip_if', 'declared_after',
'once_per_save', 'notes'))
result = dict(id=text(root['id']), kind=choice(root['kind'], KINDS))
if not result['id']:
Expand Down Expand Up @@ -115,6 +131,9 @@ def read_step(value):
items.append(dict(item=text(item['item']), quantity=integer(item['quantity'], 0, 9223372036854775807)))
if items:
result['items'] = items
args = read_args(root.get('args', {}))
if args:
result['args'] = args
skip = [text(v) for v in array(root.get('skip_if', []))]
if skip:
result['skip_if'] = skip
Expand Down
Loading