Skip to content

Commit d9a0cdf

Browse files
committed
Revert changes to existing hook functions, they can be moved in a later PR
1 parent 27ece54 commit d9a0cdf

File tree

2 files changed

+102
-102
lines changed

2 files changed

+102
-102
lines changed

src/Rules.py

Lines changed: 0 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -271,107 +271,6 @@ def allRegionsAccessible(state):
271271
# Victory requirement
272272
multiworld.completion_condition[player] = lambda state: state.has("__Victory__", player)
273273

274-
def ItemValue(world: "ManualWorld", multiworld: MultiWorld, state: CollectionState, player: int, args: str):
275-
"""When passed a string with this format: 'valueName:int',
276-
this function will check if the player has collect at least 'int' valueName worth of items\n
277-
eg. {ItemValue(Coins:12)} will check if the player has collect at least 12 coins worth of items
278-
"""
279-
280-
args_list = args.split(":")
281-
if not len(args_list) == 2 or not args_list[1].isnumeric():
282-
raise Exception(f"ItemValue needs a number after : so it looks something like 'ItemValue({args_list[0]}:12)'")
283-
args_list[0] = args_list[0].lower().strip()
284-
args_list[1] = int(args_list[1].strip())
285-
286-
if not hasattr(world, 'item_values_cache'): #Cache made for optimization purposes
287-
world.item_values_cache = {}
288-
289-
if not world.item_values_cache.get(player, {}):
290-
world.item_values_cache[player] = {
291-
'state': {},
292-
'count': {},
293-
}
294-
295-
if (args_list[0] not in world.item_values_cache[player].get('count', {}).keys()
296-
or world.item_values_cache[player].get('state') != dict(state.prog_items[player])):
297-
#Run First Time or if state changed since last check
298-
existing_item_values = get_items_with_value(world, multiworld, args_list[0])
299-
total_Count = 0
300-
for name, value in existing_item_values.items():
301-
count = state.count(name, player)
302-
if count > 0:
303-
total_Count += count * value
304-
world.item_values_cache[player]['count'][args_list[0]] = total_Count
305-
world.item_values_cache[player]['state'] = dict(state.prog_items[player]) #save the current gotten items to check later if its the same
306-
return world.item_values_cache[player]['count'][args_list[0]] >= args_list[1]
307-
308-
309-
# Two useful functions to make require work if an item is disabled instead of making it inaccessible
310-
def OptOne(world: "ManualWorld", multiworld: MultiWorld, state: CollectionState, player: int, item: str, items_counts: Optional[dict] = None):
311-
"""Check if the passed item (with or without ||) is enabled, then this returns |item:count|
312-
where count is clamped to the maximum number of said item in the itempool.\n
313-
Eg. requires: "{OptOne(|DisabledItem|)} and |other items|" become "|DisabledItem:0| and |other items|" if the item is disabled.
314-
"""
315-
if item == "":
316-
return "" #Skip this function if item is left blank
317-
if not items_counts:
318-
items_counts = world.get_item_counts()
319-
320-
require_type = 'item'
321-
322-
if '@' in item[:2]:
323-
require_type = 'category'
324-
325-
item = item.lstrip('|@$').rstrip('|')
326-
327-
item_parts = item.split(":")
328-
item_name = item
329-
item_count = '1'
330-
331-
if len(item_parts) > 1:
332-
item_name = item_parts[0]
333-
item_count = item_parts[1]
334-
335-
if require_type == 'category':
336-
if item_count.isnumeric():
337-
#Only loop if we can use the result to clamp
338-
category_items = [item for item in world.item_name_to_item.values() if "category" in item and item_name in item["category"]]
339-
category_items_counts = sum([items_counts.get(category_item["name"], 0) for category_item in category_items])
340-
item_count = clamp(int(item_count), 0, category_items_counts)
341-
return f"|@{item_name}:{item_count}|"
342-
elif require_type == 'item':
343-
if item_count.isnumeric():
344-
item_current_count = items_counts.get(item_name, 0)
345-
item_count = clamp(int(item_count), 0, item_current_count)
346-
return f"|{item_name}:{item_count}|"
347-
348-
# OptAll check the passed require string and loop every item to check if they're enabled,
349-
def OptAll(world: "ManualWorld", multiworld: MultiWorld, state: CollectionState, player: int, requires: str):
350-
"""Check the passed require string and loop every item to check if they're enabled,
351-
then returns the require string with items counts adjusted using OptOne\n
352-
eg. requires: "{OptAll(|DisabledItem| and |@CategoryWithModifedCount:10|)} and |other items|"
353-
become "|DisabledItem:0| and |@CategoryWithModifedCount:2| and |other items|" """
354-
requires_list = requires
355-
356-
items_counts = world.get_item_counts()
357-
358-
functions = {}
359-
if requires_list == "":
360-
return True
361-
for item in re.findall(r'\{(\w+)\(([^)]*)\)\}', requires_list):
362-
#so this function doesn't try to get item from other functions, in theory.
363-
func_name = item[0]
364-
functions[func_name] = item[1]
365-
requires_list = requires_list.replace("{" + func_name + "(" + item[1] + ")}", "{" + func_name + "(temp)}")
366-
# parse user written statement into list of each item
367-
for item in re.findall(r'\|[^|]+\|', requires):
368-
itemScanned = OptOne(world, multiworld, state, player, item, items_counts)
369-
requires_list = requires_list.replace(item, itemScanned)
370-
371-
for function in functions:
372-
requires_list = requires_list.replace("{" + function + "(temp)}", "{" + func_name + "(" + functions[func_name] + ")}")
373-
return requires_list
374-
375274
def YamlEnabled(world: "ManualWorld", multiworld: MultiWorld, state: CollectionState, player: int, param: str) -> bool:
376275
"""Is a yaml option enabled?"""
377276
return is_option_enabled(multiworld, player, param)

