Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New randomization opcodes #236

Merged
merged 1 commit into from
Dec 11, 2024
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
- new opcode **2702 ([clear_bit](https://library.sannybuilder.com/#/sa/math/2702))**
- new opcode **2703 ([toggle_bit](https://library.sannybuilder.com/#/sa/math/2703))**
- new opcode **2704 ([is_truthy](https://library.sannybuilder.com/#/sa/math/2704))**
- new opcode **2705 ([pick_random_int](https://library.sannybuilder.com/#/sa/math/2705))**
- new opcode **2706 ([pick_random_float](https://library.sannybuilder.com/#/sa/math/2706))**
- new opcode **2707 ([pick_random_text](https://library.sannybuilder.com/#/sa/math/2707))**
- new opcode **2708 ([random_chance](https://library.sannybuilder.com/#/sa/math/2708))**
- new [MemoryOperations](https://github.com/cleolibrary/CLEO5/tree/master/cleo_plugins/MemoryOperations) plugin
- memory related opcodes moved from CLEO core into separated plugin
- validation of input and output parameters for all opcodes
Expand Down
108 changes: 106 additions & 2 deletions cleo_plugins/Math/Math.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,21 @@
#include "CLEO.h"
#include "CLEO_Utils.h"

#include <random>

using namespace CLEO;
using namespace plugin;
using namespace std;

class Math
{
public:
Math()
random_device randomDevice;
mt19937 randomGenerator;

Math() :
randomDevice(),
randomGenerator(randomDevice())
{
auto cleoVer = CLEO_GetVersion();
if (cleoVer < CLEO_VERSION)
Expand Down Expand Up @@ -48,6 +56,10 @@ class Math
CLEO_RegisterOpcode(0x2702, opcode_2702); // clear_bit
CLEO_RegisterOpcode(0x2703, opcode_2703); // toggle_bit
CLEO_RegisterOpcode(0x2704, opcode_2704); // is_truthy
CLEO_RegisterOpcode(0x2705, opcode_2705); // pick_random_int
CLEO_RegisterOpcode(0x2706, opcode_2706); // pick_random_float
CLEO_RegisterOpcode(0x2707, opcode_2707); // pick_random_text
CLEO_RegisterOpcode(0x2708, opcode_2708); // random_chance
}

//0A8E=3,%3d% = %1d% + %2d% ; int
Expand Down Expand Up @@ -434,4 +446,96 @@ class Math
OPCODE_CONDITION_RESULT(value != 0);
return OR_CONTINUE;
}
} Math;

//2705=-1,pick_random_int values %d% store_to %d%
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

picking random array element is called sampling

please rename these it sample_int, sample_float, sample_string

Copy link
Collaborator Author

@MiranDMC MiranDMC Dec 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm not sure about that. I would never guess it takes random element from set.
"Sample - get a representative experience of". Especially in software development it is already used for totally different meanings (like texture sampling).
Originally I considered also "select". Does some programming language have similar function?
draw_int would also make sense if not suggesting crating picture.

I see some php libraries provide Array.Sample(), but it makes way more sense than Float.Sample()

Copy link
Collaborator Author

@MiranDMC MiranDMC Dec 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pick (noun) · picks (plural noun)
an act or the right of selecting something from a number of alternatives

I was baffling about name already and this seem to be the best one. Other options sounds like fancy ways to not say "pick".

random_pick_int maybe? Current choice is more in line with already existing generate_random_float_in_range.
In class syntax it is called Math.RandomPick(...)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sample is a verb too

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

@MiranDMC MiranDMC Dec 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, like sampling input sensor by averaging signal over sampling window time, or sampling audio to fill given time by repeating small portion.
I think all randomization opcodes should have word "random" in name. Then searching in SBL actually provides user with options to select from.
Math.Sample(1, 2, 3) looks meaningless.

static OpcodeResult WINAPI opcode_2705(CScriptThread* thread)
{
auto valueCount = CLEO_GetVarArgCount(thread);

if (valueCount < 2) // value + result
{
SHOW_ERROR("Insufficient number of arguments in script %s\nScript suspended.", CLEO::ScriptInfoStr(thread).c_str());
return thread->Suspend();
}
valueCount -= 1; // output param

uniform_int_distribution<size_t> dist(0, valueCount - 1); // 0 to last index
auto idx = dist(Instance.randomGenerator);

// read n-th param
OPCODE_SKIP_PARAMS(idx);
auto value = OPCODE_READ_PARAM_INT();

OPCODE_SKIP_PARAMS(valueCount - (idx + 1)); // seek to output param
OPCODE_WRITE_PARAM_INT(value);

CLEO_SkipUnusedVarArgs(thread);
return OR_CONTINUE;
}

//2706=-1,pick_random_float values %d% store_to %d%
static OpcodeResult WINAPI opcode_2706(CScriptThread* thread)
{
auto valueCount = CLEO_GetVarArgCount(thread);

if (valueCount < 2) // value + result
{
SHOW_ERROR("Insufficient number of arguments in script %s\nScript suspended.", CLEO::ScriptInfoStr(thread).c_str());
return thread->Suspend();
}
valueCount -= 1; // output param

uniform_int_distribution<size_t> dist(0, valueCount - 1); // 0 to last index
auto idx = dist(Instance.randomGenerator);

// read n-th param
OPCODE_SKIP_PARAMS(idx);
auto value = OPCODE_READ_PARAM_FLOAT();

OPCODE_SKIP_PARAMS(valueCount - (idx + 1)); // seek to output param
OPCODE_WRITE_PARAM_FLOAT(value);

CLEO_SkipUnusedVarArgs(thread);
return OR_CONTINUE;
}

//2707=-1,pick_random_text values %d% store_to %d%
static OpcodeResult WINAPI opcode_2707(CScriptThread* thread)
{
auto valueCount = CLEO_GetVarArgCount(thread);

if (valueCount < 2) // value + result
{
SHOW_ERROR("Insufficient number of arguments in script %s\nScript suspended.", CLEO::ScriptInfoStr(thread).c_str());
return thread->Suspend();
}
valueCount -= 1; // output param

uniform_int_distribution<size_t> dist(0, valueCount - 1); // 0 to last index
auto idx = dist(Instance.randomGenerator);

// read n-th param
OPCODE_SKIP_PARAMS(idx);
OPCODE_READ_PARAM_STRING(value);

OPCODE_SKIP_PARAMS(valueCount - (idx + 1)); // seek to output param
OPCODE_WRITE_PARAM_STRING(value);

CLEO_SkipUnusedVarArgs(thread);
return OR_CONTINUE;
}

//2708=1,random_chance %1d%
static OpcodeResult WINAPI opcode_2708(CRunningScript* thread)
{
auto chance = OPCODE_READ_PARAM_FLOAT();

uniform_real_distribution<float> dist(0.0f, 100.0f); // 0.0 to 99.99(9)
auto random = dist(Instance.randomGenerator);

auto result = random < chance;

OPCODE_CONDITION_RESULT(result);
return OR_CONTINUE;
}
} Instance;
Loading