Skip to content

Commit 7dad583

Browse files
committed
WIP convert_req_function_args
1 parent 71c328b commit 7dad583

File tree

1 file changed

+48
-1
lines changed

1 file changed

+48
-1
lines changed

src/Rules.py

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import re
1010
import math
11+
import inspect
1112

1213
if TYPE_CHECKING:
1314
from . import ManualWorld
@@ -93,7 +94,8 @@ def checkRequireStringForArea(state: CollectionState, area: dict):
9394

9495
if not callable(func):
9596
raise ValueError(f"Invalid function `{func_name}` in {area}.")
96-
97+
if func_args:
98+
convert_req_function_args(func, func_args, area["name"])
9799
result = func(world, multiworld, state, player, *func_args)
98100
if isinstance(result, bool):
99101
requires_list = requires_list.replace("{" + func_name + "(" + item[1] + ")}", "1" if result else "0")
@@ -271,6 +273,51 @@ def allRegionsAccessible(state):
271273
# Victory requirement
272274
multiworld.completion_condition[player] = lambda state: state.has("__Victory__", player)
273275

276+
def convert_req_function_args(func, args: list[str], areaName: str):
277+
parameters = inspect.signature(func).parameters
278+
knownArguments = ["world", "multiworld", "state", "player"]
279+
index = 0
280+
for parameter, info in parameters.items():
281+
if parameter in knownArguments:
282+
continue
283+
284+
argType = info.annotation
285+
try:
286+
value = args[index].strip().lower()
287+
288+
except IndexError:
289+
if info is not inspect.Parameter.empty:
290+
value = info.default
291+
292+
else:
293+
raise Exception(f"A call of the {func.__name__} function in '{areaName}'s requirement, asks for a value of type {argType}\nfor its argument '{info.name}' but its missing")
294+
295+
if not isinstance(value, argType):
296+
if issubclass(argType, bool):
297+
#Special conversion to bool
298+
if value in ['true', '1']:
299+
value = True
300+
301+
elif value in ['false', '0']:
302+
value = False
303+
304+
else:
305+
# warning here spam the console, might be worth to make it a data validation instead
306+
# logging.warn(f"A function in '{areaName}'s requirement, asks for a value of type {argType}\nfor its argument '{info.name}' but an unknown string was passed")
307+
value = bool(value)
308+
309+
else:
310+
try:
311+
value = argType(value)
312+
313+
except ValueError:
314+
raise Exception(f"A call of the {func.__name__} function in '{areaName}'s requirement, asks for a value of type {argType}\nfor its argument '{info.name}' but its value '{value}' cannot be converted to {argType}")
315+
316+
args[index] = value
317+
318+
index += 1
319+
320+
274321
def YamlEnabled(world: "ManualWorld", multiworld: MultiWorld, state: CollectionState, player: int, param: str) -> bool:
275322
"""Is a yaml option enabled?"""
276323
return is_option_enabled(multiworld, player, param)

0 commit comments

Comments
 (0)