From d42fe91bfb941da0b6115a34d65d9a822c6139c4 Mon Sep 17 00:00:00 2001
From: adazem009 <68537469+adazem009@users.noreply.github.com>
Date: Mon, 2 Sep 2024 19:54:57 +0200
Subject: [PATCH 1/9] Set version to 0.10.1

---
 CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 66a900c7..1b8450c0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.14)
 
-project(libscratchcpp VERSION 0.10.0 LANGUAGES C CXX)
+project(libscratchcpp VERSION 0.10.1 LANGUAGES C CXX)
 
 set(CMAKE_INCLUDE_CURRENT_DIR ON)
 set(CMAKE_CXX_STANDARD 17)

From a35433f9a20c058a40d81bd6083e224d1e5bcdee Mon Sep 17 00:00:00 2001
From: adazem009 <68537469+adazem009@users.noreply.github.com>
Date: Mon, 2 Sep 2024 19:54:00 +0200
Subject: [PATCH 2/9] Treat stopped projects with active threads as running

Resolves: #507
---
 src/engine/internal/engine.cpp | 7 ++++++-
 src/engine/internal/engine.h   | 1 +
 test/engine/engine_test.cpp    | 2 ++
 3 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/engine/internal/engine.cpp b/src/engine/internal/engine.cpp
index 448103e4..c7b0bb7c 100644
--- a/src/engine/internal/engine.cpp
+++ b/src/engine/internal/engine.cpp
@@ -95,6 +95,7 @@ void Engine::clear()
     m_edgeActivatedHatValues.clear();
 
     m_running = false;
+    m_frameActivity = false;
 
     m_unsupportedBlocks.clear();
 }
@@ -421,6 +422,7 @@ void Engine::stop()
         m_running = false;
     }
 
+    m_frameActivity = false;
     deleteClones();
     stopSounds();
     m_stopped();
@@ -578,6 +580,9 @@ void Engine::step()
         }
     }
 
+    // Check running threads (must be done here)
+    m_frameActivity = !m_threads.empty();
+
     m_redrawRequested = false;
 
     // Step threads
@@ -737,7 +742,7 @@ void Engine::eventLoop(bool untilProjectStops)
 
 bool Engine::isRunning() const
 {
-    return m_running;
+    return m_running || m_frameActivity;
 }
 
 double Engine::fps() const
diff --git a/src/engine/internal/engine.h b/src/engine/internal/engine.h
index 218dc9ba..67c10f52 100644
--- a/src/engine/internal/engine.h
+++ b/src/engine/internal/engine.h
@@ -277,6 +277,7 @@ class Engine : public IEngine
         bool m_spriteFencingEnabled = true;
 
         bool m_running = false;
+        bool m_frameActivity = false;
         bool m_redrawRequested = false;
         sigslot::signal<> m_aboutToRedraw;
         sigslot::signal<VirtualMachine *> m_threadAboutToStop;
diff --git a/test/engine/engine_test.cpp b/test/engine/engine_test.cpp
index 86670a44..88302960 100644
--- a/test/engine/engine_test.cpp
+++ b/test/engine/engine_test.cpp
@@ -2018,6 +2018,8 @@ TEST(EngineTest, StopAllBypass)
     ASSERT_VAR(stage, "j");
     ASSERT_EQ(GET_VAR(stage, "j")->value().toInt(), 5);
 
+    ASSERT_TRUE(engine->isRunning());
+    engine->step();
     ASSERT_FALSE(engine->isRunning());
 }
 

From 4ce481fd424a00c13b2ae60d097bf7ffc46daf7c Mon Sep 17 00:00:00 2001
From: adazem009 <68537469+adazem009@users.noreply.github.com>
Date: Fri, 6 Sep 2024 11:54:16 +0200
Subject: [PATCH 3/9] fix #571: Get processed bubble text before passing to
 interfaces

---
 src/scratch/sprite.cpp                        |  5 +++--
 src/scratch/stage.cpp                         |  5 +++--
 .../target_interfaces/ispritehandler_test.cpp | 19 +++++++++++++++++++
 test/target_interfaces/istagehandler_test.cpp | 19 +++++++++++++++++++
 4 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/src/scratch/sprite.cpp b/src/scratch/sprite.cpp
index d711ca7c..22d220e2 100644
--- a/src/scratch/sprite.cpp
+++ b/src/scratch/sprite.cpp
@@ -548,8 +548,9 @@ void Sprite::setBubbleType(BubbleType type)
 void Sprite::setBubbleText(const std::string &text)
 {
     Target::setBubbleText(impl->visible ? text : "");
+    const std::string &finalText = bubbleText();
 
-    if (impl->visible && !text.empty()) {
+    if (impl->visible && !finalText.empty()) {
         IEngine *eng = engine();
 
         if (eng)
@@ -557,7 +558,7 @@ void Sprite::setBubbleText(const std::string &text)
     }
 
     if (impl->iface)
-        impl->iface->onBubbleTextChanged(impl->visible ? text : "");
+        impl->iface->onBubbleTextChanged(impl->visible ? finalText : "");
 }
 
 Target *Sprite::dataSource() const
diff --git a/src/scratch/stage.cpp b/src/scratch/stage.cpp
index d798451e..567c3c07 100644
--- a/src/scratch/stage.cpp
+++ b/src/scratch/stage.cpp
@@ -224,8 +224,9 @@ void Stage::setBubbleType(BubbleType type)
 void Stage::setBubbleText(const std::string &text)
 {
     Target::setBubbleText(text);
+    const std::string &finalText = bubbleText();
 
-    if (!text.empty()) {
+    if (!finalText.empty()) {
         IEngine *eng = engine();
 
         if (eng)
@@ -233,7 +234,7 @@ void Stage::setBubbleText(const std::string &text)
     }
 
     if (impl->iface)
-        impl->iface->onBubbleTextChanged(text);
+        impl->iface->onBubbleTextChanged(finalText);
 }
 
 bool Stage::touchingClones(const std::vector<Sprite *> &clones) const
diff --git a/test/target_interfaces/ispritehandler_test.cpp b/test/target_interfaces/ispritehandler_test.cpp
index 752593e9..077d44e0 100644
--- a/test/target_interfaces/ispritehandler_test.cpp
+++ b/test/target_interfaces/ispritehandler_test.cpp
@@ -200,6 +200,25 @@ TEST_F(ISpriteHandlerTest, BubbleText)
     EXPECT_CALL(m_handler, onBubbleTextChanged("test"));
     EXPECT_CALL(m_engine, requestRedraw());
     m_sprite.setBubbleText("test");
+
+    // The text should be processed in Target::setBubbleText() (#571)
+    std::string longstr =
+        "EY8OUNzAqwgh7NRGk5TzCP3dkAhJy9TX"
+        "Y9mqKElPjdQpKddYqjyCwUk2hx6YgVZV"
+        "6BOdmZGxDMs8Hjv8W9G6j4gTxAWdOkzs"
+        "8Ih80xzEDbvLilWsDwoB6FxH2kVVI4xs"
+        "IXOETNQ6QMsCKLWc5XjHk2BS9nYvDGpJ"
+        "uEmp9zIzFGT1kRSrOlU3ZwnN1YtvqFx"
+        "3hkWVNtJ71dQ0PJHhOVQPUy19V01SPu3"
+        "KIIS2wdSUVAc4RYMzepSveghzWbdcizy"
+        "Tm1KKAj4svu9YoL8b9vsolG8gKunvKO7"
+        "MurRKSeUbECELnJEKV6683xCq7RvmjAu"
+        "2djZ54apiQc1lTixWns5GoG0SVNuFzHl"
+        "q97qUiqiMecjVFM51YVif7c1Stip52Hl";
+
+    EXPECT_CALL(m_handler, onBubbleTextChanged(longstr.substr(0, 330)));
+    EXPECT_CALL(m_engine, requestRedraw());
+    m_sprite.setBubbleText(longstr);
 }
 
 TEST_F(ISpriteHandlerTest, BoundingRect)
diff --git a/test/target_interfaces/istagehandler_test.cpp b/test/target_interfaces/istagehandler_test.cpp
index 242211ec..43038a22 100644
--- a/test/target_interfaces/istagehandler_test.cpp
+++ b/test/target_interfaces/istagehandler_test.cpp
@@ -83,6 +83,25 @@ TEST_F(IStageHandlerTest, BubbleText)
     EXPECT_CALL(m_handler, onBubbleTextChanged("test"));
     EXPECT_CALL(m_engine, requestRedraw());
     m_stage.setBubbleText("test");
+
+    // The text should be processed in Target::setBubbleText() (#571)
+    std::string longstr =
+        "EY8OUNzAqwgh7NRGk5TzCP3dkAhJy9TX"
+        "Y9mqKElPjdQpKddYqjyCwUk2hx6YgVZV"
+        "6BOdmZGxDMs8Hjv8W9G6j4gTxAWdOkzs"
+        "8Ih80xzEDbvLilWsDwoB6FxH2kVVI4xs"
+        "IXOETNQ6QMsCKLWc5XjHk2BS9nYvDGpJ"
+        "uEmp9zIzFGT1kRSrOlU3ZwnN1YtvqFx"
+        "3hkWVNtJ71dQ0PJHhOVQPUy19V01SPu3"
+        "KIIS2wdSUVAc4RYMzepSveghzWbdcizy"
+        "Tm1KKAj4svu9YoL8b9vsolG8gKunvKO7"
+        "MurRKSeUbECELnJEKV6683xCq7RvmjAu"
+        "2djZ54apiQc1lTixWns5GoG0SVNuFzHl"
+        "q97qUiqiMecjVFM51YVif7c1Stip52Hl";
+
+    EXPECT_CALL(m_handler, onBubbleTextChanged(longstr.substr(0, 330)));
+    EXPECT_CALL(m_engine, requestRedraw());
+    m_stage.setBubbleText(longstr);
 }
 
 TEST_F(IStageHandlerTest, BoundingRect)

From 908249c1ffa11b785a8cf997541fdadee4f6e778 Mon Sep 17 00:00:00 2001
From: adazem009 <68537469+adazem009@users.noreply.github.com>
Date: Fri, 6 Sep 2024 12:05:09 +0200
Subject: [PATCH 4/9] fix #478: Format bubble text according to Scratch 2.0

---
 src/scratch/target.cpp               | 15 ++++++++++++-
 test/scratch_classes/target_test.cpp | 32 ++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/src/scratch/target.cpp b/src/scratch/target.cpp
index 1e9f4b46..8ab8bd35 100644
--- a/src/scratch/target.cpp
+++ b/src/scratch/target.cpp
@@ -570,8 +570,21 @@ const std::string &Target::bubbleText() const
  */
 void Target::setBubbleText(const std::string &text)
 {
+    // https://github.com/scratchfoundation/scratch-vm/blob/7313ce5199f8a3da7850085d0f7f6a3ca2c89bf6/src/blocks/scratch3_looks.js#L251-L257
+    const Value v(text);
+    std::string converted = text;
+
+    // Non-integers should be rounded to 2 decimal places (no more, no less), unless they're small enough that rounding would display them as 0.00.
+    if (v.isValidNumber()) {
+        const double num = v.toDouble();
+
+        if (std::abs(num) >= 0.01 && (v % 1).toDouble() != 0)
+            converted = Value(std::round(num * 100) / 100).toString();
+    }
+
+    // Limit the length of the string
     size_t limit = 330;
-    impl->bubbleText = text.substr(0, limit);
+    impl->bubbleText = converted.substr(0, limit);
 }
 
 /*! Returns the engine. */
diff --git a/test/scratch_classes/target_test.cpp b/test/scratch_classes/target_test.cpp
index e71771d2..6c195ffb 100644
--- a/test/scratch_classes/target_test.cpp
+++ b/test/scratch_classes/target_test.cpp
@@ -780,6 +780,38 @@ TEST(TargetTest, BubbleText)
     target.setBubbleText(longstr);
     ASSERT_EQ(target.bubbleText().length(), 330);
     ASSERT_EQ(target.bubbleText(), longstr.substr(0, 330));
