13
\$\begingroup\$

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.

\$\endgroup\$
3
  • \$\begingroup\$ 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. \$\endgroup\$
    – lathomas64
    Commented Nov 29, 2010 at 17:57
  • \$\begingroup\$ 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 \$\endgroup\$
    – erik
    Commented Nov 29, 2010 at 18:09
  • 1
    \$\begingroup\$ I see nothing wrong with this approach, I used a similar method for determining probabilities when building a random maze. \$\endgroup\$
    – Nayrb
    Commented Dec 8, 2010 at 5:42

3 Answers 3

23
\$\begingroup\$

(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).

\$\endgroup\$
0
5
\$\begingroup\$

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...

\$\endgroup\$
4
  • 2
    \$\begingroup\$ this almost sounds like you're getting into natural language processing ;) \$\endgroup\$
    – erik
    Commented Nov 30, 2010 at 17:52
  • \$\begingroup\$ Just the best example I could think of off the top of my head where a flat table of weighted options wouldn't suffice. \$\endgroup\$
    – Asmor
    Commented Dec 2, 2010 at 6:53
  • \$\begingroup\$ er... where can I download this wonderful program? Er, I mean great example... \$\endgroup\$ Commented Dec 10, 2010 at 11:20
  • \$\begingroup\$ @espais: Generative grammars FTW! \$\endgroup\$
    – brice
    Commented Mar 26, 2012 at 13:17
3
\$\begingroup\$

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

\$\endgroup\$
0

Not the answer you're looking for? Browse other questions tagged .