Saturday, July 31, 2010

You got 25% chance of success, do you feel lucky?

I remember few years ago playing a game called Silkroad(which stolen 2 years of my life – that's another story), in this game when you do alchemy, in some situations, you have a X percent chance of success, I had a lot of successes but also failures, anyways... I was wondering how do they calculate the success? You can implement an idea in many ways...
This morning I thought of an algorithm that does just that, it returns True or False with a certain percent chance of success.
I've started the theory(in my head...) like so:
- we need a chance resolution(in this case 5%)
- we need to have an array of boolean with the number of elements equal to 100 divided by resolution(5)

Implementation:
- initialize the array of chances to false
- calculate how many 5% chances are there(if you give 20% chance, then we have to set to True 4 elements in ChanceArray
- for each 5% chance set to True a element in ChanceArray that is NOT already set to true, starting at a random index in the array
- pick a random element from the array and return it's state(True or False) as the result of the chance

Here it is, my implementation:
(add "Math" to uses clause)
function CheckSuccess(const PercentChance: Integer): Boolean;
var
  // 5% resolution
  // can give chances like 10%, 50% or 15%, 55%, 35%, etc.
  ChanceArray: array[0..19] of Boolean;
  ChanceCount: Integer;
  ChanceIndex: Integer;
  Index: Integer;

    procedure AddChance;
    begin
      ChanceIndex := RandomRange(Low(ChanceArray), High(ChanceArray));
      while ChanceArray[ChanceIndex] do begin
        Inc(ChanceIndex);
        if ChanceIndex > High(ChanceArray) then
          ChanceIndex := Low(ChanceArray);
      end; // while ChanceArray[ChanceIndex] do begin
      ChanceArray[ChanceIndex] := True;
    end; // procedure AddChance;

begin
  // you should probably call this once per application startup
  Randomize;
  // initialize chance array to false
  for Index := Low(ChanceArray) to High(ChanceArray) do
    ChanceArray[Index] := False;
  // how many 5% chances we got?
  if PercentChance > 100 then
    ChanceCount := 20
  else
    ChanceCount := (PercentChance div 5); // 5% resolution
  for Index := 1 to ChanceCount do
    AddChance;
  ChanceIndex := RandomRange(Low(ChanceArray), High(ChanceArray));
  Result := ChanceArray[ChanceIndex];
end;
Usage:
(we give the player a 25% chance of success – you can increase or decrease chance but replacing 25 with another value)
ShowMessage(BoolToStr(CheckSuccess(25), True));
P.S. Please drop me a comment with how would you implement a similar algorithm.

2 comments:

  1. suppose int(rnd(100))+1 is equally probable from 1 to 100, you have 25 probability over 100 to have a result <= 25:

    gtray:=int(rnd(100))+1;
    if gtray<=25
    then result:=true
    else result:=false;

    ReplyDelete
  2. There are many ways to implement an algorithm, however I believe that my algorithm gives a more random result but you're more welcome to prove me wrong.
    Thank you for your comment!

    ReplyDelete

Blogroll(General programming and Delphi feeds)