+
+    // Integers should be left unchanged
+    target.setBubbleText("8");
+    ASSERT_EQ(target.bubbleText(), "8");
+
+    target.setBubbleText("-52");
+    ASSERT_EQ(target.bubbleText(), "-52");
+
+    target.setBubbleText("0");
+    ASSERT_EQ(target.bubbleText(), "0");
+
+    // Non-integers should be rounded to 2 decimal places (no more, no less), unless they're small enough that rounding would display them as 0.00 (#478)
+    target.setBubbleText("8.324");
+    ASSERT_EQ(target.bubbleText(), "8.32");
+
+    target.setBubbleText("-52.576");
+    ASSERT_EQ(target.bubbleText(), "-52.58");
+
+    target.setBubbleText("3.5");
+    ASSERT_EQ(target.bubbleText(), "3.5");
+
+    target.setBubbleText("0.015");
+    ASSERT_EQ(target.bubbleText(), "0.02");
+
+    target.setBubbleText("-0.015");
+    ASSERT_EQ(target.bubbleText(), "-0.02");
+
+    target.setBubbleText("0.005");
+    ASSERT_EQ(target.bubbleText(), "0.005");
+
+    target.setBubbleText("-0.005");
+    ASSERT_EQ(target.bubbleText(), "-0.005");
 }
 
 TEST(TargetTest, Engine)

From 9cc953cac70dabf09521613e71abceadf475d8d5 Mon Sep 17 00:00:00 2001
From: adazem009 <68537469+adazem009@users.noreply.github.com>
Date: Fri, 6 Sep 2024 13:08:02 +0200
Subject: [PATCH 5/9] Drop switch costume/backdrop optimizations

They make the code too complex
---
 src/blocks/looksblocks.cpp        | 141 +-----
 src/blocks/looksblocks.h          |   4 -
 test/blocks/looks_blocks_test.cpp | 764 ++----------------------------
 3 files changed, 42 insertions(+), 867 deletions(-)

diff --git a/src/blocks/looksblocks.cpp b/src/blocks/looksblocks.cpp
index fb55f39d..7d4b07fd 100644
--- a/src/blocks/looksblocks.cpp
+++ b/src/blocks/looksblocks.cpp
@@ -347,36 +347,8 @@ void LooksBlocks::compileSwitchCostumeTo(Compiler *compiler)
     if (!target)
         return;
 
-    Input *input = compiler->input(COSTUME);
-
-    if (input->pointsToDropdownMenu()) {
-        std::string value = input->selectedMenuItem();
-        int index = target->findCostume(value);
-
-        if (index == -1) {
-            if (value == "next costume")
-                compiler->addFunctionCall(&nextCostume);
-            else if (value == "previous costume")
-                compiler->addFunctionCall(&previousCostume);
-            else {
-                Value v(value);
-
-                if (v.type() == Value::Type::Integer) {
-                    compiler->addConstValue(v.toLong() - 1);
-                    compiler->addFunctionCall(&switchCostumeToByIndex);
-                } else {
-                    compiler->addInput(input);
-                    compiler->addFunctionCall(&switchCostumeTo);
-                }
-            }
-        } else {
-            compiler->addConstValue(index);
-            compiler->addFunctionCall(&switchCostumeToByIndex);
-        }
-    } else {
-        compiler->addInput(input);
-        compiler->addFunctionCall(&switchCostumeTo);
-    }
+    compiler->addInput(COSTUME);
+    compiler->addFunctionCall(&switchCostumeTo);
 }
 
 void LooksBlocks::compileNextCostume(Compiler *compiler)
@@ -386,85 +358,14 @@ void LooksBlocks::compileNextCostume(Compiler *compiler)
 
 void LooksBlocks::compileSwitchBackdropTo(Compiler *compiler)
 {
-    Stage *stage = compiler->engine()->stage();
-
-    if (!stage)
-        return;
-
-    Input *input = compiler->input(BACKDROP);
-
-    if (input->pointsToDropdownMenu()) {
-        std::string value = input->selectedMenuItem();
-        int index = stage->findCostume(value);
-
-        if (index == -1) {
-            if (value == "next backdrop")
-                compiler->addFunctionCall(&nextBackdrop);
-            else if (value == "previous backdrop")
-                compiler->addFunctionCall(&previousBackdrop);
-            else if (value == "random backdrop")
-                compiler->addFunctionCall(&randomBackdrop);
-            else {
-                Value v(value);
-
-                if (v.type() == Value::Type::Integer) {
-                    compiler->addConstValue(v.toLong() - 1);
-                    compiler->addFunctionCall(&switchBackdropToByIndex);
-                } else {
-                    compiler->addInput(input);
-                    compiler->addFunctionCall(&switchBackdropTo);
-                }
-            }
-        } else {
-            compiler->addConstValue(index);
-            compiler->addFunctionCall(&switchBackdropToByIndex);
-        }
-    } else {
-        compiler->addInput(input);
-        compiler->addFunctionCall(&switchBackdropTo);
-    }
+    compiler->addInput(BACKDROP);
+    compiler->addFunctionCall(&switchBackdropTo);
 }
 
 void LooksBlocks::compileSwitchBackdropToAndWait(Compiler *compiler)
 {
-    Stage *stage = compiler->engine()->stage();
-
-    if (!stage)
-        return;
-
-    Input *input = compiler->input(BACKDROP);
-
-    if (input->pointsToDropdownMenu()) {
-        std::string value = input->selectedMenuItem();
-        int index = stage->findCostume(value);
-
-        if (index == -1) {
-            if (value == "next backdrop")
-                compiler->addFunctionCall(&nextBackdropAndWait);
-            else if (value == "previous backdrop")
-                compiler->addFunctionCall(&previousBackdropAndWait);
-            else if (value == "random backdrop")
-                compiler->addFunctionCall(&randomBackdropAndWait);
-            else {
-                Value v(value);
-
-                if (v.type() == Value::Type::Integer) {
-                    compiler->addConstValue(v.toLong() - 1);
-                    compiler->addFunctionCall(&switchBackdropToByIndexAndWait);
-                } else {
-                    compiler->addInput(input);
-                    compiler->addFunctionCall(&switchBackdropToAndWait);
-                }
-            }
-        } else {
-            compiler->addConstValue(index);
-            compiler->addFunctionCall(&switchBackdropToByIndexAndWait);
-        }
-    } else {
-        compiler->addInput(input);
-        compiler->addFunctionCall(&switchBackdropToAndWait);
-    }
-
+    compiler->addInput(BACKDROP);
+    compiler->addFunctionCall(&switchBackdropToAndWait);
     compiler->addFunctionCall(&backdropNumber);
     compiler->addFunctionCall(&checkBackdropScripts);
 }
@@ -932,14 +833,6 @@ void LooksBlocks::setCostumeByIndex(Target *target, long index)
     target->setCostumeIndex(index);
 }
 
-unsigned int LooksBlocks::switchCostumeToByIndex(VirtualMachine *vm)
-{
-    if (Target *target = vm->target())
-        setCostumeByIndex(target, vm->getInput(0, 1)->toLong());
-
-    return 1;
-}
-
 unsigned int LooksBlocks::switchCostumeTo(VirtualMachine *vm)
 {
     Target *target = vm->target();
@@ -990,12 +883,6 @@ void LooksBlocks::startBackdropScripts(VirtualMachine *vm, bool wait)
     }
 }
 
-void LooksBlocks::switchBackdropToByIndexImpl(VirtualMachine *vm)
-{
-    if (Stage *stage = vm->engine()->stage())
-        setCostumeByIndex(stage, vm->getInput(0, 1)->toLong());
-}
-
 void LooksBlocks::switchBackdropToImpl(VirtualMachine *vm)
 {
     Stage *stage = vm->engine()->stage();
@@ -1047,14 +934,6 @@ void LooksBlocks::randomBackdropImpl(VirtualMachine *vm)
     }
 }
 
-unsigned int LooksBlocks::switchBackdropToByIndex(VirtualMachine *vm)
-{
-    switchBackdropToByIndexImpl(vm);
-    startBackdropScripts(vm, false);
-
-    return 1;
-}
-
 unsigned int LooksBlocks::switchBackdropTo(VirtualMachine *vm)
 {
     switchBackdropToImpl(vm);
@@ -1063,14 +942,6 @@ unsigned int LooksBlocks::switchBackdropTo(VirtualMachine *vm)
     return 1;
 }
 
-unsigned int LooksBlocks::switchBackdropToByIndexAndWait(VirtualMachine *vm)
-{
-    switchBackdropToByIndexImpl(vm);
-    startBackdropScripts(vm, true);
-
-    return 1;
-}
-
 unsigned int LooksBlocks::switchBackdropToAndWait(VirtualMachine *vm)
 {
     switchBackdropToImpl(vm);
diff --git a/src/blocks/looksblocks.h b/src/blocks/looksblocks.h
index 60d54fc5..5d3e147d 100644
--- a/src/blocks/looksblocks.h
+++ b/src/blocks/looksblocks.h
@@ -129,21 +129,17 @@ class LooksBlocks : public IBlockSection
         static unsigned int size(VirtualMachine *vm);
 
         static void setCostumeByIndex(Target *target, long index);
-        static unsigned int switchCostumeToByIndex(VirtualMachine *vm);
         static unsigned int switchCostumeTo(VirtualMachine *vm);
         static unsigned int nextCostume(VirtualMachine *vm);
         static unsigned int previousCostume(VirtualMachine *vm);
 
         static void startBackdropScripts(VirtualMachine *vm, bool wait);
-        static void switchBackdropToByIndexImpl(VirtualMachine *vm);
         static void switchBackdropToImpl(VirtualMachine *vm);
         static void nextBackdropImpl(VirtualMachine *vm);
         static void previousBackdropImpl(VirtualMachine *vm);
         static void randomBackdropImpl(VirtualMachine *vm);
 
-        static unsigned int switchBackdropToByIndex(VirtualMachine *vm);
         static unsigned int switchBackdropTo(VirtualMachine *vm);
-        static unsigned int switchBackdropToByIndexAndWait(VirtualMachine *vm);
         static unsigned int switchBackdropToAndWait(VirtualMachine *vm);
         static unsigned int nextBackdrop(VirtualMachine *vm);
         static unsigned int nextBackdropAndWait(VirtualMachine *vm);
diff --git a/test/blocks/looks_blocks_test.cpp b/test/blocks/looks_blocks_test.cpp
index 950187b7..71012c78 100644
--- a/test/blocks/looks_blocks_test.cpp
+++ b/test/blocks/looks_blocks_test.cpp
@@ -1426,159 +1426,24 @@ TEST_F(LooksBlocksTest, SwitchCostumeTo)
     auto block1 = std::make_shared<Block>("a", "looks_switchcostumeto");
     addDropdownInput(block1, "COSTUME", LooksBlocks::COSTUME, "costume2");
 
-    // switch costume to (0)
-    auto block2 = std::make_shared<Block>("b", "looks_switchcostumeto");
-    addDropdownInput(block2, "COSTUME", LooksBlocks::COSTUME, "0");
-
-    // switch costume to (1)
-    auto block3 = std::make_shared<Block>("b", "looks_switchcostumeto");
-    addDropdownInput(block3, "COSTUME", LooksBlocks::COSTUME, "1");
-
-    // switch costume to (2)
-    auto block4 = std::make_shared<Block>("b", "looks_switchcostumeto");
-    addDropdownInput(block4, "COSTUME", LooksBlocks::COSTUME, "2");
-
-    // switch costume to (4)
-    auto block5 = std::make_shared<Block>("b", "looks_switchcostumeto");
-    addDropdownInput(block5, "COSTUME", LooksBlocks::COSTUME, "4");
-
-    // switch costume to (3) - there's a costume with this name
-    auto block6 = std::make_shared<Block>("c", "looks_switchcostumeto");
-    addDropdownInput(block6, "COSTUME", LooksBlocks::COSTUME, "3");
-
-    // switch costume to (next costume)
-    auto block7 = std::make_shared<Block>("d", "looks_switchcostumeto");
-    addDropdownInput(block7, "COSTUME", LooksBlocks::COSTUME, "next costume");
-
-    // switch costume to (next costume) - there's a costume with this name
-    auto block8 = std::make_shared<Block>("d", "looks_switchcostumeto");
-    addDropdownInput(block8, "COSTUME", LooksBlocks::COSTUME, "next costume");
-
-    // switch costume to (previous costume)
-    auto block9 = std::make_shared<Block>("e", "looks_switchcostumeto");
-    addDropdownInput(block9, "COSTUME", LooksBlocks::COSTUME, "previous costume");
-
-    // switch costume to (previous costume) - there's a costume with this name
-    auto block10 = std::make_shared<Block>("f", "looks_switchcostumeto");
-    addDropdownInput(block10, "COSTUME", LooksBlocks::COSTUME, "previous costume");
-
     // switch costume to (null block)
-    auto block11 = std::make_shared<Block>("g", "looks_switchcostumeto");
-    addDropdownInput(block11, "COSTUME", LooksBlocks::COSTUME, "", createNullBlock("h"));
+    auto block2 = std::make_shared<Block>("b", "looks_switchcostumeto");
+    addDropdownInput(block2, "COSTUME", LooksBlocks::COSTUME, "", createNullBlock("c"));
 
     compiler.init();
 
-    // Test without any costumes first
     compiler.setBlock(block1);
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchCostumeTo)).WillOnce(Return(3));
+    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchCostumeTo)).WillOnce(Return(0));
     LooksBlocks::compileSwitchCostumeTo(&compiler);
 
