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 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 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))