mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-25 04:15:45 -08:00
182 lines
5.3 KiB
Lua
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
|