-    target.addCostume(std::make_shared<Costume>("costume1", "c1", "svg"));
-    target.addCostume(std::make_shared<Costume>("costume2", "c2", "svg"));
-
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchCostumeToByIndex)).WillOnce(Return(0));
-    compiler.setBlock(block1);
-    LooksBlocks::compileSwitchCostumeTo(&compiler);
-
-    target.addCostume(std::make_shared<Costume>("costume3", "c3", "svg"));
-
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchCostumeTo)).WillOnce(Return(3));
+    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchCostumeTo)).WillOnce(Return(0));
     compiler.setBlock(block2);
     LooksBlocks::compileSwitchCostumeTo(&compiler);
 
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchCostumeTo)).WillOnce(Return(3));
-    compiler.setBlock(block3);
-    LooksBlocks::compileSwitchCostumeTo(&compiler);
-
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchCostumeTo)).WillOnce(Return(3));
-    compiler.setBlock(block4);
-    LooksBlocks::compileSwitchCostumeTo(&compiler);
-
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchCostumeTo)).WillOnce(Return(3));
-    compiler.setBlock(block5);
-    LooksBlocks::compileSwitchCostumeTo(&compiler);
-
-    target.addCostume(std::make_shared<Costume>("3", "c4", "svg"));
-
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchCostumeToByIndex)).WillOnce(Return(0));
-    compiler.setBlock(block6);
-    LooksBlocks::compileSwitchCostumeTo(&compiler);
-
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::nextCostume)).WillOnce(Return(1));
-    compiler.setBlock(block7);
-    LooksBlocks::compileSwitchCostumeTo(&compiler);
-
-    target.addCostume(std::make_shared<Costume>("next costume", "c5", "svg"));
-
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchCostumeToByIndex)).WillOnce(Return(0));
-    compiler.setBlock(block8);
-    LooksBlocks::compileSwitchCostumeTo(&compiler);
-
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::previousCostume)).WillOnce(Return(2));
-    compiler.setBlock(block9);
-    LooksBlocks::compileSwitchCostumeTo(&compiler);
-
-    target.addCostume(std::make_shared<Costume>("previous costume", "c6", "svg"));
-
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchCostumeToByIndex)).WillOnce(Return(0));
-    compiler.setBlock(block10);
-    LooksBlocks::compileSwitchCostumeTo(&compiler);
-
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchCostumeTo)).WillOnce(Return(3));
-    compiler.setBlock(block11);
-    LooksBlocks::compileSwitchCostumeTo(&compiler);
-
     compiler.end();
 
-    ASSERT_EQ(
-        compiler.bytecode(),
-        std::vector<unsigned int>(
-            { vm::OP_START,
-              vm::OP_CONST,
-              0,
-              vm::OP_EXEC,
-              3,
-              vm::OP_CONST,
-              1,
-              vm::OP_EXEC,
-              0,
-              vm::OP_CONST,
-              2,
-              vm::OP_EXEC,
-              3,
-              vm::OP_CONST,
-              3,
-              vm::OP_EXEC,
-              3,
-              vm::OP_CONST,
-              4,
-              vm::OP_EXEC,
-              3,
-              vm::OP_CONST,
-              5,
-              vm::OP_EXEC,
-              3,
-              vm::OP_CONST,
-              6,
-              vm::OP_EXEC,
-              0,
-              vm::OP_EXEC,
-              1,
-              vm::OP_CONST,
-              7,
-              vm::OP_EXEC,
-              0,
-              vm::OP_EXEC,
-              2,
-              vm::OP_CONST,
-              8,
-              vm::OP_EXEC,
-              0,
-              vm::OP_NULL,
-              vm::OP_EXEC,
-              3,
-              vm::OP_HALT }));
-    ASSERT_EQ(compiler.constValues(), std::vector<Value>({ "costume2", 1, "0", "1", "2", "4", 3, 4, 5 }));
+    ASSERT_EQ(compiler.bytecode(), std::vector<unsigned int>({ vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_NULL, vm::OP_EXEC, 0, vm::OP_HALT }));
+    ASSERT_EQ(compiler.constValues(), std::vector<Value>({ "costume2" }));
 }
 
 TEST_F(LooksBlocksTest, SwitchCostumeToImpl)
@@ -1591,12 +1456,8 @@ TEST_F(LooksBlocksTest, SwitchCostumeToImpl)
     static unsigned int bytecode6[] = { vm::OP_START, vm::OP_CONST, 3, vm::OP_EXEC, 0, vm::OP_HALT };
     static unsigned int bytecode7[] = { vm::OP_START, vm::OP_CONST, 5, vm::OP_EXEC, 0, vm::OP_HALT };
     static unsigned int bytecode8[] = { vm::OP_START, vm::OP_CONST, 6, vm::OP_EXEC, 0, vm::OP_HALT };
-    static unsigned int bytecode9[] = { vm::OP_START, vm::OP_CONST, 7, vm::OP_EXEC, 1, vm::OP_HALT };
-    static unsigned int bytecode10[] = { vm::OP_START, vm::OP_CONST, 8, vm::OP_EXEC, 1, vm::OP_HALT };
-    static unsigned int bytecode11[] = { vm::OP_START, vm::OP_CONST, 9, vm::OP_EXEC, 1, vm::OP_HALT };
-    static unsigned int bytecode12[] = { vm::OP_START, vm::OP_CONST, 10, vm::OP_EXEC, 1, vm::OP_HALT };
-    static BlockFunc functions[] = { &LooksBlocks::switchCostumeTo, &LooksBlocks::switchCostumeToByIndex };
-    static Value constValues[] = { "costume2", 0, 1, 2, 3, "next costume", "previous costume", -1, 0, 5, 6 };
+    static BlockFunc functions[] = { &LooksBlocks::switchCostumeTo };
+    static Value constValues[] = { "costume2", 0, 1, 2, 3, "next costume", "previous costume" };
 
     Target target;
     target.addCostume(std::make_shared<Costume>("costume1", "c1", "svg"));
@@ -1718,36 +1579,6 @@ TEST_F(LooksBlocksTest, SwitchCostumeToImpl)
 
     ASSERT_EQ(vm.registerCount(), 0);
     ASSERT_EQ(target.costumeIndex(), 5);
-
-    // -1 (index)
-    target.setCostumeIndex(1);
-
-    vm.setBytecode(bytecode9);
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_EQ(target.costumeIndex(), 5);
-
-    // 0 (index)
-    vm.setBytecode(bytecode10);
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_EQ(target.costumeIndex(), 0);
-
-    // 5 (index)
-    vm.setBytecode(bytecode11);
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_EQ(target.costumeIndex(), 5);
-
-    // 6 (index)
-    vm.setBytecode(bytecode12);
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_EQ(target.costumeIndex(), 0);
 }
 
 TEST_F(LooksBlocksTest, NextCostume)
@@ -1834,204 +1665,30 @@ TEST_F(LooksBlocksTest, PreviousCostume)
 TEST_F(LooksBlocksTest, SwitchBackdropTo)
 {
     Target target;
-    Stage stage;
     Compiler compiler(&m_engineMock, &target);
 
     // switch backdrop to (backdrop2)
     auto block1 = std::make_shared<Block>("a", "looks_switchbackdropto");
     addDropdownInput(block1, "BACKDROP", LooksBlocks::BACKDROP, "backdrop2");
 
-    // switch backdrop to (0)
-    auto block2 = std::make_shared<Block>("b", "looks_switchbackdropto");
-    addDropdownInput(block2, "BACKDROP", LooksBlocks::BACKDROP, "0");
-
-    // switch backdrop to (1)
-    auto block3 = std::make_shared<Block>("b", "looks_switchbackdropto");
-    addDropdownInput(block3, "BACKDROP", LooksBlocks::BACKDROP, "1");
-
-    // switch backdrop to (2)
-    auto block4 = std::make_shared<Block>("b", "looks_switchbackdropto");
-    addDropdownInput(block4, "BACKDROP", LooksBlocks::BACKDROP, "2");
-
-    // switch backdrop to (4)
-    auto block5 = std::make_shared<Block>("b", "looks_switchbackdropto");
-    addDropdownInput(block5, "BACKDROP", LooksBlocks::BACKDROP, "4");
-
-    // switch backdrop to (3) - there's a backdrop with this name
-    auto block6 = std::make_shared<Block>("c", "looks_switchbackdropto");
-    addDropdownInput(block6, "BACKDROP", LooksBlocks::BACKDROP, "3");
-
-    // switch backdrop to (next backdrop)
-    auto block7 = std::make_shared<Block>("d", "looks_switchbackdropto");
-    addDropdownInput(block7, "BACKDROP", LooksBlocks::BACKDROP, "next backdrop");
-
-    // switch backdrop to (next backdrop) - there's a backdrop with this name
-    auto block8 = std::make_shared<Block>("d", "looks_switchbackdropto");
-    addDropdownInput(block8, "BACKDROP", LooksBlocks::BACKDROP, "next backdrop");
-
-    // switch backdrop to (previous backdrop)
-    auto block9 = std::make_shared<Block>("e", "looks_switchbackdropto");
-    addDropdownInput(block9, "BACKDROP", LooksBlocks::BACKDROP, "previous backdrop");
-
-    // switch backdrop to (previous backdrop) - there's a backdrop with this name
-    auto block10 = std::make_shared<Block>("f", "looks_switchbackdropto");
-    addDropdownInput(block10, "BACKDROP", LooksBlocks::BACKDROP, "previous backdrop");
-
-    // switch backdrop to (random backdrop)
-    auto block11 = std::make_shared<Block>("g", "looks_switchbackdropto");
-    addDropdownInput(block11, "BACKDROP", LooksBlocks::BACKDROP, "random backdrop");
-
-    // switch backdrop to (random backdrop) - there's a backdrop with this name
-    auto block12 = std::make_shared<Block>("h", "looks_switchbackdropto");
-    addDropdownInput(block12, "BACKDROP", LooksBlocks::BACKDROP, "random backdrop");
-
     // switch backdrop to (null block)
-    auto block13 = std::make_shared<Block>("i", "looks_switchbackdropto");
-    addDropdownInput(block13, "BACKDROP", LooksBlocks::BACKDROP, "", createNullBlock("j"));
+    auto block2 = std::make_shared<Block>("b", "looks_switchbackdropto");
+    addDropdownInput(block2, "BACKDROP", LooksBlocks::BACKDROP, "", createNullBlock("c"));
 
     compiler.init();
 
-    // Test without any backdrops first
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropTo)).WillOnce(Return(4));
+    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropTo)).WillOnce(Return(0));
     compiler.setBlock(block1);
     LooksBlocks::compileSwitchBackdropTo(&compiler);
 
-    stage.addCostume(std::make_shared<Costume>("backdrop1", "b1", "svg"));
-    stage.addCostume(std::make_shared<Costume>("backdrop2", "b2", "svg"));
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToByIndex)).WillOnce(Return(0));
-    compiler.setBlock(block1);
-    LooksBlocks::compileSwitchBackdropTo(&compiler);
-
-    stage.addCostume(std::make_shared<Costume>("backdrop3", "b3", "svg"));
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropTo)).WillOnce(Return(4));
+    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropTo)).WillOnce(Return(0));
     compiler.setBlock(block2);
     LooksBlocks::compileSwitchBackdropTo(&compiler);
 
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropTo)).WillOnce(Return(4));
-    compiler.setBlock(block3);
-    LooksBlocks::compileSwitchBackdropTo(&compiler);
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropTo)).WillOnce(Return(4));
-    compiler.setBlock(block4);
-    LooksBlocks::compileSwitchBackdropTo(&compiler);
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropTo)).WillOnce(Return(4));
-    compiler.setBlock(block5);
-    LooksBlocks::compileSwitchBackdropTo(&compiler);
-
-    stage.addCostume(std::make_shared<Costume>("3", "b4", "svg"));
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToByIndex)).WillOnce(Return(0));
-    compiler.setBlock(block6);
-    LooksBlocks::compileSwitchBackdropTo(&compiler);
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::nextBackdrop)).WillOnce(Return(1));
-    compiler.setBlock(block7);
-    LooksBlocks::compileSwitchBackdropTo(&compiler);
-
-    stage.addCostume(std::make_shared<Costume>("next backdrop", "b5", "svg"));
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToByIndex)).WillOnce(Return(0));
-    compiler.setBlock(block8);
-    LooksBlocks::compileSwitchBackdropTo(&compiler);
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::previousBackdrop)).WillOnce(Return(2));
-    compiler.setBlock(block9);
-    LooksBlocks::compileSwitchBackdropTo(&compiler);
-
-    stage.addCostume(std::make_shared<Costume>("previous backdrop", "b6", "svg"));
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToByIndex)).WillOnce(Return(0));
-    compiler.setBlock(block10);
-    LooksBlocks::compileSwitchBackdropTo(&compiler);
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::randomBackdrop)).WillOnce(Return(3));
-    compiler.setBlock(block11);
-    LooksBlocks::compileSwitchBackdropTo(&compiler);
-
-    stage.addCostume(std::make_shared<Costume>("random backdrop", "b7", "svg"));
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToByIndex)).WillOnce(Return(0));
-    compiler.setBlock(block12);
-    LooksBlocks::compileSwitchBackdropTo(&compiler);
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropTo)).WillOnce(Return(4));
-    compiler.setBlock(block13);
-    LooksBlocks::compileSwitchBackdropTo(&compiler);
-
     compiler.end();
 