src/hooks/Rules.py

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import Optional
22
from worlds.AutoWorld import World
3-
from ..Helpers import clamp, get_items_with_value, is_option_enabled
3+
from ..Helpers import clamp, get_items_with_value
44
from BaseClasses import MultiWorld, CollectionState
55

66
import re
@@ -27,3 +27,104 @@ def anyClassLevel(world: World, multiworld: MultiWorld, state: CollectionState,
2727
def requiresMelee(world: World, multiworld: MultiWorld, state: CollectionState, player: int):
2828
"""Returns a requires string that checks if the player has unlocked the tank."""
2929
return "|Figher Level:15| or |Black Belt Level:15| or |Thief Level:15|"
30+
31+
def ItemValue(world: World, multiworld: MultiWorld, state: CollectionState, player: int, args: str):
32+
"""When passed a string with this format: 'valueName:int',
33+
this function will check if the player has collect at least 'int' valueName worth of items\n
34+
eg. {ItemValue(Coins:12)} will check if the player has collect at least 12 coins worth of items
35+
"""
36+
37+
args_list = args.split(":")
38+
if not len(args_list) == 2 or not args_list[1].isnumeric():
39+
raise Exception(f"ItemValue needs a number after : so it looks something like 'ItemValue({args_list[0]}:12)'")
40+
args_list[0] = args_list[0].lower().strip()
41+
args_list[1] = int(args_list[1].strip())
42+
43+
if not hasattr(world, 'item_values_cache'): #Cache made for optimization purposes
44+
world.item_values_cache = {}
45+
46+
if not world.item_values_cache.get(player, {}):
47+
world.item_values_cache[player] = {
48+
'state': {},
49+
'count': {},
50+
}
51+
52+
if (args_list[0] not in world.item_values_cache[player].get('count', {}).keys()
53+
or world.item_values_cache[player].get('state') != dict(state.prog_items[player])):
54+
#Run First Time or if state changed since last check
55+
existing_item_values = get_items_with_value(world, multiworld, args_list[0])
56+
total_Count = 0
57+
for name, value in existing_item_values.items():
58+
count = state.count(name, player)
59+
if count > 0:
60+
total_Count += count * value
61+
world.item_values_cache[player]['count'][args_list[0]] = total_Count
62+
world.item_values_cache[player]['state'] = dict(state.prog_items[player]) #save the current gotten items to check later if its the same
63+
return world.item_values_cache[player]['count'][args_list[0]] >= args_list[1]
64+
65+
66+
# Two useful functions to make require work if an item is disabled instead of making it inaccessible
67+
def OptOne(world: World, multiworld: MultiWorld, state: CollectionState, player: int, item: str, items_counts: Optional[dict] = None):
68+
"""Check if the passed item (with or without ||) is enabled, then this returns |item:count|
69+
where count is clamped to the maximum number of said item in the itempool.\n
70+
Eg. requires: "{OptOne(|DisabledItem|)} and |other items|" become "|DisabledItem:0| and |other items|" if the item is disabled.
71+
"""
72+
if item == "":
73+
return "" #Skip this function if item is left blank
74+
if not items_counts:
75+
items_counts = world.get_item_counts()
76+
77+
require_type = 'item'
78+
79+
if '@' in item[:2]:
80+
require_type = 'category'
81+
82+
item = item.lstrip('|@$').rstrip('|')
83+
84+
item_parts = item.split(":")
85+
item_name = item
86+
item_count = '1'
87+
88+
if len(item_parts) > 1:
89+
item_name = item_parts[0]
90+
item_count = item_parts[1]
91+
92+
if require_type == 'category':
93+
if item_count.isnumeric():
94+
#Only loop if we can use the result to clamp
95+
category_items = [item for item in world.item_name_to_item.values() if "category" in item and item_name in item["category"]]
96+
category_items_counts = sum([items_counts.get(category_item["name"], 0) for category_item in category_items])
97+
item_count = clamp(int(item_count), 0, category_items_counts)
98+
return f"|@{item_name}:{item_count}|"
99+
elif require_type == 'item':
100+
if item_count.isnumeric():
101+
item_current_count = items_counts.get(item_name, 0)
102+
item_count = clamp(int(item_count), 0, item_current_count)
103+
return f"|{item_name}:{item_count}|"
104+
105+
# OptAll check the passed require string and loop every item to check if they're enabled,
106+
def OptAll(world: World, multiworld: MultiWorld, state: CollectionState, player: int, requires: str):
107+
"""Check the passed require string and loop every item to check if they're enabled,
108+
then returns the require string with items counts adjusted using OptOne\n
109+
eg. requires: "{OptAll(|DisabledItem| and |@CategoryWithModifedCount:10|)} and |other items|"
110+
become "|DisabledItem:0| and |@CategoryWithModifedCount:2| and |other items|" """
111+
requires_list = requires
112+
113+
items_counts = world.get_item_counts()
114+
115+
functions = {}
116+
if requires_list == "":
117+
return True
118+
for item in re.findall(r'\{(\w+)\(([^)]*)\)\}', requires_list):
119+
#so this function doesn't try to get item from other functions, in theory.
120+
func_name = item[0]
121+
functions[func_name] = item[1]
122+
requires_list = requires_list.replace("{" + func_name + "(" + item[1] + ")}", "{" + func_name + "(temp)}")
123+
# parse user written statement into list of each item
124+
for item in re.findall(r'\|[^|]+\|', requires):
125+
itemScanned = OptOne(world, multiworld, state, player, item, items_counts)
126+
requires_list = requires_list.replace(item, itemScanned)
127+
128+
for function in functions:
129+
requires_list = requires_list.replace("{" + function + "(temp)}", "{" + func_name + "(" + functions[func_name] + ")}")
130+
return requires_list

0 commit comments

Comments
 (0)