Files
basic-computer-games/03_Animal/lua/Animal.lua
2023-04-29 19:40:42 -07:00

182 lines
5.3 KiB
Lua

--
-- Animal.lua
--
-- maintain a flat table/list of all the known animals
local animals = {
"FISH",
"BIRD"
}
-- store the questions as a binary tree with each node having a
-- "y" or "n" branch
-- if the node has a member named "a" it's an answer, with an index
-- into the animals list.
-- Otherwise, it's a question that leads to more nodes.
local questionTree = {
q = "DOES IT SWIM",
y = { a = 1 },
n = { a = 2 }
}
-- print the given prompt string and then wait for input
-- loops until a non-empty input is given
-- returns the input as an upper-case string
function askPrompt(promptString)
local answered = false
local a
while (not answered) do
print(promptString)
a = io.read()
a = string.upper(a)
if (string.len(a) > 0) then
answered = true
end
end
return a
end
-- print the given prompt string and then wait for the
-- user to enter a string beginning with "Y" or "N"
function askYesOrNo(promptString)
local a
while ((a ~= "Y") and (a ~= "N")) do
a = askPrompt(promptString)
a = a:sub(1,1)
end
return a
end
-- prints the introductory text from the original BASIC program
function printIntro()
print(string.format("%32s", " ") .. "ANIMAL")
print(string.format("%15s", " ") .. "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
print()
print()
print()
print("PLAY 'GUESS THE ANIMAL'")
print("THINK OF AN ANIMAL AND THE COMPUTER WILL TRY TO GUESS IT.")
print()
end
-- prints the animals known in the source list
function listKnownAnimals()
print()
print("ANIMALS I ALREADY KNOW ARE:")
local x
local item
for x = 1,#animals do
-- use string.format to space each animal in a 12-character-wide "cell"
item = string.format("%-12s", animals[x])
-- io.write() works like print(), but doesn't automatically add a carriage return/newline
io.write(item)
-- every fifth item, start a new line
if ((x % 5) == 0) then
io.write("\n")
end
end
print()
print()
end
-- Prompts the user for info about the animal they were thinking of, then
-- uses that to add a new branch to the tree
-- curNode: the node in the tree where the computer made a wrong guess
-- branch: the answer the user gave to curNode's question
function addAnimalToTree(curNode, branch)
local newAnimal
local curResponse = curNode[branch]
local guessedIndex = curResponse.a
local guessedAnimal = animals[guessedIndex]
local newQuestion, newAnswer, newIndex
local newNode
newAnimal = askPrompt("THE ANIMAL YOU WERE THINKING OF WAS A ?")
newQuestion = askPrompt("PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A "..
tostring(newAnimal).." FROM A "..tostring(guessedAnimal))
newAnswer = askYesOrNo("FOR A "..tostring(newAnimal).." THE ANSWER WOULD BE?")
-- add the new animal to the master list at the end, and
-- save off its index in the list
table.insert(animals, newAnimal)
newIndex = #animals
-- create a new node for the question we just learned
newNode = {}
newNode.q = newQuestion
if (newAnswer == "Y") then
newNode.y = { a = newIndex }
newNode.n = { a = guessedIndex }
else
newNode.y = { a = guessedIndex }
newNode.n = { a = newIndex }
end
-- replace the previous answer with our new node
curNode[branch] = newNode
end
-- Starts at the root of the question tree and asks questions about
-- the user's animal until the computer hits an "a" answer node and tries
-- to make a guess
function askAboutAnimal()
local curNode = questionTree
local finished = false
local response, responseIndex
local nextNode, animalName
while (not finished) do
response = askYesOrNo(curNode.q .. "?")
-- convert the response "Y" or "N" to the lowercase "y" or "n" that we use to name our branches
branch = string.lower(response)
nextNode = curNode[branch]
-- is the next node an answer node, or another question?
if (nextNode.a ~= nil) then
-- it's an answer, so make a guess
animalName = animals[nextNode.a]
response = askYesOrNo("IS IT A "..tostring(animalName).."?")
if (response == "Y") then
-- we got the correct answer, so prompt for a new animal
print()
print("WHY NOT TRY ANOTHER ANIMAL?")
else
-- incorrect answer, so add a new entry at this point in the tree
addAnimalToTree(curNode, branch)
end
-- whether we were right or wrong, we're finished with this round
finished = true
else
-- it's another question, so advance down the tree
curNode = nextNode
end
end
end
-- MAIN CONTROL SECTION
printIntro()
-- loop forever until the player requests an exit by entering a blank line
local exitRequested = false
local answer
while (not exitRequested) do
print("ARE YOU THINKING OF AN ANIMAL?")
answer = io.read()
answer = string.upper(answer)
if (string.len(answer) == 0) then
exitRequested = true
elseif (answer:sub(1,4) == "LIST") then
listKnownAnimals()
elseif (answer:sub(1,1) == "Y") then
askAboutAnimal()
end
end