-    ASSERT_EQ(
-        compiler.bytecode(),
-        std::vector<unsigned int>(
-            { vm::OP_START,
-              vm::OP_CONST,
-              0,
-              vm::OP_EXEC,
-              4,
-              vm::OP_CONST,
-              1,
-              vm::OP_EXEC,
-              0,
-              vm::OP_CONST,
-              2,
-              vm::OP_EXEC,
-              4,
-              vm::OP_CONST,
-              3,
-              vm::OP_EXEC,
-              4,
-              vm::OP_CONST,
-              4,
-              vm::OP_EXEC,
-              4,
-              vm::OP_CONST,
-              5,
-              vm::OP_EXEC,
-              4,
-              vm::OP_CONST,
-              6,
-              vm::OP_EXEC,
-              0,
-              vm::OP_EXEC,
-              1,
-              vm::OP_CONST,
-              7,
-              vm::OP_EXEC,
-              0,
-              vm::OP_EXEC,
-              2,
-              vm::OP_CONST,
-              8,
-              vm::OP_EXEC,
-              0,
-              vm::OP_EXEC,
-              3,
-              vm::OP_CONST,
-              9,
-              vm::OP_EXEC,
-              0,
-              vm::OP_NULL,
-              vm::OP_EXEC,
-              4,
-              vm::OP_HALT }));
-    ASSERT_EQ(compiler.constValues(), std::vector<Value>({ "backdrop2", 1, "0", "1", "2", "4", 3, 4, 5, 6 }));
+    ASSERT_EQ(compiler.bytecode(), std::vector<unsigned int>({ vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_NULL, vm::OP_EXEC, 0, vm::OP_HALT }));
+    ASSERT_EQ(compiler.constValues(), std::vector<Value>({ "backdrop2" }));
 }
 
 TEST_F(LooksBlocksTest, SwitchBackdropToImpl)
@@ -2044,12 +1701,8 @@ TEST_F(LooksBlocksTest, SwitchBackdropToImpl)
     static unsigned int bytecode6[] = { vm::OP_START, vm::OP_CONST, 3, vm::OP_EXEC, 0, vm::OP_HALT };
     static unsigned int bytecode7[] = { vm::OP_START, vm::OP_CONST, 5, vm::OP_EXEC, 0, vm::OP_HALT };
     static unsigned int bytecode8[] = { vm::OP_START, vm::OP_CONST, 6, vm::OP_EXEC, 0, vm::OP_HALT };
-    static unsigned int bytecode9[] = { vm::OP_START, vm::OP_CONST, 7, vm::OP_EXEC, 1, vm::OP_HALT };
-    static unsigned int bytecode10[] = { vm::OP_START, vm::OP_CONST, 8, vm::OP_EXEC, 1, vm::OP_HALT };
-    static unsigned int bytecode11[] = { vm::OP_START, vm::OP_CONST, 9, vm::OP_EXEC, 1, vm::OP_HALT };
-    static unsigned int bytecode12[] = { vm::OP_START, vm::OP_CONST, 10, vm::OP_EXEC, 1, vm::OP_HALT };
-    static BlockFunc functions[] = { &LooksBlocks::switchBackdropTo, &LooksBlocks::switchBackdropToByIndex };
-    static Value constValues[] = { "backdrop2", 0, 1, 2, 3, "next backdrop", "previous backdrop", -1, 0, 5, 6 };
+    static BlockFunc functions[] = { &LooksBlocks::switchBackdropTo };
+    static Value constValues[] = { "backdrop2", 0, 1, 2, 3, "next backdrop", "previous backdrop" };
 
     Target target;
 
@@ -2203,349 +1856,55 @@ TEST_F(LooksBlocksTest, SwitchBackdropToImpl)
 
     ASSERT_EQ(vm.registerCount(), 0);
     ASSERT_EQ(stage.costumeIndex(), 5);
-
-    // -1 (index)
-    stage.setCostumeIndex(1);
-
-    EXPECT_CALL(m_engineMock, stage()).Times(2).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(5)->broadcast()));
-    vm.setBytecode(bytecode9);
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_EQ(stage.costumeIndex(), 5);
-
-    // 0 (index)
-    EXPECT_CALL(m_engineMock, stage()).Times(2).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(0)->broadcast()));
-    vm.setBytecode(bytecode10);
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_EQ(stage.costumeIndex(), 0);
-
-    // 5 (index)
-    EXPECT_CALL(m_engineMock, stage()).Times(2).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(5)->broadcast()));
-    vm.setBytecode(bytecode11);
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_EQ(stage.costumeIndex(), 5);
-
-    // 6 (index)
-    EXPECT_CALL(m_engineMock, stage()).Times(2).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(0)->broadcast()));
-    vm.setBytecode(bytecode12);
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_EQ(stage.costumeIndex(), 0);
 }
 
 TEST_F(LooksBlocksTest, SwitchBackdropToAndWait)
 {
     Target target;
-    Stage stage;
     Compiler compiler(&m_engineMock, &target);
 
     // switch backdrop to (backdrop2) and wait
     auto block1 = std::make_shared<Block>("a", "looks_switchbackdroptoandwait");
     addDropdownInput(block1, "BACKDROP", LooksBlocks::BACKDROP, "backdrop2");
 
-    // switch backdrop to (0) and wait
-    auto block2 = std::make_shared<Block>("b", "looks_switchbackdroptoandwait");
-    addDropdownInput(block2, "BACKDROP", LooksBlocks::BACKDROP, "0");
-
-    // switch backdrop to (1) and wait
-    auto block3 = std::make_shared<Block>("b", "looks_switchbackdroptoandwait");
-    addDropdownInput(block3, "BACKDROP", LooksBlocks::BACKDROP, "1");
-
-    // switch backdrop to (2) and wait
-    auto block4 = std::make_shared<Block>("b", "looks_switchbackdroptoandwait");
-    addDropdownInput(block4, "BACKDROP", LooksBlocks::BACKDROP, "2");
-
-    // switch backdrop to (4) and wait
-    auto block5 = std::make_shared<Block>("b", "looks_switchbackdroptoandwait");
-    addDropdownInput(block5, "BACKDROP", LooksBlocks::BACKDROP, "4");
-
-    // switch backdrop to (3) and wait - there's a backdrop with this name
-    auto block6 = std::make_shared<Block>("c", "looks_switchbackdroptoandwait");
-    addDropdownInput(block6, "BACKDROP", LooksBlocks::BACKDROP, "3");
-
-    // switch backdrop to (next backdrop) and wait
-    auto block7 = std::make_shared<Block>("d", "looks_switchbackdroptoandwait");
-    addDropdownInput(block7, "BACKDROP", LooksBlocks::BACKDROP, "next backdrop");
-
-    // switch backdrop to (next backdrop) and wait - there's a backdrop with this name
-    auto block8 = std::make_shared<Block>("d", "looks_switchbackdroptoandwait");
-    addDropdownInput(block8, "BACKDROP", LooksBlocks::BACKDROP, "next backdrop");
-
-    // switch backdrop to (previous backdrop) and wait
-    auto block9 = std::make_shared<Block>("e", "looks_switchbackdroptoandwait");
-    addDropdownInput(block9, "BACKDROP", LooksBlocks::BACKDROP, "previous backdrop");
-
-    // switch backdrop to (previous backdrop) and wait - there's a backdrop with this name
-    auto block10 = std::make_shared<Block>("f", "looks_switchbackdroptoandwait");
-    addDropdownInput(block10, "BACKDROP", LooksBlocks::BACKDROP, "previous backdrop");
-
-    // switch backdrop to (random backdrop) and wait
-    auto block11 = std::make_shared<Block>("g", "looks_switchbackdroptoandwait");
-    addDropdownInput(block11, "BACKDROP", LooksBlocks::BACKDROP, "random backdrop");
-
-    // switch backdrop to (random backdrop) and wait - there's a backdrop with this name
-    auto block12 = std::make_shared<Block>("h", "looks_switchbackdroptoandwait");
-    addDropdownInput(block12, "BACKDROP", LooksBlocks::BACKDROP, "random backdrop");
-
     // switch backdrop to (null block) and wait
-    auto block13 = std::make_shared<Block>("i", "looks_switchbackdroptoandwait");
-    addDropdownInput(block13, "BACKDROP", LooksBlocks::BACKDROP, "", createNullBlock("j"));
+    auto block2 = std::make_shared<Block>("b", "looks_switchbackdroptoandwait");
+    addDropdownInput(block2, "BACKDROP", LooksBlocks::BACKDROP, "", createNullBlock("c"));
 
     compiler.init();
 
-    // Test without any backdrops first
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToAndWait)).WillOnce(Return(4));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::backdropNumber)).WillOnce(Return(6));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::checkBackdropScripts)).WillOnce(Return(5));
+    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToAndWait)).WillOnce(Return(0));
+    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::backdropNumber)).WillOnce(Return(1));
+    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::checkBackdropScripts)).WillOnce(Return(2));
     compiler.setBlock(block1);
     LooksBlocks::compileSwitchBackdropToAndWait(&compiler);
 
