scratch_agent / utils /block_function.py
WebashalarForML's picture
Upload 24 files
3d3703f verified
import json
import copy
import re
def generate_blocks_from_opcodes(opcode_counts, all_block_definitions):
"""
Generates a dictionary of Scratch-like blocks based on a list of opcodes and a reference block definition.
It now correctly links parent and menu blocks using their generated unique keys, and handles various block categories.
It ensures that menu blocks are only generated as children of their respective parent blocks.
Args:
opcode_counts (list): An array of objects, each with an 'opcode' and 'count' property.
Example: [{"opcode": "motion_gotoxy", "count": 1}]
all_block_definitions (dict): A comprehensive dictionary containing definitions for all block types.
Returns:
tuple: A tuple containing:
- dict: A JSON object where keys are generated block IDs and values are the block definitions.
- dict: The opcode_occurrences dictionary for consistent unique key generation across functions.
"""
generated_blocks = {}
opcode_occurrences = {} # To keep track of how many times each opcode (main or menu) has been used for unique keys
# Define explicit parent-menu relationships for linking purposes
# This maps main_opcode -> list of (input_field_name, menu_opcode)
explicit_menu_links = {
"motion_goto": [("TO", "motion_goto_menu")],
"motion_glideto": [("TO", "motion_glideto_menu")],
"motion_pointtowards": [("TOWARDS", "motion_pointtowards_menu")],
"sensing_keypressed": [("KEY_OPTION", "sensing_keyoptions")],
"sensing_of": [("OBJECT", "sensing_of_object_menu")],
"sensing_touchingobject": [("TOUCHINGOBJECTMENU", "sensing_touchingobjectmenu")],
"control_create_clone_of": [("CLONE_OPTION", "control_create_clone_of_menu")],
"sound_play": [("SOUND_MENU", "sound_sounds_menu")],
"sound_playuntildone": [("SOUND_MENU", "sound_sounds_menu")],
"looks_switchcostumeto": [("COSTUME", "looks_costume")],
"looks_switchbackdropto": [("BACKDROP", "looks_backdrops")],
}
# --- Step 1: Process explicitly requested opcodes and generate their instances and associated menus ---
for item in opcode_counts:
opcode = item.get("opcode")
count = item.get("count", 1)
if not opcode:
print("Warning: Skipping item with missing 'opcode'.")
continue
if opcode not in all_block_definitions:
print(f"Warning: Opcode '{opcode}' not found in all_block_definitions. Skipping.")
continue
for _ in range(count):
# Increment occurrence count for the current main opcode
opcode_occurrences[opcode] = opcode_occurrences.get(opcode, 0) + 1
main_block_instance_num = opcode_occurrences[opcode]
main_block_unique_key = f"{opcode}_{main_block_instance_num}"
# Create a deep copy of the main block definition
main_block_data = copy.deepcopy(all_block_definitions[opcode])
# Set properties for a top-level main block
main_block_data["parent"] = None
main_block_data["next"] = None
main_block_data["topLevel"] = True
main_block_data["shadow"] = False # Main blocks are typically not shadows
generated_blocks[main_block_unique_key] = main_block_data
# If this main block has associated menus, generate and link them now
if opcode in explicit_menu_links:
for input_field_name, menu_opcode_type in explicit_menu_links[opcode]:
if menu_opcode_type in all_block_definitions:
# Increment the occurrence for the menu block type
opcode_occurrences[menu_opcode_type] = opcode_occurrences.get(menu_opcode_type, 0) + 1
menu_block_instance_num = opcode_occurrences[menu_opcode_type]
menu_block_data = copy.deepcopy(all_block_definitions[menu_opcode_type])
# Generate a unique key for this specific menu instance
menu_unique_key = f"{menu_opcode_type}_{menu_block_instance_num}"
# Set properties for a shadow menu block
menu_block_data["shadow"] = True
menu_block_data["topLevel"] = False
menu_block_data["next"] = None
menu_block_data["parent"] = main_block_unique_key # Link menu to its parent instance
# Update the main block's input to point to this unique menu instance
if input_field_name in main_block_data.get("inputs", {}) and \
isinstance(main_block_data["inputs"][input_field_name], list) and \
len(main_block_data["inputs"][input_field_name]) > 1 and \
main_block_data["inputs"][input_field_name][0] == 1:
main_block_data["inputs"][input_field_name][1] = menu_unique_key
generated_blocks[menu_unique_key] = menu_block_data
return generated_blocks, opcode_occurrences
def interpret_pseudo_code_and_update_blocks(generated_blocks_json, pseudo_code, all_block_definitions, opcode_occurrences):
"""
Interprets pseudo-code to update the generated Scratch blocks, replacing static values
with dynamic values and establishing stacking/nesting logic.
Args:
generated_blocks_json (dict): The JSON object of pre-generated blocks.
pseudo_code (str): The pseudo-code string to interpret.
all_block_definitions (dict): A comprehensive dictionary containing definitions for all block types.
opcode_occurrences (dict): A dictionary to keep track of opcode occurrences for unique key generation.
Returns:
dict: The updated JSON object of Scratch blocks.
"""
updated_blocks = copy.deepcopy(generated_blocks_json)
# Helper to find a block by opcode and optionally by a unique part of its key
def find_block_by_opcode(opcode_to_find, instance_num=None, parent_key=None):
for key, block in updated_blocks.items():
if block["opcode"] == opcode_to_find:
if instance_num is not None:
# Check if the key ends with the instance number
if key.endswith(f"_{instance_num}"):
return key, block
elif parent_key is not None:
# For menu blocks, check if their parent matches
if block.get("shadow") and block.get("parent") == parent_key:
return key, block
else:
# Return the first one found if no specific instance is needed
return key, block
return None, None
# Helper to get a unique key for a new block if needed
def get_unique_key(opcode_prefix):
count = 1
while f"{opcode_prefix}_{count}" in updated_blocks:
count += 1
return f"{opcode_prefix}_{count}"
lines = [line.strip() for line in pseudo_code.strip().split('\n') if line.strip()]
# Track the current script and nesting
current_script_head = None
current_parent_stack = [] # Stores (parent_block_key, indent_level, last_child_key)
indent_level = 0
# Create a mapping from block name patterns to their opcodes and input details
# Prioritize more specific patterns first
pseudo_code_to_opcode_map = {
re.compile(r"when green flag clicked"): {"opcode": "event_whenflagclicked"},
re.compile(r"go to x: \((.+?)\) y: \((.+?)\)"): {"opcode": "motion_gotoxy", "input_names": ["X", "Y"]},
re.compile(r"set \[(.+?) v\] to (.+)"): {"opcode": "data_setvariableto", "field_name": "VARIABLE", "input_name": "VALUE"},
re.compile(r"change \[(.+?) v\] by \((.+)\)"): {"opcode": "data_changevariableby", "field_name": "VARIABLE", "input_name": "VALUE"},
re.compile(r"show variable \[(.+?) v\]"): {"opcode": "data_showvariable", "field_name": "VARIABLE"},
re.compile(r"hide variable \[(.+?) v\]"): {"opcode": "data_hidevariable", "field_name": "VARIABLE"},
re.compile(r"forever"): {"opcode": "control_forever"},
re.compile(r"glide \((.+?)\) seconds to x: \((.+?)\) y: \((.+?)\)"): {"opcode": "motion_glidesecstoxy", "input_names": ["SECS", "X", "Y"]},
re.compile(r"if <\((.+)\) < \((.+)\)> then"): {"opcode": "control_if", "input_names": ["OPERAND1", "OPERAND2"], "condition_opcode": "operator_lt"},
re.compile(r"if <touching \[(.+?) v\]\?> then"): {"opcode": "control_if", "input_name": "TOUCHINGOBJECTMENU", "condition_opcode": "sensing_touchingobject"},
re.compile(r"set x to \((.+?)\)"): {"opcode": "motion_setx", "input_name": "X"},
re.compile(r"broadcast \[(.+?) v\]"): {"opcode": "event_broadcast", "input_name": "BROADCAST_INPUT"},
re.compile(r"stop \[(.+?) v\]"): {"opcode": "control_stop", "field_name": "STOP_OPTION"},
re.compile(r"end"): {"opcode": "end_block"}, # Special marker for script end/C-block end
}
# Create a reverse lookup for reporter block opcodes based on their pseudo-code representation
reporter_opcode_lookup = {}
for opcode, definition in all_block_definitions.items():
if definition.get("block_shape") == "Reporter Block":
block_name = definition.get("block_name")
if block_name:
# Remove parentheses for matching
clean_name = block_name.replace("(", "").replace(")", "").strip()
reporter_opcode_lookup[clean_name] = opcode
# Handle cases like "x position" vs "(x position)"
if clean_name not in reporter_opcode_lookup:
reporter_opcode_lookup[clean_name] = opcode
# Function to create a new block instance
def create_block_instance(opcode, opcode_occurrences, parent_key=None, is_shadow=False, is_top_level=False):
# Ensure unique key generation is consistent
opcode_occurrences[opcode] = opcode_occurrences.get(opcode, 0) + 1
unique_key = f"{opcode}_{opcode_occurrences[opcode]}"
new_block = copy.deepcopy(all_block_definitions.get(opcode, {}))
if not new_block:
print(f"Error: Definition for opcode '{opcode}' not found.")
return None, None
new_block["parent"] = parent_key
new_block["next"] = None # Will be set by stacking logic
new_block["topLevel"] = is_top_level
new_block["shadow"] = is_shadow
# Clear inputs/fields to be populated by pseudo-code parsing
if "inputs" in new_block:
new_block["inputs"] = {k: copy.deepcopy(v) for k, v in new_block["inputs"].items()} # Deep copy inputs
for input_name in new_block["inputs"]:
if isinstance(new_block["inputs"][input_name], list) and len(new_block["inputs"][input_name]) > 1:
# Reset input value, keep type 1 for block reference or type 4/10 for literal
if new_block["inputs"][input_name][0] == 1:
new_block["inputs"][input_name][1] = None # Placeholder for linked block ID
else:
new_block["inputs"][input_name][1] = ["", ""] # Default empty value
if "fields" in new_block:
new_block["fields"] = {k: copy.deepcopy(v) for k, v in new_block["fields"].items()} # Deep copy fields
for field_name in new_block["fields"]:
if isinstance(new_block["fields"][field_name], list) and len(new_block["fields"][field_name]) > 0:
new_block["fields"][field_name][0] = "" # Reset field value
updated_blocks[unique_key] = new_block
return unique_key, new_block
# Helper to parse input values
def parse_input_value(value_str):
value_str = value_str.strip()
# Handle numeric values (including those with + or - prefix)
if re.fullmatch(r"[-+]?\d+(\.\d+)?", value_str):
return [4, value_str] # Type 4 for number
# Handle string literals (e.g., "Hello!")
if value_str.startswith('"') and value_str.endswith('"'):
return [10, value_str.strip('"')] # Type 10 for string
# Handle variable/list names (e.g., [score v], [my list v])
if value_str.startswith('[') and value_str.endswith(']'):
var_name = value_str[1:-1].replace(' v', '').strip()
# For inputs that expect a variable, we might need a data_variable block
# For now, if it's a variable reference in an input, we'll return its name.
# The calling context (e.g., set variable's field vs. an input) will determine type.
return [12, var_name] # Custom type 12 for variable name, to be resolved later
# Handle nested reporter blocks (e.g., (x position))
if value_str.startswith('(') and value_str.endswith(')'):
inner_content = value_str[1:-1].strip()
# Check if it's a known reporter block
if inner_content in reporter_opcode_lookup:
return [3, reporter_opcode_lookup[inner_content]] # Type 3 for reporter block reference
# If not a known reporter, treat as a number or string
if re.fullmatch(r"[-+]?\d+(\.\d+)?", inner_content):
return [4, inner_content]
return [10, inner_content] # Default to string if not found in reporters
# Handle boolean conditions (e.g., <(x position) < (-235)>) - these are usually handled by parent regex
if value_str.startswith('<') and value_str.endswith('>'):
inner_condition = value_str[1:-1].strip()
# This is typically handled by the regex that matched the 'if' block itself.
# If this is called for a standalone boolean, it would be a reporter.
for op, def_ in all_block_definitions.items():
if def_.get("block_shape") == "Boolean Block" and def_.get("block_name") and \
def_["block_name"].replace("<", "").replace(">", "").strip() == inner_condition:
return [2, op] # Type 2 for boolean block reference
return [10, inner_condition] # Default to string if not found
return [10, value_str] # Default to string literal
# Main parsing loop
block_stack = [] # (block_key, indent_level, last_child_key_in_scope) for tracking nesting
for line_idx, raw_line in enumerate(lines):
current_line_indent = len(raw_line) - len(raw_line.lstrip())
line = raw_line.strip()
# Adjust block_stack based on current indent level
while block_stack and current_line_indent <= block_stack[-1][1]:
block_stack.pop()
matched_block_info = None
matched_values = None
# Try to match the line against known block patterns
for pattern_regex, info in pseudo_code_to_opcode_map.items():
match = pattern_regex.match(line)
if match:
matched_block_info = info
matched_values = match.groups()
break
if not matched_block_info:
print(f"Warning: Could not interpret line: '{line}'")
continue
opcode = matched_block_info["opcode"]
# Handle 'end' block separately as it signifies closing a C-block
if opcode == "end_block":
if block_stack:
block_stack.pop() # Pop the C-block parent
continue
parent_key = None
if block_stack:
parent_key = block_stack[-1][0] # The last block on the stack is the parent
# Create the new block instance
new_block_key, new_block_data = create_block_instance(
opcode,
opcode_occurrences,
parent_key=parent_key,
is_top_level=(parent_key is None)
)
if not new_block_key:
continue
# Link to previous block in the same script/nesting level
if block_stack:
# Update the 'next' of the previous block in the current scope
last_child_key_in_scope = block_stack[-1][2] if len(block_stack[-1]) > 2 else None
if last_child_key_in_scope and last_child_key_in_scope in updated_blocks:
updated_blocks[last_child_key_in_scope]["next"] = new_block_key
# Update the last child in the current scope
block_stack[-1] = (block_stack[-1][0], block_stack[-1][1], new_block_key)
# Populate inputs and fields
if matched_values:
# Handle specific block types with their inputs/fields
if opcode == "motion_gotoxy":
x_val = parse_input_value(matched_values[0])
y_val = parse_input_value(matched_values[1])
new_block_data["inputs"]["X"][1] = x_val[1]
new_block_data["inputs"]["Y"][1] = y_val[1]
new_block_data["inputs"]["X"][0] = x_val[0]
new_block_data["inputs"]["Y"][0] = y_val[0]
elif opcode == "data_setvariableto":
var_name = matched_values[0].replace(' v', '').strip()
value_parsed = parse_input_value(matched_values[1])
new_block_data["fields"]["VARIABLE"][0] = var_name
# Assuming variable ID is generated elsewhere or can be looked up
new_block_data["fields"]["VARIABLE"][1] = f"`var_{var_name}" # Placeholder for variable ID
new_block_data["inputs"]["VALUE"][0] = value_parsed[0]
new_block_data["inputs"]["VALUE"][1] = value_parsed[1]
elif opcode == "data_showvariable":
var_name = matched_values[0].replace(' v', '').strip()
new_block_data["fields"]["VARIABLE"][0] = var_name
new_block_data["fields"]["VARIABLE"][1] = f"`var_{var_name}" # Placeholder for variable ID
elif opcode == "motion_glidesecstoxy":
secs_val = parse_input_value(matched_values[0])
x_val = parse_input_value(matched_values[1])
y_val = parse_input_value(matched_values[2])
new_block_data["inputs"]["SECS"][1] = secs_val[1]
new_block_data["inputs"]["X"][1] = x_val[1]
new_block_data["inputs"]["Y"][1] = y_val[1]
new_block_data["inputs"]["SECS"][0] = secs_val[0]
new_block_data["inputs"]["X"][0] = x_val[0]
new_block_data["inputs"]["Y"][0] = y_val[0]
elif opcode == "motion_setx":
x_val = parse_input_value(matched_values[0])
new_block_data["inputs"]["X"][1] = x_val[1]
new_block_data["inputs"]["X"][0] = x_val[0]
elif opcode == "control_if":
condition_opcode = matched_block_info["condition_opcode"]
if condition_opcode == "operator_lt":
op1_str = matched_values[0].strip()
op2_str = matched_values[1].strip()
op1_parsed = parse_input_value(op1_str)
op2_parsed = parse_input_value(op2_str)
# Create operator_lt block as a shadow input for the IF condition
lt_block_key, lt_block_data = create_block_instance(
"operator_lt",
opcode_occurrences,
parent_key=new_block_key,
is_shadow=True,
is_top_level=False
)
if lt_block_key:
new_block_data["inputs"]["CONDITION"][1] = lt_block_key
new_block_data["inputs"]["CONDITION"][0] = 2 # Type 2 for boolean block reference
# Populate operator_lt inputs
if op1_parsed[0] == 3: # If it's a reporter block
op1_reporter_key, op1_reporter_data = create_block_instance(
op1_parsed[1], # Opcode of the reporter
opcode_occurrences,
parent_key=lt_block_key,
is_shadow=True,
is_top_level=False
)
if op1_reporter_key:
lt_block_data["inputs"]["OPERAND1"][1] = op1_reporter_key
lt_block_data["inputs"]["OPERAND1"][0] = 3
else: # Literal value
lt_block_data["inputs"]["OPERAND1"][1] = op1_parsed[1]
lt_block_data["inputs"]["OPERAND1"][0] = op1_parsed[0]
lt_block_data["inputs"]["OPERAND2"][1] = op2_parsed[1]
lt_block_data["inputs"]["OPERAND2"][0] = op2_parsed[0]
elif condition_opcode == "sensing_touchingobject":
sprite_name = matched_values[0].replace(' v', '').strip()
touching_opcode = "sensing_touchingobject"
touching_block_key, touching_block_data = create_block_instance(
touching_opcode,
opcode_occurrences,
parent_key=new_block_key,
is_shadow=True,
is_top_level=False
)
if touching_block_key:
new_block_data["inputs"]["CONDITION"][1] = touching_block_key
new_block_data["inputs"]["CONDITION"][0] = 2 # Type 2 for boolean block reference
# Create the menu block for TOUCHINGOBJECTMENU
menu_opcode = "sensing_touchingobjectmenu"
menu_key, menu_data = create_block_instance(
menu_opcode,
opcode_occurrences,
parent_key=touching_block_key,
is_shadow=True,
is_top_level=False
)
if menu_key:
touching_block_data["inputs"]["TOUCHINGOBJECTMENU"][1] = menu_key
touching_block_data["inputs"]["TOUCHINGOBJECTMENU"][0] = 1 # Type 1 for block reference
menu_data["fields"]["TOUCHINGOBJECTMENU"][0] = sprite_name
else:
print(f"Warning: Could not create touching object block for condition: '{line}'")
elif opcode == "control_forever":
# Forever blocks are C-blocks, so push them onto the stack
block_stack.append((new_block_key, current_line_indent, None)) # (parent_key, indent, last_child_key)
elif opcode == "control_stop":
option = matched_values[0].replace(' v', '').strip()
new_block_data["fields"]["STOP_OPTION"][0] = option
elif opcode == "event_broadcast":
message = matched_values[0].replace(' v', '').strip()
# For broadcast, the input is usually a string literal or a variable
new_block_data["inputs"]["BROADCAST_INPUT"][0] = 11 # Type 11 for broadcast input (string or variable)
new_block_data["inputs"]["BROADCAST_INPUT"][1] = [10, message] # Assume string literal for now
# A more robust solution would create a data_variable block if it's a variable.
# For C-blocks, push onto stack to track nesting
if all_block_definitions[opcode].get("block_shape") == "C-Block" and opcode != "control_if": # if is handled above
block_stack.append((new_block_key, current_line_indent, None)) # (parent_key, indent, last_child_key)
return updated_blocks
# --- Consolidated Block Definitions from all provided JSONs ---
all_block_definitions = {
# motion_block.json
"motion_movesteps": {
"opcode": "motion_movesteps", "next": None, "parent": None,
"inputs": {"STEPS": [1, [4, "10"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 464, "y": -416
},
"motion_turnright": {
"opcode": "motion_turnright", "next": None, "parent": None,
"inputs": {"DEGREES": [1, [4, "15"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 467, "y": -316
},
"motion_turnleft": {
"opcode": "motion_turnleft", "next": None, "parent": None,
"inputs": {"DEGREES": [1, [4, "15"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 464, "y": -210
},
"motion_goto": {
"opcode": "motion_goto", "next": None, "parent": None,
"inputs": {"TO": [1, "motion_goto_menu"]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 465, "y": -95
},
"motion_goto_menu": {
"opcode": "motion_goto_menu", "next": None, "parent": "motion_goto",
"inputs": {}, "fields": {"TO": ["_random_", None]}, "shadow": True, "topLevel": False
},
"motion_gotoxy": {
"opcode": "motion_gotoxy", "next": None, "parent": None,
"inputs": {"X": [1, [4, "0"]], "Y": [1, [4, "0"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 468, "y": 12
},
"motion_glideto": {
"opcode": "motion_glideto", "next": None, "parent": None,
"inputs": {"SECS": [1, [4, "1"]], "TO": [1, "motion_glideto_menu"]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 470, "y": 129
},
"motion_glideto_menu": {
"opcode": "motion_glideto_menu", "next": None, "parent": "motion_glideto",
"inputs": {}, "fields": {"TO": ["_random_", None]}, "shadow": True, "topLevel": False
},
"motion_glidesecstoxy": {
"opcode": "motion_glidesecstoxy", "next": None, "parent": None,
"inputs": {"SECS": [1, [4, "1"]], "X": [1, [4, "0"]], "Y": [1, [4, "0"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 476, "y": 239
},
"motion_pointindirection": {
"opcode": "motion_pointindirection", "next": None, "parent": None,
"inputs": {"DIRECTION": [1, [8, "90"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 493, "y": 361
},
"motion_pointtowards": {
"opcode": "motion_pointtowards", "next": None, "parent": None,
"inputs": {"TOWARDS": [1, "motion_pointtowards_menu"]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 492, "y": 463
},
"motion_pointtowards_menu": {
"opcode": "motion_pointtowards_menu", "next": None, "parent": "motion_pointtowards",
"inputs": {}, "fields": {"TOWARDS": ["_mouse_", None]}, "shadow": True, "topLevel": False
},
"motion_changexby": {
"opcode": "motion_changexby", "next": None, "parent": None,
"inputs": {"DX": [1, [4, "10"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 851, "y": -409
},
"motion_setx": {
"opcode": "motion_setx", "next": None, "parent": None,
"inputs": {"X": [1, [4, "0"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 864, "y": -194
},
"motion_changeyby": {
"opcode": "motion_changeyby", "next": None, "parent": None,
"inputs": {"DY": [1, [4, "10"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 861, "y": -61
},
"motion_sety": {
"opcode": "motion_sety", "next": None, "parent": None,
"inputs": {"Y": [1, [4, "0"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 864, "y": 66
},
"motion_ifonedgebounce": {
"opcode": "motion_ifonedgebounce", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 1131, "y": -397
},
"motion_setrotationstyle": {
"opcode": "motion_setrotationstyle", "next": None, "parent": None,
"inputs": {}, "fields": {"STYLE": ["left-right", None]}, "shadow": False, "topLevel": True,
"x": 1128, "y": -287
},
"motion_xposition": {
"opcode": "motion_xposition", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 1193, "y": -136
},
"motion_yposition": {
"opcode": "motion_yposition", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 1181, "y": -64
},
"motion_direction": {
"opcode": "motion_direction", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 1188, "y": 21
},
# control_block.json
"control_wait": {
"opcode": "control_wait", "next": None, "parent": None,
"inputs": {"DURATION": [1, [5, "1"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 337, "y": 129
},
"control_repeat": {
"opcode": "control_repeat", "next": None, "parent": None,
"inputs": {"TIMES": [1, [6, "10"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 348, "y": 265
},
"control_forever": {
"opcode": "control_forever", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 334, "y": 439
},
"control_if": {
"opcode": "control_if", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 331, "y": 597
},
"control_if_else": {
"opcode": "control_if_else", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 335, "y": 779
},
"control_wait_until": {
"opcode": "control_wait_until", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 676, "y": 285
},
"control_repeat_until": {
"opcode": "control_repeat_until", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 692, "y": 381
},
"control_stop": {
"opcode": "control_stop", "next": None, "parent": None,
"inputs": {}, "fields": {"STOP_OPTION": ["all", None]}, "shadow": False, "topLevel": True,
"x": 708, "y": 545, "mutation": {"tagName": "mutation", "children": [], "hasnext": "false"}
},
"control_start_as_clone": {
"opcode": "control_start_as_clone", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 665, "y": 672
},
"control_create_clone_of": {
"opcode": "control_create_clone_of", "next": None, "parent": None,
"inputs": {"CLONE_OPTION": [1, "control_create_clone_of_menu"]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 648, "y": 797
},
"control_create_clone_of_menu": {
"opcode": "control_create_clone_of_menu", "next": None, "parent": "control_create_clone_of",
"inputs": {}, "fields": {"CLONE_OPTION": ["_myself_", None]}, "shadow": True, "topLevel": False
},
"control_delete_this_clone": {
"opcode": "control_delete_this_clone", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 642, "y": 914
},
# data_block.json
"data_setvariableto": {
"opcode": "data_setvariableto", "next": None, "parent": None,
"inputs": {"VALUE": [1, [10, "0"]]}, "fields": {"VARIABLE": ["my variable", "`jEk@4|i[#Fk?(8x)AV.-my variable"]}, "shadow": False, "topLevel": True,
"x": 348, "y": 241
},
"data_changevariableby": {
"opcode": "data_changevariableby", "next": None, "parent": None,
"inputs": {"VALUE": [1, [4, "1"]]}, "fields": {"VARIABLE": ["my variable", "`jEk@4|i[#Fk?(8x)AV.-my variable"]}, "shadow": False, "topLevel": True,
"x": 313, "y": 363
},
"data_showvariable": {
"opcode": "data_showvariable", "next": None, "parent": None,
"inputs": {}, "fields": {"VARIABLE": ["my variable", "`jEk@4|i[#Fk?(8x)AV.-my variable"]}, "shadow": False, "topLevel": True,
"x": 415, "y": 473
},
"data_hidevariable": {
"opcode": "data_hidevariable", "next": None, "parent": None,
"inputs": {}, "fields": {"VARIABLE": ["my variable", "`jEk@4|i[#Fk?(8x)AV.-my variable"]}, "shadow": False, "topLevel": True,
"x": 319, "y": 587
},
"data_addtolist": {
"opcode": "data_addtolist", "next": None, "parent": None,
"inputs": {"ITEM": [1, [10, "thing"]]}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True,
"x": 385, "y": 109
},
"data_deleteoflist": {
"opcode": "data_deleteoflist", "next": None, "parent": None,
"inputs": {"INDEX": [1, [7, "1"]]}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True,
"x": 384, "y": 244
},
"data_deletealloflist": {
"opcode": "data_deletealloflist", "next": None, "parent": None,
"inputs": {}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True,
"x": 387, "y": 374
},
"data_insertatlist": {
"opcode": "data_insertatlist", "next": None, "parent": None,
"inputs": {"ITEM": [1, [10, "thing"]], "INDEX": [1, [7, "1"]]}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True,
"x": 366, "y": 527
},
"data_replaceitemoflist": {
"opcode": "data_replaceitemoflist", "next": None, "parent": None,
"inputs": {"INDEX": [1, [7, "1"]], "ITEM": [1, [10, "thing"]]}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True,
"x": 365, "y": 657
},
"data_itemoflist": {
"opcode": "data_itemoflist", "next": None, "parent": None,
"inputs": {"INDEX": [1, [7, "1"]]}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True,
"x": 862, "y": 117
},
"data_itemnumoflist": {
"opcode": "data_itemnumoflist", "next": None, "parent": None,
"inputs": {"ITEM": [1, [10, "thing"]]}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True,
"x": 883, "y": 238
},
"data_lengthoflist": {
"opcode": "data_lengthoflist", "next": None, "parent": None,
"inputs": {}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True,
"x": 876, "y": 342
},
"data_listcontainsitem": {
"opcode": "data_listcontainsitem", "next": None, "parent": None,
"inputs": {"ITEM": [1, [10, "thing"]]}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True,
"x": 871, "y": 463
},
"data_showlist": {
"opcode": "data_showlist", "next": None, "parent": None,
"inputs": {}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True,
"x": 931, "y": 563
},
"data_hidelist": {
"opcode": "data_hidelist", "next": None, "parent": None,
"inputs": {}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True,
"x": 962, "y": 716
},
# event_block.json
"event_whenflagclicked": {
"opcode": "event_whenflagclicked", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 166, "y": -422
},
"event_whenkeypressed": {
"opcode": "event_whenkeypressed", "next": None, "parent": None,
"inputs": {}, "fields": {"KEY_OPTION": ["space", None]}, "shadow": False, "topLevel": True,
"x": 151, "y": -329
},
"event_whenthisspriteclicked": {
"opcode": "event_whenthisspriteclicked", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 156, "y": -223
},
"event_whenbackdropswitchesto": {
"opcode": "event_whenbackdropswitchesto", "next": None, "parent": None,
"inputs": {}, "fields": {"BACKDROP": ["backdrop1", None]}, "shadow": False, "topLevel": True,
"x": 148, "y": -101
},
"event_whengreaterthan": {
"opcode": "event_whengreaterthan", "next": None, "parent": None,
"inputs": {"VALUE": [1, [4, "10"]]}, "fields": {"WHENGREATERTHANMENU": ["LOUDNESS", None]}, "shadow": False, "topLevel": True,
"x": 150, "y": 10
},
"event_whenbroadcastreceived": {
"opcode": "event_whenbroadcastreceived", "next": None, "parent": None,
"inputs": {}, "fields": {"BROADCAST_OPTION": ["message1", "5O!nei;S$!c!=hCT}0:a"]}, "shadow": False, "topLevel": True,
"x": 141, "y": 118
},
"event_broadcast": {
"opcode": "event_broadcast", "next": None, "parent": None,
"inputs": {"BROADCAST_INPUT": [1, [11, "message1", "5O!nei;S$!c!=hCT}0:a"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 151, "y": 229
},
"event_broadcastandwait": {
"opcode": "event_broadcastandwait", "next": None, "parent": None,
"inputs": {"BROADCAST_INPUT": [1, [11, "message1", "5O!nei;S$!c!=hCT}0:a"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 157, "y": 340
},
# look_block.json
"looks_sayforsecs": {
"opcode": "looks_sayforsecs", "next": None, "parent": None,
"inputs": {"MESSAGE": [1, [10, "Hello!"]], "SECS": [1, [4, "2"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 408, "y": 91
},
"looks_say": {
"opcode": "looks_say", "next": None, "parent": None,
"inputs": {"MESSAGE": [1, [10, "Hello!"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 413, "y": 213
},
"looks_thinkforsecs": {
"opcode": "looks_thinkforsecs", "next": None, "parent": None,
"inputs": {"MESSAGE": [1, [10, "Hmm..."]], "SECS": [1, [4, "2"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 413, "y": 317
},
"looks_think": {
"opcode": "looks_think", "next": None, "parent": None,
"inputs": {"MESSAGE": [1, [10, "Hmm..."]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 412, "y": 432
},
"looks_switchcostumeto": {
"opcode": "looks_switchcostumeto", "next": None, "parent": None,
"inputs": {"COSTUME": [1, "8;bti4wv(iH9nkOacCJ|"]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 411, "y": 555
},
"looks_costume": {
"opcode": "looks_costume", "next": None, "parent": "Q#a,6LPWHqo9-0Nu*[SV",
"inputs": {}, "fields": {"COSTUME": ["costume2", None]}, "shadow": True, "topLevel": False
},
"looks_nextcostume": {
"opcode": "looks_nextcostume", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 419, "y": 687
},
"looks_switchbackdropto": {
"opcode": "looks_switchbackdropto", "next": None, "parent": None,
"inputs": {"BACKDROP": [1, "-?yeX}29V*wd6W:unW0i"]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 901, "y": 91
},
"looks_backdrops": {
"opcode": "looks_backdrops", "next": None, "parent": "`Wm^p~l[(IWzc1|wNv*.",
"inputs": {}, "fields": {"BACKDROP": ["backdrop1", None]}, "shadow": True, "topLevel": False
},
"looks_changesizeby": {
"opcode": "looks_changesizeby", "next": None, "parent": None,
"inputs": {"CHANGE": [1, [4, "10"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 895, "y": 192
},
"looks_setsizeto": {
"opcode": "looks_setsizeto", "next": None, "parent": None,
"inputs": {"SIZE": [1, [4, "100"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 896, "y": 303
},
"looks_changeeffectby": {
"opcode": "looks_changeeffectby", "next": None, "parent": None,
"inputs": {"CHANGE": [1, [4, "25"]]}, "fields": {"EFFECT": ["COLOR", None]}, "shadow": False, "topLevel": True,
"x": 892, "y": 416
},
"looks_seteffectto": {
"opcode": "looks_seteffectto", "next": None, "parent": None,
"inputs": {"VALUE": [1, [4, "0"]]}, "fields": {"EFFECT": ["COLOR", None]}, "shadow": False, "topLevel": True,
"x": 902, "y": 527
},
"looks_cleargraphiceffects": {
"opcode": "looks_cleargraphiceffects", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 902, "y": 638
},
"looks_show": {
"opcode": "looks_show", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 908, "y": 758
},
"looks_hide": {
"opcode": "looks_hide", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 455, "y": 861
},
"looks_gotofrontback": {
"opcode": "looks_gotofrontback", "next": None, "parent": None,
"inputs": {}, "fields": {"FRONT_BACK": ["front", None]}, "shadow": False, "topLevel": True,
"x": 853, "y": 878
},
"looks_goforwardbackwardlayers": {
"opcode": "looks_goforwardbackwardlayers", "next": None, "parent": None,
"inputs": {"NUM": [1, [7, "1"]]}, "fields": {"FORWARD_BACKWARD": ["forward", None]}, "shadow": False, "topLevel": True,
"x": 851, "y": 999
},
"looks_costumenumbername": {
"opcode": "looks_costumenumbername", "next": None, "parent": None,
"inputs": {}, "fields": {"NUMBER_NAME": ["number", None]}, "shadow": False, "topLevel": True,
"x": 458, "y": 1007
},
"looks_backdropnumbername": {
"opcode": "looks_backdropnumbername", "next": None, "parent": None,
"inputs": {}, "fields": {"NUMBER_NAME": ["number", None]}, "shadow": False, "topLevel": True,
"x": 1242, "y": 753
},
"looks_size": {
"opcode": "looks_size", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 1249, "y": 876
},
# operator_block.json
"operator_add": {
"opcode": "operator_add", "next": None, "parent": None,
"inputs": {"NUM1": [1, [4, ""]], "NUM2": [1, [4, ""]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 128, "y": 153
},
"operator_subtract": {
"opcode": "operator_subtract", "next": None, "parent": None,
"inputs": {"NUM1": [1, [4, ""]], "NUM2": [1, [4, ""]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 134, "y": 214
},
"operator_multiply": {
"opcode": "operator_multiply", "next": None, "parent": None,
"inputs": {"NUM1": [1, [4, ""]], "NUM2": [1, [4, ""]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 134, "y": 278
},
"operator_divide": {
"opcode": "operator_divide", "next": None, "parent": None,
"inputs": {"NUM1": [1, [4, ""]], "NUM2": [1, [4, ""]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 138, "y": 359
},
"operator_random": {
"opcode": "operator_random", "next": None, "parent": None,
"inputs": {"FROM": [1, [4, "1"]], "TO": [1, [4, "10"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 311, "y": 157
},
"operator_gt": {
"opcode": "operator_gt", "next": None, "parent": None,
"inputs": {"OPERAND1": [1, [10, ""]], "OPERAND2": [1, [10, "50"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 348, "y": 217
},
"operator_lt": {
"opcode": "operator_lt", "next": None, "parent": None,
"inputs": {"OPERAND1": [1, [10, ""]], "OPERAND2": [1, [10, "50"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 345, "y": 286
},
"operator_equals": {
"opcode": "operator_equals", "next": None, "parent": None,
"inputs": {"OPERAND1": [1, [10, ""]], "OPERAND2": [1, [10, "50"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 345, "y": 372
},
"operator_and": {
"opcode": "operator_and", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 701, "y": 158
},
"operator_or": {
"opcode": "operator_or", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 705, "y": 222
},
"operator_not": {
"opcode": "operator_not", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 734, "y": 283
},
"operator_join": {
"opcode": "operator_join", "next": None, "parent": None,
"inputs": {"STRING1": [1, [10, "apple "]], "STRING2": [1, [10, "banana"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 663, "y": 378
},
"operator_letter_of": {
"opcode": "operator_letter_of", "next": None, "parent": None,
"inputs": {"LETTER": [1, [6, "1"]], "STRING": [1, [10, "apple"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 664, "y": 445
},
"operator_length": {
"opcode": "operator_length", "next": None, "parent": None,
"inputs": {"STRING": [1, [10, "apple"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 664, "y": 521
},
"operator_contains": {
"opcode": "operator_contains", "next": None, "parent": None,
"inputs": {"STRING1": [1, [10, "apple"]], "STRING2": [1, [10, "a"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 634, "y": 599
},
"operator_mod": {
"opcode": "operator_mod", "next": None, "parent": None,
"inputs": {"NUM1": [1, [4, ""]], "NUM2": [1, [4, ""]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 295, "y": 594
},
"operator_round": {
"opcode": "operator_round", "next": None, "parent": None,
"inputs": {"NUM": [1, [4, ""]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 307, "y": 674
},
"operator_mathop": {
"opcode": "operator_mathop", "next": None, "parent": None,
"inputs": {"NUM": [1, [4, ""]]}, "fields": {"OPERATOR": ["abs", None]}, "shadow": False, "topLevel": True,
"x": 280, "y": 754
},
# sensing_block.json
"sensing_touchingobject": {
"opcode": "sensing_touchingobject", "next": None, "parent": None,
"inputs": {"TOUCHINGOBJECTMENU": [1, "sensing_touchingobjectmenu"]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 359, "y": 116
},
"sensing_touchingobjectmenu": {
"opcode": "sensing_touchingobjectmenu", "next": None, "parent": "sensing_touchingobject",
"inputs": {}, "fields": {"TOUCHINGOBJECTMENU": ["_mouse_", None]}, "shadow": True, "topLevel": False
},
"sensing_touchingcolor": {
"opcode": "sensing_touchingcolor", "next": None, "parent": None,
"inputs": {"COLOR": [1, [9, "#55b888"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 360, "y": 188
},
"sensing_coloristouchingcolor": {
"opcode": "sensing_coloristouchingcolor", "next": None, "parent": None,
"inputs": {"COLOR": [1, [9, "#d019f2"]], "COLOR2": [1, [9, "#2b0de3"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 348, "y": 277
},
"sensing_askandwait": {
"opcode": "sensing_askandwait", "next": None, "parent": None,
"inputs": {"QUESTION": [1, [10, "What's your name?"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 338, "y": 354
},
"sensing_answer": {
"opcode": "sensing_answer", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 782, "y": 111
},
"sensing_keypressed": {
"opcode": "sensing_keypressed", "next": None, "parent": None,
"inputs": {"KEY_OPTION": [1, "sensing_keyoptions"]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 762, "y": 207
},
"sensing_keyoptions": {
"opcode": "sensing_keyoptions", "next": None, "parent": "sensing_keypressed",
"inputs": {}, "fields": {"KEY_OPTION": ["space", None]}, "shadow": True, "topLevel": False
},
"sensing_mousedown": {
"opcode": "sensing_mousedown", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 822, "y": 422
},
"sensing_mousex": {
"opcode": "sensing_mousex", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 302, "y": 528
},
"sensing_mousey": {
"opcode": "sensing_mousey", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 668, "y": 547
},
"sensing_setdragmode": {
"opcode": "sensing_setdragmode", "next": None, "parent": None,
"inputs": {}, "fields": {"DRAG_MODE": ["draggable", None]}, "shadow": False, "topLevel": True,
"x": 950, "y": 574
},
"sensing_loudness": {
"opcode": "sensing_loudness", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 658, "y": 703
},
"sensing_timer": {
"opcode": "sensing_timer", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 459, "y": 671
},
"sensing_resettimer": {
"opcode": "sensing_resettimer", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 462, "y": 781
},
"sensing_of": {
"opcode": "sensing_of", "next": None, "parent": None,
"inputs": {"OBJECT": [1, "sensing_of_object_menu"]}, "fields": {"PROPERTY": ["backdrop #", None]}, "shadow": False, "topLevel": True,
"x": 997, "y": 754
},
"sensing_of_object_menu": {
"opcode": "sensing_of_object_menu", "next": None, "parent": "sensing_of",
"inputs": {}, "fields": {"OBJECT": ["_stage_", None]}, "shadow": True, "topLevel": False
},
"sensing_current": {
"opcode": "sensing_current", "next": None, "parent": None,
"inputs": {}, "fields": {"CURRENTMENU": ["YEAR", None]}, "shadow": False, "topLevel": True,
"x": 627, "y": 884
},
"sensing_dayssince2000": {
"opcode": "sensing_dayssince2000", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 959, "y": 903
},
"sensing_username": {
"opcode": "sensing_username", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 833, "y": 757
},
# sound_block.json
"sound_playuntildone": {
"opcode": "sound_playuntildone", "next": None, "parent": None,
"inputs": {"SOUND_MENU": [1, "sound_sounds_menu"]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 253, "y": 17
},
"sound_sounds_menu": {
"opcode": "sound_sounds_menu", "next": None, "parent": "sound_playuntildone and sound_play",
"inputs": {}, "fields": {"SOUND_MENU": ["Meow", None]}, "shadow": True, "topLevel": False
},
"sound_play": {
"opcode": "sound_play", "next": None, "parent": None,
"inputs": {"SOUND_MENU": [1, "sound_sounds_menu"]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 245, "y": 122
},
"sound_stopallsounds": {
"opcode": "sound_stopallsounds", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 253, "y": 245
},
"sound_changeeffectby": {
"opcode": "sound_changeeffectby", "next": None, "parent": None,
"inputs": {"VALUE": [1, [4, "10"]]}, "fields": {"EFFECT": ["PITCH", None]}, "shadow": False, "topLevel": True,
"x": 653, "y": 14
},
"sound_seteffectto": {
"opcode": "sound_seteffectto", "next": None, "parent": None,
"inputs": {"VALUE": [1, [4, "100"]]}, "fields": {"EFFECT": ["PITCH", None]}, "shadow": False, "topLevel": True,
"x": 653, "y": 139
},
"sound_cleareffects": {
"opcode": "sound_cleareffects", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 651, "y": 242
},
"sound_changevolumeby": {
"opcode": "sound_changevolumeby", "next": None, "parent": None,
"inputs": {"VOLUME": [1, [4, "-10"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 645, "y": 353
},
"sound_setvolumeto": {
"opcode": "sound_setvolumeto", "next": None, "parent": None,
"inputs": {"VOLUME": [1, [4, "100"]]}, "fields": {}, "shadow": False, "topLevel": True,
"x": 1108, "y": 5
},
"sound_volume": {
"opcode": "sound_volume", "next": None, "parent": None,
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True,
"x": 1136, "y": 123
},
}
# #Example input with opcodes from various categories
# input_opcodes = [
# {"opcode": "sound_play", "count": 2}, # New: Sound block with menu
# {"opcode": "sound_playuntildone", "count": 2}, # New: Sound block with menu
# ]
# Example input with opcodes from various categories
# input_opcodes = [
# {"opcode": "sound_play", "count": 2},
# {"opcode": "sound_playuntildone", "count": 2},
# {"opcode":"motion_goto","count":2},
# {"opcode":"motion_glideto","count":2},
# {"opcode":"looks_switchbackdropto","count":2},
# {"opcode":"looks_switchcostumeto","count":2},
# {"opcode":"control_create_clone_of","count":2},
# {"opcode":"sensing_touchingobject","count":2},
# {"opcode":"sensing_of","count":2},
# {"opcode":"sensing_keypressed","count":2},
# {"opcode":"motion_pointtowards","count":2},
# ]
# generated_output = generate_blocks_from_opcodes(input_opcodes, all_block_definitions)
# print(json.dumps(generated_output, indent=2))
initial_opcode_counts = [
{"opcode":"event_whenflagclicked","count":1},
{"opcode":"motion_gotoxy","count":1},
{"opcode":"motion_glidesecstoxy","count":1},
{"opcode":"motion_xposition","count":1},
{"opcode":"motion_setx","count":1},
{"opcode":"control_forever","count":1},
{"opcode":"control_if","count":1},
{"opcode":"control_stop","count":1},
{"opcode":"operator_lt","count":1},
{"opcode":"sensing_istouching","count":1},
{"opcode":"sensing_touchingobjectmenu","count":1}, # This will now be generated as a child of sensing_touchingobject
{"opcode":"event_broadcast","count":1},
{"opcode":"data_setvariableto","count":2},
{"opcode":"data_showvariable","count":2},
]
# Generate the initial blocks and get the opcode_occurrences
generated_output_json, initial_opcode_occurrences = generate_blocks_from_opcodes(initial_opcode_counts, all_block_definitions)
# Pseudo-code to interpret
pseudo_code_input = """
when green flag clicked
go to x: (240) y: (-135)
set [score v] to +1
set [speed v] to +1
show variable [score v]
show variable [speed v]
forever
glide (2) seconds to x: (-240) y: (-135)
if <((x position)) < (-235)> then
set x to (240)
end
if <touching [Sprite1 v]?> then
broadcast [Game Over v]
stop [all v]
end
end
end
"""
# Interpret the pseudo-code and update the blocks, passing opcode_occurrences
final_generated_blocks = interpret_pseudo_code_and_update_blocks(generated_output_json, pseudo_code_input, all_block_definitions, initial_opcode_occurrences)
print(json.dumps(final_generated_blocks, indent=2))