Files
basic-computer-games/03_Animal/python/animal.py
2024-08-19 03:46:27 +03:00

201 lines
7.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Animal
From: Basic computer Games(1978)
Unlike other computer games in which the computer
picks a number or letter and you must guess what it is,
in this game you think of an animal and the computer asks
you questions and tries to guess the name of your animal.
If the computer guesses incorrectly, it will ask you for a
question that differentiates the animal it guessed
from the one you were thinking of. In this way the
computer "learns" new animals. Questions to differentiate
new animals should be input without a question mark.
This version of the game does not have a SAVE feature.
If your sistem allows, you may modify the program to
save array A$, then reload the array when you want
to play the game again. This way you can save what the
computer learns over a series of games.
At any time if you reply 'LIST' to the question "ARE YOU
THINKING OF AN ANIMAL", the computer will tell you all the
animals it knows so far.
The program starts originally by knowing only FISH and BIRD.
As you build up a file of animals you should use broad,
general questions first and then narrow down to more specific
ones with later animals. For example, If an elephant was to be
your first animal, the computer would ask for a question to distinguish
an elephant from a bird. Naturally there are hundreds of possibilities,
however, if you plan to build a large file of animals a good question
would be "IS IT A MAMAL".
This program can be easily modified to deal with categories of
things other than animals by simply modifying the initial data
in Line 530 and the dialogue references to animal in Lines 10,
40, 50, 130, 230, 240 and 600. In an educational environment, this
would be a valuable program to teach the distinguishing chacteristics
of many classes of objects -- rock formations, geography, marine life,
cell structures, etc.
Originally developed by Arthur Luehrmann at Dartmouth College,
Animal was subsequently shortened and modified by Nathan Teichholtz at
DEC and Steve North at Creative Computing
"""
from typing import Optional
class Node:
"""
Node of the binary tree of questions.
"""
def __init__(
self, text: str, yes_node: Optional["Node"], no_node: Optional["Node"]
):
# the nodes that are leafs have as text the animal's name, otherwise
# a yes/no question
self.text = text
self.yes_node = yes_node
self.no_node = no_node
def update_node(
self, new_question: str, answer_new_ques: str, new_animal: str
) -> None:
# update the leaf with a question
old_animal = self.text
# we replace the animal with a new question
self.text = new_question
if answer_new_ques == "y":
self.yes_node = Node(new_animal, None, None)
self.no_node = Node(old_animal, None, None)
else:
self.yes_node = Node(old_animal, None, None)
self.no_node = Node(new_animal, None, None)
# the leafs have as children None
def is_leaf(self) -> bool:
return self.yes_node is None and self.no_node is None
def list_known_animals(root_node: Optional[Node]) -> None:
"""Traversing the tree by recursion until we reach the leafs."""
if root_node is None:
return
if root_node.is_leaf():
print(root_node.text, end=" " * 11)
return
if root_node.yes_node:
list_known_animals(root_node.yes_node)
if root_node.no_node:
list_known_animals(root_node.no_node)
def parse_input(message: str, check_list: bool, root_node: Optional[Node]) -> str:
"""only accepts yes or no inputs and recognizes list operation"""
token = ""
while token not in ["y", "n"]:
inp = input(message)
if check_list and inp.lower() == "list":
print("Animals I already know are:")
list_known_animals(root_node)
print("\n")
token = inp[0].lower() if len(inp) > 0 else ""
return token
def avoid_void_input(message: str) -> str:
answer = ""
while not answer:
answer = input(message)
return answer
def print_intro() -> None:
print(" " * 32 + "Animal")
print(" " * 15 + "Creative Computing Morristown, New Jersey\n")
print("Play ´Guess the Animal´")
print("Think of an animal and the computer will try to guess it.\n")
def main() -> None:
# Initial tree
yes_child = Node("Fish", None, None)
no_child = Node("Bird", None, None)
root = Node("Does it swim?", yes_child, no_child)
# Main loop of game
print_intro()
while (
keep_playing := parse_input(
"Are you thinking of an animal? ", True, root
)
== "y"
):
keep_asking = True
# Start traversing the tree by the root
actual_node: Node = root
while keep_asking:
if not actual_node.is_leaf():
# we have to keep asking i.e. traversing nodes
answer = parse_input(actual_node.text, False, None)
# As this is an inner node, both children are not None
if answer == "y":
assert actual_node.yes_node is not None
actual_node = actual_node.yes_node
else:
assert actual_node.no_node is not None
actual_node = actual_node.no_node
else:
# we have reached a possible answer
answer = parse_input(f"Is it a {actual_node.text}? ", False, None)
if answer == "n":
# add the new animal to the tree
new_animal = avoid_void_input(
"The animal you were thinking of was a ? "
)
new_question = avoid_void_input(
"Please type in a question that would distinguish a "
f"{new_animal} from a {actual_node.text}: "
)
answer_new_question = parse_input(
f"for a {new_animal} the answer would be: ", False, None
)
actual_node.update_node(f"{new_question}?", answer_new_question, new_animal)
else:
print("Why not try another animal?")
keep_asking = False
########################################################
# Porting Notes
#
# The data structure used for storing questions and
# animals is a binary tree where each non-leaf node
# has a question, while the leafs store the animals.
#
# As the original program, this program doesn't store
# old questions and animals. A good modification would
# be to add a database to store the tree.
# Also as the original program, this one can be easily
# modified to not only make guesses about animals, by
# modyfing the initial data of the tree, the questions
# that are asked to the user and the initial message
# function (Lines 120 to 130, 135, 158, 160, 168, 173)
########################################################
if __name__ == "__main__":
main()