Build an Akinator-style guessing game

Akinator is a guessing game that asks yes-or-no questions to identify a character. The version in this question knows the five characters and four clues in Table 1.

Table 1: Clues that distinguish the five characters.
Character Can it fly? Can it breathe fire? Is it made of metal? Does it meow?
Owl Yes No No No
Dragon Yes Yes No No
Robot No No Yes No
Fox No No No No
Cat No No No Yes

Listing 1 represents the table as two lists. The questions list contains the four clue headings. In characters, each row begins with a name followed by its four clues as Boolean values, in the same order as the questions. For example, Owl can fly, cannot breathe fire, is not made of metal, and does not meow.

Listing 1: Question headings and character rows, with True for yes and False for no.
questions = [
    "Can it fly?",
    "Can it breathe fire?",
    "Is it made of metal?",
    "Does it meow?",
]

# Each row contains a name followed by its four clues.
characters = [
    ["Owl",    True,  False, False, False],
    ["Dragon", True,  True,  False, False],
    ["Robot",  False, False, True,  False],
    ["Fox",    False, False, False, False],
    ["Cat",    False, False, False, True],
]

You may use the supplied ask(question) procedure. It displays a question and returns True for yes or False for no. For example, ask("Can it fly?") returns the player’s answer to that question.

Assume that:

  • The character list is nonempty.
  • The player’s chosen character is in the list, and the player answers truthfully.
  • The clues distinguish every character, so the game always finishes with one character remaining.

Design the game in Python, pseudocode, or a flowchart. Choose one form and follow these rules:

  1. Consider the questions in table order.
  2. Before asking a question, check whether some of the remaining characters would answer yes and others no. Skip the question if every remaining character would give the same answer.
  3. After the player answers, keep only the characters whose clue matches the answer. Give this row-filtering step its own procedure and show what it receives and returns. For example, if the remaining rows are Owl, Robot, and Fox, the answer no to “Can it fly?” keeps Robot and Fox.
  4. Stop when one character remains and report its name.

Then:

  • Show how the remaining characters change when the player thinks of Fox. Include any question the game skips and explain why.
  • Test the game with two different characters. State the questions asked and the expected guess for each.
  • Could a different fixed question order identify Dragon in fewer questions than table order? Explain.

For question position j, read the clue at position j + 1 in each row. Compare the remaining rows with the first row: if one clue differs, both answers are possible. After asking, build a new list containing only the rows whose clue matches the answer.