-    stage.addCostume(std::make_shared<Costume>("backdrop1", "b1", "svg"));
-    stage.addCostume(std::make_shared<Costume>("backdrop2", "b2", "svg"));
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToByIndexAndWait)).WillOnce(Return(0));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::backdropNumber)).WillOnce(Return(6));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::checkBackdropScripts)).WillOnce(Return(5));
-    compiler.setBlock(block1);
-    LooksBlocks::compileSwitchBackdropToAndWait(&compiler);
-
-    stage.addCostume(std::make_shared<Costume>("backdrop3", "b3", "svg"));
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToAndWait)).WillOnce(Return(4));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::backdropNumber)).WillOnce(Return(6));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::checkBackdropScripts)).WillOnce(Return(5));
+    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToAndWait)).WillOnce(Return(0));
+    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::backdropNumber)).WillOnce(Return(1));
+    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::checkBackdropScripts)).WillOnce(Return(2));
     compiler.setBlock(block2);
     LooksBlocks::compileSwitchBackdropToAndWait(&compiler);
 
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToAndWait)).WillOnce(Return(4));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::backdropNumber)).WillOnce(Return(6));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::checkBackdropScripts)).WillOnce(Return(5));
-    compiler.setBlock(block3);
-    LooksBlocks::compileSwitchBackdropToAndWait(&compiler);
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToAndWait)).WillOnce(Return(4));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::backdropNumber)).WillOnce(Return(6));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::checkBackdropScripts)).WillOnce(Return(5));
-    compiler.setBlock(block4);
-    LooksBlocks::compileSwitchBackdropToAndWait(&compiler);
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToAndWait)).WillOnce(Return(4));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::backdropNumber)).WillOnce(Return(6));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::checkBackdropScripts)).WillOnce(Return(5));
-    compiler.setBlock(block5);
-    LooksBlocks::compileSwitchBackdropToAndWait(&compiler);
-
-    stage.addCostume(std::make_shared<Costume>("3", "b4", "svg"));
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToByIndexAndWait)).WillOnce(Return(0));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::backdropNumber)).WillOnce(Return(6));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::checkBackdropScripts)).WillOnce(Return(5));
-    compiler.setBlock(block6);
-    LooksBlocks::compileSwitchBackdropToAndWait(&compiler);
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::nextBackdropAndWait)).WillOnce(Return(1));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::backdropNumber)).WillOnce(Return(6));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::checkBackdropScripts)).WillOnce(Return(5));
-    compiler.setBlock(block7);
-    LooksBlocks::compileSwitchBackdropToAndWait(&compiler);
-
-    stage.addCostume(std::make_shared<Costume>("next backdrop", "b5", "svg"));
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToByIndexAndWait)).WillOnce(Return(0));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::backdropNumber)).WillOnce(Return(6));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::checkBackdropScripts)).WillOnce(Return(5));
-    compiler.setBlock(block8);
-    LooksBlocks::compileSwitchBackdropToAndWait(&compiler);
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::previousBackdropAndWait)).WillOnce(Return(2));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::backdropNumber)).WillOnce(Return(6));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::checkBackdropScripts)).WillOnce(Return(5));
-    compiler.setBlock(block9);
-    LooksBlocks::compileSwitchBackdropToAndWait(&compiler);
-
-    stage.addCostume(std::make_shared<Costume>("previous backdrop", "b6", "svg"));
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToByIndexAndWait)).WillOnce(Return(0));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::backdropNumber)).WillOnce(Return(6));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::checkBackdropScripts)).WillOnce(Return(5));
-    compiler.setBlock(block10);
-    LooksBlocks::compileSwitchBackdropToAndWait(&compiler);
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::randomBackdropAndWait)).WillOnce(Return(3));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::backdropNumber)).WillOnce(Return(6));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::checkBackdropScripts)).WillOnce(Return(5));
-    compiler.setBlock(block11);
-    LooksBlocks::compileSwitchBackdropToAndWait(&compiler);
-
-    stage.addCostume(std::make_shared<Costume>("random backdrop", "b7", "svg"));
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToByIndexAndWait)).WillOnce(Return(0));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::backdropNumber)).WillOnce(Return(6));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::checkBackdropScripts)).WillOnce(Return(5));
-    compiler.setBlock(block12);
-    LooksBlocks::compileSwitchBackdropToAndWait(&compiler);
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::switchBackdropToAndWait)).WillOnce(Return(4));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::backdropNumber)).WillOnce(Return(6));
-    EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::checkBackdropScripts)).WillOnce(Return(5));
-    compiler.setBlock(block13);
-    LooksBlocks::compileSwitchBackdropToAndWait(&compiler);
-
     compiler.end();
 
     ASSERT_EQ(
         compiler.bytecode(),
-        std::vector<unsigned int>(
-            { vm::OP_START,
-              vm::OP_CONST,
-              0,
-              vm::OP_EXEC,
-              4,
-              vm::OP_EXEC,
-              6,
-              vm::OP_EXEC,
-              5,
-              vm::OP_CONST,
-              1,
-              vm::OP_EXEC,
-              0,
-              vm::OP_EXEC,
-              6,
-              vm::OP_EXEC,
-              5,
-              vm::OP_CONST,
-              2,
-              vm::OP_EXEC,
-              4,
-              vm::OP_EXEC,
-              6,
-              vm::OP_EXEC,
-              5,
-              vm::OP_CONST,
-              3,
-              vm::OP_EXEC,
-              4,
-              vm::OP_EXEC,
-              6,
-              vm::OP_EXEC,
-              5,
-              vm::OP_CONST,
-              4,
-              vm::OP_EXEC,
-              4,
-              vm::OP_EXEC,
-              6,
-              vm::OP_EXEC,
-              5,
-              vm::OP_CONST,
-              5,
-              vm::OP_EXEC,
-              4,
-              vm::OP_EXEC,
-              6,
-              vm::OP_EXEC,
-              5,
-              vm::OP_CONST,
-              6,
-              vm::OP_EXEC,
-              0,
-              vm::OP_EXEC,
-              6,
-              vm::OP_EXEC,
-              5,
-              vm::OP_EXEC,
-              1,
-              vm::OP_EXEC,
-              6,
-              vm::OP_EXEC,
-              5,
-              vm::OP_CONST,
-              7,
-              vm::OP_EXEC,
-              0,
-              vm::OP_EXEC,
-              6,
-              vm::OP_EXEC,
-              5,
-              vm::OP_EXEC,
-              2,
-              vm::OP_EXEC,
-              6,
-              vm::OP_EXEC,
-              5,
-              vm::OP_CONST,
-              8,
-              vm::OP_EXEC,
-              0,
-              vm::OP_EXEC,
-              6,
-              vm::OP_EXEC,
-              5,
-              vm::OP_EXEC,
-              3,
-              vm::OP_EXEC,
-              6,
-              vm::OP_EXEC,
-              5,
-              vm::OP_CONST,
-              9,
-              vm::OP_EXEC,
-              0,
-              vm::OP_EXEC,
-              6,
-              vm::OP_EXEC,
-              5,
-              vm::OP_NULL,
-              vm::OP_EXEC,
-              4,
-              vm::OP_EXEC,
-              6,
-              vm::OP_EXEC,
-              5,
-              vm::OP_HALT }));
-    ASSERT_EQ(compiler.constValues(), std::vector<Value>({ "backdrop2", 1, "0", "1", "2", "4", 3, 4, 5, 6 }));
+        std::vector<unsigned int>({ vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_NULL, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT }));
+    ASSERT_EQ(compiler.constValues(), std::vector<Value>({ "backdrop2" }));
 }
 
 TEST_F(LooksBlocksTest, SwitchBackdropToAndWaitImpl)
 {
-    static unsigned int bytecode1[] = { vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_EXEC, 2, vm::OP_EXEC, 3, vm::OP_HALT };
-    static unsigned int bytecode2[] = { vm::OP_START, vm::OP_CONST, 1, vm::OP_EXEC, 0, vm::OP_EXEC, 2, vm::OP_EXEC, 3, vm::OP_HALT };
-    static unsigned int bytecode3[] = { vm::OP_START, vm::OP_CONST, 2, vm::OP_EXEC, 0, vm::OP_EXEC, 2, vm::OP_EXEC, 3, vm::OP_HALT };
-    static unsigned int bytecode4[] = { vm::OP_START, vm::OP_CONST, 3, vm::OP_EXEC, 0, vm::OP_EXEC, 2, vm::OP_EXEC, 3, vm::OP_HALT };
-    static unsigned int bytecode5[] = { vm::OP_START, vm::OP_CONST, 4, vm::OP_EXEC, 0, vm::OP_EXEC, 2, vm::OP_EXEC, 3, vm::OP_HALT };
-    static unsigned int bytecode6[] = { vm::OP_START, vm::OP_CONST, 3, vm::OP_EXEC, 0, vm::OP_EXEC, 2, vm::OP_EXEC, 3, vm::OP_HALT };
-    static unsigned int bytecode7[] = { vm::OP_START, vm::OP_CONST, 5, vm::OP_EXEC, 0, vm::OP_EXEC, 2, vm::OP_EXEC, 3, vm::OP_HALT };
-    static unsigned int bytecode8[] = { vm::OP_START, vm::OP_CONST, 6, vm::OP_EXEC, 0, vm::OP_EXEC, 2, vm::OP_EXEC, 3, vm::OP_HALT };
-    static unsigned int bytecode9[] = { vm::OP_START, vm::OP_CONST, 7, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_EXEC, 3, vm::OP_HALT };
-    static unsigned int bytecode10[] = { vm::OP_START, vm::OP_CONST, 8, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_EXEC, 3, vm::OP_HALT };
-    static unsigned int bytecode11[] = { vm::OP_START, vm::OP_CONST, 9, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_EXEC, 3, vm::OP_HALT };
-    static unsigned int bytecode12[] = { vm::OP_START, vm::OP_CONST, 10, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_EXEC, 3, vm::OP_HALT };
-    static BlockFunc functions[] = { &LooksBlocks::switchBackdropToAndWait, &LooksBlocks::switchBackdropToByIndexAndWait, &LooksBlocks::backdropNumber, &LooksBlocks::checkBackdropScripts };
-    static Value constValues[] = { "backdrop2", 0, 1, 2, 3, "next backdrop", "previous backdrop", -1, 0, 5, 6 };
+    static unsigned int bytecode1[] = { vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode2[] = { vm::OP_START, vm::OP_CONST, 1, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode3[] = { vm::OP_START, vm::OP_CONST, 2, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode4[] = { vm::OP_START, vm::OP_CONST, 3, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode5[] = { vm::OP_START, vm::OP_CONST, 4, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode6[] = { vm::OP_START, vm::OP_CONST, 3, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode7[] = { vm::OP_START, vm::OP_CONST, 5, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode8[] = { vm::OP_START, vm::OP_CONST, 6, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static BlockFunc functions[] = { &LooksBlocks::switchBackdropToAndWait, &LooksBlocks::backdropNumber, &LooksBlocks::checkBackdropScripts };
+    static Value constValues[] = { "backdrop2", 0, 1, 2, 3, "next backdrop", "previous backdrop" };
 
     Target target;
 
@@ -2750,57 +2109,6 @@ TEST_F(LooksBlocksTest, SwitchBackdropToAndWaitImpl)
 
     ASSERT_EQ(vm.registerCount(), 0);
     ASSERT_EQ(stage.costumeIndex(), 5);
-
-    // -1 (index)
-    stage.setCostumeIndex(1);
-
-    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(5)->broadcast()));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(5)->broadcast())).WillOnce(Return(true));
-    vm.setBytecode(bytecode9);
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 1);
-    ASSERT_EQ(stage.costumeIndex(), 5);
-    ASSERT_FALSE(vm.atEnd());
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(5)->broadcast())).WillOnce(Return(false));
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_TRUE(vm.atEnd());
-
-    // 0 (index)
-    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(0)->broadcast()));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(0)->broadcast())).WillOnce(Return(false));
-    vm.setBytecode(bytecode10);
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_EQ(stage.costumeIndex(), 0);
-    ASSERT_TRUE(vm.atEnd());
-
-    // 5 (index)
-    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(5)->broadcast()));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(5)->broadcast())).WillOnce(Return(false));
-    vm.setBytecode(bytecode11);
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_EQ(stage.costumeIndex(), 5);
-
-    // 6 (index)
-    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(0)->broadcast()));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(0)->broadcast())).WillOnce(Return(false));
-    vm.setBytecode(bytecode12);
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_EQ(stage.costumeIndex(), 0);
 }
 
 TEST_F(LooksBlocksTest, NextBackdrop)

From 9edda43bedcc1dd733214ee2940de213c6e4b79d Mon Sep 17 00:00:00 2001
From: adazem009 <68537469+adazem009@users.noreply.github.com>
Date: Fri, 6 Sep 2024 14:30:00 +0200
Subject: [PATCH 6/9] fix #522: Fix switch costume/backdrop block behavior

---
 src/blocks/looksblocks.cpp        |  72 +++++---
 test/blocks/looks_blocks_test.cpp | 276 ++++++++++++++++++++++++++----
 2 files changed, 292 insertions(+), 56 deletions(-)

