# Icon

To use this language, use the class "language-icon".

## Comments

    #
    # Foobar

## Strings and csets

    ""
    "Foo\"bar"
    ''
    'a\'bcdefg'

## Numbers

    42
    3.14159
    5.2E+8
    16rface
    2r1101

## Full example

    # Author: Robert J. Alexander
    global GameObject, Tree, 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
    #  Game() -- Conducts a game.
    #
    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
    #  Confirm() -- Handles yes/no questions and answers.
    #
    procedure Confirm(q[])
       local answer, s
       static ok
       initial {
          ok := table()
          every ok["y" | "yes" | "yeah" | "uh huh"] := "yes"
          every ok["n" | "no"  | "nope" | "uh uh" ] := "no"
          }
       while /answer do {
          every writes(!q)
          write("?")
          case s := read() | exit(1) of {
             #  Commands recognized at a yes/no prompt.
             #
             "save":    Save()
             "get":     Get()
             "list":    List()
             "dump":    Output(Tree)
             default:   {
                (answer := \ok[map(s, &ucase, &lcase)]) |
                   write("This is a \"yes\" or \"no\" question.")
                }
             }
          }
       return answer == "yes"
    end
    #  Ask() -- Navigates through the barrage of questions leading to a
    #  guess.
    #
    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
    #  Article() -- Come up with the appropriate indefinite article.
    #
    procedure Article(word)
       return if any('aeiouAEIOU', word) then "an" else "a"
    end
    #  Save() -- Store our acquired knowledge in a disk file name
    #  based on the GameObject.
    #
    procedure Save()
       local f
       f := open(GameObject || "s", "w")
       Output(Tree, f)
       close(f)
       return
    end
    #  Output() -- Recursive procedure used to output the knowledge tree.
    #
    procedure Output(node, f, sense)
       static indent
       initial indent := 0
       /f := &output
       /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
    #  Get() -- Read in a knowledge base from a file.
    #
    procedure Get()
       local f
       f := open(GameObject || "s", "r") | fail
       Tree := Input(f)
       close(f)
       return
    end
    #  Input() -- Recursive procedure used to input the knowledge tree.
    #
    procedure Input(f)
       local nodetype, s
       read(f) ? (tab(upto(~' \t')) & =("y" | "n" | "") &
          nodetype := move(1) & move(2) & s := tab(0))
       return if nodetype == "Q" then Question(s, Input(f), Input(f)) else s
    end
    #  List() -- Lists the objects in the knowledge base.
    #
    $define Length           78
    procedure List()
       local lst, line, item
       lst := Show(Tree, [ ])
       line := ""
       every item := !sort(lst) do {
          if *line + *item > Length then {
             write(trim(line))
             line := ""
             }
          line ||:= item || ", "
          }
       write(line[1:-2])
       return
    end
    #
    #  Show() -- Recursive procedure used to navigate the knowledge tree.
    #
    procedure Show(node, lst)
       if type(node) == "Question" then {
          lst := Show(node.yes, lst)
          lst := Show(node.no, lst)
          }
       else put(lst, node)
       return lst
    end