Spaces:
Runtime error
Runtime error
File size: 62,239 Bytes
a522962 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 |
import json
import copy
import re
import re
from collections import defaultdict
#from opcode_occurrence import generated_output_json
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,
and groups all generated block keys by their corresponding opcode.
Returns:
tuple: (generated_blocks, opcode_to_keys)
- generated_blocks: dict of block_key -> block_data
- opcode_to_keys: dict of opcode -> list of block_keys
"""
generated_blocks = {}
opcode_counts_map = {} # For counting unique suffix per opcode
opcode_to_keys = {} # For grouping block keys by 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")],
}
for item in opcode_counts:
opcode = item.get("opcode")
count = item.get("count", 1)
if opcode == "sensing_istouching":
opcode = "sensing_touchingobject"
if not opcode or opcode not in all_block_definitions:
print(f"Warning: Skipping opcode '{opcode}' (missing or not in definitions).")
continue
for _ in range(count):
# Count occurrences per opcode for unique key generation
opcode_counts_map[opcode] = opcode_counts_map.get(opcode, 0) + 1
instance_num = opcode_counts_map[opcode]
main_key = f"{opcode}_{instance_num}"
# Track the generated key
opcode_to_keys.setdefault(opcode, []).append(main_key)
main_block_data = copy.deepcopy(all_block_definitions[opcode])
main_block_data["parent"] = None
main_block_data["next"] = None
main_block_data["topLevel"] = True
main_block_data["shadow"] = False
generated_blocks[main_key] = main_block_data
# Handle menus
if opcode in explicit_menu_links:
for input_name, menu_opcode in explicit_menu_links[opcode]:
if menu_opcode not in all_block_definitions:
continue
opcode_counts_map[menu_opcode] = opcode_counts_map.get(menu_opcode, 0) + 1
menu_instance_num = opcode_counts_map[menu_opcode]
menu_key = f"{menu_opcode}_{menu_instance_num}"
opcode_to_keys.setdefault(menu_opcode, []).append(menu_key)
menu_block_data = copy.deepcopy(all_block_definitions[menu_opcode])
menu_block_data["shadow"] = True
menu_block_data["topLevel"] = False
menu_block_data["next"] = None
menu_block_data["parent"] = main_key
if input_name in main_block_data.get("inputs", {}) and \
isinstance(main_block_data["inputs"][input_name], list) and \
len(main_block_data["inputs"][input_name]) > 1 and \
main_block_data["inputs"][input_name][0] == 1:
main_block_data["inputs"][input_name][1] = menu_key
generated_blocks[menu_key] = menu_block_data
return generated_blocks, opcode_to_keys
all_block_definitions = {
# motion_block.json
"motion_movesteps": {
"block_name": "move () steps", "block_type": "Motion", "block_shape": "Stack Block", "op_code": "motion_movesteps",
"functionality": "Moves the sprite forward by the specified number of steps in the direction it is currently facing. A positive value moves it forward, and a negative value moves it backward.",
"inputs": {"STEPS": [1, [4, "10"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"motion_turnright": {
"block_name": "turn right () degrees", "block_type": "Motion", "block_shape": "Stack Block", "op_code": "motion_turnright",
"functionality": "Turns the sprite clockwise by the specified number of degrees.",
"inputs": {"DEGREES": [1, [4, "15"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"motion_turnleft": {
"block_name": "turn left () degrees", "block_type": "Motion", "block_shape": "Stack Block", "op_code": "motion_turnleft",
"functionality": "Turns the sprite counter-clockwise by the specified number of degrees.",
"inputs": {"DEGREES": [1, [4, "15"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"motion_goto": {
"block_name": "go to ()", "block_type": "Motion", "block_shape": "Stack Block", "op_code": "motion_goto",
"functionality": "Moves the sprite to a specified location, which can be a random position or at the mouse pointer or another to the sprite.",
"inputs": {"TO": [1, "motion_goto_menu"]}, "fields": {}, "shadow": False, "topLevel": True
},
"motion_goto_menu": {
"block_name": "go to menu", "block_type": "Motion", "block_shape": "Reporter Block", "op_code": "motion_goto_menu",
"functionality": "Menu for go to block.",
"inputs": {}, "fields": {"TO": ["_random_", None]}, "shadow": True, "topLevel": False
},
"motion_gotoxy": {
"block_name": "go to x: () y: ()", "block_type": "Motion", "block_shape": "Stack Block", "op_code": "motion_gotoxy",
"functionality": "Moves the sprite to the specified X and Y coordinates on the stage.",
"inputs": {"X": [1, [4, "0"]], "Y": [1, [4, "0"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"motion_glideto": {
"block_name": "glide () secs to ()", "block_type": "Motion", "block_shape": "Stack Block", "op_code": "motion_glideto",
"functionality": "Glides the sprite smoothly to a specified location (random position, mouse pointer, or another sprite) over a given number of seconds.",
"inputs": {"SECS": [1, [4, "1"]], "TO": [1, "motion_glideto_menu"]}, "fields": {}, "shadow": False, "topLevel": True
},
"motion_glideto_menu": {
"block_name": "glide to menu", "block_type": "Motion", "block_shape": "Reporter Block", "op_code": "motion_glideto_menu",
"functionality": "Menu for glide to block.",
"inputs": {}, "fields": {"TO": ["_random_", None]}, "shadow": True, "topLevel": False
},
"motion_glidesecstoxy": {
"block_name": "glide () secs to x: () y: ()", "block_type": "Motion", "block_shape": "Stack Block", "op_code": "motion_glidesecstoxy",
"functionality": "Glides the sprite smoothly to the specified X and Y coordinates over a given number of seconds.",
"inputs": {"SECS": [1, [4, "1"]], "X": [1, [4, "0"]], "Y": [1, [4, "0"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"motion_pointindirection": {
"block_name": "point in direction ()", "block_type": "Motion", "block_shape": "Stack Block", "op_code": "motion_pointindirection",
"functionality": "Sets the sprite's direction to a specified angle in degrees (0 = up, 90 = right, 180 = down, -90 = left).",
"inputs": {"DIRECTION": [1, [8, "90"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"motion_pointtowards": {
"block_name": "point towards ()", "block_type": "Motion", "block_shape": "Stack Block", "op_code": "motion_pointtowards",
"functionality": "Points the sprite towards the mouse pointer or another specified sprite.",
"inputs": {"TOWARDS": [1, "motion_pointtowards_menu"]}, "fields": {}, "shadow": False, "topLevel": True
},
"motion_pointtowards_menu": {
"block_name": "point towards menu", "block_type": "Motion", "block_shape": "Reporter Block", "op_code": "motion_pointtowards_menu",
"functionality": "Menu for point towards block.",
"inputs": {}, "fields": {"TOWARDS": ["_mouse_", None]}, "shadow": True, "topLevel": False
},
"motion_changexby": {
"block_name": "change x by ()", "block_type": "Motion", "block_shape": "Stack Block", "op_code": "motion_changexby",
"functionality": "Changes the sprite's X-coordinate by the specified amount, moving it horizontally.",
"inputs": {"DX": [1, [4, "10"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"motion_setx": {
"block_name": "set x to ()", "block_type": "Motion", "block_shape": "Stack Block", "op_code": "motion_setx",
"functionality": "Sets the sprite's X-coordinate to a specific value, placing it at a precise horizontal position.",
"inputs": {"X": [1, [4, "0"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"motion_changeyby": {
"block_name": "change y by ()", "block_type": "Motion", "block_shape": "Stack Block", "op_code": "motion_changeyby",
"functionality": "Changes the sprite's Y-coordinate by the specified amount, moving it vertically.",
"inputs": {"DY": [1, [4, "10"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"motion_sety": {
"block_name": "set y to ()", "block_type": "Motion", "block_shape": "Stack Block", "op_code": "motion_sety",
"functionality": "Sets the sprite's Y-coordinate to a specific value, placing it at a precise vertical position.",
"inputs": {"Y": [1, [4, "0"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"motion_ifonedgebounce": {
"block_name": "if on edge, bounce", "block_type": "Motion", "block_shape": "Stack Block", "op_code": "motion_ifonedgebounce",
"functionality": "Reverses the sprite's direction if it touches the edge of the stage.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"motion_setrotationstyle": {
"block_name": "set rotation style ()", "block_type": "Motion", "block_shape": "Stack Block", "op_code": "motion_setrotationstyle",
"functionality": "Determines how the sprite rotates: 'left-right' (flips horizontally), 'don't rotate' (stays facing one direction), or 'all around' (rotates freely).",
"inputs": {}, "fields": {"STYLE": ["left-right", None]}, "shadow": False, "topLevel": True
},
"motion_xposition": {
"block_name": "(x position)", "block_type": "Motion", "block_shape": "Reporter Block", "op_code": "motion_xposition",
"functionality": "Reports the current X-coordinate of the sprite.[NOTE: not used in stage/backdrops]",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"motion_yposition": {
"block_name": "(y position)", "block_type": "Motion", "block_shape": "Reporter Block", "op_code": "motion_yposition",
"functionality": "Reports the current Y coordinate of the sprite on the stage.[NOTE: not used in stage/backdrops]",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"motion_direction": {
"block_name": "(direction)", "block_type": "Motion", "block_shape": "Reporter Block", "op_code": "motion_direction",
"functionality": "Reports the current direction of the sprite in degrees (0 = up, 90 = right, 180 = down, -90 = left).[NOTE: not used in stage/backdrops]",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
# control_block.json
"control_wait": {
"block_name": "wait () seconds", "block_type": "Control", "block_shape": "Stack Block", "op_code": "control_wait",
"functionality": "Pauses the script for a specified duration.",
"inputs": {"DURATION": [1, [5, "1"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"control_repeat": {
"block_name": "repeat ()", "block_type": "Control", "block_shape": "C-Block", "op_code": "control_repeat",
"functionality": "Repeats the blocks inside it a specified number of times.",
"inputs": {"TIMES": [1, [6, "10"]], "SUBSTACK": [2, None]}, "fields": {}, "shadow": False, "topLevel": True
},
"control_forever": {
"block_name": "forever", "block_type": "Control", "block_shape": "C-Block", "op_code": "control_forever",
"functionality": "Continuously runs the blocks inside it.",
"inputs": {"SUBSTACK": [2, None]}, "fields": {}, "shadow": False, "topLevel": True
},
"control_if": {
"block_name": "if <> then", "block_type": "Control", "block_shape": "C-Block", "op_code": "control_if",
"functionality": "Executes the blocks inside it only if the specified boolean condition is true. [NOTE: it takes boolean blocks as input]",
"inputs": {"CONDITION": [2, None], "SUBSTACK": [2, None]}, "fields": {}, "shadow": False, "topLevel": True
},
"control_if_else": {
"block_name": "if <> then else", "block_type": "Control", "block_shape": "C-Block", "op_code": "control_if_else",
"functionality": "Executes one set of blocks if the specified boolean condition is true, and a different set of blocks if the condition is false. [NOTE: it takes boolean blocks as input]",
"inputs": {"CONDITION": [2, None], "SUBSTACK": [2, None], "SUBSTACK2": [2, None]}, "fields": {}, "shadow": False, "topLevel": True
},
"control_wait_until": {
"block_name": "wait until <>", "block_type": "Control", "block_shape": "Stack Block", "op_code": "control_wait_until",
"functionality": "Pauses the script until the specified boolean condition becomes true. [NOTE: it takes boolean blocks as input]",
"inputs": {"CONDITION": [2, None]}, "fields": {}, "shadow": False, "topLevel": True
},
"control_repeat_until": {
"block_name": "repeat until <>", "block_type": "Control", "block_shape": "C-Block", "op_code": "control_repeat_until",
"functionality": "Repeats the blocks inside it until the specified boolean condition becomes true. [NOTE: it takes boolean blocks as input]",
"inputs": {"CONDITION": [2, None], "SUBSTACK": [2, None]}, "fields": {}, "shadow": False, "topLevel": True
},
"control_stop": {
"block_name": "stop [v]", "block_type": "Control", "block_shape": "Cap Block", "op_code": "control_stop",
"functionality": "Halts all scripts, only the current script, or other scripts within the same sprite. Its shape can dynamically change based on the selected option.",
"inputs": {}, "fields": {"STOP_OPTION": ["all", None]}, "shadow": False, "topLevel": True, "mutation": {"tagName": "mutation", "children": [], "hasnext": "false"}
},
"control_start_as_clone": {
"block_name": "When I Start as a Clone", "block_type": "Control", "block_shape": "Hat Block", "op_code": "control_start_as_clone",
"functionality": "This Hat block initiates the script when a clone of the sprite is created. It defines the behavior of individual clones.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"control_create_clone_of": {
"block_name": "create clone of ()", "block_type": "Control", "block_shape": "Stack Block", "op_code": "control_create_clone_of",
"functionality": "Generates a copy, or clone, of a specified sprite (or 'myself' for the current sprite).",
"inputs": {"CLONE_OPTION": [1, "control_create_clone_of_menu"]}, "fields": {}, "shadow": False, "topLevel": True
},
"control_create_clone_of_menu": {
"block_name": "create clone of menu", "block_type": "Control", "block_shape": "Reporter Block", "op_code": "control_create_clone_of_menu",
"functionality": "Menu for create clone of block.",
"inputs": {}, "fields": {"CLONE_OPTION": ["_myself_", None]}, "shadow": True, "topLevel": False
},
"control_delete_this_clone": {
"block_name": "delete this clone", "block_type": "Control", "block_shape": "Cap Block", "op_code": "control_delete_this_clone",
"functionality": "Removes the clone that is executing it from the stage.",
"inputs":None, "fields": {}, "shadow": False, "topLevel": True
},
# data_block.json
"data_setvariableto": {
"block_name": "set [my variable v] to ()", "block_type": "Data", "block_shape": "Stack Block", "op_code": "data_setvariableto",
"functionality": "Assigns a specific value (number, string, or boolean) to a variable.",
"inputs": {"VALUE": [1, [10, "0"]]}, "fields": {"VARIABLE": ["my variable", "`jEk@4|i[#Fk?(8x)AV.-my variable"]}, "shadow": False, "topLevel": True
},
"data_changevariableby": {
"block_name": "change [my variable v] by ()", "block_type": "Data", "block_shape": "Stack Block", "op_code": "data_changevariableby",
"functionality": "Increases or decreases a variable's numerical value by a specified amount.",
"inputs": {"VALUE": [1, [4, "1"]]}, "fields": {"VARIABLE": ["my variable", "`jEk@4|i[#Fk?(8x)AV.-my variable"]}, "shadow": False, "topLevel": True
},
"data_showvariable": {
"block_name": "show variable [my variable v]", "block_type": "Data", "block_shape": "Stack Block", "op_code": "data_showvariable",
"functionality": "Makes a variable's monitor visible on the stage.",
"inputs": {}, "fields": {"VARIABLE": ["my variable", "`jEk@4|i[#Fk?(8x)AV.-my variable"]}, "shadow": False, "topLevel": True
},
"data_hidevariable": {
"block_name": "hide variable [my variable v]", "block_type": "Data", "block_shape": "Stack Block", "op_code": "data_hidevariable",
"functionality": "Hides a variable's monitor from the stage.",
"inputs": {}, "fields": {"VARIABLE": ["my variable", "`jEk@4|i[#Fk?(8x)AV.-my variable"]}, "shadow": False, "topLevel": True
},
"data_addtolist": {
"block_name": "add () to [my list v]", "block_type": "Data", "block_shape": "Stack Block", "op_code": "data_addtolist",
"functionality": "Appends an item to the end of a list.",
"inputs": {"ITEM": [1, [10, "thing"]]}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True
},
"data_deleteoflist": {
"block_name": "delete () of [my list v]", "block_type": "Data", "block_shape": "Stack Block", "op_code": "data_deleteoflist",
"functionality": "Removes an item from a list by its index or by selecting 'all' items.",
"inputs": {"INDEX": [1, [7, "1"]]}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True
},
"data_deletealloflist": {
"block_name": "delete all of [my list v]", "block_type": "Data", "block_shape": "Stack Block", "op_code": "data_deletealloflist",
"functionality": "Removes all items from a list.",
"inputs": {}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True
},
"data_insertatlist": {
"block_name": "insert () at () of [my list v]", "block_type": "Data", "block_shape": "Stack Block", "op_code": "data_insertatlist",
"functionality": "Inserts an item at a specific position within a list.",
"inputs": {"ITEM": [1, [10, "thing"]], "INDEX": [1, [7, "1"]]}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True
},
"data_replaceitemoflist": {
"block_name": "replace item () of [my list v] with ()", "block_type": "Data", "block_shape": "Stack Block", "op_code": "data_replaceitemoflist",
"functionality": "Replaces an item at a specific position in a list with a new value.",
"inputs": {"INDEX": [1, [7, "1"]], "ITEM": [1, [10, "thing"]]}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True
},
"data_itemoflist": {
"block_name": "(item (2) of [myList v])", "block_type": "Data", "block_shape": "Reporter Block", "op_code": "data_itemoflist",
"functionality": "Reports the item located at a specific position in a list.",
"inputs": {"INDEX": [1, [7, "1"]]}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True
},
"data_itemnumoflist": {
"block_name": "(item # of [Dog] in [myList v])", "block_type": "Data", "block_shape": "Reporter Block", "op_code": "data_itemnumoflist",
"functionality": "Reports the index number of the first occurrence of a specified item in a list. If the item is not found, it reports 0.",
"inputs": {"ITEM": [1, [10, "thing"]]}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True
},
"data_lengthoflist": {
"block_name": "(length of [myList v])", "block_type": "Data", "block_shape": "Reporter Block", "op_code": "data_lengthoflist",
"functionality": "Provides the total number of items contained in a list.",
"inputs": {}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True
},
"data_listcontainsitem": {
"block_name": "<[my list v] contains ()?>", "block_type": "Data", "block_shape": "Boolean Block", "op_code": "data_listcontainsitem",
"functionality": "Checks if a list includes a specific item.",
"inputs": {"ITEM": [1, [10, "thing"]]}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True
},
"data_showlist": {
"block_name": "show list [my list v]", "block_type": "Data", "block_shape": "Stack Block", "op_code": "data_showlist",
"functionality": "Makes a list's monitor visible on the stage.",
"inputs": {}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True
},
"data_hidelist": {
"block_name": "hide list [my list v]", "block_type": "Data", "block_shape": "Stack Block", "op_code": "data_hidelist",
"functionality": "Hides a list's monitor from the stage.",
"inputs": {}, "fields": {"LIST": ["MY_LIST", "o6`kIhtT{xWH+rX(5d,A"]}, "shadow": False, "topLevel": True
},
"data_variable": { # This is a reporter block for a variable's value
"block_name": "[variable v]", "block_type": "Data", "block_shape": "Reporter Block", "op_code": "data_variable",
"functionality": "Provides the current value stored in a variable.",
"inputs": {}, "fields": {"VARIABLE": ["my variable", None]}, "shadow": True, "topLevel": False
},
# event_block.json
"event_whenflagclicked": {
"block_name": "when green flag pressed", "block_type": "Events", "op_code": "event_whenflagclicked", "block_shape": "Hat Block",
"functionality": "This Hat block initiates the script when the green flag is clicked, serving as the common starting point for most Scratch projects.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"event_whenkeypressed": {
"block_name": "when () key pressed", "block_type": "Events", "op_code": "event_whenkeypressed", "block_shape": "Hat Block",
"functionality": "This Hat block initiates the script when a specified keyboard key is pressed.",
"inputs": {}, "fields": {"KEY_OPTION": ["space", None]}, "shadow": False, "topLevel": True
},
"event_whenthisspriteclicked": {
"block_name": "when this sprite clicked", "block_type": "Events", "op_code": "event_whenthisspriteclicked", "block_shape": "Hat Block",
"functionality": "This Hat block starts the script when the sprite itself is clicked.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"event_whenbackdropswitchesto": {
"block_name": "when backdrop switches to ()", "block_type": "Events", "op_code": "event_whenbackdropswitchesto", "block_shape": "Hat Block",
"functionality": "This Hat block triggers the script when the stage backdrop changes to a specified backdrop.",
"inputs": {}, "fields": {"BACKDROP": ["backdrop1", None]}, "shadow": False, "topLevel": True
},
"event_whengreaterthan": {
"block_name": "when () > ()", "block_type": "Events", "op_code": "event_whengreaterthan", "block_shape": "Hat Block",
"functionality": "This Hat block starts the script when a certain value (e.g., loudness from a microphone, or the timer) exceeds a defined threshold.",
"inputs": {"VALUE": [1, [4, "10"]]}, "fields": {"WHENGREATERTHANMENU": ["LOUDNESS", None]}, "shadow": False, "topLevel": True
},
"event_whenbroadcastreceived": {
"block_name": "when I receive ()", "block_type": "Events", "op_code": "event_whenbroadcastreceived", "block_shape": "Hat Block",
"functionality": "This Hat block initiates the script upon the reception of a specific broadcast message. This mechanism facilitates indirect communication between sprites or the stage.",
"inputs": {}, "fields": {"BROADCAST_OPTION": ["message1", "5O!nei;S$!c!=hCT}0:a"]}, "shadow": False, "topLevel": True
},
"event_broadcast": {
"block_name": "broadcast ()", "block_type": "Events", "block_shape": "Stack Block", "op_code": "event_broadcast",
"functionality": "Sends a broadcast message throughout the Scratch program, activating any 'when I receive ()' blocks that are set to listen for that message, enabling indirect communication.",
"inputs": {"BROADCAST_INPUT": [1, [11, "message1", "5O!nei;S$!c!=hCT}0:a"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"event_broadcastandwait": {
"block_name": "broadcast () and wait", "block_type": "Events", "block_shape": "Stack Block", "op_code": "event_broadcastandwait",
"functionality": "Sends a broadcast message and pauses the current script until all other scripts activated by that broadcast have completed their execution, ensuring sequential coordination.",
"inputs": {"BROADCAST_INPUT": [1, [11, "message1", "5O!nei;S$!c!=hCT}0:a"]]}, "fields": {}, "shadow": False, "topLevel": True
},
# looks_block.json
"looks_sayforsecs": {
"block_name": "say () for () seconds", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_sayforsecs",
"functionality": "Displays a speech bubble containing specified text for a set duration.",
"inputs": {"MESSAGE": [1, [10, "Hello!"]], "SECS": [1, [4, "2"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"looks_say": {
"block_name": "say ()", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_say",
"functionality": "Displays a speech bubble with the specified text indefinitely until another 'say' or 'think' block is activated.",
"inputs": {"MESSAGE": [1, [10, "Hello!"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"looks_thinkforsecs": {
"block_name": "think () for () seconds", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_thinkforsecs",
"functionality": "Displays a thought bubble containing specified text for a set duration.",
"inputs": {"MESSAGE": [1, [10, "Hmm..."]], "SECS": [1, [4, "2"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"looks_think": {
"block_name": "think ()", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_think",
"functionality": "Displays a thought bubble with the specified text indefinitely until another 'say' or 'think' block is activated.",
"inputs": {"MESSAGE": [1, [10, "Hmm..."]]}, "fields": {}, "shadow": False, "topLevel": True
},
"looks_switchcostumeto": {
"block_name": "switch costume to ()", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_switchcostumeto",
"functionality": "Alters the sprite's appearance to a designated costume.",
"inputs": {"COSTUME": [1, "looks_costume"]}, "fields": {}, "shadow": False, "topLevel": True
},
"looks_costume": {
"block_name": "costume menu", "block_type": "Looks", "block_shape": "Reporter Block", "op_code": "looks_costume",
"functionality": "Menu for switch costume to block.",
"inputs": {}, "fields": {"COSTUME": ["costume1", None]}, "shadow": True, "topLevel": False
},
"looks_nextcostume": {
"block_name": "next costume", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_nextcostume",
"functionality": "Switches the sprite's costume to the next one in its costume list. If it's the last costume, it cycles back to the first.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"looks_switchbackdropto": {
"block_name": "switch backdrop to ()", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_switchbackdropto",
"functionality": "Changes the stage's backdrop to a specified backdrop.",
"inputs": {"BACKDROP": [1, "looks_backdrops"]}, "fields": {}, "shadow": False, "topLevel": True
},
"looks_backdrops": {
"block_name": "backdrop menu", "block_type": "Looks", "block_shape": "Reporter Block", "op_code": "looks_backdrops",
"functionality": "Menu for switch backdrop to block.",
"inputs": {}, "fields": {"BACKDROP": ["backdrop1", None]}, "shadow": True, "topLevel": False
},
"looks_switchbackdroptowait": {
"block_name": "switch backdrop to () and wait", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_switchbackdroptowait",
"functionality": "Changes the stage's backdrop to a specified backdrop and pauses the script until any 'When backdrop switches to' scripts for that backdrop have finished.",
"inputs": {"BACKDROP": [1, "looks_backdrops"]}, "fields": {}, "shadow": False, "topLevel": True
},
"looks_nextbackdrop": {
"block_name": "next backdrop", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_nextbackdrop",
"functionality": "Switches the stage's backdrop to the next one in its backdrop list. If it's the last backdrop, it cycles back to the first.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"looks_changesizeby": {
"block_name": "change size by ()", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_changesizeby",
"functionality": "Changes the sprite's size by a specified percentage. Positive values make it larger, negative values make it smaller.",
"inputs": {"CHANGE": [1, [4, "10"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"looks_setsizeto": {
"block_name": "set size to () %", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_setsizeto",
"functionality": "Sets the sprite's size to a specific percentage of its original size.",
"inputs": {"SIZE": [1, [4, "100"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"looks_changeeffectby": {
"block_name": "change () effect by ()", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_changeeffectby",
"functionality": "Changes a visual effect on the sprite by a specified amount (e.g., color, fisheye, whirl, pixelate, mosaic, brightness, ghost).",
"inputs": {"CHANGE": [1, [4, "25"]]}, "fields": {"EFFECT": ["COLOR", None]}, "shadow": False, "topLevel": True
},
"looks_seteffectto": {
"block_name": "set () effect to ()", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_seteffectto",
"functionality": "Sets a visual effect on the sprite to a specific value.",
"inputs": {"VALUE": [1, [4, "0"]]}, "fields": {"EFFECT": ["COLOR", None]}, "shadow": False, "topLevel": True
},
"looks_cleargraphiceffects": {
"block_name": "clear graphic effects", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_cleargraphiceffects",
"functionality": "Removes all visual effects applied to the sprite.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"looks_show": {
"block_name": "show", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_show",
"functionality": "Makes the sprite visible on the stage.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"looks_hide": {
"block_name": "hide", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_hide",
"functionality": "Makes the sprite invisible on the stage.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"looks_gotofrontback": {
"block_name": "go to () layer", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_gotofrontback",
"functionality": "Moves the sprite to the front-most or back-most layer of other sprites on the stage.",
"inputs": {}, "fields": {"FRONT_BACK": ["front", None]}, "shadow": False, "topLevel": True
},
"looks_goforwardbackwardlayers": {
"block_name": "go () layers", "block_type": "Looks", "block_shape": "Stack Block", "op_code": "looks_goforwardbackwardlayers",
"functionality": "Moves the sprite forward or backward a specified number of layers in relation to other sprites.",
"inputs": {"NUM": [1, [7, "1"]]}, "fields": {"FORWARD_BACKWARD": ["forward", None]}, "shadow": False, "topLevel": True
},
"looks_costumenumbername": {
"block_name": "(costume ())", "block_type": "Looks", "block_shape": "Reporter Block", "op_code": "looks_costumenumbername",
"functionality": "Reports the current costume's number or name.",
"inputs": {}, "fields": {"NUMBER_NAME": ["number", None]}, "shadow": False, "topLevel": True
},
"looks_backdropnumbername": {
"block_name": "(backdrop ())", "block_type": "Looks", "block_shape": "Reporter Block", "op_code": "looks_backdropnumbername",
"functionality": "Reports the current backdrop's number or name.",
"inputs": {}, "fields": {"NUMBER_NAME": ["number", None]}, "shadow": False, "topLevel": True
},
"looks_size": {
"block_name": "(size)", "block_type": "Looks", "block_shape": "Reporter Block", "op_code": "looks_size",
"functionality": "Reports the current size of the sprite as a percentage.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
# operator_block.json
"operator_add": {
"block_name": "(() + ())", "block_type": "operator", "block_shape": "Reporter Block", "op_code": "operator_add",
"functionality": "Adds two numerical values.",
"inputs": {"NUM1": [1, [4, ""]], "NUM2": [1, [4, ""]]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_subtract": {
"block_name": "(() - ())", "block_type": "operator", "block_shape": "Reporter Block", "op_code": "operator_subtract",
"functionality": "Subtracts the second numerical value from the first.",
"inputs": {"NUM1": [1, [4, ""]], "NUM2": [1, [4, ""]]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_multiply": {
"block_name": "(() * ())", "block_type": "operator", "block_shape": "Reporter Block", "op_code": "operator_multiply",
"functionality": "Multiplies two numerical values.",
"inputs": {"NUM1": [1, [4, ""]], "NUM2": [1, [4, ""]]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_divide": {
"block_name": "(() / ())", "block_type": "operator", "block_shape": "Reporter Block", "op_code": "operator_divide",
"functionality": "Divides the first numerical value by the second.",
"inputs": {"NUM1": [1, [4, ""]], "NUM2": [1, [4, ""]]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_random": {
"block_name": "(pick random () to ())", "block_type": "operator", "block_shape": "Reporter Block", "op_code": "operator_random",
"functionality": "Generates a random integer within a specified inclusive range.",
"inputs": {"FROM": [1, [4, "1"]], "TO": [1, [4, "10"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_gt": {
"block_name": "<() > ()>", "block_type": "operator", "block_shape": "Boolean Block", "op_code": "operator_gt",
"functionality": "Checks if the first value is greater than the second.",
"inputs": {"OPERAND1": [1, [10, ""]], "OPERAND2": [1, [10, "50"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_lt": {
"block_name": "<() < ()>", "block_type": "operator", "block_shape": "Boolean Block", "op_code": "operator_lt",
"functionality": "Checks if the first value is less than the second.",
"inputs": {"OPERAND1": [1, [10, ""]], "OPERAND2": [1, [10, "50"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_equals": {
"block_name": "<() = ()>", "block_type": "operator", "block_shape": "Boolean Block", "op_code": "operator_equals",
"functionality": "Checks if two values are equal.",
"inputs": {"OPERAND1": [1, [10, ""]], "OPERAND2": [1, [10, "50"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_and": {
"block_name": "<<> and <>>", "block_type": "operator", "block_shape": "Boolean Block", "op_code": "operator_and",
"functionality": "Returns 'true' if both provided Boolean conditions are 'true'.",
"inputs": {"OPERAND1": [2, None], "OPERAND2": [2, None]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_or": {
"block_name": "<<> or <>>", "block_type": "operator", "block_shape": "Boolean Block", "op_code": "operator_or",
"functionality": "Returns 'true' if at least one of the provided Boolean conditions is 'true'.",
"inputs": {"OPERAND1": [2, None], "OPERAND2": [2, None]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_not": {
"block_name": "<not <>>", "block_type": "operator", "block_shape": "Boolean Block", "op_code": "operator_not",
"functionality": "Returns 'true' if the provided Boolean condition is 'false', and 'false' if it is 'true'.",
"inputs": {"OPERAND": [2, None]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_join": {
"block_name": "(join ()())", "block_type": "operator", "block_shape": "Reporter Block", "op_code": "operator_join",
"functionality": "Concatenates two strings or values into a single string.",
"inputs": {"STRING1": [1, [10, "apple "]], "STRING2": [1, [10, "banana"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_letterof": {
"block_name": "letter () of ()", "block_type": "operator", "block_shape": "Reporter Block", "op_code": "operator_letterof",
"functionality": "Reports the character at a specific numerical position within a string.",
"inputs": {"LETTER": [1, [6, "1"]], "STRING": [1, [10, "apple"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_length": {
"block_name": "(length of ())", "block_type": "operator", "block_shape": "Reporter Block", "op_code": "operator_length",
"functionality": "Reports the total number of characters in a given string.",
"inputs": {"STRING": [1, [10, "apple"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_contains": {
"block_name": "<() contains ()?>", "block_type": "operator", "block_shape": "Boolean Block", "op_code": "operator_contains",
"functionality": "Checks if one string contains another string.",
"inputs": {"STRING1": [1, [10, "apple"]], "STRING2": [1, [10, "a"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_mod": {
"block_name": "(() mod ())", "block_type": "operator", "block_shape": "Reporter Block", "op_code": "operator_mod",
"functionality": "Reports the remainder when the first number is divided by the second.",
"inputs": {"NUM1": [1, [4, ""]], "NUM2": [1, [4, ""]]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_round": {
"block_name": "(round ())", "block_type": "operator", "block_shape": "Reporter Block", "op_code": "operator_round",
"functionality": "Rounds a numerical value to the nearest integer.",
"inputs": {"NUM": [1, [4, ""]]}, "fields": {}, "shadow": False, "topLevel": True
},
"operator_mathop": {
"block_name": "(() of ())", "block_type": "operator", "block_shape": "Reporter Block", "op_code": "operator_mathop",
"functionality": "Performs various mathematical functions (e.g., absolute value, square root, trigonometric functions).",
"inputs": {"NUM": [1, [4, ""]]}, "fields": {"OPERATOR": ["abs", None]}, "shadow": False, "topLevel": True
},
# sensing_block.json
"sensing_touchingobject": {
"block_name": "<touching [edge v]?>", "block_type": "Sensing", "op_code": "sensing_touchingobject", "block_shape": "Boolean Block",
"functionality": "Checks if its sprite is touching the mouse-pointer, edge, or another specified sprite.",
"inputs": {"TOUCHINGOBJECTMENU": [1, "sensing_touchingobjectmenu"]}, "fields": {}, "shadow": False, "topLevel": True
},
"sensing_touchingobjectmenu": {
"block_name": "touching object menu", "block_type": "Sensing", "block_shape": "Reporter Block", "op_code": "sensing_touchingobjectmenu",
"functionality": "Menu for touching object block.",
"inputs": {}, "fields": {"TOUCHINGOBJECTMENU": ["_mouse_", None]}, "shadow": True, "topLevel": False
},
"sensing_touchingcolor": {
"block_name": "<touching color ()?>", "block_type": "Sensing", "op_code": "sensing_touchingcolor", "block_shape": "Boolean Block",
"functionality": "Checks whether its sprite is touching a specified color.",
"inputs": {"COLOR": [1, [9, "#55b888"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"sensing_coloristouchingcolor": {
"block_name": "<color () is touching ()?>", "block_type": "Sensing", "op_code": "sensing_coloristouchingcolor", "block_shape": "Boolean Block",
"functionality": "Checks whether a specific color on its sprite is touching another specified color on the stage or another sprite.",
"inputs": {"COLOR1": [1, [9, "#d019f2"]], "COLOR2": [1, [9, "#2b0de3"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"sensing_askandwait": {
"block_name": "Ask () and Wait", "block_type": "Sensing", "block_shape": "Stack Block", "op_code": "sensing_askandwait",
"functionality": "Displays an input box with specified text at the bottom of the screen, allowing users to input text, which is stored in the 'Answer' block.",
"inputs": {"QUESTION": [1, [10, "What's your name?"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"sensing_answer": {
"block_name": "(answer)", "block_type": "Sensing", "block_shape": "Reporter Block", "op_code": "sensing_answer",
"functionality": "Holds the most recent text inputted using the 'Ask () and Wait' block.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"sensing_keypressed": {
"block_name": "<key () pressed?>", "block_type": "Sensing", "op_code": "sensing_keypressed", "block_shape": "Boolean Block",
"functionality": "Checks if a specified keyboard key is currently being pressed.",
"inputs": {"KEY_OPTION": [1, "sensing_keyoptions"]}, "fields": {}, "shadow": False, "topLevel": True
},
"sensing_keyoptions": {
"block_name": "key options menu", "block_type": "Sensing", "block_shape": "Reporter Block", "op_code": "sensing_keyoptions",
"functionality": "Menu for key pressed block.",
"inputs": {}, "fields": {"KEY_OPTION": ["space", None]}, "shadow": True, "topLevel": False
},
"sensing_mousedown": {
"block_name": "<mouse down?>", "block_type": "Sensing", "op_code": "sensing_mousedown", "block_shape": "Boolean Block",
"functionality": "Checks if the computer mouse's primary button is being clicked while the cursor is over the stage.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"sensing_mousex": {
"block_name": "(mouse x)", "block_type": "Sensing", "block_shape": "Reporter Block", "op_code": "sensing_mousex",
"functionality": "Reports the mouse-pointer’s current X position on the stage.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"sensing_mousey": {
"block_name": "(mouse y)", "block_type": "Sensing", "block_shape": "Reporter Block", "op_code": "sensing_mousey",
"functionality": "Reports the mouse-pointer’s current Y position on the stage.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"sensing_setdragmode": {
"block_name": "set drag mode [draggable v]", "block_type": "Sensing", "block_shape": "Stack Block", "op_code": "sensing_setdragmode",
"functionality": "Sets whether the sprite can be dragged by the mouse on the stage.",
"inputs": {}, "fields": {"DRAG_MODE": ["draggable", None]}, "shadow": False, "topLevel": True
},
"sensing_loudness": {
"block_name": "(loudness)", "block_type": "Sensing", "block_shape": "Reporter Block", "op_code": "sensing_loudness",
"functionality": "Reports the loudness of noise received by a microphone on a scale of 0 to 100.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"sensing_timer": {
"block_name": "(timer)", "block_type": "Sensing", "block_shape": "Reporter Block", "op_code": "sensing_timer",
"functionality": "Reports the elapsed time since Scratch was launched or the timer was reset, increasing by 1 every second.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"sensing_resettimer": {
"block_name": "Reset Timer", "block_type": "Sensing", "block_shape": "Stack Block", "op_code": "sensing_resettimer",
"functionality": "Sets the timer’s value back to 0.0.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"sensing_of": {
"block_name": "(() of ())", "block_type": "Sensing", "block_shape": "Reporter Block", "op_code": "sensing_of",
"functionality": "Reports a specified value (e.g., x position, direction, costume number) of a specified sprite or the Stage to be accessed in current sprite or stage.",
"inputs": {"OBJECT": [1, "sensing_of_object_menu"]}, "fields": {"PROPERTY": ["backdrop #", None]}, "shadow": False, "topLevel": True
},
"sensing_of_object_menu": {
"block_name": "of object menu", "block_type": "Sensing", "block_shape": "Reporter Block", "op_code": "sensing_of_object_menu",
"functionality": "Menu for of block.",
"inputs": {}, "fields": {"OBJECT": ["_stage_", None]}, "shadow": True, "topLevel": False
},
"sensing_current": {
"block_name": "(current ())", "block_type": "Sensing", "block_shape": "Reporter Block", "op_code": "sensing_current",
"functionality": "Reports the current local year, month, date, day of the week, hour, minutes, or seconds.",
"inputs": {}, "fields": {"CURRENTMENU": ["YEAR", None]}, "shadow": False, "topLevel": True
},
"sensing_dayssince2000": {
"block_name": "(days since 2000)", "block_type": "Sensing", "block_shape": "Reporter Block", "op_code": "sensing_dayssince2000",
"functionality": "Reports the number of days (and fractions of a day) since 00:00:00 UTC on January 1, 2000.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"sensing_username": {
"block_name": "(username)", "block_type": "Sensing", "block_shape": "Reporter Block", "op_code": "sensing_username",
"functionality": "Reports the username of the user currently logged into Scratch. If no user is logged in, it reports nothing.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
# sound_block.json
"sound_playuntildone": {
"block_name": "play sound () until done", "block_type": "Sound", "block_shape": "Stack Block", "op_code": "sound_playuntildone",
"functionality": "Plays a specified sound and pauses the script's execution until the sound has completed.",
"inputs": {"SOUND_MENU": [1, "sound_sounds_menu"]}, "fields": {}, "shadow": False, "topLevel": True
},
"sound_sounds_menu": {
"block_name": "sound menu", "block_type": "Sound", "block_shape": "Reporter Block", "op_code": "sound_sounds_menu",
"functionality": "Menu for sound blocks.",
"inputs": {}, "fields": {"SOUND_MENU": ["Meow", None]}, "shadow": True, "topLevel": False
},
"sound_play": {
"block_name": "start sound ()", "block_type": "Sound", "block_shape": "Stack Block", "op_code": "sound_play",
"functionality": "Initiates playback of a specified sound without pausing the script, allowing other actions to proceed concurrently.",
"inputs": {"SOUND_MENU": [1, "sound_sounds_menu"]}, "fields": {}, "shadow": False, "topLevel": True
},
"sound_stopallsounds": {
"block_name": "stop all sounds", "block_type": "Sound", "block_shape": "Stack Block", "op_code": "sound_stopallsounds",
"functionality": "Stops all currently playing sounds.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"sound_changeeffectby": {
"block_name": "change () effect by ()", "block_type": "Sound", "block_shape": "Stack Block", "op_code": "sound_changeeffectby",
"functionality": "Changes the project's sound effect by a specified amount.",
"inputs": {"VALUE": [1, [4, "10"]]}, "fields": {"EFFECT": ["PITCH", None]}, "shadow": False, "topLevel": True
},
"sound_seteffectto": {
"block_name": "set () effect to ()", "block_type": "Sound", "block_shape": "Stack Block", "op_code": "sound_seteffectto",
"functionality": "Sets the sound effect to a specific value.",
"inputs": {"VALUE": [1, [4, "100"]]}, "fields": {"EFFECT": ["PITCH", None]}, "shadow": False, "topLevel": True
},
"sound_cleareffects": {
"block_name": "clear sound effects", "block_type": "Sound", "block_shape": "Stack Block", "op_code": "sound_cleareffects",
"functionality": "Removes all sound effects applied to the sprite.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
"sound_changevolumeby": {
"block_name": "change volume by ()", "block_type": "Sound", "block_shape": "Stack Block", "op_code": "sound_changevolumeby",
"functionality": "Changes the project's sound volume by a specified amount.",
"inputs": {"VOLUME": [1, [4, "-10"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"sound_setvolumeto": {
"block_name": "set volume to () %", "block_type": "Sound", "block_shape": "Stack Block", "op_code": "sound_setvolumeto",
"functionality": "Sets the sound volume to a specific percentage (0-100).",
"inputs": {"VOLUME": [1, [4, "100"]]}, "fields": {}, "shadow": False, "topLevel": True
},
"sound_volume": {
"block_name": "(volume)", "block_type": "Sound", "block_shape": "Reporter Block", "op_code": "sound_volume",
"functionality": "Reports the current volume level of the sprite.",
"inputs": {}, "fields": {}, "shadow": False, "topLevel": True
},
}
# # Example input with opcodes for the initial generation
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_touchingobject","count":1}, # Changed from sensing_istouching
{"opcode":"sensing_touchingobjectmenu","count":1},
{"opcode":"event_broadcast","count":1},
{"opcode":"data_setvariableto","count":2},
{"opcode":"data_showvariable","count":2},
]
# initial_opcode_counts = [
# {"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},
# ]
# 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)
#print(generated_output_json)
#print(initial_opcode_occurrences)
def build_block_patterns(def_list):
"""
Given a list of block definitions (from one JSON file),
return a dict opcode -> { regex:Compiled, inputs:[names], shape, block_name }.
"""
out = {}
for d in def_list:
# 1) escape the literal text
pattern = re.escape(d['block_name'])
# 2) replace the escaped "()" placeholders with a capture for anything inside
pattern = pattern.replace(r"\(\)", r"\((.+?)\)")
# 3) replace the escaped "<>" placeholders likewise
pattern = pattern.replace(r"\<\>", r"<(.+?)>")
# 4) allow any whitespace where spaces occur
pattern = pattern.replace(r"\ ", r"\s+")
# anchor from start to end, ignore case
regex = re.compile(r"^\s*" + pattern + r"\s*$", re.IGNORECASE)
inputs = [inp['name'] for inp in (d.get('inputs') or [])]
out[d['op_code']] = {
'regex': regex,
'inputs': inputs,
'shape': d['block_shape'],
'block_name':d['block_name'],
'definition':d
}
return out
def load_all_definitions():
# Load your JSON files here; adjust paths as needed
hats = json.load(open(r'blocks\hat_blocks.json'))['blocks']
c_blocks = json.load(open(r'blocks\c_blocks.json'))['blocks']
reporters = json.load(open(r'blocks\reporter_blocks.json'))['blocks']
booleans = json.load(open(r'blocks\boolean_blocks.json'))['blocks']
# you can also load stack_blocks.json, cap_blocks.json, etc. if you have them
merged = hats + c_blocks + reporters + booleans
return build_block_patterns(merged)
def generate_plan(generated_input, opcode_keys, pseudo_code):
"""
A truly generic plan generator.
Inputs:
- generated_input: dict of block_key -> block_data
- opcode_keys: dict of opcode -> [block_key,...]
- pseudo_code: multiline string
Returns: { flow: [...] }
"""
all_defs = load_all_definitions()
# pointer into each opcode_keys list
ptrs = defaultdict(int)
def pick_key(opcode):
lst = opcode_keys.get(opcode, [])
if ptrs[opcode] >= len(lst):
raise KeyError(f"No more generated keys for opcode {opcode!r}")
key = lst[ptrs[opcode]]
ptrs[opcode] += 1
return key
# Recursively parse an expression fragment like "(x position)" or "<touching [A]?>"
def parse_expression(expr_text):
expr_text = expr_text.strip()
# Try to match every reporter/boolean pattern
for op, info in all_defs.items():
m = info['regex'].match(expr_text)
if not m: continue
# Got a match
node = {'op_code': op, 'inputs': {}}
groups = m.groups()
for name, val in zip(info['inputs'], groups):
# decide kind by input type in definition
inp_def = next(
(i for i in info['definition'].get('inputs', []) if i['name']==name),
{}
)
t = inp_def.get('type','any')
if t in ('number','any'):
try:
node['inputs'][name] = {'kind':'value', 'value': float(val) if '.' in val else int(val)}
except:
node['inputs'][name] = {'kind':'variable', 'name': val.strip()}
elif t in ('dropdown','string','string/number'):
node['inputs'][name] = {'kind':'menu', 'option': val.strip()}
elif t=='boolean':
# nested boolean: recurse
node['inputs'][name] = {'kind':'nested', 'expr': parse_expression(val)}
else:
node['inputs'][name] = {'kind':'nested', 'expr': parse_expression(val)}
return node
# fallback: literal?
lit = re.match(r"^\(?\s*(-?\d+(\.\d+)?)\s*\)?$", expr_text)
if lit:
num = lit.group(1)
return {'literal': True, 'kind':'value', 'value': float(num) if '.' in num else int(num)}
# else treat as raw string
return {'literal':True, 'kind':'variable', 'name':expr_text}
flow = []
# stack of (indent, container)
stack = [(-1, flow)]
for raw in pseudo_code.splitlines():
if not raw.strip(): continue
indent = (len(raw) - len(raw.lstrip())) // 2
line = raw.strip()
# drop trailing 'then' or 'end'
line_clean = re.sub(r'\s*(then|end)\s*$', '', line, flags=re.IGNORECASE)
# find a matching block definition
for opcode, info in all_defs.items():
if not info['regex'].match(line_clean):
continue
# pop up to correct level
while stack and stack[-1][0] >= indent:
stack.pop()
container = stack[-1][1]
key = pick_key(opcode)
node = {'block_key': key}
shape = info['shape']
# determine node type
if 'Hat Block' in shape:
node['type'] = 'hat'
node['description'] = info['block_name']
node['next'] = []
target_list = node['next']
elif 'C-Block' in shape:
node['type'] = 'c_block'
node['description'] = info['block_name']
node['condition'] = None
node['body'] = []
target_list = node['body']
# the first input is usually the boolean condition
if info['inputs']:
cond_name = info['inputs'][0]
# extract the <...> portion
cond_match = re.search(r'<(.+)>', line)
if cond_match:
node['condition'] = parse_expression(cond_match.group(1))
elif 'Cap Block' in shape:
node['type'] = 'cap'
# e.g. stop [all v]
if 'inputs' in info['definition'] and info['definition']['inputs']:
fld = info['definition']['inputs'][0]['name']
val = re.search(r'\[\s*([^\]]+)\s*\]', line)
if val:
node['option'] = val.group(1)
target_list = None
else:
node['type'] = 'stack'
# parse any inputs in parentheses or brackets
node['inputs'] = {}
# for each input name in the definition, find its occurrence
for inp_name in info['inputs']:
# look for "(...)" after the input name or anywhere
# brute-force: find all "(...)" then map in order
pass
target_list = None
container.append(node)
if target_list is not None:
stack.append((indent, target_list))
break
else:
# no matching opcode — you can log or raise here
raise ValueError(f"Could not classify line: {line!r}")
return {'flow': flow}
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
"""
# ── USAGE ──
plan = generate_plan(generated_output_json, initial_opcode_occurrences, pseudo_code_input)
import json
print(json.dumps(plan, indent=2)) |