Spaces:
Running
Running
Update utils/block_relation_builder.py
Browse files- utils/block_relation_builder.py +46 -59
utils/block_relation_builder.py
CHANGED
@@ -277,7 +277,7 @@ all_block_definitions = {
|
|
277 |
"control_stop": {
|
278 |
"block_name": "stop [v]", "block_type": "Control", "block_shape": "Cap Block", "op_code": "control_stop",
|
279 |
"functionality": "Halts all scripts, only the current script, or other scripts within the same sprite. Its shape can dynamically change based on the selected option.",
|
280 |
-
"inputs": {}, "fields": {"STOP_OPTION": ["all", None]}, "shadow": False, "topLevel": True
|
281 |
},
|
282 |
"control_start_as_clone": {
|
283 |
"block_name": "When I Start as a Clone", "block_type": "Control", "block_shape": "Hat Block", "op_code": "control_start_as_clone",
|
@@ -1017,7 +1017,6 @@ def parse_reporter_or_value(text, parent_key, pick_key_func, all_generated_block
|
|
1017 |
# [ORDER NO: ]
|
1018 |
# Variable reporter: [score v] or (score) or just "score"
|
1019 |
m_var = re.fullmatch(r"\[([^\]]+)\s*v\]", text)
|
1020 |
-
|
1021 |
if m_var:
|
1022 |
var_name = m_var.group(1).strip()
|
1023 |
print("the reportor block variable: ",var_name)
|
@@ -1026,18 +1025,18 @@ def parse_reporter_or_value(text, parent_key, pick_key_func, all_generated_block
|
|
1026 |
|
1027 |
# [ORDER NO: ]
|
1028 |
m_paren_var = re.fullmatch(r"\(([^)]+)\)", text)
|
1029 |
-
m_cos
|
1030 |
if m_paren_var and not m_cos:
|
1031 |
-
|
1032 |
-
|
1033 |
-
|
1034 |
-
if
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
|
1039 |
return {"kind": "block", "block": block_id}
|
1040 |
-
|
1041 |
# [ORDER NO: ]
|
1042 |
# List reporter: [my list v]
|
1043 |
m_list_reporter = re.fullmatch(r"\[([^\]]+)\s*v\]", text.strip())
|
@@ -1618,7 +1617,7 @@ def parse_condition(stmt, parent_key, pick_key_func, all_generated_blocks):
|
|
1618 |
m_not = re.fullmatch(r"\s*(?:<\s*)?not\s+(.+?)(?:\s*>)?\s*", s_lower, re.IGNORECASE)
|
1619 |
if m_not:
|
1620 |
inner = m_not.group(1).strip()
|
1621 |
-
print("Boolean NOT",m_not)
|
1622 |
inner_obj = parse_condition(inner, parent_key, pick_key_func, all_generated_blocks)
|
1623 |
bid = _register_block("operator_not", parent_key, True, pick_key_func, all_generated_blocks,
|
1624 |
inputs={"OPERAND": inner_obj})
|
@@ -1714,13 +1713,7 @@ def parse_condition(stmt, parent_key, pick_key_func, all_generated_blocks):
|
|
1714 |
return {"kind": "block", "block": block_id}
|
1715 |
|
1716 |
# 5) Touching object: <touching [edge v]?>
|
1717 |
-
m_touch = re.fullmatch(r"""
|
1718 |
-
\s*<?\s* # optional leading '<'
|
1719 |
-
touching\s*\[\s* # 'touching ['
|
1720 |
-
(?P<sprite>[^\]]+?) # sprite name
|
1721 |
-
\s*(?:v)?\s*\] # optional 'v' and close ']'
|
1722 |
-
\s*\?\s*>? # literal '?' and optional '>'
|
1723 |
-
""", s_lower, re.IGNORECASE | re.VERBOSE)
|
1724 |
if m_touch:
|
1725 |
sprite = m_touch.group('sprite').strip()
|
1726 |
val = {'mouse-pointer':'_mouse_', 'edge':'_edge_'}.get(sprite, sprite)
|
@@ -1753,11 +1746,20 @@ def parse_condition(stmt, parent_key, pick_key_func, all_generated_blocks):
|
|
1753 |
return {"kind": "block", "block": block_id}
|
1754 |
|
1755 |
# 8) Key pressed: <key [key v] pressed?>
|
1756 |
-
m = re.search(r"key \[([^\]]+)\s*v\] pressed\?", s_lower)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1757 |
if m:
|
1758 |
option = m.group(1).strip()
|
1759 |
menu_block_id = _register_block("sensing_keyoptions", parent_key, True, pick_key_func, all_generated_blocks, fields={"KEY_OPTION": [option, None]})
|
1760 |
-
print("<key [
|
1761 |
inputs = {"KEY_OPTION": {"kind": "block", "block": menu_block_id}}
|
1762 |
block_id = _register_block("sensing_keypressed", parent_key, True, pick_key_func, all_generated_blocks, inputs=inputs)
|
1763 |
all_generated_blocks[menu_block_id]["parent"] = block_id
|
@@ -1785,7 +1787,7 @@ def classify(line):
|
|
1785 |
Order of checks matters: more specific patterns should come before more general ones.
|
1786 |
"""
|
1787 |
l = line.lower().strip()
|
1788 |
-
|
1789 |
# Ignore comments
|
1790 |
if l.startswith("//"): return None, None
|
1791 |
|
@@ -1960,7 +1962,7 @@ def generate_plan(generated_input, opcode_keys, pseudo_code):
|
|
1960 |
while i < len(lines):
|
1961 |
raw_line = lines[i]
|
1962 |
stripped_line = raw_line.strip()
|
1963 |
-
|
1964 |
# Skip empty lines and comments
|
1965 |
if not stripped_line or stripped_line.startswith("//"):
|
1966 |
i += 1
|
@@ -1993,6 +1995,7 @@ def generate_plan(generated_input, opcode_keys, pseudo_code):
|
|
1993 |
# Pop the current substack's scope
|
1994 |
popped_indent, popped_owner_key, popped_last_block_in_chain = stack.pop()
|
1995 |
if popped_last_block_in_chain:
|
|
|
1996 |
all_generated_blocks[popped_last_block_in_chain]["next"] = None
|
1997 |
|
1998 |
# If the popped scope had an owner (C-block or procedure definition),
|
@@ -2036,9 +2039,11 @@ def generate_plan(generated_input, opcode_keys, pseudo_code):
|
|
2036 |
current_scope_indent, current_owner_block_id, last_block_in_current_chain = stack[-1]
|
2037 |
|
2038 |
# Classify the statement and create the block
|
2039 |
-
stmt_for_parse = stripped_line.rstrip("then").strip()
|
|
|
|
|
2040 |
opcode, ntype = classify(stmt_for_parse)
|
2041 |
-
|
2042 |
if opcode is None: # Should not happen if classify is robust
|
2043 |
i += 1
|
2044 |
continue
|
@@ -2238,7 +2243,9 @@ def generate_plan(generated_input, opcode_keys, pseudo_code):
|
|
2238 |
if m_item: info["inputs"]["ITEM"] = {"kind": "value", "value": m_item.group(1).strip()}
|
2239 |
elif opcode == "event_whengreaterthan":
|
2240 |
#m = re.search(r">\s*\(\s*(-?\d+(\.\d+)?)\s*\)", stmt_for_parse, re.IGNORECASE)
|
2241 |
-
|
|
|
|
|
2242 |
#if m: info["inputs"]["VALUE"] = {"kind": "value", "value": float(m.group(1)) if '.' in m.group(1) else int(m.group(1))}
|
2243 |
if m: info["inputs"]["VALUE"] = parse_reporter_or_value(m.group(1).strip(), key, pick_key, all_generated_blocks)
|
2244 |
|
@@ -2341,6 +2348,7 @@ def generate_plan(generated_input, opcode_keys, pseudo_code):
|
|
2341 |
m = re.search(r"switch costume to\s*\[([^\]]+)\s*v\]", stmt_for_parse, re.IGNORECASE)
|
2342 |
if m:
|
2343 |
option = m.group(1).strip()
|
|
|
2344 |
menu_block_id = _register_block("looks_costume", key, True, pick_key, all_generated_blocks, fields={"COSTUME": [option, None]})
|
2345 |
info["inputs"]["COSTUME"] = {"kind": "block", "block": menu_block_id}
|
2346 |
elif opcode in ["looks_switchbackdropto", "looks_switchbackdroptowait"]:
|
@@ -3058,39 +3066,18 @@ def block_builder(opcode_count,pseudo_code):
|
|
3058 |
#################################################################################################################################################################
|
3059 |
|
3060 |
initial_opcode_counts = [
|
3061 |
-
|
3062 |
-
|
3063 |
-
|
3064 |
-
|
3065 |
-
|
3066 |
-
|
3067 |
-
|
3068 |
-
|
3069 |
-
|
3070 |
-
{"opcode":"operator_lt","count":1},
|
3071 |
-
{"opcode":"sensing_touchingobject","count":1},
|
3072 |
-
#{"opcode":"sensing_touchingobjectmenu","count":1},
|
3073 |
-
{"opcode":"event_broadcast","count":1},
|
3074 |
-
{"opcode":"data_setvariableto","count":2},
|
3075 |
-
{"opcode":"data_showvariable","count":2},
|
3076 |
-
]
|
3077 |
pseudo_code="""
|
3078 |
-
when
|
3079 |
-
|
3080 |
-
go to x: (pick random -240 to 240) y: (-135)
|
3081 |
-
set [score v] to (1)
|
3082 |
-
set [speed v] to (1)
|
3083 |
-
show variable [score v]
|
3084 |
-
show variable [speed v]
|
3085 |
-
forever
|
3086 |
-
if <((x position)) < (-235)> then
|
3087 |
-
change y by (x position)
|
3088 |
-
end
|
3089 |
-
if <touching [Sprite1 v]?> then
|
3090 |
-
broadcast [Game Over v]
|
3091 |
-
stop [all v]
|
3092 |
-
end
|
3093 |
-
end
|
3094 |
end
|
3095 |
"""
|
3096 |
# print(pseudo_code)
|
|
|
277 |
"control_stop": {
|
278 |
"block_name": "stop [v]", "block_type": "Control", "block_shape": "Cap Block", "op_code": "control_stop",
|
279 |
"functionality": "Halts all scripts, only the current script, or other scripts within the same sprite. Its shape can dynamically change based on the selected option.",
|
280 |
+
"inputs": {}, "fields": {"STOP_OPTION": ["all", None]}, "shadow": False, "topLevel": True, "mutation": {"tagName": "mutation", "children": [], "hasnext": "false"}
|
281 |
},
|
282 |
"control_start_as_clone": {
|
283 |
"block_name": "When I Start as a Clone", "block_type": "Control", "block_shape": "Hat Block", "op_code": "control_start_as_clone",
|
|
|
1017 |
# [ORDER NO: ]
|
1018 |
# Variable reporter: [score v] or (score) or just "score"
|
1019 |
m_var = re.fullmatch(r"\[([^\]]+)\s*v\]", text)
|
|
|
1020 |
if m_var:
|
1021 |
var_name = m_var.group(1).strip()
|
1022 |
print("the reportor block variable: ",var_name)
|
|
|
1025 |
|
1026 |
# [ORDER NO: ]
|
1027 |
m_paren_var = re.fullmatch(r"\(([^)]+)\)", text)
|
1028 |
+
m_cos = re.fullmatch(r"""\(\s*costume\s+(?:\(\s*(.+?)\s*\)|\[\s*([^\]]+?)\s*v\s*\])\s*\)""",text,re.IGNORECASE | re.VERBOSE)
|
1029 |
if m_paren_var and not m_cos:
|
1030 |
+
potential = m_paren_var.group(1).strip()
|
1031 |
+
# If it's literally “[name v]”, pull out just “name”
|
1032 |
+
m_bracket_var = re.fullmatch(r"\[\s*([^\]]+?)\s*v\s*\]", potential)
|
1033 |
+
if m_bracket_var: potential = m_bracket_var.group(1).strip()
|
1034 |
+
print("the potential_var_name variable:", potential)
|
1035 |
+
# Only create a data_variable if it’s not a reporter or a number or contains arithmetic
|
1036 |
+
if (potential not in simple_reporters and not re.fullmatch(r"-?\d+(\.\d+)?", potential) and not re.search(r"[+\-*/]", potential)):
|
1037 |
+
block_id = _register_block("data_variable",parent_key,True,pick_key_func,all_generated_blocks,fields={"VARIABLE": [potential, None]})
|
1038 |
return {"kind": "block", "block": block_id}
|
1039 |
+
|
1040 |
# [ORDER NO: ]
|
1041 |
# List reporter: [my list v]
|
1042 |
m_list_reporter = re.fullmatch(r"\[([^\]]+)\s*v\]", text.strip())
|
|
|
1617 |
m_not = re.fullmatch(r"\s*(?:<\s*)?not\s+(.+?)(?:\s*>)?\s*", s_lower, re.IGNORECASE)
|
1618 |
if m_not:
|
1619 |
inner = m_not.group(1).strip()
|
1620 |
+
print("Boolean NOT--->",m_not.group(1).strip())
|
1621 |
inner_obj = parse_condition(inner, parent_key, pick_key_func, all_generated_blocks)
|
1622 |
bid = _register_block("operator_not", parent_key, True, pick_key_func, all_generated_blocks,
|
1623 |
inputs={"OPERAND": inner_obj})
|
|
|
1713 |
return {"kind": "block", "block": block_id}
|
1714 |
|
1715 |
# 5) Touching object: <touching [edge v]?>
|
1716 |
+
m_touch = re.fullmatch(r"""\s*<?\s*touching\s*\[\s*(?P<sprite>[^\]]+?)\s*(?:v)?\s*\]\s*\?\s*>?""", s_lower, re.IGNORECASE | re.VERBOSE)
|
|
|
|
|
|
|
|
|
|
|
|
|
1717 |
if m_touch:
|
1718 |
sprite = m_touch.group('sprite').strip()
|
1719 |
val = {'mouse-pointer':'_mouse_', 'edge':'_edge_'}.get(sprite, sprite)
|
|
|
1746 |
return {"kind": "block", "block": block_id}
|
1747 |
|
1748 |
# 8) Key pressed: <key [key v] pressed?>
|
1749 |
+
# m = re.search(r"key \[([^\]]+)\s*v\] pressed\?", s_lower)
|
1750 |
+
# if m:
|
1751 |
+
# option = m.group(1).strip()
|
1752 |
+
# menu_block_id = _register_block("sensing_keyoptions", parent_key, True, pick_key_func, all_generated_blocks, fields={"KEY_OPTION": [option, None]})
|
1753 |
+
# print("<key [key v] pressed?> : ",option)
|
1754 |
+
# inputs = {"KEY_OPTION": {"kind": "block", "block": menu_block_id}}
|
1755 |
+
# block_id = _register_block("sensing_keypressed", parent_key, True, pick_key_func, all_generated_blocks, inputs=inputs)
|
1756 |
+
# all_generated_blocks[menu_block_id]["parent"] = block_id
|
1757 |
+
# return {"kind": "block", "block": block_id}
|
1758 |
+
m = re.search(r"(?:<)?(?:key\s*)?\[([^\]]+?)\s*v\](?:\s*key)?\s*pressed\?(?:>)?", s_lower, re.IGNORECASE)
|
1759 |
if m:
|
1760 |
option = m.group(1).strip()
|
1761 |
menu_block_id = _register_block("sensing_keyoptions", parent_key, True, pick_key_func, all_generated_blocks, fields={"KEY_OPTION": [option, None]})
|
1762 |
+
print("<key [...] pressed?> : ", option)
|
1763 |
inputs = {"KEY_OPTION": {"kind": "block", "block": menu_block_id}}
|
1764 |
block_id = _register_block("sensing_keypressed", parent_key, True, pick_key_func, all_generated_blocks, inputs=inputs)
|
1765 |
all_generated_blocks[menu_block_id]["parent"] = block_id
|
|
|
1787 |
Order of checks matters: more specific patterns should come before more general ones.
|
1788 |
"""
|
1789 |
l = line.lower().strip()
|
1790 |
+
print("the line is this:", l)
|
1791 |
# Ignore comments
|
1792 |
if l.startswith("//"): return None, None
|
1793 |
|
|
|
1962 |
while i < len(lines):
|
1963 |
raw_line = lines[i]
|
1964 |
stripped_line = raw_line.strip()
|
1965 |
+
print("Stripped line here -----1---->", stripped_line)
|
1966 |
# Skip empty lines and comments
|
1967 |
if not stripped_line or stripped_line.startswith("//"):
|
1968 |
i += 1
|
|
|
1995 |
# Pop the current substack's scope
|
1996 |
popped_indent, popped_owner_key, popped_last_block_in_chain = stack.pop()
|
1997 |
if popped_last_block_in_chain:
|
1998 |
+
print("popped_last_block_in_chain is executed here")
|
1999 |
all_generated_blocks[popped_last_block_in_chain]["next"] = None
|
2000 |
|
2001 |
# If the popped scope had an owner (C-block or procedure definition),
|
|
|
2039 |
current_scope_indent, current_owner_block_id, last_block_in_current_chain = stack[-1]
|
2040 |
|
2041 |
# Classify the statement and create the block
|
2042 |
+
#stmt_for_parse = stripped_line.rstrip("then").strip()
|
2043 |
+
stmt_for_parse = re.sub(r"\bthen\s*$", "", stripped_line, flags=re.IGNORECASE).strip()
|
2044 |
+
print("befor the classify hit here: ",stmt_for_parse)
|
2045 |
opcode, ntype = classify(stmt_for_parse)
|
2046 |
+
print("the opcode classify: ",opcode)
|
2047 |
if opcode is None: # Should not happen if classify is robust
|
2048 |
i += 1
|
2049 |
continue
|
|
|
2243 |
if m_item: info["inputs"]["ITEM"] = {"kind": "value", "value": m_item.group(1).strip()}
|
2244 |
elif opcode == "event_whengreaterthan":
|
2245 |
#m = re.search(r">\s*\(\s*(-?\d+(\.\d+)?)\s*\)", stmt_for_parse, re.IGNORECASE)
|
2246 |
+
print(stmt_for_parse)
|
2247 |
+
m = re.search(r">\s*(?:\(\s*(.*?)\s*\)|([^\s\)]+))", stmt_for_parse, re.IGNORECASE)
|
2248 |
+
print("event_whengreaterthan parse",m.group(1).strip())
|
2249 |
#if m: info["inputs"]["VALUE"] = {"kind": "value", "value": float(m.group(1)) if '.' in m.group(1) else int(m.group(1))}
|
2250 |
if m: info["inputs"]["VALUE"] = parse_reporter_or_value(m.group(1).strip(), key, pick_key, all_generated_blocks)
|
2251 |
|
|
|
2348 |
m = re.search(r"switch costume to\s*\[([^\]]+)\s*v\]", stmt_for_parse, re.IGNORECASE)
|
2349 |
if m:
|
2350 |
option = m.group(1).strip()
|
2351 |
+
print("option at looks_switchcostumeto: ",option)
|
2352 |
menu_block_id = _register_block("looks_costume", key, True, pick_key, all_generated_blocks, fields={"COSTUME": [option, None]})
|
2353 |
info["inputs"]["COSTUME"] = {"kind": "block", "block": menu_block_id}
|
2354 |
elif opcode in ["looks_switchbackdropto", "looks_switchbackdroptowait"]:
|
|
|
3066 |
#################################################################################################################################################################
|
3067 |
|
3068 |
initial_opcode_counts = [
|
3069 |
+
{
|
3070 |
+
"opcode": "event_whenbroadcastreceived",
|
3071 |
+
"count": 1
|
3072 |
+
},
|
3073 |
+
{
|
3074 |
+
"opcode": "looks_hide",
|
3075 |
+
"count": 1
|
3076 |
+
}
|
3077 |
+
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3078 |
pseudo_code="""
|
3079 |
+
when I receive [Game Over v]
|
3080 |
+
hide
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3081 |
end
|
3082 |
"""
|
3083 |
# print(pseudo_code)
|