diff --git a/src/blocks/looksblocks.cpp b/src/blocks/looksblocks.cpp
index 7d4b07fd..6361a5aa 100644
--- a/src/blocks/looksblocks.cpp
+++ b/src/blocks/looksblocks.cpp
@@ -835,26 +835,41 @@ void LooksBlocks::setCostumeByIndex(Target *target, long index)
 
 unsigned int LooksBlocks::switchCostumeTo(VirtualMachine *vm)
 {
+    // https://github.com/scratchfoundation/scratch-vm/blob/8dbcc1fc8f8d8c4f1e40629fe8a388149d6dfd1c/src/blocks/scratch3_looks.js#L389-L413
     Target *target = vm->target();
 
     if (!target)
         return 1;
 
     const Value *name = vm->getInput(0, 1);
-    std::string nameStr = name->toString();
-    int index = target->findCostume(nameStr);
 
-    if (index == -1) {
-        if (nameStr == "next costume")
+    if (!name->isString()) {
+        // Numbers should be treated as costume indices, always
+        if (name->isNaN() || name->isInfinity() || name->isNegativeInfinity())
+            target->setCostumeIndex(0);
+        else
+            setCostumeByIndex(target, name->toLong() - 1);
+    } else {
+        // Strings should be treated as costume names, where possible
+        const int costumeIndex = target->findCostume(name->toString());
+        std::string nameStr = name->toString();
+
+        auto it = std::find_if(nameStr.begin(), nameStr.end(), [](char c) { return !std::isspace(c); });
+        bool isWhiteSpace = (it == nameStr.end());
+
+        if (costumeIndex != -1) {
+            setCostumeByIndex(target, costumeIndex);
+        } else if (nameStr == "next costume") {
             nextCostume(vm);
-        else if (nameStr == "previous costume")
+        } else if (nameStr == "previous costume") {
             previousCostume(vm);
-        else {
-            if (name->isValidNumber())
-                setCostumeByIndex(target, name->toLong() - 1);
+            // Try to cast the string to a number (and treat it as a costume index)
+            // Pure whitespace should not be treated as a number
+            // Note: isNaN will cast the string to a number before checking if it's NaN
+        } else if (!(name->isNaN() || isWhiteSpace)) {
+            target->setCostumeIndex(name->toInt() - 1);
         }
-    } else
-        setCostumeByIndex(target, index);
+    }
 
     return 1;
 }
@@ -885,28 +900,43 @@ void LooksBlocks::startBackdropScripts(VirtualMachine *vm, bool wait)
 
 void LooksBlocks::switchBackdropToImpl(VirtualMachine *vm)
 {
+    // https://github.com/scratchfoundation/scratch-vm/blob/8dbcc1fc8f8d8c4f1e40629fe8a388149d6dfd1c/src/blocks/scratch3_looks.js#L423-L462
     Stage *stage = vm->engine()->stage();
 
     if (!stage)
         return;
 
     const Value *name = vm->getInput(0, 1);
-    std::string nameStr = name->toString();
-    int index = stage->findCostume(nameStr);
 
-    if (index == -1) {
-        if (nameStr == "next backdrop")
+    if (!name->isString()) {
+        // Numbers should be treated as costume indices, always
+        if (name->isNaN() || name->isInfinity() || name->isNegativeInfinity())
+            stage->setCostumeIndex(0);
+        else
+            setCostumeByIndex(stage, name->toLong() - 1);
+    } else {
+        // Strings should be treated as costume names, where possible
+        const int costumeIndex = stage->findCostume(name->toString());
+        std::string nameStr = name->toString();
+
+        auto it = std::find_if(nameStr.begin(), nameStr.end(), [](char c) { return !std::isspace(c); });
+        bool isWhiteSpace = (it == nameStr.end());
+
+        if (costumeIndex != -1) {
+            setCostumeByIndex(stage, costumeIndex);
+        } else if (nameStr == "next backdrop") {
             nextBackdropImpl(vm);
-        else if (nameStr == "previous backdrop")
+        } else if (nameStr == "previous backdrop") {
             previousBackdropImpl(vm);
-        else if (nameStr == "random backdrop") {
+        } else if (nameStr == "random backdrop") {
             randomBackdropImpl(vm);
-        } else {
-            if (name->isValidNumber())
-                setCostumeByIndex(stage, name->toLong() - 1);
+            // Try to cast the string to a number (and treat it as a costume index)
+            // Pure whitespace should not be treated as a number
+            // Note: isNaN will cast the string to a number before checking if it's NaN
+        } else if (!(name->isNaN() || isWhiteSpace)) {
+            stage->setCostumeIndex(name->toInt() - 1);
         }
-    } else
-        setCostumeByIndex(stage, index);
+    }
 }
 
 void LooksBlocks::nextBackdropImpl(VirtualMachine *vm)
diff --git a/test/blocks/looks_blocks_test.cpp b/test/blocks/looks_blocks_test.cpp
index 71012c78..24f8aede 100644
--- a/test/blocks/looks_blocks_test.cpp
+++ b/test/blocks/looks_blocks_test.cpp
@@ -1453,11 +1453,19 @@ TEST_F(LooksBlocksTest, SwitchCostumeToImpl)
     static unsigned int bytecode3[] = { vm::OP_START, vm::OP_CONST, 2, vm::OP_EXEC, 0, vm::OP_HALT };
     static unsigned int bytecode4[] = { vm::OP_START, vm::OP_CONST, 3, vm::OP_EXEC, 0, vm::OP_HALT };
     static unsigned int bytecode5[] = { vm::OP_START, vm::OP_CONST, 4, vm::OP_EXEC, 0, vm::OP_HALT };
-    static unsigned int bytecode6[] = { vm::OP_START, vm::OP_CONST, 3, vm::OP_EXEC, 0, vm::OP_HALT };
-    static unsigned int bytecode7[] = { vm::OP_START, vm::OP_CONST, 5, vm::OP_EXEC, 0, vm::OP_HALT };
-    static unsigned int bytecode8[] = { vm::OP_START, vm::OP_CONST, 6, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode6[] = { vm::OP_START, vm::OP_CONST, 5, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode7[] = { vm::OP_START, vm::OP_CONST, 6, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode8[] = { vm::OP_START, vm::OP_CONST, 7, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode9[] = { vm::OP_START, vm::OP_CONST, 8, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode10[] = { vm::OP_START, vm::OP_CONST, 9, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode11[] = { vm::OP_START, vm::OP_CONST, 10, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode12[] = { vm::OP_START, vm::OP_CONST, 11, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode13[] = { vm::OP_START, vm::OP_CONST, 12, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode14[] = { vm::OP_START, vm::OP_CONST, 13, vm::OP_EXEC, 0, vm::OP_HALT };
     static BlockFunc functions[] = { &LooksBlocks::switchCostumeTo };
-    static Value constValues[] = { "costume2", 0, 1, 2, 3, "next costume", "previous costume" };
+    static Value constValues[] = {
+        "costume2", 0, 1, 2, 3, "2", "3", Value::SpecialValue::NaN, Value::SpecialValue::Infinity, Value::SpecialValue::NegativeInfinity, "", "   ", "next costume", "previous costume"
+    };
 
     Target target;
     target.addCostume(std::make_shared<Costume>("costume1", "c1", "svg"));
@@ -1513,21 +1521,84 @@ TEST_F(LooksBlocksTest, SwitchCostumeToImpl)
 
     target.setCostumeIndex(1);
 
-    // "2"
+    // 2
     target.addCostume(std::make_shared<Costume>("2", "c3", "svg"));
     target.addCostume(std::make_shared<Costume>("test", "c4", "svg"));
     target.setCostumeIndex(0);
 
+    vm.setBytecode(bytecode4);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(target.costumeIndex(), 1);
+
+    // "2"
+    target.setCostumeIndex(0);
+
     vm.setBytecode(bytecode6);
     vm.run();
 
     ASSERT_EQ(vm.registerCount(), 0);
     ASSERT_EQ(target.costumeIndex(), 2);
 
-    // "next costume"
+    // "3"
+    target.setCostumeIndex(0);
+
     vm.setBytecode(bytecode7);
     vm.run();
 
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(target.costumeIndex(), 2);
+
+    // NaN
+    target.setCostumeIndex(2);
+
+    vm.setBytecode(bytecode8);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(target.costumeIndex(), 0);
+
+    // Infinity
+    target.setCostumeIndex(2);
+
+    vm.setBytecode(bytecode9);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(target.costumeIndex(), 0);
+
+    // -Infinity
+    target.setCostumeIndex(2);
+
+    vm.setBytecode(bytecode10);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(target.costumeIndex(), 0);
+
+    // ""
+    target.setCostumeIndex(2);
+
+    vm.setBytecode(bytecode11);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(target.costumeIndex(), 2);
+
+    // "   "
+    target.setCostumeIndex(2);
+
+    vm.setBytecode(bytecode12);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(target.costumeIndex(), 2);
+
+    // "next costume"
+    vm.setBytecode(bytecode13);
+    vm.run();
+
     ASSERT_EQ(vm.registerCount(), 0);
     ASSERT_EQ(target.costumeIndex(), 3);
 
@@ -1552,7 +1623,7 @@ TEST_F(LooksBlocksTest, SwitchCostumeToImpl)
     ASSERT_EQ(target.costumeIndex(), 4);
 
     // "previous costume"
-    vm.setBytecode(bytecode8);
+    vm.setBytecode(bytecode14);
     vm.run();
 
     ASSERT_EQ(vm.registerCount(), 0);
@@ -1698,11 +1769,19 @@ TEST_F(LooksBlocksTest, SwitchBackdropToImpl)
     static unsigned int bytecode3[] = { vm::OP_START, vm::OP_CONST, 2, vm::OP_EXEC, 0, vm::OP_HALT };
     static unsigned int bytecode4[] = { vm::OP_START, vm::OP_CONST, 3, vm::OP_EXEC, 0, vm::OP_HALT };
     static unsigned int bytecode5[] = { vm::OP_START, vm::OP_CONST, 4, vm::OP_EXEC, 0, vm::OP_HALT };
-    static unsigned int bytecode6[] = { vm::OP_START, vm::OP_CONST, 3, vm::OP_EXEC, 0, vm::OP_HALT };
-    static unsigned int bytecode7[] = { vm::OP_START, vm::OP_CONST, 5, vm::OP_EXEC, 0, vm::OP_HALT };
-    static unsigned int bytecode8[] = { vm::OP_START, vm::OP_CONST, 6, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode6[] = { vm::OP_START, vm::OP_CONST, 5, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode7[] = { vm::OP_START, vm::OP_CONST, 6, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode8[] = { vm::OP_START, vm::OP_CONST, 7, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode9[] = { vm::OP_START, vm::OP_CONST, 8, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode10[] = { vm::OP_START, vm::OP_CONST, 9, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode11[] = { vm::OP_START, vm::OP_CONST, 10, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode12[] = { vm::OP_START, vm::OP_CONST, 11, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode13[] = { vm::OP_START, vm::OP_CONST, 12, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode14[] = { vm::OP_START, vm::OP_CONST, 13, vm::OP_EXEC, 0, vm::OP_HALT };
     static BlockFunc functions[] = { &LooksBlocks::switchBackdropTo };
-    static Value constValues[] = { "backdrop2", 0, 1, 2, 3, "next backdrop", "previous backdrop" };
+    static Value constValues[] = {
+        "backdrop2", 0, 1, 2, 3, "2", "3", Value::SpecialValue::NaN, Value::SpecialValue::Infinity, Value::SpecialValue::NegativeInfinity, "", "   ", "next backdrop", "previous backdrop"
+    };
 
     Target target;
 
@@ -1755,31 +1834,88 @@ TEST_F(LooksBlocksTest, SwitchBackdropToImpl)
     // 2
     EXPECT_CALL(m_engineMock, stage()).Times(2).WillRepeatedly(Return(&stage));
     EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(1)->broadcast()));
+    stage.addCostume(std::make_shared<Costume>("2", "b3", "svg"));
+    stage.addCostume(std::make_shared<Costume>("test", "b4", "svg"));
+    stage.setCostumeIndex(0);
+
     vm.setBytecode(bytecode4);
     vm.run();
 
     ASSERT_EQ(vm.registerCount(), 0);
     ASSERT_EQ(stage.costumeIndex(), 1);
 
-    // 3
+    // "2"
+    EXPECT_CALL(m_engineMock, stage()).Times(2).WillRepeatedly(Return(&stage));
+    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(2)->broadcast()));
+    stage.setCostumeIndex(0);
+
+    vm.setBytecode(bytecode6);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(stage.costumeIndex(), 2);
+
+    // "3"
+    EXPECT_CALL(m_engineMock, stage()).Times(2).WillRepeatedly(Return(&stage));
+    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(2)->broadcast()));
+    stage.setCostumeIndex(0);
+
+    vm.setBytecode(bytecode7);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(stage.costumeIndex(), 2);
+
+    // NaN
     EXPECT_CALL(m_engineMock, stage()).Times(2).WillRepeatedly(Return(&stage));
     EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(0)->broadcast()));
-    vm.setBytecode(bytecode5);
+    stage.setCostumeIndex(2);
+
+    vm.setBytecode(bytecode8);
     vm.run();
 
     ASSERT_EQ(vm.registerCount(), 0);
     ASSERT_EQ(stage.costumeIndex(), 0);
 
-    stage.setCostumeIndex(1);
+    // Infinity
+    EXPECT_CALL(m_engineMock, stage()).Times(2).WillRepeatedly(Return(&stage));
+    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(0)->broadcast()));
+    stage.setCostumeIndex(2);
 
-    // "2"
-    stage.addCostume(std::make_shared<Costume>("2", "b3", "svg"));
-    stage.addCostume(std::make_shared<Costume>("test", "b4", "svg"));
-    stage.setCostumeIndex(0);
+    vm.setBytecode(bytecode9);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(stage.costumeIndex(), 0);
+
+    // -Infinity
+    EXPECT_CALL(m_engineMock, stage()).Times(2).WillRepeatedly(Return(&stage));
+    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(0)->broadcast()));
+    stage.setCostumeIndex(2);
+
+    vm.setBytecode(bytecode10);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(stage.costumeIndex(), 0);
 
+    // ""
     EXPECT_CALL(m_engineMock, stage()).Times(2).WillRepeatedly(Return(&stage));
     EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(2)->broadcast()));
-    vm.setBytecode(bytecode6);
+    stage.setCostumeIndex(2);
+
+    vm.setBytecode(bytecode11);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(stage.costumeIndex(), 2);
+
+    // "   "
+    EXPECT_CALL(m_engineMock, stage()).Times(2).WillRepeatedly(Return(&stage));
+    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(2)->broadcast()));
+    stage.setCostumeIndex(2);
+
+    vm.setBytecode(bytecode12);
     vm.run();
 
     ASSERT_EQ(vm.registerCount(), 0);
@@ -1788,7 +1924,7 @@ TEST_F(LooksBlocksTest, SwitchBackdropToImpl)
     // "next backdrop"
     EXPECT_CALL(m_engineMock, stage()).Times(3).WillRepeatedly(Return(&stage));
     EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(3)->broadcast()));
-    vm.setBytecode(bytecode7);
+    vm.setBytecode(bytecode13);
     vm.run();
 
     ASSERT_EQ(vm.registerCount(), 0);
@@ -1823,7 +1959,7 @@ TEST_F(LooksBlocksTest, SwitchBackdropToImpl)
     // "previous backdrop"
     EXPECT_CALL(m_engineMock, stage()).Times(3).WillRepeatedly(Return(&stage));
     EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(3)->broadcast()));
