This kind of problem comes down to trying to represent a set of predicates (the equivalent to your yes/no questions).
Let's say that we have a world of three objects, let's call them X, Y and Z. We also have 5 predicates: P1, P2, P3, P4 and P5 (which are yes/no questions).
If we can describe the objects thus:
Code:
X satisfies P1, P3, P5
Y satisfies P2 and P4
Z satisfies P1, P2, P5
I.e. you could ask P1, P2, P3, P4, and P5 and from this know what the object is. You could just ask all 5 questions and from that know the object. But that's useless when you have thousands and thousands of predicates. "Five thousand questions" isn't much of a fun game to play.
If you assume that you know about every possible object that exists, you could cut this down a bit (you would only have to ask two correct questions to get Y).
If you represented this in a code tree, it might look like this:
Code:
If P1:
If P3:
If P5:
=> It's X
Else: # not p5
=> It's unknown
Else: # not P3
If P2:
If P5:
=> It's Y
Else: 3 not P5
=> It's unknown
Else: 3 # not P2
Else: # not P1
If P2:
If P5:
=> It's Z
Else: # not P5
=> It's unknown
Else: not P2
=> It's unknown
You could simplify that a little if you took out the unknowns, but the point still stands.
Note that you're repeating yourself quite a lot. You have to put P5 in the code three times. Imagine the complexity for P6, P16 or P160.
This is because whilst some of the questions can lead on from another ("is it an animal? Is it a mammal?") others may be cross-cutting an unrelated. As such, you might find the same question in two branches of the code. And since it's a binary tree, complexity could get bad the worse case.
And imagine you wanted to extend your code. You might have to make changes in dozens if not hundreds of places. And such large nested conditional structures make mistakes easy. Even the above code is confusing to read, even when I put helpers in.
What you really want to do is represent predicates as above, as a list of objects and the predicates that must be fulfilled to decide that the object has been chosen.
These predicates are the real 'information'. The python code is just the way the game is implemented with this information. The information is a graph structure and you're trying to coerce it into a binary tree structure. It'll go, but it won't be pretty.
There are two classes of special-purpose languages (that I know of): backward chaining logic programming languages (for example Prolog) and forward chaining rule based systems (for example CLIPS). They work in very different ways, but are both centred around representing your knowledge in a natural way. The language runtime takes care of executing the code in a meaningful manner. Prolog has a very nice feature called back-tracking which means if you wrote a 20Q game it could go down one avenue of questioning, and if that failed, back-track up and try a different direction.
I used both these languages and they were the most fun of my computer science degree. I suggest you have a play with them. Get a feeling for logic programming. This will give you the mental framework to implement this in Python. It's certainly very doable. But a massive set of if statements really isn't the way to go. It really won't be much fun!
Good luck with it!