home *** CD-ROM | disk | FTP | other *** search
- #
- # Animal Game
- # ===========
- #
- # This is the familiar "animal game" written in Icon. The computer
- # will ask its human opponent questions in an attempt to guess
- # what animal he is thinking of. It is an "expert system" that
- # starts out with limited knowledge, but gets smarter as it plays
- # and learns from its opponents. At the conclusion of a session,
- # the computer will ask permission to remember for future sessions
- # that which it learned.
- #
- # The game is not limited to guessing animals only. By simply
- # modifying the first two lines of procedure "main" it will happily
- # guess things in other categories. For example, the lines:
- #
- # GameObject := "president"
- # Tree := Question("Has he ever been known as Bonzo",
- # "Reagan","Lincoln")
- #
- # can be substituted and it works reasonably well. The knowledge files
- # will be kept separate, too.
- #
- # Typing "list" at any yes/no prompt will show an inventory of
- # animals known, and there are some other commands (see procedure
- # "Confirm").
- #
-
- global GameObject,Tree,ShowLine,Learn
- record Question(question,yes,no)
-
- procedure main()
- GameObject := "animal"
- Tree := Question("Does it live in water","goldfish","canary")
- Get() # Recall prior knowledge
- Game() # Play a game
- return
- end
-
- procedure Game()
- while Confirm("Are you thinking of ",Article(GameObject)," ",
- GameObject) do {
- Ask(Tree)
- }
- write("Thanks for a great game.")
- if \Learn &
- Confirm("Want to save knowledge learned this session") then Save()
- return
- end
-
- procedure Confirm(q1,q2,q3,q4,q5,q6)
- local answer,s
- static ok
- initial {
- ok := table()
- ok["y"] := ok["yes"] := ok["yeah"] := ok["uh huh"] := "yes"
- ok["n"] := ok["no"] := ok["nope"] := ok["uh uh"] := "no"
- }
- while /answer do {
- write(q1,q2,q3,q4,q5,q6,"?")
- case s := read() | exit(1) of {
- "save": Save()
- "get": Get()
- "list": List()
- "dump": Output(Tree,&output)
- default: {
- (answer := \ok[map(s,&ucase,&lcase)]) |
- write("This is a \"yes\" or \"no\" question.")
- }
- }
- }
- return answer == "yes"
- end
-
- procedure Ask(node)
- local guess,question
- case type(node) of {
- "string": {
- if not Confirm("It must be ",Article(node)," ",node,", right") then {
- Learn := "yes"
- write("What were you thinking of?")
- guess := read() | exit(1)
- write("What question would distinguish ",Article(guess)," ",
- guess," from ",Article(node)," ",node,"?")
- question := read() | exit(1)
- if question[-1] == "?" then question[-1] := ""
- question[1] := map(question[1],&lcase,&ucase)
- if Confirm("For ",Article(guess)," ",guess,", what would the _
- answer be") then {
- return Question(question,guess,node)
- }
- else {
- return Question(question,node,guess)
- }
- }
- }
- "Question": {
- if Confirm(node.question) then {
- node.yes := Ask(node.yes)
- }
- else {
- node.no := Ask(node.no)
- }
- }
- }
- end
-
- procedure Article(word)
- return if any('aeiouAEIOU',word) then "an" else "a"
- end
-
- procedure Save()
- local f
- f := open(GameObject || "s","w")
- Output(Tree,f)
- close(f)
- return
- end
-
- procedure Output(node,f,sense)
- static indent
- initial indent := 0
- /sense := " "
- case type(node) of {
- "string": write(f,repl(" ",indent),sense,"A: ",node)
- "Question": {
- write(f,repl(" ",indent),sense,"Q: ", node.question)
- indent +:= 1
- Output(node.yes,f,"y")
- Output(node.no,f,"n")
- indent -:= 1
- }
- }
- return
- end
-
- procedure Get()
- local f
- f := open(GameObject || "s","r") | fail
- Tree := Input(f)
- close(f)
- return
- end
-
- procedure Input(f)
- local nodetype,s
- read(f) ? (tab(upto(~' \t')) & =("y" | "n" | "") &
- nodetype := move(1) & move(2) & s := tab(0))
- if nodetype == "Q" then {
- return Question(s,Input(f),Input(f))
- }
- else {
- return s
- }
- end
-
- procedure List()
- ShowLine := ""
- Show(Tree)
- write(trim(ShowLine))
- return
- end
-
- procedure Show(node)
- if type(node) == "Question" then {
- Show(node.yes)
- Show(node.no)
- }
- else {
- if *ShowLine + *node > 78 then {
- write(trim(ShowLine))
- ShowLine := ""
- }
- ShowLine ||:= node || " "
- }
- return
- end
-