Topical Information

This lab should help you with the concept of [indeterminite] looping while continuing to let you practice with fancy input.

Program Information

After talking with not only those who play games with heavy dice usage but now talking with those who develop such dice-heavy games, you realize there is a gap in your 'dice stats' program. Players need to roll dice and some find the stats interesting or useful. Developers, on the other hand, actually want to see the stats, do not need the rolls, but also want to know what dice would create a certain range of values.

For instance, suppose a games developer wanted random values in the range [5..15] but does not know what dice-roll would produce such a range. You can not just tell a player, "pick a random value in this range." (They'd always pick the maximum, you see. Unless it would hurt them, then they'd always pick the minimum...*shrug*) You have to tell them the dice-roll to make!

You start from your min and max formulas from earlier for a dice roll of NdS+A:

   min = N+A

   max = N*S+A

With a little math, you hit upon a strategy:

  1. take the user's desired range: min..max; we'll assume the adjustment is 0 — a natural dice roll

  2. divide the max by the min and check if the remainder is zero (0) and the quotient is a standard die size (4, 6, 8, 10, 12, 20, 100).

    if so, you are done: {min}d{quotient}+{adjustment} is the roll to get the user's original [min..max] range.

    if not, subtract 1 from both the max and the min and add 1 to an adjustment counter (which started at 0 — the additive identity for integers).

    (before subtracting, you can also check to see if the quotient you arrived at with a 0 remainder divides evenly into a die size

    if so, you can be done: {min}d{quotient}+{adjustment} is a roll to get the user's original [min..max] range.)

  3. if you reach a min of 1 and you did not get a quotient that was a standard die size, either report failure...

    or try starting back at the original range values and increasing the max and min by 1 each 'round' (instead of decreasing them; of course, reset the adjustment to 0 and decrease it by 1 each 'round').

    stop and ask if the developer wants to keep searching at every -10-divisible adjustment (0, -10, -20, -30, etc.), though. (the negative search, your mathematical testing revealed, may never end.)

    even better, ask the developer how many tests/rounds to do before stopping to ask. (i.e. the user enters the 10 for a 10-divisible stop — or whatever value they choose.)

For the example above [5..15]:

        |      |      |      |          | even divide?  |
  round | min  | max  | adj  | max/min  | die size?     | action
--------+------+------+------+----------+---------------+----------------------
   0    |  5   |  15  |  0   |   3      |   yes, no     | min--; max--; adj++
   1    |  4   |  14  |  1   |   3 (R2) |   no, no      | min--; max--; adj++
   2    |  3   |  13  |  2   |   4 (R1) |   no, yes     | min--; max--; adj++
   3    |  2   |  12  |  3   |   6      |   yes, yes    | DONE

    REPORT:  roll 2d6+3 to get [5..15]

(Notice that this could also be 5d3 right off the bat if we were allowing non-standard die sizes. This is up to you depending on the options you choose.)

Or perhaps the user wants values [-1..20]:

        |      |      |      |          | even divide?  |
  round | min  | max  | adj  | max/min  | die size?     | action
--------+------+------+------+----------+---------------+----------------------
   0    | -1   |  20  |  0   |   NA     |   NA          | try negative adj?  yes

        |      |      |      |          | even divide?  |
  round | min  | max  | adj  | max/min  | die size?     | action
--------+------+------+------+----------+---------------+----------------------
   0    | -1   |  20  |  0   |   NA     |   NA          | min++; max++; adj--
   1    |  0   |  21  | -1   |   NA     |   NA          | min++; max++; adj--
   2    |  1   |  22  | -2   |  22      |   yes, no     | min++; max++; adj--
   3    |  2   |  23  | -3   |  11 (R1) |   no, no      | min++; max++; adj--
   4    |  3   |  24  | -4   |   8      |   yes, yes    | DONE

    REPORT:  roll 3d8-4 to get [-1..20]

Or perhaps the desired range of values is [1..21]:

        |      |      |      |          | even divide?  |
  round | min  | max  | adj  | max/min  | die size?     | action
--------+------+------+------+----------+---------------+----------------------
   0    |  1   |  21  |  0   |  21      |   yes, no     | try negative adj?  yes

        |      |      |      |          | even divide?  |
  round | min  | max  | adj  | max/min  | die size?     | action
--------+------+------+------+----------+---------------+----------------------
   0    |  1   |  21  |  0   |  21      |   yes, no     | min++; max++; adj--
   1    |  2   |  22  | -1   |  11      |   yes, no     | min++; max++; adj--
   2    |  3   |  23  | -2   |   7 (R2) |   no, no      | min++; max++; adj--
   3    |  4   |  24  | -3   |   6      |   yes, yes    | DONE

    REPORT:  roll 4d6-3 to get [1..21]

Another developer would like a range of [4..12]:

        |      |      |      |          | even divide?  |
  round | min  | max  | adj  | max/min  | die size?     | action
--------+------+------+------+----------+---------------+----------------------
   0    |  4   |  12  |  0   |   3      |   yes, no     | min--; max--; adj++
   1    |  3   |  11  |  1   |   2 (R2) |   no, no      | min--; max--; adj++
   2    |  2   |  10  |  2   |   5      |   yes, no     | min--; max--; adj++
   3    |  1   |   9  |  3   |   9      |   yes, no     | try negative adj?  yes

        |      |      |      |          | even divide?  |
  round | min  | max  | adj  | max/min  | die size?     | action
--------+------+------+------+----------+---------------+----------------------
   0    |   4  |  12  |   0  |   3      |   yes, no     | min++; max++; adj--
   1    |   5  |  13  |  -1  |   2 (R3) |   no, no      | min++; max++; adj--
   2    |   6  |  14  |  -2  |   2 (R2) |   no, no      | min++; max++; adj--
   3    |   7  |  15  |  -3  |   2 (R1) |   no, no      | min++; max++; adj--
   4    |   8  |  16  |  -4  |   2      |   yes, no     | min++; max++; adj--
   5    |   9  |  17  |  -5  |   1 (R8) |   no, no      | min++; max++; adj--
   6    |  10  |  18  |  -6  |   1 (R8) |   no, no      | min++; max++; adj--
   7    |  11  |  19  |  -7  |   1 (R8) |   no, no      | min++; max++; adj--
   8    |  12  |  20  |  -8  |   1 (R8) |   no, no      | min++; max++; adj--
   9    |  13  |  21  |  -9  |   1 (R8) |   no, no      | min++; max++; adj--
  10    |  14  |  22  | -10  |   1 (R8) |   no, no      | adj is -10, cont?  no

    REPORT:  cannot create [4..12] with standard dice

(Of course, the savy among you realize that [4..12] is really just 4d3. (And everyone who games knows that 'd3', although non-standard, can be done with a d6 — or a d12 — by simply using integer division or wrapping (aka integer modulo...plus 1). That is integer division of a d6 would give:

     d6 roll:   1   2   3   4   5   6
   d3 result:   1   1   2   2   3   3
    (d6 / 2)

Versus wrapping of a d6 would give:

     d6 roll:   1   2   3   4   5   6
   d3 result:   1   2   3   1   2   3
  (d6 % 3 + 1)

You could add checks for such non-standard die sizes if you like, but they are not required.)

(Another nice one is [3..5] which is d3+2.)


So, what are we proposing? A developer's version of your dice program that allows the user to enter a range to be produced and then produces a dice-roll that will produce such a range!


As an example, you might have the program interaction look something like (as usual, the parts in this color were typed by the user):

$ ./devdice.out

                 Welcome to the Developer's Dice Program!!!

Enter your desired range:  [5..38]

Thank you!!  Calculating...  Done.

You can achieve a range of [5..38] by rolling 3d12+2.

Thank you for using the DDP!!

Endeavor to have an enclosed day!

$

Thought Provoking Questions

  1. How can you check if a division is 'even' or not? (Like "min evenly divides max"...)

  2. How can you have a loop stop when one of two conditions is met? (Like "min == 1 or max/min is even and a die size" or like "max/min is even and a die size or adj/-10 is even and user wants to stop"... Oo! That was a pair of pairs, was not it?)

  3. How can you check that a value is one of a group of values — not a range, but a set of discrete values? (Like max/min is one of 4, 6, 8, 10, 12, 20, 100...) There must be a simple and efficient way to decide if one value is equal to one or another of a set of unique, discrete-typed literally known values! Hmm...

    ...or maybe it can be even simpler than that!

  4. How can you remember a truth value for later testing? (Like remembering if a division is even and remembering if a value is one of a group of values and then later using those truth values in a loop condition...)

  5. Bonus:

    1. How did the min and max formulas lead you to the ingenious solution of dividing the max and min values and 'reducing' by an adjustment?

    2. Why do you sometimes have to go the other direction?

    3. Why is this mathematically sound?

This assignment is (Level 3.5).

Options


Total Level Possible

If you did all above options, this lab could be worth as much as (Level 43.5).