Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Randomness and Probability (Harlowe)

I understand that
You (either: "walk", "run") to the bus stop.

is a mechanism for generating randomness in text, links, or passages. But I assume that creates a 50/50 chance of walking or running, right? What if I want a 70% chance of walking and a 30% chance of running?

Comments

  • Maybe something like:
    You (either: "walk", "walk", "walk", "walk", "walk", "walk", "walk", "run", "run", "run") to the bus stop.
    
  • Hahaha oh god, so if I want there to be a .5% chance of running, I'll have to type 199 walks and one run?

    I'm using real world stats like infant mortality, which are, thankfully, low but important.

    If that's the case then maybe it'll be cleanest to have a separate passage for each long string of probabilities and then plug them into the part of the story where they belong via (display:) ? Probability / luck is the key factor in whether a choice is displayable in the twine I'm building right now.
  • edited September 2015
    You want the (random:) macro:
    You (if: (random: 1, 10) <= 7)[walk](else:)[run] to the bus stop.
    
  • Great!

    So a more complex example might be formatted like:
    (if: (random: 0, 100) <= .38)[(display:"Die at birth")](else:)[(display: "It's a boy!")]

    Is that right?
  • And one with more than two choices would look like:
    You are (if: (random: 0, 100) <= 5)[high](else:) <= 60)[middle](else:) < = 35)[low] class.

    ...Right?
  • edited September 2015
    Not quite.

    Your range is off in both examples. If you want percentile, the range would be [1, 100] not [0, 100].

    Your first example seems to be trying to compare the result to 0.38%. If that's the case and the .38 isn't a typo, then that won't work as (random:) returns integers (i.e. whole numbers). Other than that, it seems okay.

    Your second example is problematic on multiple levels. The syntax of the (else:) macros is incorrect and you're using the wrong macro anyway; at least the first needs to be an (elseif:). You're also not testing against anything in the latter two macros. Finally, your third conditional is unreachable as the preceding conditional will always match the same conditions. It should be something more like the following: (assuming the chances are: low is 35%, middle is 60%, and high is 5%)
    (set: $roll to (random: 1, 100))You are (if: $roll <= 35)[low](elseif: $roll <= 95)[middle](else:)[high] class.
    
  • The .38 isn't a typo. So I definitely can't roll odds of something that's less than 1%? I guess I'll have to round up... That's a big difference though. :-/

    I don't understand what you mean by
    Finally, your third conditional is unreachable as the preceding conditional will always match the same conditions.
    Can you explain that more?

    Can you recommend a tutorial or guide on if, elseif, and else macros? They've been giving me trouble in general. There's clearly something about it I'm just not getting. I've been looking at tons of examples ... that never work when I try them. And obviosuly the wiki hasn't been updated for Twine 2...
  • I don't understand what you mean by
    Finally, your third conditional is unreachable as the preceding conditional will always match the same conditions.
    Can you explain that more?
    Well, first let me clarify. I should have said that the third conditional will be unreachable for any value which could make it true.

    An (if:)(elseif:)(else:) chain is processed in-order. So, if you do something like the following:
    (if: $roll <= 5)[…](elseif: $roll <= 60)[…](elseif: $roll <= 35)[…]
    
    Then the third macro will never be true because the preceding macro's condition, $roll <= 60, will always yield true for any value which would also make its condition, $roll <= 35, true. So, the only values which will make it down the chain to the third macro are those that are greater than 60, which will never drive its condition true.

    Can you recommend a tutorial or guide on if, elseif, and else macros? They've been giving me trouble in general. There's clearly something about it I'm just not getting. I've been looking at tons of examples ... that never work when I try them. And obviosuly the wiki hasn't been updated for Twine 2...
    Have you tried the Harlowe docs?

    Beyond that, it sounds like you need to review some beginners programming guides. I'd suggest asking the Oracle of Delphi Google.
  • Ah yes putting values in order makes sense. I got it now. Thanks for taking the time to break it down for me a little more.

    I'll click around! A lot of what I've seen doesn't *quite* work as epxected in Twine. Doing a lot of trial by error. But I'm learing a ton really fast, which is really exciting!
  • Surely something with syntax is weird here, but I'm not sure what.
    ##(set: $oddsGEN to (random: 1, 100))Congratulations! It's a...
    (if: $oddsGEN is > 0 and $oddsGEN is < 14)[(set:$GEN to 3)](elseif: $oodsGEN is > 14 and $oddsGEN is < 29)[(set:$GEN to 4)](elseif: $oodsGEN is > 29 and $oddsGEN is < 64)[(set:$GEN to 2)](elseif:$oddsGEN is > 64 and $oddsGEN is < 99)[(set:$GEN to 1)](else: $oddsGEN is 100)[(set:$GEN to 5)]

    (if:$GEN is 1 or $GEN is 3)[Boy!](elseif:$GEN is 2 or $GEN is 4)[Girl!](else: $GEN is 5)[It's a...

    Well...]

    For some reason, even though $oddsGEN is getting randomly assigned values as it should, $GEN is being set to 5 no matter what. Earlier I had a slightly different syntax in place (I forget what), I was only getting 1s and 2s, even though other $oddGEN values were populating.

    Can anyone tell me what I'm doing wrong?
  • edited September 2015
    1. You're using two operators when you need one. You don't combine the is operator with the > or < operators.

    2. The (else:) macro does not take a condition, it always succeeds. So, the last macro in the chain either needs to be an (elseif:) or you should remove the condition from the (else:).

    3. You're skipping parts of your range, which I doubt you intended, because you're doing things like < 14 then > 14, which skips 14.

    Your code is also highly redundant, it would be better like so: (added extra whitespace and comments for clarity)
    (if:     $oddsGEN <= 14)[(set: $GEN to 3)] <!-- [ 1, 14] -->
    (elseif: $oddsGEN <= 29)[(set: $GEN to 4)] <!-- [15, 29] -->
    (elseif: $oddsGEN <= 64)[(set: $GEN to 2)] <!-- [30, 64] -->
    (elseif: $oddsGEN <= 99)[(set: $GEN to 1)] <!-- [65, 99] -->
    (else:)[(set: $GEN to 5)]                  <!-- [ 100  ] -->
    
    I don't know if I hit the ranges you wanted there, but your code wasn't doing that anyway, so….
  • edited September 2015
    EDIT: Ignore my comment, TheMadExile going in first!

    A couple of issues with your example:

    a. The (else:) macro ignores any condition parameters you pass to it so things like (else: $oddsGEN is 100) should be just (else:)

    b. Because of the way you are coding your ranges the variable $GEN will be set to 5 whenever $oddsGEN equals the values of 14, 29, 64, 99 or 100.

    c. You don't use the is keyword when using symbols like >, <, >=, <=

    d. Because you are using (else-if:) and (else:) macros you do not need to include a test for the lower edge of each of your ranges.

    e. It is a good idea to insert a single space character between the colon at the end of a macro name and the parameter(s) of that macro.

    Try the following:
    ##(set: $oddsGEN to (random: 1, 100))Congratulations! It's a...
    (if: $oddsGEN <= 14)[(set: $GEN to 3)](elseif: $oddsGEN <= 29)[(set: $GEN to 4)](elseif: $oddsGEN <= 64)[(set: $GEN to 2)](elseif: $oddsGEN <= 99)[(set: $GEN to 1)](else:)[(set: $GEN to 5)]
    
    (if: $GEN is 1 or $GEN is 3)[Boy!](elseif: $GEN is 2 or $GEN is 4)[Girl!](else:)[It's a...
    
    Well...]
    
  • The usual fudge for faking lower values with an integer PRN is to scale up the range and the test value. So 0.38 percent would be 38 in a 1 to 10000 range.
  • Can't help but think that a couple of arrays would simplify the code immensely.

    First would hold the cumulative threshold values - search through it and return the index into the array of the first value that greater than the generated value.

    Second would be a set of text messages and links for each index value...
Sign In or Register to comment.