I am going to start a practice project and want to describe my plan here and get advice

Ok I want to create a GM emulator as a practice project to see if I have actually learned anything. Over the past three years I’ve bounced around between HTML, C++, Javascript, Python, Ruby, and others I’ve forgotten the names of. Just going through the lessons and then redoing the courses whenever they are updated. And I realized I probably should actually do something.

You don’t need the backstory as to why I’ve chosen this but I’m going to try and make this with Python.

My plan is basically a user asks a yes or no question or one of a set of other questions, the program will then roll on some probability tables with varying results, ask the user for elaboration, roll some more, repeat and over and over again until outputting a final result. Then store some of the results from its last series of rolls to influence the answers it generates for future questions.

My plan is to do this using basically just variables and a lot of if/else trees. And it’ll probably need a function or two somewhere. I thought it sounded like something that might use loops, but I figure I can just have the if/else statements go back and trigger previous if/else statements if needed and loop that way.

I just am wondering if my intended approach is the right one.

Those if-statements would all look the same, wouldn’t they.

You could store the questions and follow-up questions in a tree shaped data structure instead, and then let your code traverse those trees. (or maybe it’s not a tree, but some other shape of graph)

Each node would contain information about the question there, plus references to what the next question might be.

Nodes could be functions or lists or whatever else is able to represent what’s going on.

Or maybe you’d keep buckets of nodes, and inspect your buckets to figure out which question should be asked first - a question that eliminates half the bucket content would be a good question, while a question that only eliminates one thing would be a bad one.

Point is that if your program is supposed to do operations on your questions, then your questions are data, aren’t they?
It’s much easier to manipulate data than whatever is hard-coded in the source code.

For one of these:

There are 8 total outcomes, so one might define those…as strings, perhaps.

Only 4 outcomes are presented at a time and there are two ways to present them, two buckets, two lists.

outcomes = ['', '', '', '', '', '', '', '']
[[outcome[0], outcome[1], outcome[4], outcome[5]],
 [outcome[2], outcome[3], outcome[6], outcome[7]]
]

Yeah okay, not the largest tree ever

So now the device is represented as data, and one can move on to writing some code for using it.

Can’t help myself sometimes, so:

from itertools import cycle

outcomes = [
    (1, 'You can see a lot just by looking.'),
    (2, 'You are next in line for promotion in your firm.'),
    (5, 'Love is a warm fire to keep the soul warm.'),
    (6, 'Happy life is just in front of you.'),
    (3, 'Welcome change.'),
    (4, 'Your difficulties will strengthen you.'),
    (7, 'Bide your time, for success is near.'),
    (8, 'You are never selfish with your advice or your help.')
]

presentations = cycle([outcomes[:4], outcomes[4:]])
colors = ['BLUE', 'RED', 'GREEN', 'YELLOW']

print('There are four colors to choose from:')
print(' '.join(colors))
color = input('Pick one: ')
for letter, options in zip(color, presentations):
    print(letter.upper(), ' '.join(str(i) for i, _ in options))
options = dict((str(i), pres) for i, pres in options)
print('The available numbers are:', ' '.join(options))
choice = input('Pick one to reveal your fortune! ')
if choice in options:
    print(options[choice])
else:
    print('Hmm no such option, I must have forgotten to put "Dark days ahead."'
          ' in there.')

I’m a few hours past when I should probably be asleep. So maybe my brain is just too fuzzy to make sense. Also as a note I will be responding to your posts as I read each line rather than reading your post and responding to the whole thing at once.

I don’t know what you mean by all look the same.

The idea was in simple example like the user asks “Hey, does the library have the book I want?”

Then the computer would ask if the question is related to information gathering, conflict, resolutions ect. The user would answer information gathering. The computer would then generate a number between 1 and a hundred, at this point modifiers can be applied, then an if/else chain spits out a response based on that 1 through 100, the return of that likely leading to more numbers generated to check different if/else chains with occasional additional input from the user like “Is the object you are searching for common, rare ect. Is it dangerous, do others want it?” with those triggering additional rolls in different if/else chains until finally a result comes out that says like “Yes you find it, but it is well guarded by an irritated neutral party and an old acquaintance is already closer to acquiring it than you.” Obviously that line would actually be the result of many different checks just joined together. It probably won’t be possible to make the grammar pretty. Anyway it’ll likely also then store a couple boolean values as true, Unknown Acquaintance and unknown neutral third party so those can affect future checks.

