Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/blocks/looksblocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -964,8 +964,9 @@ void LooksBlocks::randomBackdropImpl(VirtualMachine *vm)
if (Stage *stage = vm->engine()->stage()) {
std::size_t count = stage->costumes().size();

if (count > 0)
stage->setCostumeIndex(rng->randint(0, count - 1));
if (count > 1) {
stage->setCostumeIndex(rng->randintExcept(0, count - 1, stage->costumeIndex()));
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/engine/internal/irandomgenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class IRandomGenerator

virtual long randint(long start, long end) const = 0;
virtual double randintDouble(double start, double end) const = 0;
virtual long randintExcept(long start, long end, long except) const = 0;
};

} // namespace libscratchcpp
26 changes: 26 additions & 0 deletions src/engine/internal/randomgenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,29 @@ double RandomGenerator::randintDouble(double start, double end) const
std::uniform_real_distribution<double> distribution(start, end);
return distribution(*m_generator);
}

long RandomGenerator::randintExcept(long start, long end, long except) const
{
if (start > end) {
std::swap(start, end);
}

if (except < start || except > end) {
return randint(start, end);
} else if (start == end) {
return start;
} else if (end - start == 1) {
if (except == start)
return end;
else
return start;
}

if (randint(0, 1) == 0) {
std::uniform_int_distribution<long> distribution(start, except - 1);
return distribution(*m_generator);
} else {
std::uniform_int_distribution<long> distribution(except + 1, end);
return distribution(*m_generator);
}
}
1 change: 1 addition & 0 deletions src/engine/internal/randomgenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class RandomGenerator : public IRandomGenerator

long randint(long start, long end) const override;
double randintDouble(double start, double end) const override;
long randintExcept(long start, long end, long except) const;

private:
static std::shared_ptr<RandomGenerator> m_instance;
Expand Down
19 changes: 10 additions & 9 deletions test/blocks/looks_blocks_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1992,7 +1992,7 @@ TEST_F(LooksBlocksTest, SwitchBackdropToImpl)
LooksBlocks::rng = &rng;

EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(3)->broadcast(), &thread, false));
EXPECT_CALL(rng, randint(0, 5)).WillOnce(Return(3));
EXPECT_CALL(rng, randintExcept(0, 5, 0)).WillOnce(Return(3));
stage.setCostumeIndex(0);
vm->setBytecode(bytecode15);
vm->run();
Expand All @@ -2001,7 +2001,7 @@ TEST_F(LooksBlocksTest, SwitchBackdropToImpl)
ASSERT_EQ(stage.costumeIndex(), 3);

EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(5)->broadcast(), &thread, false));
EXPECT_CALL(rng, randint(0, 5)).WillOnce(Return(5));
EXPECT_CALL(rng, randintExcept(0, 5, 3)).WillOnce(Return(5));
vm->reset();
vm->run();

Expand All @@ -2011,7 +2011,7 @@ TEST_F(LooksBlocksTest, SwitchBackdropToImpl)
stage.addCostume(std::make_shared<Costume>("random backdrop", "b7", "svg"));

EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(6)->broadcast(), &thread, false));
EXPECT_CALL(rng, randint).Times(0);
EXPECT_CALL(rng, randintExcept).Times(0);
vm->reset();
vm->run();

Expand Down Expand Up @@ -2337,7 +2337,7 @@ TEST_F(LooksBlocksTest, SwitchBackdropToAndWaitImpl)
LooksBlocks::rng = &rng;

EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(3)->broadcast(), &thread, true));
EXPECT_CALL(rng, randint(0, 5)).WillOnce(Return(3));
EXPECT_CALL(rng, randintExcept(0, 5, 0)).WillOnce(Return(3));
stage.setCostumeIndex(0);
vm->resolvePromise();
vm->setBytecode(bytecode15);
Expand All @@ -2349,7 +2349,7 @@ TEST_F(LooksBlocksTest, SwitchBackdropToAndWaitImpl)
ASSERT_EQ(stage.costumeIndex(), 3);

EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(5)->broadcast(), &thread, true));
EXPECT_CALL(rng, randint(0, 5)).WillOnce(Return(5));
EXPECT_CALL(rng, randintExcept(0, 5, 3)).WillOnce(Return(5));
vm->reset();
vm->run();
vm->resolvePromise();
Expand All @@ -2361,7 +2361,7 @@ TEST_F(LooksBlocksTest, SwitchBackdropToAndWaitImpl)
stage.addCostume(std::make_shared<Costume>("random backdrop", "b7", "svg"));

EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(6)->broadcast(), &thread, true));
EXPECT_CALL(rng, randint).Times(0);
EXPECT_CALL(rng, randintExcept).Times(0);
vm->reset();
vm->run();
vm->resolvePromise();
Expand Down Expand Up @@ -2488,16 +2488,17 @@ TEST_F(LooksBlocksTest, RandomBackdrop)
RandomGeneratorMock rng;
LooksBlocks::rng = &rng;

EXPECT_CALL(rng, randint).Times(0);
EXPECT_CALL(rng, randintExcept).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"));
stage.setCostumeIndex(0);

EXPECT_CALL(rng, randint(0, 2)).WillOnce(Return(1));
EXPECT_CALL(rng, randintExcept(0, 2, 0)).WillOnce(Return(1));
EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(1)->broadcast(), &thread, false));
vm->reset();
vm->run();
Expand All @@ -2507,7 +2508,7 @@ TEST_F(LooksBlocksTest, RandomBackdrop)

stage.addCostume(std::make_shared<Costume>("backdrop4", "b4", "svg"));

EXPECT_CALL(rng, randint(0, 3)).WillOnce(Return(2));
EXPECT_CALL(rng, randintExcept(0, 3, 1)).WillOnce(Return(2));
EXPECT_CALL(m_engineMock, startBackdropScripts(stage.costumeAt(2)->broadcast(), &thread, false));
vm->reset();
vm->run();
Expand Down
1 change: 1 addition & 0 deletions test/mocks/randomgeneratormock.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ class RandomGeneratorMock : public IRandomGenerator
public:
MOCK_METHOD(long, randint, (long, long), (const, override));
MOCK_METHOD(double, randintDouble, (double, double), (const, override));
MOCK_METHOD(long, randintExcept, (long, long, long), (const, override));
};
54 changes: 54 additions & 0 deletions test/randomgenerator/randomgenerator_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,57 @@ TEST(RandomGeneratorTest, RandIntDouble)
ASSERT_LE(num, 5.081);
}
}

TEST(RandomGeneratorTest, RandIntExcept)
{
auto rng = RandomGenerator::instance();
ASSERT_TRUE(rng);

long num;

for (int i = 0; i < 25; i++) {
num = rng->randintExcept(-2, 3, 0);
ASSERT_GE(num, -2);
ASSERT_LE(num, 3);
ASSERT_NE(num, 0);
}

for (int i = 0; i < 25; i++) {
num = rng->randintExcept(5, -3, 2);
ASSERT_GE(num, -3);
ASSERT_LE(num, 5);
ASSERT_NE(num, 2);
}

for (int i = 0; i < 25; i++) {
num = rng->randintExcept(5, 8, 2);
ASSERT_GE(num, 5);
ASSERT_LE(num, 8);
}

for (int i = 0; i < 25; i++) {
num = rng->randintExcept(5, 8, 10);
ASSERT_GE(num, 5);
ASSERT_LE(num, 8);
}

for (int i = 0; i < 25; i++) {
num = rng->randintExcept(2, 2, 2);
ASSERT_EQ(num, 2);
}

for (int i = 0; i < 25; i++) {
num = rng->randintExcept(2, 2, 5);
ASSERT_EQ(num, 2);
}

for (int i = 0; i < 25; i++) {
num = rng->randintExcept(1, 2, 1);
ASSERT_EQ(num, 2);
}

for (int i = 0; i < 25; i++) {
num = rng->randintExcept(1, 2, 2);
ASSERT_EQ(num, 1);
}
}
Loading