-    vm.setBytecode(bytecode8);
+    vm.setBytecode(bytecode14);
     vm.run();
 
     ASSERT_EQ(vm.registerCount(), 0);
@@ -1900,11 +2036,19 @@ TEST_F(LooksBlocksTest, SwitchBackdropToAndWaitImpl)
     static unsigned int bytecode3[] = { vm::OP_START, vm::OP_CONST, 2, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
     static unsigned int bytecode4[] = { vm::OP_START, vm::OP_CONST, 3, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
     static unsigned int bytecode5[] = { vm::OP_START, vm::OP_CONST, 4, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
-    static unsigned int bytecode6[] = { vm::OP_START, vm::OP_CONST, 3, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
-    static unsigned int bytecode7[] = { vm::OP_START, vm::OP_CONST, 5, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
-    static unsigned int bytecode8[] = { vm::OP_START, vm::OP_CONST, 6, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode6[] = { vm::OP_START, vm::OP_CONST, 5, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode7[] = { vm::OP_START, vm::OP_CONST, 6, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode8[] = { vm::OP_START, vm::OP_CONST, 7, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode9[] = { vm::OP_START, vm::OP_CONST, 8, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode10[] = { vm::OP_START, vm::OP_CONST, 9, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode11[] = { vm::OP_START, vm::OP_CONST, 10, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode12[] = { vm::OP_START, vm::OP_CONST, 11, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode13[] = { vm::OP_START, vm::OP_CONST, 12, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode14[] = { vm::OP_START, vm::OP_CONST, 13, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
     static BlockFunc functions[] = { &LooksBlocks::switchBackdropToAndWait, &LooksBlocks::backdropNumber, &LooksBlocks::checkBackdropScripts };
-    static Value constValues[] = { "backdrop2", 0, 1, 2, 3, "next backdrop", "previous backdrop" };
+    static Value constValues[] = {
+        "backdrop2", 0, 1, 2, 3, "2", "3", Value::SpecialValue::NaN, Value::SpecialValue::Infinity, Value::SpecialValue::NegativeInfinity, "", "   ", "next backdrop", "previous backdrop"
+    };
 
     Target target;
 
@@ -1980,33 +2124,95 @@ TEST_F(LooksBlocksTest, SwitchBackdropToAndWaitImpl)
     EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
     EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(1)->broadcast()));
     EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(1)->broadcast())).WillOnce(Return(false));
+    stage.addCostume(std::make_shared<Costume>("2", "b3", "svg"));
+    stage.addCostume(std::make_shared<Costume>("test", "b4", "svg"));
+    stage.setCostumeIndex(0);
+
     vm.setBytecode(bytecode4);
     vm.run();
 
     ASSERT_EQ(vm.registerCount(), 0);
     ASSERT_EQ(stage.costumeIndex(), 1);
 
-    // 3
+    // "2"
+    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
+    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(2)->broadcast()));
+    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(2)->broadcast())).WillOnce(Return(false));
+    stage.setCostumeIndex(0);
+
+    vm.setBytecode(bytecode6);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(stage.costumeIndex(), 2);
+
+    // "3"
+    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
+    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(2)->broadcast()));
+    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(2)->broadcast())).WillOnce(Return(false));
+    stage.setCostumeIndex(0);
+
+    vm.setBytecode(bytecode7);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(stage.costumeIndex(), 2);
+
+    // NaN
     EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
     EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(0)->broadcast()));
     EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(0)->broadcast())).WillOnce(Return(false));
-    vm.setBytecode(bytecode5);
+    stage.setCostumeIndex(2);
+
+    vm.setBytecode(bytecode8);
     vm.run();
 
     ASSERT_EQ(vm.registerCount(), 0);
     ASSERT_EQ(stage.costumeIndex(), 0);
 
-    stage.setCostumeIndex(1);
+    // Infinity
+    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
+    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(0)->broadcast()));
+    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(0)->broadcast())).WillOnce(Return(false));
+    stage.setCostumeIndex(2);
 
-    // "2"
-    stage.addCostume(std::make_shared<Costume>("2", "b3", "svg"));
-    stage.addCostume(std::make_shared<Costume>("test", "b4", "svg"));
-    stage.setCostumeIndex(0);
+    vm.setBytecode(bytecode9);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(stage.costumeIndex(), 0);
 
+    // -Infinity
+    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
+    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(0)->broadcast()));
+    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(0)->broadcast())).WillOnce(Return(false));
+    stage.setCostumeIndex(2);
+
+    vm.setBytecode(bytecode10);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(stage.costumeIndex(), 0);
+
+    // ""
     EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
     EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(2)->broadcast()));
     EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(2)->broadcast())).WillOnce(Return(false));
-    vm.setBytecode(bytecode6);
+    stage.setCostumeIndex(2);
+
+    vm.setBytecode(bytecode11);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(stage.costumeIndex(), 2);
+
+    // "   "
+    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
+    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(2)->broadcast()));
+    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(2)->broadcast())).WillOnce(Return(false));
+    stage.setCostumeIndex(2);
+
+    vm.setBytecode(bytecode12);
     vm.run();
 
     ASSERT_EQ(vm.registerCount(), 0);
@@ -2016,7 +2222,7 @@ TEST_F(LooksBlocksTest, SwitchBackdropToAndWaitImpl)
     EXPECT_CALL(m_engineMock, stage()).Times(5).WillRepeatedly(Return(&stage));
     EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(3)->broadcast()));
     EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(3)->broadcast())).WillOnce(Return(true));
-    vm.setBytecode(bytecode7);
+    vm.setBytecode(bytecode13);
     vm.run();
 
     ASSERT_EQ(vm.registerCount(), 1);
@@ -2063,7 +2269,7 @@ TEST_F(LooksBlocksTest, SwitchBackdropToAndWaitImpl)
     EXPECT_CALL(m_engineMock, stage()).Times(5).WillRepeatedly(Return(&stage));
     EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(3)->broadcast()));
     EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(3)->broadcast())).WillOnce(Return(true));
-    vm.setBytecode(bytecode8);
+    vm.setBytecode(bytecode14);
     vm.run();
 
     ASSERT_EQ(vm.registerCount(), 1);

From da9fd7eb3d66c5e9011ada59d87f4676e87337cb Mon Sep 17 00:00:00 2001
From: adazem009 <68537469+adazem009@users.noreply.github.com>
Date: Fri, 6 Sep 2024 15:01:01 +0200
Subject: [PATCH 7/9] Add test for random backdrop in switch backdrop block

---
 test/blocks/looks_blocks_test.cpp | 83 ++++++++++++++++++++++++++++++-
 1 file changed, 81 insertions(+), 2 deletions(-)

diff --git a/test/blocks/looks_blocks_test.cpp b/test/blocks/looks_blocks_test.cpp
index 24f8aede..ef094000 100644
--- a/test/blocks/looks_blocks_test.cpp
+++ b/test/blocks/looks_blocks_test.cpp
@@ -1778,9 +1778,11 @@ TEST_F(LooksBlocksTest, SwitchBackdropToImpl)
     static unsigned int bytecode12[] = { vm::OP_START, vm::OP_CONST, 11, vm::OP_EXEC, 0, vm::OP_HALT };
     static unsigned int bytecode13[] = { vm::OP_START, vm::OP_CONST, 12, vm::OP_EXEC, 0, vm::OP_HALT };
     static unsigned int bytecode14[] = { vm::OP_START, vm::OP_CONST, 13, vm::OP_EXEC, 0, vm::OP_HALT };
+    static unsigned int bytecode15[] = { vm::OP_START, vm::OP_CONST, 14, vm::OP_EXEC, 0, vm::OP_HALT };
     static BlockFunc functions[] = { &LooksBlocks::switchBackdropTo };
     static Value constValues[] = {
-        "backdrop2", 0, 1, 2, 3, "2", "3", Value::SpecialValue::NaN, Value::SpecialValue::Infinity, Value::SpecialValue::NegativeInfinity, "", "   ", "next backdrop", "previous backdrop"
+        "backdrop2",      0, 1, 2, 3, "2", "3", Value::SpecialValue::NaN, Value::SpecialValue::Infinity, Value::SpecialValue::NegativeInfinity, "", "   ", "next backdrop", "previous backdrop",
+        "random backdrop"
     };
 
     Target target;
@@ -1992,6 +1994,42 @@ TEST_F(LooksBlocksTest, SwitchBackdropToImpl)
 
     ASSERT_EQ(vm.registerCount(), 0);
     ASSERT_EQ(stage.costumeIndex(), 5);
+
+    // random backdrop
+    RandomGeneratorMock rng;
+    LooksBlocks::rng = &rng;
+
+    EXPECT_CALL(m_engineMock, stage()).Times(3).WillRepeatedly(Return(&stage));
+    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(3)->broadcast()));
+    EXPECT_CALL(rng, randint(0, 5)).WillOnce(Return(3));
+    stage.setCostumeIndex(0);
+    vm.setBytecode(bytecode15);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(stage.costumeIndex(), 3);
+
+    EXPECT_CALL(m_engineMock, stage()).Times(3).WillRepeatedly(Return(&stage));
+    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(5)->broadcast()));
+    EXPECT_CALL(rng, randint(0, 5)).WillOnce(Return(5));
+    vm.reset();
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(stage.costumeIndex(), 5);
+
+    stage.addCostume(std::make_shared<Costume>("random backdrop", "b7", "svg"));
+
+    EXPECT_CALL(m_engineMock, stage()).Times(2).WillRepeatedly(Return(&stage));
+    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(6)->broadcast()));
+    EXPECT_CALL(rng, randint).Times(0);
+    vm.reset();
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(stage.costumeIndex(), 6);
+
+    LooksBlocks::rng = RandomGenerator::instance().get();
 }
 
 TEST_F(LooksBlocksTest, SwitchBackdropToAndWait)
@@ -2045,9 +2083,11 @@ TEST_F(LooksBlocksTest, SwitchBackdropToAndWaitImpl)
     static unsigned int bytecode12[] = { vm::OP_START, vm::OP_CONST, 11, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
     static unsigned int bytecode13[] = { vm::OP_START, vm::OP_CONST, 12, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
     static unsigned int bytecode14[] = { vm::OP_START, vm::OP_CONST, 13, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
+    static unsigned int bytecode15[] = { vm::OP_START, vm::OP_CONST, 14, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
     static BlockFunc functions[] = { &LooksBlocks::switchBackdropToAndWait, &LooksBlocks::backdropNumber, &LooksBlocks::checkBackdropScripts };
     static Value constValues[] = {
-        "backdrop2", 0, 1, 2, 3, "2", "3", Value::SpecialValue::NaN, Value::SpecialValue::Infinity, Value::SpecialValue::NegativeInfinity, "", "   ", "next backdrop", "previous backdrop"
+        "backdrop2",      0, 1, 2, 3, "2", "3", Value::SpecialValue::NaN, Value::SpecialValue::Infinity, Value::SpecialValue::NegativeInfinity, "", "   ", "next backdrop", "previous backdrop",
+        "random backdrop"
     };
 
     Target target;
@@ -2315,6 +2355,45 @@ TEST_F(LooksBlocksTest, SwitchBackdropToAndWaitImpl)
 
     ASSERT_EQ(vm.registerCount(), 0);
     ASSERT_EQ(stage.costumeIndex(), 5);
+
+    // random backdrop
+    RandomGeneratorMock rng;
+    LooksBlocks::rng = &rng;
+
+    EXPECT_CALL(m_engineMock, stage()).Times(5).WillRepeatedly(Return(&stage));
+    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(3)->broadcast()));
+    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(3)->broadcast())).WillOnce(Return(false));
+    EXPECT_CALL(rng, randint(0, 5)).WillOnce(Return(3));
+    stage.setCostumeIndex(0);
+    vm.setBytecode(bytecode15);
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(stage.costumeIndex(), 3);
+
+    EXPECT_CALL(m_engineMock, stage()).Times(5).WillRepeatedly(Return(&stage));
+    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(5)->broadcast()));
+    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(5)->broadcast())).WillOnce(Return(false));
+    EXPECT_CALL(rng, randint(0, 5)).WillOnce(Return(5));
+    vm.reset();
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(stage.costumeIndex(), 5);
+
+    stage.addCostume(std::make_shared<Costume>("random backdrop", "b7", "svg"));
+
+    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
+    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(6)->broadcast()));
+    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(6)->broadcast())).WillOnce(Return(false));
+    EXPECT_CALL(rng, randint).Times(0);
+    vm.reset();
+    vm.run();
+
+    ASSERT_EQ(vm.registerCount(), 0);
+    ASSERT_EQ(stage.costumeIndex(), 6);
+
+    LooksBlocks::rng = RandomGenerator::instance().get();
 }
 
 TEST_F(LooksBlocksTest, NextBackdrop)

