Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm struggling with coming up with an elegant solution to generating random events in the game that I'm working on.

Say there are 4 classes of events that can happen, with varying events in those classes that may occur.

So something along the lines of

main_events = {"common event", "not so common event", "somewhat rare event", "rare event"}
sub_events[0] = {"common event 1", "common event 2",..}
...

I have a somewhat kludgey solution in place that first just has a random number generated between 0 and 100, and if the number falls within a given range then a main event will be triggered. Then I'll do another random roll to see which sub event occurs.

Is there a better solution than something along these lines? Like I mention, it doesn't feel very elegant, and I'd like to make it easily expandable for the addition of future events.

share|improve this question
    
better in what way? it seems expandable enough if you want more events just add to the sub events or main events arrays. The only improvment to make it easier to expand would be possibly reading the events and sub-events in from a file so you don't have to recompile if you change the rarity of an event. –  lathomas64 Nov 29 '10 at 17:57
    
moreso that this was my initial take on the issue, and my guess was that there is a better or more elegant way of handling the generation of random events –  espais Nov 29 '10 at 18:09
1  
I see nothing wrong with this approach, I used a similar method for determining probabilities when building a random maze. –  Bryan Harrington Dec 8 '10 at 5:42
add comment

3 Answers

up vote 18 down vote accepted

(This is based on my answer for a similar question on Stack Overflow.)

It sounds like you're asking for a more flexible way of specifying the probability of each event. For that, you can use a simple weighing algorithm: simply decide how common each event should be and assign it a weight that is appropriate compared to the other weights. For example, if you have events A, B and C, with probabilities 70%, 25% and 5%, you could give them the weights 70, 25 and 5 (or 14, 5, and 1 - the important thing is the relative difference).

Once you have that, you can use the following algorithm to select an event:

Given a list L of items (I,W), where I is the item and W is the weight:

  1. Add all of the weights together. Call this sum S.
  2. Generate a random number between 0 and S (excluding S, but including 0). Call this value R.
  3. Initialize a variable to 0 to keep track of the running total. We'll call this T.
  4. For each item (I,W) in L:
    1. T=T+W
    2. If T > R, return I.

It's up to you if you want to first select between the different groups of events, or if you want a single table with all of the events (where each "group" has an appropriate sum compared to the others).

share|improve this answer
add comment

Michael's solution is perfect if you want a single table of possible events.

Let's say you want to build a random insult generator, though. In this case, a series of tables would work best. You'd start with a table that has a list of general patterns. For example,

Your [RELATIVE] [RELATION] [ANIMAL]!
Go [VERB] [NOUN] in your [ORIFICE]!

Now say the random generator picks the second pattern. You call the verb table, which has entries like:

stick
jam
shove

But here's where it gets interesting, your noun table might look like

[ANIMAL]
your [RELATIVE]
[ADJECTIVE] [NOUN]

So you see, in this manner you can generate sophisticated and complex results.

As for actually implementing something like this, here's an example of how you might do it in JavaScript.

function Noun() {
    var items = 3;
    var i = Math.floor(Math.random()*items);
    switch (i)
        case 0:
            return Animal();
            break;
        case 1:
            return "your " + Relative();
            break;
        case 2:
            return Adjective() + Noun();
            break;
}

Obviously this is a crude example (you might generate, for example, "Go shove flaming your mom in your eye socket!"), but it's meant more as an illustration, since I don't think I explained it very well...

share|improve this answer
2  
this almost sounds like you're getting into natural language processing ;) –  espais Nov 30 '10 at 17:52
    
Just the best example I could think of off the top of my head where a flat table of weighted options wouldn't suffice. –  Asmor Dec 2 '10 at 6:53
    
er... where can I download this wonderful program? Er, I mean great example... –  TokenMacGuy Dec 10 '10 at 11:20
    
@espais: Generative grammars FTW! –  brice Mar 26 '12 at 13:17
add comment

My answer to a question on generating random drops may very well work for this too.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.