I expect this to take months to do.

I don’t know what you mean by shape of graph. Is there any shape other than trees and lines? I guess the shape I planned was more of a fractal or flow chart?

And I don’t know what you mean by data, I thought everything is data. But I guess you mean in a less abstract way? Is bucket a programming term? As I haven’t heard it used before.

I’m not sure what to make of your second post. Are you suggesting I use lists and loops? I suppose it may be easier, though I don’t know if there is a way to randomly select an item from a list without resorting to if/else statements. And unless my sleepy brain just is missing it, your example doesn’t use random numbers.

Presumably each node would have a lot of code identical to that of the others, so perhaps that identical code could be split out into some kind of driving code, leaving the differing parts as data.

a tree is one-directional from some root, a flowchart might have loops or paths that split and then join again - that’s not possible in a tree.

a collection of things, yeah.

everything is indeed data when it comes to programming, including your code. but the code might not be so easy to manipulate.

my example could have been a whole lot of if-statements but instead the paths are represented in a list
though, it’s too trivial :expressionless:

Perhaps you would define some 20 different books, and give them various tags/attributes.
The questions might relate to those tags, and perhaps there may be a way of telling which questions are most relevant based on remaining books/tags.

If the questions are yes/no ones, then you could for example run all questions with both yes and no as the answer, and see which question best divides the possibilities into half, that would be a good question to ask.

Or, if the questions have paths between them (like in a flowchart), then which question has the shortest maximum path to the answers?

A question together with its answer might be a filter to the outcomes. Literally.

def hasAttr(attr):
    def p(outcome):
        return attr in outcome['attributes']
    return p


def lacksAttr(attr):
    def p(outcome):
        return attr not in outcome['attributes']
    return p


outcomes = [
    {'name': 'banana', 'attributes': ['sweet', 'yellow']},
    {'name': 'peanut', 'attributes': ['brown', 'salty']},
    {'name': 'sun',    'attributes': ['yellow', 'hot']},
]

questions = [
    ('Is it salty?', [('yes', hasAttr('salty')),
                      ('no', lacksAttr('salty'))]),
    ('Is it brown?', [('yes', hasAttr('brown')),
                      ('no', lacksAttr('brown'))]),
    ('Is it yellow?', [('yes', hasAttr('yellow')),
                       ('no', lacksAttr('yellow'))]),
]

for q in questions:
    text, options = q
    print('For the question:', text,
          'the remaining groups after answering are:')
    for option, predicate in options:
        remaining_outcomes = list(filter(predicate, outcomes))
        print(option, len(remaining_outcomes),
              '(' + ', '.join(o['name'] for o in remaining_outcomes) + ')')

output:

For the question: Is it salty? the remaining groups after answering are:
yes 1 (peanut)
no 2 (banana, sun)
For the question: Is it brown? the remaining groups after answering are:
yes 1 (peanut)
no 2 (banana, sun)
For the question: Is it yellow? the remaining groups after answering are:
yes 2 (banana, sun)
no 1 (peanut)

Something like this would allow for choosing a question based on what possible outcomes remain. So… one would have a loop of: choose a question->ask->filter until there’s only one remaining outcome.
Perhaps one might have more interesting questions too, maybe asking for a number (though, that complicates choosing a question a bit, because it’s no longer a fixed set of answers, but then again, one could look at the possible amounts and get fixed amounts from that)

One might imagine reading information about known books from a file - that’s not code, it’s information, belongs in data structures, not if-statements.
One might also imagine creating questions based on what’s known about different outcomes. My three questions for example look all the same, except for one word.

yay my example makes some sense this time. multi tier questions made me think of those paper fortune teller things but, nope.

You make it sound like if/else statements are easier to use than for loops in this case. This is not true tho.

I think @ionatan wants to make this clear to you as well. Loops are a little harder to understand than if/else statements and both could probably be a solution to your problem, but since this is a practice project i would advice to use loops instead of if/else statements where this is possible.

A nice general rule as to decide when to use loops instead of if/else statements is: When you are repeating the same checks on different data.

Since you intend to use only if/else statements and variables i don’t think it is the right approach. You would be practicing things you are already comfortable with to a certain degree.
Since loops are a big thing in programming that are there to make your live easier i suggest you do make use of it when working on this project.

Okay I guess that makes sense. I’ll try to do it the hard way.

I guess that makes sense. Thank you.