From 1f7f1e566b659af35714855beb96fc46c084bf26 Mon Sep 17 00:00:00 2001
From: adazem009 <68537469+adazem009@users.noreply.github.com>
Date: Sat, 7 Sep 2024 10:25:26 +0200
Subject: [PATCH 8/9] VirtualMachine: Fix a typo in docs

---
 include/scratchcpp/virtualmachine.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/scratchcpp/virtualmachine.h b/include/scratchcpp/virtualmachine.h
index 58541495..ac642837 100644
--- a/include/scratchcpp/virtualmachine.h
+++ b/include/scratchcpp/virtualmachine.h
@@ -76,7 +76,7 @@ enum Opcode
     OP_STR_CONTAINS,   /*!< Stores true in the last register if the string stored in the second last register contains the substring in the last register. */
     OP_EXEC,           /*!< Calls the function with the index in the argument. */
     OP_INIT_PROCEDURE, /*!< Initializes the list of procedure (custom block) arguments. */
-    OP_CALL_PROCEDURE, /*! Calls the procedure (custom block) with the index in the argument. */
+    OP_CALL_PROCEDURE, /*!< Calls the procedure (custom block) with the index in the argument. */
     OP_ADD_ARG,        /*!< Adds a procedure (custom block) argument with the value from the last register. */
     OP_READ_ARG,       /*!< Reads the procedure (custom block) argument with the index in the argument and stores the value in the last register. */
     OP_BREAK_FRAME,    /*!< Breaks current frame at the end of the loop. */

From c04335d446c8859ea33249d6a83fb771c79ad9a8 Mon Sep 17 00:00:00 2001
From: adazem009 <68537469+adazem009@users.noreply.github.com>
Date: Sat, 7 Sep 2024 15:56:58 +0200
Subject: [PATCH 9/9] Remove unused functions from looks blocks

---
 src/blocks/looksblocks.cpp        |  24 -----
 src/blocks/looksblocks.h          |   3 -
 test/blocks/looks_blocks_test.cpp | 167 ------------------------------
 3 files changed, 194 deletions(-)

diff --git a/src/blocks/looksblocks.cpp b/src/blocks/looksblocks.cpp
index 6361a5aa..e2961a7d 100644
--- a/src/blocks/looksblocks.cpp
+++ b/src/blocks/looksblocks.cpp
@@ -988,14 +988,6 @@ unsigned int LooksBlocks::nextBackdrop(VirtualMachine *vm)
     return 0;
 }
 
-unsigned int LooksBlocks::nextBackdropAndWait(VirtualMachine *vm)
-{
-    nextBackdropImpl(vm);
-    startBackdropScripts(vm, true);
-
-    return 0;
-}
-
 unsigned int LooksBlocks::previousBackdrop(VirtualMachine *vm)
 {
     previousBackdropImpl(vm);
@@ -1004,14 +996,6 @@ unsigned int LooksBlocks::previousBackdrop(VirtualMachine *vm)
     return 0;
 }
 
-unsigned int LooksBlocks::previousBackdropAndWait(VirtualMachine *vm)
-{
-    previousBackdropImpl(vm);
-    startBackdropScripts(vm, true);
-
-    return 0;
-}
-
 unsigned int LooksBlocks::randomBackdrop(VirtualMachine *vm)
 {
     randomBackdropImpl(vm);
@@ -1020,14 +1004,6 @@ unsigned int LooksBlocks::randomBackdrop(VirtualMachine *vm)
     return 0;
 }
 
-unsigned int LooksBlocks::randomBackdropAndWait(VirtualMachine *vm)
-{
-    randomBackdropImpl(vm);
-    startBackdropScripts(vm, true);
-
-    return 0;
-}
-
 unsigned int LooksBlocks::checkBackdropScripts(VirtualMachine *vm)
 {
     if (Stage *stage = vm->engine()->stage()) {
diff --git a/src/blocks/looksblocks.h b/src/blocks/looksblocks.h
index 5d3e147d..ed80f1b3 100644
--- a/src/blocks/looksblocks.h
+++ b/src/blocks/looksblocks.h
@@ -142,11 +142,8 @@ class LooksBlocks : public IBlockSection
         static unsigned int switchBackdropTo(VirtualMachine *vm);
         static unsigned int switchBackdropToAndWait(VirtualMachine *vm);
         static unsigned int nextBackdrop(VirtualMachine *vm);
-        static unsigned int nextBackdropAndWait(VirtualMachine *vm);
         static unsigned int previousBackdrop(VirtualMachine *vm);
-        static unsigned int previousBackdropAndWait(VirtualMachine *vm);
         static unsigned int randomBackdrop(VirtualMachine *vm);
-        static unsigned int randomBackdropAndWait(VirtualMachine *vm);
         static unsigned int checkBackdropScripts(VirtualMachine *vm);
 
         static unsigned int goToFront(VirtualMachine *vm);
diff --git a/test/blocks/looks_blocks_test.cpp b/test/blocks/looks_blocks_test.cpp
index ef094000..9e6c7b66 100644
--- a/test/blocks/looks_blocks_test.cpp
+++ b/test/blocks/looks_blocks_test.cpp
@@ -2454,59 +2454,6 @@ TEST_F(LooksBlocksTest, NextBackdropImpl)
     ASSERT_EQ(stage.costumeIndex(), 0);
 }
 
-TEST_F(LooksBlocksTest, NextBackdropAndWait)
-{
-    static unsigned int bytecode[] = { vm::OP_START, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
-    static BlockFunc functions[] = { &LooksBlocks::nextBackdropAndWait, &LooksBlocks::backdropNumber, &LooksBlocks::checkBackdropScripts };
-
-    Target target;
-
-    Stage stage;
-    stage.addCostume(std::make_shared<Costume>("backdrop1", "b1", "svg"));
-    stage.addCostume(std::make_shared<Costume>("backdrop2", "b2", "svg"));
-    stage.addCostume(std::make_shared<Costume>("backdrop3", "b3", "svg"));
-    stage.setCostumeIndex(0);
-
-    VirtualMachine vm(&target, &m_engineMock, nullptr);
-    vm.setBytecode(bytecode);
-    vm.setFunctions(functions);
-
-    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(1)->broadcast()));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(1)->broadcast())).WillOnce(Return(true));
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 1);
-    ASSERT_EQ(stage.costumeIndex(), 1);
-    ASSERT_FALSE(vm.atEnd());
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(1)->broadcast())).WillOnce(Return(false));
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_TRUE(vm.atEnd());
-
-    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(2)->broadcast()));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(2)->broadcast())).WillOnce(Return(false));
-    vm.reset();
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_EQ(stage.costumeIndex(), 2);
-    ASSERT_TRUE(vm.atEnd());
-
-    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(0)->broadcast()));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(0)->broadcast())).WillOnce(Return(false));
-    vm.reset();
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_EQ(stage.costumeIndex(), 0);
-}
-
 TEST_F(LooksBlocksTest, PreviousBackdrop)
 {
     static unsigned int bytecode[] = { vm::OP_START, vm::OP_EXEC, 0, vm::OP_HALT };
@@ -2548,59 +2495,6 @@ TEST_F(LooksBlocksTest, PreviousBackdrop)
     ASSERT_EQ(stage.costumeIndex(), 2);
 }
 
-TEST_F(LooksBlocksTest, PreviousBackdropAndWait)
-{
-    static unsigned int bytecode[] = { vm::OP_START, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
-    static BlockFunc functions[] = { &LooksBlocks::previousBackdropAndWait, &LooksBlocks::backdropNumber, &LooksBlocks::checkBackdropScripts };
-
-    Target target;
-
-    Stage stage;
-    stage.addCostume(std::make_shared<Costume>("backdrop1", "b1", "svg"));
-    stage.addCostume(std::make_shared<Costume>("backdrop2", "b2", "svg"));
-    stage.addCostume(std::make_shared<Costume>("backdrop3", "b3", "svg"));
-    stage.setCostumeIndex(2);
-
-    VirtualMachine vm(&target, &m_engineMock, nullptr);
-    vm.setBytecode(bytecode);
-    vm.setFunctions(functions);
-
-    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(1)->broadcast()));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(1)->broadcast())).WillOnce(Return(true));
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 1);
-    ASSERT_EQ(stage.costumeIndex(), 1);
-    ASSERT_FALSE(vm.atEnd());
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(1)->broadcast())).WillOnce(Return(false));
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_TRUE(vm.atEnd());
-
-    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(0)->broadcast()));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(0)->broadcast())).WillOnce(Return(false));
-    vm.reset();
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_EQ(stage.costumeIndex(), 0);
-    ASSERT_TRUE(vm.atEnd());
-
-    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(2)->broadcast()));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(2)->broadcast())).WillOnce(Return(false));
-    vm.reset();
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_EQ(stage.costumeIndex(), 2);
-}
-
 TEST_F(LooksBlocksTest, RandomBackdrop)
 {
     static unsigned int bytecode[] = { vm::OP_START, vm::OP_EXEC, 0, vm::OP_HALT };
@@ -2650,67 +2544,6 @@ TEST_F(LooksBlocksTest, RandomBackdrop)
     LooksBlocks::rng = RandomGenerator::instance().get();
 }
 
-TEST_F(LooksBlocksTest, RandomBackdropAndWait)
-{
-    static unsigned int bytecode[] = { vm::OP_START, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_EXEC, 2, vm::OP_HALT };
-    static BlockFunc functions[] = { &LooksBlocks::randomBackdropAndWait, &LooksBlocks::backdropNumber, &LooksBlocks::checkBackdropScripts };
-
-    Target target;
-
-    Stage stage;
-
-    VirtualMachine vm(&target, &m_engineMock, nullptr);
-    vm.setBytecode(bytecode);
-    vm.setFunctions(functions);
-
-    RandomGeneratorMock rng;
-    LooksBlocks::rng = &rng;
-
-    EXPECT_CALL(rng, randint).Times(0);
-    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning).Times(0);
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-
-    stage.addCostume(std::make_shared<Costume>("backdrop1", "b1", "svg"));
-    stage.addCostume(std::make_shared<Costume>("backdrop2", "b2", "svg"));
-    stage.addCostume(std::make_shared<Costume>("backdrop3", "b3", "svg"));
-
-    EXPECT_CALL(rng, randint(0, 2)).WillOnce(Return(1));
-    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(1)->broadcast()));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(1)->broadcast())).WillOnce(Return(true));
-    vm.reset();
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 1);
-    ASSERT_EQ(stage.costumeIndex(), 1);
-    ASSERT_FALSE(vm.atEnd());
-
-    EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(1)->broadcast())).WillOnce(Return(false));
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_TRUE(vm.atEnd());
-
-    stage.addCostume(std::make_shared<Costume>("backdrop4", "b4", "svg"));
-
-    EXPECT_CALL(rng, randint(0, 3)).WillOnce(Return(2));
-    EXPECT_CALL(m_engineMock, stage()).Times(4).WillRepeatedly(Return(&stage));
-    EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(2)->broadcast()));
-    EXPECT_CALL(m_engineMock, broadcastByPtrRunning(stage.costumeAt(2)->broadcast())).WillOnce(Return(false));
-    vm.reset();
-    vm.run();
-
-    ASSERT_EQ(vm.registerCount(), 0);
-    ASSERT_EQ(stage.costumeIndex(), 2);
-    ASSERT_TRUE(vm.atEnd());
-
-    LooksBlocks::rng = RandomGenerator::instance().get();
-}
-
 TEST_F(LooksBlocksTest, GoToFrontBack)
 {
     Compiler compiler(&m_engineMock);
