SRL Archive - SRL Snippets

Be less predictable


zmon

2012-05-29 05:35:46

when you watch bots mining in mining guild, you can predict where they will go mine with rather high degree of accuracy because the coal is searched through spiral … so they end up going after the nearest

it's not that bad when there is one bot - it almost looks human-like but when there are 5 or 7 shadowing same moves, it's a dead giveaway

now if you have a list ordered from most preferable to least preferable, it would be nice if you could go through it in semi random fashion while still giving 50% or so chance to the first pick going first

there are many ways of doing it but this one is simple - call GetAccessor which will return integer array of indexes already random sorted for you

in following example i'm generating accessor for array 1..7 - give it a spin and see what i mean - you will notice that 1 ends up in first position often but sometimes (lot less likely) you will see 7 in first position of the accessor array

and of course you then just iterate through your array as such:


for Index := 0 to Length(accessor) - 1 do
begin
myArray[accessor[Index]];
end;

here is the code

program RandomizedWeightedAccessor;

function GetAccessor(Low, High : Integer) : TIntegerArray;
var TargetLength : Integer;
var Index : Integer;
begin
TargetLength := High - Low + 1;
SetLength(Result, TargetLength);
for Index := 0 to Length(Result) - 1 do
begin
Result[Index] := Low + Index;
end;
// randomize with weight by double sweep
for Index := Length(Result) - 1 downto 1 do
begin
if (RandomE > 0.5) then continue;
// swap
swap(Result[Index], Result[Index - 1]);
end;
for Index := 1 to Length(Result) - 1 do
begin
if (RandomE > 0.5) then continue;
// swap
swap(Result[Index], Result[Index - 1]);
end;
end;

var i : Integer;
var ac : TIntegerArray;
begin
ac := GetAccessor (1, 7);
for i := 0 to Length(ac) - 1 do
begin
WriteLN('pos ' + IntToStr(i) + ' value ' + IntToStr(ac[i]));
end;
end.

bg5

2012-05-29 05:47:07

You remind me something like this I made in my first script:biggrin:
function RandArray(IntArray:array of integer):array of integer; //Randomize sequence of elements in array
var
RandomizedArray: array of integer;
BoolArr: array of boolean;
a,b,Len:integer;
begin
Len:=Length(IntArray);
SetArrayLength(RandomizedArray, Len)
SetArrayLength(BoolArr, Len)
for a:=0 to Len-1 do
begin
b:= random(Len);
if (not(BoolArr[b])) then
begin
BoolArr[b]:=True;
RandomizedArray[a]:=IntArray[b];
end else
a:=a-1;
Result:=RandomizedArray;
end;
end;

But your have big advantage can be use with any type of array.:)

zmon

2012-05-29 05:53:15

yeah, you can deal with the randomization in few different ways, but essentially i wanted to make sure that the first element has 50% chance of being 1, 25% chance of being 2 and so on… so that you can still enjoy the benefit of close results, but just slightly less predictable

because in all honesty it's sometimes hard to tell which of two rocks are closer to you when you stand between them, yet the army of bots would always chose same

so this way you have 50% chance of going with the rest, 25% chance of going to the other one and 25% chance that you go some place entirely different

[S]paz

2012-05-29 05:53:24

I agree when you go to a busy world and head down to the mining guild it's amusing watching the bots all run to the same rock and compete with each other. I had something similar way back. Thanks for the snippet though!

Sirenia

2012-05-29 07:30:51

I dont want to pretend that I know what im doing but couldnt
var TargetLength : Integer;
var Index : Integer;
be
var
TargetLenght, Index: integer;
instead ?

Abu

2012-05-29 07:34:06

From: Sirenia
I dont want to pretend that I know what im doing but couldnt
var TargetLength : Integer;
var Index : Integer;
be
var
TargetLenght, Index: integer;
instead ?


Yes, but that's just zmon's style of scripting ;)

Anyway, I remember doing something like this before but users don't like the fact it sometimes goes to coal which is further away - even if it means everyone else is going for a different coal.

zmon

2012-05-29 08:58:24

From: Sirenia
I dont want to pretend that I know what im doing but couldnt
var TargetLength : Integer;
var Index : Integer;
be
var
TargetLenght, Index: integer;
instead ?


yes, but past has taught me to not leave anything to chance, imagine that i need to change TargetLength to something else, such as ShortInt for whatever reason, i find the TargetLength line, and it's late in the evening so i overlook Index, and end up changing code to

var
TargetLenght, Index: ShortInt;

and everything compiles and works great except every now and then in marginal cases when short int is not enough for index, my program will crash or worse - mess up data - and i will spend days tracking it down

that's why i prefer one per line - less chance of mistake

From: abu_jwka
Anyway, I remember doing something like this before but users don't like the fact it sometimes goes to coal which is further away - even if it means everyone else is going for a different coal.


that is exactly why i did this to be weighted, if you have pure random pick - you will on average go to middle distance, but this accessor will average on 2nd closest coal with 50% of picks being the closest

EDIT

if you change main body to:


var i : Integer;
var ac : TIntegerArray;
var COUNTER : array [1..7] of Integer;
begin
for i := 1 to 7 do COUNTER[i] := 0;
for i := 1 to 10000 do
begin
ac := GetAccessor (1, 7);
Inc(COUNTER[ac[0]]);
end;
for i := 1 to 7 do
begin
WriteLN('PICK ' + IntToStr(i) + ' chosen ' + IntToStr(COUNTER[i]) + ' times.');
end;
end.

you will see what i'm talking about - this is 10,000 tests:

PICK 1 chosen 5039 times.
PICK 2 chosen 2488 times.
PICK 3 chosen 1203 times.
PICK 4 chosen 665 times.
PICK 5 chosen 301 times.
PICK 6 chosen 151 times.
PICK 7 chosen 153 times.
Successfully executed.

Parade

2012-06-06 14:26:39

Wow, this is awesome! I'm going to be stashing this in my script. Need credit?

shstiger2009

2012-06-06 14:50:48

From: Parade
Wow, this is awesome! I'm going to be stashing this in my script. Need credit?


If you release your script to the public, then yes, credit is needed. :)

[S]paz

2012-06-07 04:32:48

More out of courtesy. Thought and effort went into creating the function. If you use someone's work then credit where credit it due :)